示例#1
0
BOOLEAN
NTAPI
ObpCheckTraverseAccess(IN PVOID Object,
                       IN ACCESS_MASK TraverseAccess,
                       IN PACCESS_STATE AccessState OPTIONAL,
                       IN BOOLEAN LockHeld,
                       IN KPROCESSOR_MODE AccessMode,
                       OUT PNTSTATUS AccessStatus)
{
    POBJECT_HEADER ObjectHeader;
    POBJECT_TYPE ObjectType;
    PSECURITY_DESCRIPTOR SecurityDescriptor;
    BOOLEAN SdAllocated;
    BOOLEAN Result;
    ACCESS_MASK GrantedAccess = 0;
    PPRIVILEGE_SET Privileges = NULL;
    NTSTATUS Status;
    PAGED_CODE();

    /* Get the header and type */
    ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
    ObjectType = ObjectHeader->Type;

    /* Get the security descriptor */
    Status = ObGetObjectSecurity(Object, &SecurityDescriptor, &SdAllocated);
    if (!NT_SUCCESS(Status))
    {
        /* We failed */
        *AccessStatus = Status;
        return FALSE;
    }

    /* Lock the security context */
    SeLockSubjectContext(&AccessState->SubjectSecurityContext);

    /* Now do the entire access check */
    Result = SeAccessCheck(SecurityDescriptor,
                           &AccessState->SubjectSecurityContext,
                           TRUE,
                           TraverseAccess,
                           0,
                           &Privileges,
                           &ObjectType->TypeInfo.GenericMapping,
                           AccessMode,
                           &GrantedAccess,
                           AccessStatus);
    if (Privileges)
    {
        /* We got privileges, append them to the access state and free them */
        Status = SeAppendPrivileges(AccessState, Privileges);
        SeFreePrivileges(Privileges);
    }

    /* We're done, unlock the context and release security */
    SeUnlockSubjectContext(&AccessState->SubjectSecurityContext);
    ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated);
    return Result;
}
示例#2
0
文件: data.c 项目: GYGit/reactos
NTSTATUS
NTAPI
CreateDeviceSecurityDescriptor(IN PDEVICE_OBJECT *DeviceObject)
{
    NTSTATUS Status;
    PSECURITY_DESCRIPTOR SecurityDescriptor;
    BOOLEAN MemoryAllocated = FALSE;
    PACL Dacl = NULL;
    PVOID ObjectSecurityDescriptor = NULL;
    SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC CreateDeviceSecurityDescriptor: Entering.\n");

    /* Get the current SD of the device object */
    Status = ObGetObjectSecurity(*DeviceObject, &SecurityDescriptor, &MemoryAllocated);
    if (!NT_SUCCESS(Status))
    {
        SAC_DBG(SAC_DBG_INIT, "SAC: Unable to get security descriptor, error: %x\n", Status);
        NT_ASSERT(MemoryAllocated == FALSE);
        SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC CreateDeviceSecurityDescriptor: Exiting with status 0x%x\n", Status);
        return Status;
    }

    /* Build a DACL for it */
    Status = BuildDeviceAcl(&Dacl);
    if (Status >= 0)
    {
        ASSERT(FALSE);
    }
    else
    {
        SAC_DBG(SAC_DBG_INIT, "SAC CreateDeviceSecurityDescriptor : Unable to create Raw ACL, error : %x\n", Status);
        /* FIXME: Temporary hack */
        Status = STATUS_SUCCESS;
        goto CleanupPath;
    }

CleanupPath:
    /* Release the SD we queried */
    ObReleaseObjectSecurity(SecurityDescriptor, MemoryAllocated);

    /* Free anything else we may have allocated */
    if (ObjectSecurityDescriptor) ExFreePool(ObjectSecurityDescriptor);
    if (Dacl) SacFreePool(Dacl);

    /* All done */
    SAC_DBG(SAC_DBG_ENTRY_EXIT, "SAC CreateDeviceSecurityDescriptor: Exiting with status 0x%x\n", Status);
    return Status;
}
示例#3
0
NTSTATUS
ObInsertObject (
    __in PVOID Object,
    __in_opt PACCESS_STATE AccessState,
    __in_opt ACCESS_MASK DesiredAccess,
    __in ULONG ObjectPointerBias,
    __out_opt PVOID *NewObject,
    __out_opt PHANDLE Handle
    )

/*++

Routine Description:

    This routine inserts an object into the current processes handle table.

    The Object header includes a pointer to a SecurityDescriptor passed in
    an object creation call.  This SecurityDescriptor is not assumed to have
    been captured.  This routine is responsible for making an appropriate
    SecurityDescriptor and removing the reference in the object header.

Arguments:

    Object - Supplies a pointer to the new object body

    AccessState - Optionally supplies the access state for the new
        handle

    DesiredAccess - Optionally supplies the desired access we want for the
        new handle

    ObjectPointerBias - Supplies a bias to apply for the pointer count for the
        object

    NewObject - Optionally receives the pointer to the new object that we've
        created a handle for

    Handle - Receives the new handle, If NULL then no handle is created.
             Objects that don't have handles created must be unnamed and
             have an object bias of zero.

Return Value:

    An appropriate NTSTATUS value.

--*/

{
    POBJECT_CREATE_INFORMATION ObjectCreateInfo;
    POBJECT_HEADER ObjectHeader;
    PUNICODE_STRING ObjectName;
    POBJECT_TYPE ObjectType;
    POBJECT_HEADER_NAME_INFO NameInfo;
    PSECURITY_DESCRIPTOR ParentDescriptor = NULL;
    PVOID InsertObject;
    HANDLE NewHandle;
    OB_OPEN_REASON OpenReason;
    NTSTATUS Status = STATUS_SUCCESS;
    ACCESS_STATE LocalAccessState;
    AUX_ACCESS_DATA AuxData;
    BOOLEAN SecurityDescriptorAllocated;
    KPROCESSOR_MODE PreviousMode;
    NTSTATUS ReturnStatus;
    PVOID DirObject = NULL;
    OBP_LOOKUP_CONTEXT LookupContext;

    PAGED_CODE();

    ObpValidateIrql("ObInsertObject");

    //
    //  Get the address of the object header, the object create information,
    //  the object type, and the address of the object name descriptor, if
    //  specified.
    //

    ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);

#if DBG

    if ((ObjectHeader->Flags & OB_FLAG_NEW_OBJECT) == 0) {

        KdPrint(("OB: Attempting to insert existing object %08x\n", Object));
        KdBreakPoint();

        ObDereferenceObject(Object);

        return STATUS_INVALID_PARAMETER;
    }

#endif

    ObjectCreateInfo = ObjectHeader->ObjectCreateInfo;

    ObjectType = ObjectHeader->Type;

    NameInfo = ObpReferenceNameInfo( ObjectHeader );

    ObjectName = NULL;

    if ((NameInfo != NULL) && (NameInfo->Name.Buffer != NULL)) {

        ObjectName = &NameInfo->Name;
    }

    ASSERT (ARGUMENT_PRESENT (Handle) || (ObjectPointerBias == 0 && ObjectName == NULL &&
                                          ObjectType->TypeInfo.SecurityRequired && NewObject == NULL));

    //
    //  If security checks are not required and an object name is not
    //  specified, insert an unnamed object, biasing the count
    //  by one, dereference the bias, and return to our caller
    //

    PreviousMode = KeGetPreviousMode();

    if (!ObjectType->TypeInfo.SecurityRequired && (ObjectName == NULL)) {

        ObjectHeader->ObjectCreateInfo = NULL;

        *Handle = NULL;

        Status = ObpCreateUnnamedHandle( Object,
                                         DesiredAccess,
                                         1 + ObjectPointerBias,
                                         ObjectCreateInfo->Attributes,
                                         PreviousMode,
                                         NewObject,
                                         Handle );
        //
        //  Free the object creation information and dereference the object.
        //

        ObpFreeObjectCreateInformation(ObjectCreateInfo);

        ObpDereferenceNameInfo( NameInfo );
        ObDereferenceObject(Object);

        return Status;
    }

    //
    //  The object is either named or requires full security checks.  If the
    //  caller hasn't specified an access state then dummy up a local one
    //  using the requested desired access
    //

    if (!ARGUMENT_PRESENT(AccessState)) {

        AccessState = &LocalAccessState;

        Status = SeCreateAccessState( &LocalAccessState,
                                      &AuxData,
                                      DesiredAccess,
                                      &ObjectType->TypeInfo.GenericMapping );

        if (!NT_SUCCESS(Status)) {

            ObpDereferenceNameInfo( NameInfo );
            ObDereferenceObject(Object);

            return Status;
        }
    }

    AccessState->SecurityDescriptor = ObjectCreateInfo->SecurityDescriptor;

    //
    //  Check the desired access mask against the security descriptor
    //

    Status = ObpValidateAccessMask( AccessState );

    if (!NT_SUCCESS( Status )) {

        if (AccessState == &LocalAccessState) {

            SeDeleteAccessState( AccessState );
        }

        ObpDereferenceNameInfo( NameInfo );
        ObDereferenceObject(Object);

        if (AccessState == &LocalAccessState) {

            SeDeleteAccessState( AccessState );
        }

        return( Status );
    }

    //
    //  Set some local state variables
    //

    ObpInitializeLookupContext(&LookupContext);

    InsertObject = Object;
    OpenReason = ObCreateHandle;

    //
    //  Check if we have an object name.  If so then
    //  lookup the name
    //

    if (ObjectName != NULL) {

        Status = ObpLookupObjectName( ObjectCreateInfo->RootDirectory,
                                      ObjectName,
                                      ObjectCreateInfo->Attributes,
                                      ObjectType,
                                      (KPROCESSOR_MODE)(ObjectHeader->Flags & OB_FLAG_KERNEL_OBJECT
                                                            ? KernelMode : UserMode),
                                      ObjectCreateInfo->ParseContext,
                                      ObjectCreateInfo->SecurityQos,
                                      Object,
                                      AccessState,
                                      &LookupContext,
                                      &InsertObject );

        //
        //  We found the name and it is not the object we have as our input.
        //  So we cannot insert the object again so we'll return an
        //  appropriate status
        //

        if (NT_SUCCESS(Status) &&
            (InsertObject != NULL) &&
            (InsertObject != Object)) {

            OpenReason = ObOpenHandle;

            if (ObjectCreateInfo->Attributes & OBJ_OPENIF) {

                if (ObjectType != OBJECT_TO_OBJECT_HEADER(InsertObject)->Type) {

                    Status = STATUS_OBJECT_TYPE_MISMATCH;

                } else {

                    Status = STATUS_OBJECT_NAME_EXISTS;     // Warning only
                }

            } else {

                if (OBJECT_TO_OBJECT_HEADER(InsertObject)->Type == ObpSymbolicLinkObjectType) {

                     ObDereferenceObject(InsertObject);
                }
                
                Status = STATUS_OBJECT_NAME_COLLISION;
            }
        }

        //
        //  We did not find the name so we'll cleanup after ourselves
        //  and return to our caller
        //

        if (!NT_SUCCESS( Status )) {

            ObpReleaseLookupContext( &LookupContext );

            ObpDereferenceNameInfo( NameInfo );
            ObDereferenceObject( Object );

            //
            //  Free security information if we allocated it
            //

            if (AccessState == &LocalAccessState) {

                SeDeleteAccessState( AccessState );
            }

            return( Status );

        } else {

            //
            //  Otherwise we did locate the object name
            //
            //  If we just created a named symbolic link then call out to
            //  handle any Dos Device name semantics.
            //

            if (ObjectType == ObpSymbolicLinkObjectType) {

                ObpCreateSymbolicLinkName( (POBJECT_SYMBOLIC_LINK)InsertObject );
            }
        }
    }

    //
    //  If we are creating a new object, then we need assign security
    //  to it.  A pointer to the captured caller-proposed security
    //  descriptor is contained in the AccessState structure.  The
    //  SecurityDescriptor field in the object header must point to
    //  the final security descriptor, or to NULL if no security is
    //  to be assigned to the object.
    //

    if (InsertObject == Object) {

        //
        //  Only the following objects have security descriptors:
        //
        //       - Named Objects
        //       - Unnamed objects whose object-type information explicitly
        //         indicates a security descriptor is required.
        //

        if ((ObjectName != NULL) || ObjectType->TypeInfo.SecurityRequired) {

            //
            //  Get the parent's descriptor, if there is one...
            //

            if ((NameInfo != NULL) && (NameInfo->Directory != NULL)) {

                //
                //  This will allocate a block of memory and copy
                //  the parent's security descriptor into it, and
                //  return the pointer to the block.
                //
                //  Call ObReleaseObjectSecurity to free up this
                //  memory.
                //

                ObGetObjectSecurity( NameInfo->Directory,
                                     &ParentDescriptor,
                                     &SecurityDescriptorAllocated );
            }
            else {
                SecurityDescriptorAllocated = FALSE;
            }

            //
            //  Take the captured security descriptor in the AccessState,
            //  put it into the proper format, and call the object's
            //  security method to assign the new security descriptor to
            //  the new object.
            //

            Status = ObAssignSecurity( AccessState,
                                       ParentDescriptor,
                                       Object,
                                       ObjectType );

            if (ParentDescriptor != NULL) {

                ObReleaseObjectSecurity( ParentDescriptor,
                                         SecurityDescriptorAllocated );

            } else if (NT_SUCCESS( Status )) {

                SeReleaseSecurityDescriptor( ObjectCreateInfo->SecurityDescriptor,
                                             ObjectCreateInfo->ProbeMode,
                                             TRUE );

                ObjectCreateInfo->SecurityDescriptor = NULL;
                AccessState->SecurityDescriptor = NULL;
            }
        }

        if (!NT_SUCCESS( Status )) {

            //
            //  The attempt to assign the security descriptor to
            //  the object failed.
            //
            
            if (LookupContext.DirectoryLocked) {
                
                //
                //  If ObpLookupObjectName already inserted the 
                //  object into the directory we have to backup this
                //

                //
                //  Capture the object Directory 
                //

                DirObject = NameInfo->Directory;

                ObpDeleteDirectoryEntry( &LookupContext ); 
            }

            ObpReleaseLookupContext( &LookupContext );

            //
            //  If ObpLookupObjectName inserted the object into the directory
            //  it added a reference to the object and to its directory
            //  object. We should remove the extra-references
            //

            if (DirObject) {

                ObDereferenceObject( Object );
                ObDereferenceObject( DirObject );
            }

            //
            //  The first backout logic used ObpDeleteNameCheck
            //  which is wrong because the security descriptor for
            //  the object is not initialized. Actually  ObpDeleteNameCheck
            //  had no effect because the object was removed before from 
            //  the directory
            //

            ObpDereferenceNameInfo( NameInfo );
            ObDereferenceObject( Object );

            //
            //  Free security information if we allocated it
            //

            if (AccessState == &LocalAccessState) {

                SeDeleteAccessState( AccessState );
            }

            return( Status );
        }
    }

    ReturnStatus = Status;

    ObjectHeader->ObjectCreateInfo = NULL;

    //
    //  Create a named handle for the object with a pointer bias
    //  This call also will unlock the directory lock is necessary
    //  on return
    //

    if (ARGUMENT_PRESENT (Handle)) {

        Status = ObpCreateHandle( OpenReason,
                                  InsertObject,
                                  NULL,
                                  AccessState,
                                  1 + ObjectPointerBias,
                                  ObjectCreateInfo->Attributes,
                                  &LookupContext,
                                  PreviousMode,
                                  NewObject,
                                  &NewHandle );

        //
        //  If the insertion failed, the following dereference will cause
        //  the newly created object to be deallocated.
        //

        if (!NT_SUCCESS( Status )) {

            //
            //  Make the name reference go away if an error.
            //

            if (ObjectName != NULL) {

                ObpDeleteNameCheck( Object );
            }

            *Handle = NULL;

            ReturnStatus = Status;

        } else {
            *Handle = NewHandle;
        }

        ObpDereferenceNameInfo( NameInfo );

        ObDereferenceObject( Object );


    } else {

        BOOLEAN IsNewObject;

        //
        //  Charge the user quota for the object.
        //

        ObpLockObject( ObjectHeader );

        ReturnStatus = ObpChargeQuotaForObject( ObjectHeader, ObjectType, &IsNewObject );

        ObpUnlockObject( ObjectHeader );

        if (!NT_SUCCESS (ReturnStatus)) {
            ObDereferenceObject( Object );
        }

        //
        //  N.B. An object cannot be named if no Handle parameter is specified.
        //  The calls to ObpDereferenceNameInfo and ObpReleaseLookupContext are 
        //  not necessary in this path then.
        //
    }

    ObpFreeObjectCreateInformation( ObjectCreateInfo );

    //
    //  Free security information if we allocated it
    //

    if (AccessState == &LocalAccessState) {

        SeDeleteAccessState( AccessState );
    }

    return( ReturnStatus );
}
示例#4
0
/*++
* @name ObCheckObjectAccess
*
*     The ObCheckObjectAccess routine <FILLMEIN>
*
* @param Object
*        <FILLMEIN>
*
* @param AccessState
*        <FILLMEIN>
*
* @param LockHeld
*        <FILLMEIN>
*
* @param AccessMode
*        <FILLMEIN>
*
* @param ReturnedStatus
*        <FILLMEIN>
*
* @return TRUE if access was granted, FALSE otherwise.
*
* @remarks None.
*
*--*/
BOOLEAN
NTAPI
ObCheckObjectAccess(IN PVOID Object,
                    IN OUT PACCESS_STATE AccessState,
                    IN BOOLEAN LockHeld,
                    IN KPROCESSOR_MODE AccessMode,
                    OUT PNTSTATUS ReturnedStatus)
{
    POBJECT_HEADER ObjectHeader;
    POBJECT_TYPE ObjectType;
    PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
    BOOLEAN SdAllocated;
    NTSTATUS Status;
    BOOLEAN Result;
    ACCESS_MASK GrantedAccess;
    PPRIVILEGE_SET Privileges = NULL;
    PAGED_CODE();

    /* Get the object header and type */
    ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
    ObjectType = ObjectHeader->Type;

    /* Get security information */
    Status = ObGetObjectSecurity(Object, &SecurityDescriptor, &SdAllocated);
    if (!NT_SUCCESS(Status))
    {
        /* Return failure */
        *ReturnedStatus = Status;
        return FALSE;
    }
    else if (!SecurityDescriptor)
    {
        /* Otherwise, if we don't actually have an SD, return success */
        *ReturnedStatus = Status;
        return TRUE;
    }

    /* Lock the security context */
    SeLockSubjectContext(&AccessState->SubjectSecurityContext);

    /* Now do the entire access check */
    Result = SeAccessCheck(SecurityDescriptor,
                           &AccessState->SubjectSecurityContext,
                           TRUE,
                           AccessState->RemainingDesiredAccess,
                           AccessState->PreviouslyGrantedAccess,
                           &Privileges,
                           &ObjectType->TypeInfo.GenericMapping,
                           AccessMode,
                           &GrantedAccess,
                           ReturnedStatus);
    if (Privileges)
    {
        /* We got privileges, append them to the access state and free them */
        Status = SeAppendPrivileges(AccessState, Privileges);
        SeFreePrivileges(Privileges);
    }

    /* Check if access was granted */
    if (Result)
    {
        /* Update the access state */
        AccessState->RemainingDesiredAccess &= ~(GrantedAccess |
                                                 MAXIMUM_ALLOWED);
        AccessState->PreviouslyGrantedAccess |= GrantedAccess;
    }

    /* Do audit alarm */
    SeOpenObjectAuditAlarm(&ObjectType->Name,
                           Object,
                           NULL,
                           SecurityDescriptor,
                           AccessState,
                           FALSE,
                           Result,
                           AccessMode,
                           &AccessState->GenerateOnClose);

    /* We're done, unlock the context and release security */
    SeUnlockSubjectContext(&AccessState->SubjectSecurityContext);
    ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated);
    return Result;
}
示例#5
0
BOOLEAN
NTAPI
ObpCheckObjectReference(IN PVOID Object,
                        IN OUT PACCESS_STATE AccessState,
                        IN BOOLEAN LockHeld,
                        IN KPROCESSOR_MODE AccessMode,
                        OUT PNTSTATUS AccessStatus)
{
    POBJECT_HEADER ObjectHeader;
    POBJECT_TYPE ObjectType;
    PSECURITY_DESCRIPTOR SecurityDescriptor;
    BOOLEAN SdAllocated;
    BOOLEAN Result;
    ACCESS_MASK GrantedAccess = 0;
    PPRIVILEGE_SET Privileges = NULL;
    NTSTATUS Status;
    PAGED_CODE();

    /* Get the header and type */
    ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
    ObjectType = ObjectHeader->Type;

    /* Get the security descriptor */
    Status = ObGetObjectSecurity(Object, &SecurityDescriptor, &SdAllocated);
    if (!NT_SUCCESS(Status))
    {
        /* We failed */
        *AccessStatus = Status;
        return FALSE;
    }

    /* Lock the security context */
    SeLockSubjectContext(&AccessState->SubjectSecurityContext);

    /* Now do the entire access check */
    Result = SeAccessCheck(SecurityDescriptor,
                           &AccessState->SubjectSecurityContext,
                           TRUE,
                           AccessState->RemainingDesiredAccess,
                           AccessState->PreviouslyGrantedAccess,
                           &Privileges,
                           &ObjectType->TypeInfo.GenericMapping,
                           AccessMode,
                           &GrantedAccess,
                           AccessStatus);
    if (Result)
    {
        /* Update the access state */
        AccessState->RemainingDesiredAccess &= ~GrantedAccess;
        AccessState->PreviouslyGrantedAccess |= GrantedAccess;
    }

    /* Check if we have an SD */
    if (SecurityDescriptor)
    {
        /* Do audit alarm */
#if 0
        SeObjectReferenceAuditAlarm(&AccessState->OperationID,
                                    Object,
                                    SecurityDescriptor,
                                    &AccessState->SubjectSecurityContext,
                                    AccessState->RemainingDesiredAccess |
                                    AccessState->PreviouslyGrantedAccess,
                                    ((PAUX_ACCESS_DATA)(AccessState->AuxData))->
                                    PrivilegeSet,
                                    Result,
                                    AccessMode);
#endif
    }

    /* We're done, unlock the context and release security */
    SeUnlockSubjectContext(&AccessState->SubjectSecurityContext);
    ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated);
    return Result;
}
示例#6
0
NTSTATUS
NTAPI
PspSetPrimaryToken(IN PEPROCESS Process,
                   IN HANDLE TokenHandle OPTIONAL,
                   IN PACCESS_TOKEN Token OPTIONAL)
{
    KPROCESSOR_MODE PreviousMode = ExGetPreviousMode();
    BOOLEAN IsChild;
    PACCESS_TOKEN NewToken = Token;
    NTSTATUS Status, AccessStatus;
    BOOLEAN Result, SdAllocated;
    PSECURITY_DESCRIPTOR SecurityDescriptor = NULL;
    SECURITY_SUBJECT_CONTEXT SubjectContext;
    PSTRACE(PS_SECURITY_DEBUG, "Process: %p Token: %p\n", Process, Token);

    /* Make sure we got a handle */
    if (TokenHandle)
    {
        /* Reference it */
        Status = ObReferenceObjectByHandle(TokenHandle,
                                           TOKEN_ASSIGN_PRIMARY,
                                           SeTokenObjectType,
                                           PreviousMode,
                                           (PVOID*)&NewToken,
                                           NULL);
        if (!NT_SUCCESS(Status)) return Status;
    }

    /* Check if this is a child */
    Status = SeIsTokenChild(NewToken, &IsChild);
    if (!NT_SUCCESS(Status))
    {
        /* Failed, dereference */
        if (TokenHandle) ObDereferenceObject(NewToken);
        return Status;
    }

    /* Check if this was an independent token */
    if (!IsChild)
    {
        /* Make sure we have the privilege to assign a new one */
        if (!SeSinglePrivilegeCheck(SeAssignPrimaryTokenPrivilege,
                                    PreviousMode))
        {
            /* Failed, dereference */
            if (TokenHandle) ObDereferenceObject(NewToken);
            return STATUS_PRIVILEGE_NOT_HELD;
        }
    }

    /* Assign the token */
    Status = PspAssignPrimaryToken(Process, NULL, NewToken);
    if (NT_SUCCESS(Status))
    {
        /*
         * We need to completely reverify if the process still has access to
         * itself under this new token.
         */
        Status = ObGetObjectSecurity(Process,
                                     &SecurityDescriptor,
                                     &SdAllocated);
        if (NT_SUCCESS(Status))
        {
            /* Setup the security context */
            SubjectContext.ProcessAuditId = Process;
            SubjectContext.PrimaryToken = PsReferencePrimaryToken(Process);
            SubjectContext.ClientToken = NULL;

            /* Do the access check */
            Result = SeAccessCheck(SecurityDescriptor,
                                   &SubjectContext,
                                   FALSE,
                                   MAXIMUM_ALLOWED,
                                   0,
                                   NULL,
                                   &PsProcessType->TypeInfo.GenericMapping,
                                   PreviousMode,
                                   &Process->GrantedAccess,
                                   &AccessStatus);

            /* Dereference the token and let go the SD */
            ObFastDereferenceObject(&Process->Token,
                                    SubjectContext.PrimaryToken);
            ObReleaseObjectSecurity(SecurityDescriptor, SdAllocated);

            /* Remove access if it failed */
            if (!Result) Process->GrantedAccess = 0;

            /* Setup granted access */
            Process->GrantedAccess |= (PROCESS_VM_OPERATION |
                                       PROCESS_VM_READ |
                                       PROCESS_VM_WRITE |
                                       PROCESS_QUERY_INFORMATION |
                                       PROCESS_TERMINATE |
                                       PROCESS_CREATE_THREAD |
                                       PROCESS_DUP_HANDLE |
                                       PROCESS_CREATE_PROCESS |
                                       PROCESS_SET_INFORMATION |
                                       STANDARD_RIGHTS_ALL |
                                       PROCESS_SET_QUOTA);
        }
    }

    /* Dereference the token */
    if (TokenHandle) ObDereferenceObject(NewToken);
    return Status;
}
示例#7
0
文件: init.c 项目: BillTheBest/WinNT4
NTSTATUS
AfdCreateRawSecurityDescriptor(
    VOID
    )

/*++

Routine Description:

    This routine creates a security descriptor which gives access
    only to Administrtors and LocalSystem. This descriptor is used
    to access check raw endpoint opens.

Arguments:

    None.

Return Value:

    STATUS_SUCCESS or an appropriate error code.

--*/

{
    PACL                  rawAcl;
    NTSTATUS              status;
    BOOLEAN               memoryAllocated = FALSE;
    PSECURITY_DESCRIPTOR  afdSecurityDescriptor;
    ULONG                 afdSecurityDescriptorLength;
    CHAR                  buffer[SECURITY_DESCRIPTOR_MIN_LENGTH];
    PSECURITY_DESCRIPTOR  localSecurityDescriptor =
                             (PSECURITY_DESCRIPTOR) &buffer;
    SECURITY_INFORMATION  securityInformation = DACL_SECURITY_INFORMATION;


    //
    // Get a pointer to the security descriptor from the AFD device object.
    //
    status = ObGetObjectSecurity(
                 AfdDeviceObject,
                 &afdSecurityDescriptor,
                 &memoryAllocated
                 );

    if (!NT_SUCCESS(status)) {
        KdPrint((
            "AFD: Unable to get security descriptor, error: %x\n",
            status
            ));
        ASSERT(memoryAllocated == FALSE);
        return(status);
    }

    //
    // Build a local security descriptor with an ACL giving only
    // administrators and system access.
    //
    status = AfdBuildDeviceAcl(&rawAcl);

    if (!NT_SUCCESS(status)) {
        KdPrint(("AFD: Unable to create Raw ACL, error: %x\n", status));
        goto error_exit;
    }

    (VOID) RtlCreateSecurityDescriptor(
                localSecurityDescriptor,
                SECURITY_DESCRIPTOR_REVISION
                );

    (VOID) RtlSetDaclSecurityDescriptor(
                localSecurityDescriptor,
                TRUE,
                rawAcl,
                FALSE
                );

    //
    // Make a copy of the AFD descriptor. This copy will be the raw descriptor.
    //
    afdSecurityDescriptorLength = RtlLengthSecurityDescriptor(
                                      afdSecurityDescriptor
                                      );

    AfdRawSecurityDescriptor = AFD_ALLOCATE_POOL(
                                   PagedPool,
                                   afdSecurityDescriptorLength,
                                   AFD_SECURITY_POOL_TAG
                                   );

    if (AfdRawSecurityDescriptor == NULL) {
        KdPrint(("AFD: couldn't allocate security descriptor\n"));
        goto error_exit;
    }

    RtlMoveMemory(
        AfdRawSecurityDescriptor,
        afdSecurityDescriptor,
        afdSecurityDescriptorLength
        );

    //
    // Now apply the local descriptor to the raw descriptor.
    //
    status = SeSetSecurityDescriptorInfo(
                 NULL,
                 &securityInformation,
                 localSecurityDescriptor,
                 &AfdRawSecurityDescriptor,
                 PagedPool,
                 IoGetFileObjectGenericMapping()
                 );

    if (!NT_SUCCESS(status)) {
        KdPrint(("AFD: SeSetSecurity failed, %lx\n", status));
        AFD_FREE_POOL(
            AfdRawSecurityDescriptor,
            AFD_SECURITY_POOL_TAG
            );
        AFD_FREE_POOL(
            rawAcl,
            AFD_SECURITY_POOL_TAG
            );
        AfdRawSecurityDescriptor = NULL;
        goto error_exit;
    }

    status = STATUS_SUCCESS;

error_exit:

    ObReleaseObjectSecurity(
        afdSecurityDescriptor,
        memoryAllocated
        );

    return(status);
}
示例#8
0
VOID
ObpProcessDosDeviceSymbolicLink(
    POBJECT_SYMBOLIC_LINK SymbolicLink,
    ULONG Action
    )

/*++

Routine Description:

    This function is called whenever a symbolic link is created or deleted
    in the \?? object directory.

    For creates, it attempts to snap the symbolic link to a non-object
    directory object.  It does this by walking the symbolic link target
    string, until it sees a non-directory object or a directory object
    that does NOT allow World traverse access.  It stores a referenced
    pointer to this object in the symbolic link object.  It also
    increments a count in each of the object directory objects that it
    walked over.  This count is used to disallow any attempt to remove
    World traverse access from a directory object after it has
    participated in a snapped symbolic link.

    For deletes, it repeats the walk of the target string, decrementing
    the count associated with each directory object walked over.  It also
    dereferences the snapped object pointer.

Arguments:

    SymbolicLink - pointer to symbolic link object being created or deleted.

    Action - describes whether this is a create or a delete action

Return Value:

    None.

--*/

{
    NTSTATUS Status;
    PVOID Object;
    POBJECT_HEADER ObjectHeader;
    PSECURITY_DESCRIPTOR SecurityDescriptor;
    BOOLEAN MemoryAllocated;
    UNICODE_STRING RemainingName;
    UNICODE_STRING ComponentName;
    BOOLEAN HaveWorldTraverseAccess;
    ULONG Depth;
    POBJECT_DIRECTORY Directories[ MAX_DEPTH ], Directory, ParentDirectory;
    PDEVICE_OBJECT DeviceObject;
    ULONG DosDeviceDriveType;

    Object = NULL;
    if (Action == CREATE_SYMBOLIC_LINK || SymbolicLink->LinkTargetObject != NULL) {

        ParentDirectory = NULL;
        Depth = 0;
        Directory = ObpRootDirectoryObject;
        RemainingName = SymbolicLink->LinkTarget;
        while (TRUE) {
            if (*(RemainingName.Buffer) == OBJ_NAME_PATH_SEPARATOR) {
                RemainingName.Buffer++;
                RemainingName.Length -= sizeof( OBJ_NAME_PATH_SEPARATOR );
                }

            ComponentName = RemainingName;
            while (RemainingName.Length != 0) {
                if (*(RemainingName.Buffer) == OBJ_NAME_PATH_SEPARATOR) {
                    break;
                    }

                RemainingName.Buffer++;
                RemainingName.Length -= sizeof( OBJ_NAME_PATH_SEPARATOR );
                }

            ComponentName.Length -= RemainingName.Length;
            if (ComponentName.Length == 0) {
                return;
                }

            //
            // See if we have world traverse access to look this name up
            //
            if (ParentDirectory != NULL) {
                HaveWorldTraverseAccess = FALSE;

                //
                // Obtain the object's security descriptor
                //

                Status = ObGetObjectSecurity( ParentDirectory,
                                              &SecurityDescriptor,
                                              &MemoryAllocated
                                            );

                if (NT_SUCCESS( Status )) {
                    //
                    // Check to see if WORLD has TRAVERSE access
                    //

                    HaveWorldTraverseAccess = SeFastTraverseCheck( SecurityDescriptor,
                                                                   DIRECTORY_TRAVERSE,
                                                                   UserMode
                                                                 );
                    }

                if (!HaveWorldTraverseAccess) {
                    Object = NULL;
                    break;
                    }

                Directories[ Depth++ ] = ParentDirectory;
                }

            //
            // Look this component name up in this directory.  If not found, then
            // bail.
            //

            Object = ObpLookupDirectoryEntry( Directory, &ComponentName, OBJ_CASE_INSENSITIVE );
            if (Object == NULL) {
                break;
                }

            //
            // See if this is a object directory object.  If so, keep going
            //

            ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
            if (ObjectHeader->Type == ObpDirectoryObjectType) {
                ParentDirectory = Directory;
                Directory = (POBJECT_DIRECTORY)Object;
                }
            else {
                //
                // Not a object directory object, so all done.  Exit the loop
                //
                break;
                }
            }

        //
        // Done walking the target path.  Now update the counts associated
        // with each directory object walked over.
        //

        while (Depth--) {
            Directory = Directories[ Depth ];
            if (Action == CREATE_SYMBOLIC_LINK) {
                if (Object != NULL) {
                    Directory->SymbolicLinkUsageCount += 1;
                    }
                }
            else {
                Directory->SymbolicLinkUsageCount += 1;
                }
            }
        }


    //
    // Done processing symbolic link target path.  Update symbolic link
    // object as appropriate for passed in reason
    //

    if (Action == CREATE_SYMBOLIC_LINK) {
        //
        // Default is to calculate the drive type in user mode if we are
        // unable to snap the symbolic link or it does not resolve to a
        // DEVICE_OBJECT we know about.
        //
        DosDeviceDriveType = DOSDEVICE_DRIVE_CALCULATE;
        if (Object != NULL) {
            //
            // Create action.  Store a referenced pointer to the snapped object
            // along with the description of any remaining name string.  Also,
            // for Dos drive letters, update the drive type in KUSER_SHARED_DATA
            // array.
            //
            ObReferenceObject( Object );
            SymbolicLink->LinkTargetObject = Object;
            if (*(RemainingName.Buffer) == OBJ_NAME_PATH_SEPARATOR &&
                RemainingName.Length == sizeof( OBJ_NAME_PATH_SEPARATOR )
               ) {
                RtlInitUnicodeString( &SymbolicLink->LinkTargetRemaining, NULL );
                }
            else {
                SymbolicLink->LinkTargetRemaining = RemainingName;
                }
            if (SymbolicLink->DosDeviceDriveIndex != 0) {
                ObjectHeader = OBJECT_TO_OBJECT_HEADER( Object );
                if (ObjectHeader->Type == IoDeviceObjectType) {
                    DeviceObject = (PDEVICE_OBJECT)Object;
                    switch (DeviceObject->DeviceType) {
                        case FILE_DEVICE_CD_ROM:
                        case FILE_DEVICE_CD_ROM_FILE_SYSTEM:
                            DosDeviceDriveType = DOSDEVICE_DRIVE_CDROM;
                            break;

                        case FILE_DEVICE_DISK:
                        case FILE_DEVICE_DISK_FILE_SYSTEM:
                        case FILE_DEVICE_FILE_SYSTEM:
                            if (DeviceObject->Characteristics & FILE_REMOVABLE_MEDIA) {
                                DosDeviceDriveType = DOSDEVICE_DRIVE_REMOVABLE;
                                }
                            else {
                                DosDeviceDriveType = DOSDEVICE_DRIVE_FIXED;
                                }
                            break;

                        case FILE_DEVICE_MULTI_UNC_PROVIDER:
                        case FILE_DEVICE_NETWORK:
                        case FILE_DEVICE_NETWORK_BROWSER:
                        case FILE_DEVICE_NETWORK_FILE_SYSTEM:
                        case FILE_DEVICE_NETWORK_REDIRECTOR:
                            DosDeviceDriveType = DOSDEVICE_DRIVE_REMOTE;
                            break;

                        case FILE_DEVICE_VIRTUAL_DISK:
                            DosDeviceDriveType = DOSDEVICE_DRIVE_RAMDISK;
                            break;

                        default:
                            DosDeviceDriveType = DOSDEVICE_DRIVE_UNKNOWN;
                            break;
                        }
                    }
                }
            }

        //
        // If this is a drive letter symbolic link, update the drive type and
        // and mark as valid drive letter.
        //

        if (SymbolicLink->DosDeviceDriveIndex != 0) {
            SharedUserData->DosDeviceDriveType[ SymbolicLink->DosDeviceDriveIndex-1 ] = (UCHAR)DosDeviceDriveType;
            SharedUserData->DosDeviceMap |= 1 << (SymbolicLink->DosDeviceDriveIndex-1) ;
            }
        }
    else {
        //
        // Deleting the symbolic link.  Dereference the snapped object pointer if any
        // and zero out the snapped object fields.
        //

        RtlInitUnicodeString( &SymbolicLink->LinkTargetRemaining, NULL );
        Object = SymbolicLink->LinkTargetObject;
        if (Object != NULL) {
            SymbolicLink->LinkTargetObject = NULL;
            ObDereferenceObject( Object );
            }

        //
        // If this is a drive letter symbolic link, set the drive type to
        // unknown and clear the bit in the drive letter bit map.
        //

        if (SymbolicLink->DosDeviceDriveIndex != 0) {
            SharedUserData->DosDeviceMap &= ~(1 << SymbolicLink->DosDeviceDriveIndex-1);
            SharedUserData->DosDeviceDriveType[ SymbolicLink->DosDeviceDriveIndex-1 ] = DOSDEVICE_DRIVE_UNKNOWN;
            SymbolicLink->DosDeviceDriveIndex = 0;
            }

        //
        // If we allocated a target buffer, free it.
        //

        if (SymbolicLink->LinkTarget.Buffer != NULL) {
            ExFreePool( SymbolicLink->LinkTarget.Buffer );
            RtlInitUnicodeString( &SymbolicLink->LinkTarget, NULL );
            }
        }

    return;
}