Example #1
0
int
get_sid_id(struct _SID_AND_ATTRIBUTES *sid_a, ULONG sid_a_size)
{
	// doing linear search (optimize?)
	KIRQL irql;
	int i, result = 0;

    KdPrint(("[tdi_fw] get_sid_id: (sid_size = %u/%u)\n",
        SeLengthSid(sid_a->Sid), sid_a_size));

	KeAcquireSpinLock(&g_sids.guard, &irql);

    for (i = 1; i < g_sids.count; i++) {
        // comparing sids byte by byte (can't call RtlEqualSid() due to DISPATCH_LEVEL)

        KdPrint(("[tdi_fw] get_sid_id: sid #%d size %u\n", i, SeLengthSid((PSID)g_sids.list[i]->sid_data)));

		if (SeLengthSid(sid_a->Sid) == SeLengthSid((PSID)g_sids.list[i]->sid_data) &&
            memcmp(sid_a->Sid, (PSID)g_sids.list[i]->sid_data, SeLengthSid(sid_a->Sid)) == 0) {
			result = i;
			break;
		}
    }

	KeReleaseSpinLock(&g_sids.guard, irql);

	KdPrint(("[tdi_fw] get_sid_id: %d\n", result));
	return result;
}
Example #2
0
VOID
SepFreePrimaryGroup(
    IN PTOKEN Token
    )

/*++


Routine Description:

    Free up the space in the dynamic part of the token take up by the primary
    group.

    The token is assumed to be locked for write access before calling
    this routine.

Arguments:

    Token - Pointer to the token.

Return Value:

    None.

--*/
{
    PAGED_CODE();

    //
    // Add the size of the primary group to the DynamicAvailable field.
    //

    Token->DynamicAvailable += SeLengthSid( Token->PrimaryGroup );

    //
    // If there is a default discretionary ACL, and it is not already at the
    // beginning of the dynamic part, move it there (remember to update the
    // pointer to it).
    //

    if (ARGUMENT_PRESENT(Token->DefaultDacl)) {
        if (Token->DynamicPart != (PULONG)(Token->DefaultDacl)) {

            RtlMoveMemory(
                (PVOID)(Token->DynamicPart),
                (PVOID)(Token->DefaultDacl),
                Token->DefaultDacl->AclSize
                );

            Token->DefaultDacl = (PACL)(Token->DynamicPart);

        }
    }

    return;

}
Example #3
0
VOID
SepInitSystemDacls( VOID )
/*++

Routine Description:

    This function initializes the system's default dacls & security
    descriptors.

Arguments:

    None.

Return Value:

    None.


--*/
{

    NTSTATUS
        Status;

    ULONG
        PublicLength,
        PublicUnrestrictedLength,
        SystemLength,
        PublicOpenLength,
        LocalServiceLength;



    PAGED_CODE();

    //
    // Set up a default ACLs
    //
    //    Public:       WORLD:execute, SYSTEM:all, ADMINS:all
    //    PublicUnrestricted: WORLD:execute, SYSTEM:all, ADMINS:all, Restricted:execute
    //    Public Open:  WORLD:(Read|Write|Execute), ADMINS:(all), SYSTEM:all
    //    System:       SYSTEM:all, ADMINS:(read|execute|read_control)
    //    Unrestricted: WORLD:(all), Restricted:(all)

    SystemLength = (ULONG)sizeof(ACL) +
                   (2*((ULONG)sizeof(ACCESS_ALLOWED_ACE))) +
                   SeLengthSid( SeLocalSystemSid ) +
                   SeLengthSid( SeAliasAdminsSid );

    PublicLength = SystemLength +
                   ((ULONG)sizeof(ACCESS_ALLOWED_ACE)) +
                   SeLengthSid( SeWorldSid );

    PublicUnrestrictedLength = PublicLength +
                   ((ULONG)sizeof(ACCESS_ALLOWED_ACE)) +
                   SeLengthSid( SeRestrictedSid );

    PublicOpenLength = PublicLength;

    LocalServiceLength = (ULONG)sizeof(ACL) +
                         4 * (ULONG)sizeof(ACCESS_ALLOWED_ACE) +
                         SeLengthSid(SeWorldSid) +
                         SeLengthSid(SeLocalSystemSid) +
                         SeLengthSid(SeLocalServiceSid) +
                         SeLengthSid(SeAliasAdminsSid);


    SePublicDefaultDacl = (PACL)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, PublicLength, 'cAeS');
    SePublicDefaultUnrestrictedDacl = (PACL)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, PublicUnrestrictedLength, 'cAeS');
    SePublicOpenDacl = (PACL)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, PublicOpenLength, 'cAeS');
    SePublicOpenUnrestrictedDacl = (PACL)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, PublicUnrestrictedLength, 'cAeS');
    SeSystemDefaultDacl = (PACL)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, SystemLength, 'cAeS');
    SeLocalServicePublicDacl = (PACL)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, LocalServiceLength, 'cAeS');
    ASSERT(SePublicDefaultDacl != NULL);
    ASSERT(SePublicDefaultUnrestrictedDacl != NULL);
    ASSERT(SePublicOpenDacl    != NULL);
    ASSERT(SePublicOpenUnrestrictedDacl    != NULL);
    ASSERT(SeSystemDefaultDacl != NULL);
    ASSERT(SeLocalServicePublicDacl != NULL);



    Status = RtlCreateAcl( SePublicDefaultDacl, PublicLength, ACL_REVISION2);
    ASSERT( NT_SUCCESS(Status) );
    Status = RtlCreateAcl( SePublicDefaultUnrestrictedDacl, PublicUnrestrictedLength, ACL_REVISION2);
    ASSERT( NT_SUCCESS(Status) );
    Status = RtlCreateAcl( SePublicOpenDacl, PublicOpenLength, ACL_REVISION2);
    ASSERT( NT_SUCCESS(Status) );
    Status = RtlCreateAcl( SePublicOpenUnrestrictedDacl, PublicUnrestrictedLength, ACL_REVISION2);
    ASSERT( NT_SUCCESS(Status) );
    Status = RtlCreateAcl( SeSystemDefaultDacl, SystemLength, ACL_REVISION2);
    ASSERT( NT_SUCCESS(Status) );
    Status = RtlCreateAcl( SeLocalServicePublicDacl, LocalServiceLength, ACL_REVISION2);
    ASSERT( NT_SUCCESS(Status) );


    //
    // WORLD access (Public DACLs and OpenUnrestricted only)
    //

    Status = RtlAddAccessAllowedAce (
                 SePublicDefaultDacl,
                 ACL_REVISION2,
                 GENERIC_EXECUTE,
                 SeWorldSid
                 );
    ASSERT( NT_SUCCESS(Status) );

    Status = RtlAddAccessAllowedAce (
                 SePublicDefaultUnrestrictedDacl,
                 ACL_REVISION2,
                 GENERIC_EXECUTE,
                 SeWorldSid
                 );
    ASSERT( NT_SUCCESS(Status) );

    Status = RtlAddAccessAllowedAce (
                 SePublicOpenDacl,
                 ACL_REVISION2,
                 (GENERIC_READ | GENERIC_WRITE  | GENERIC_EXECUTE),
                 SeWorldSid
                 );
    ASSERT( NT_SUCCESS(Status) );

    Status = RtlAddAccessAllowedAce (
                 SePublicOpenUnrestrictedDacl,
                 ACL_REVISION2,
                 (GENERIC_READ | GENERIC_WRITE  | GENERIC_EXECUTE),
                 SeWorldSid
                 );
    ASSERT( NT_SUCCESS(Status) );

    Status = RtlAddAccessAllowedAce (
                 SeLocalServicePublicDacl,
                 ACL_REVISION2,
                 GENERIC_EXECUTE,
                 SeWorldSid
                 );
    ASSERT( NT_SUCCESS(Status) );

    //
    // SYSTEM access  (PublicDefault, PublicOpen, and SystemDefault)
    //


    Status = RtlAddAccessAllowedAce (
                 SePublicDefaultDacl,
                 ACL_REVISION2,
                 GENERIC_ALL,
                 SeLocalSystemSid
                 );
    ASSERT( NT_SUCCESS(Status) );


    Status = RtlAddAccessAllowedAce (
                 SePublicDefaultUnrestrictedDacl,
                 ACL_REVISION2,
                 GENERIC_ALL,
                 SeLocalSystemSid
                 );
    ASSERT( NT_SUCCESS(Status) );


    Status = RtlAddAccessAllowedAce (
                 SePublicOpenDacl,
                 ACL_REVISION2,
                 GENERIC_ALL,
                 SeLocalSystemSid
                 );
    ASSERT( NT_SUCCESS(Status) );

    Status = RtlAddAccessAllowedAce (
                 SePublicOpenUnrestrictedDacl,
                 ACL_REVISION2,
                 GENERIC_ALL,
                 SeLocalSystemSid
                 );
    ASSERT( NT_SUCCESS(Status) );


    Status = RtlAddAccessAllowedAce (
                 SeSystemDefaultDacl,
                 ACL_REVISION2,
                 GENERIC_ALL,
                 SeLocalSystemSid
                 );
    ASSERT( NT_SUCCESS(Status) );

    Status = RtlAddAccessAllowedAce (
                 SeLocalServicePublicDacl,
                 ACL_REVISION2,
                 GENERIC_ALL,
                 SeLocalSystemSid
                 );
    ASSERT( NT_SUCCESS(Status) );

    //
    // ADMINISTRATORS access  (PublicDefault, PublicOpen, and SystemDefault)
    //

    Status = RtlAddAccessAllowedAce (
                 SePublicDefaultDacl,
                 ACL_REVISION2,
                 GENERIC_ALL,
                 SeAliasAdminsSid
                 );
    ASSERT( NT_SUCCESS(Status) );


    Status = RtlAddAccessAllowedAce (
                 SePublicDefaultUnrestrictedDacl,
                 ACL_REVISION2,
                 GENERIC_ALL,
                 SeAliasAdminsSid
                 );
    ASSERT( NT_SUCCESS(Status) );


    Status = RtlAddAccessAllowedAce (
                 SePublicOpenDacl,
                 ACL_REVISION2,
                 GENERIC_ALL,
                 SeAliasAdminsSid
                 );
    ASSERT( NT_SUCCESS(Status) );


    Status = RtlAddAccessAllowedAce (
                 SePublicOpenUnrestrictedDacl,
                 ACL_REVISION2,
                 GENERIC_ALL,
                 SeAliasAdminsSid
                 );
    ASSERT( NT_SUCCESS(Status) );


    Status = RtlAddAccessAllowedAce (
                 SeSystemDefaultDacl,
                 ACL_REVISION2,
                 GENERIC_READ | GENERIC_EXECUTE | READ_CONTROL,
                 SeAliasAdminsSid
                 );
    ASSERT( NT_SUCCESS(Status) );

    Status = RtlAddAccessAllowedAce (
                 SeLocalServicePublicDacl,
                 ACL_REVISION2,
                 GENERIC_ALL,
                 SeAliasAdminsSid
                 );
    ASSERT( NT_SUCCESS(Status) );

    //
    // RESTRICTED access  (PublicDefaultUnrestricted and OpenUnrestricted)
    //

    Status = RtlAddAccessAllowedAce (
                 SePublicDefaultUnrestrictedDacl,
                 ACL_REVISION2,
                 GENERIC_EXECUTE,
                 SeRestrictedSid
                 );
    ASSERT( NT_SUCCESS(Status) );

    Status = RtlAddAccessAllowedAce (
                 SePublicOpenUnrestrictedDacl,
                 ACL_REVISION2,
                 GENERIC_EXECUTE | GENERIC_READ,
                 SeRestrictedSid
                 );
    ASSERT( NT_SUCCESS(Status) );


    //
    // Local Service
    //

    Status = RtlAddAccessAllowedAce (
                 SeLocalServicePublicDacl,
                 ACL_REVISION2,
                 GENERIC_ALL,
                 SeLocalServiceSid
                 );
    ASSERT( NT_SUCCESS(Status) );


    //
    // Now initialize security descriptors
    // that export this protection
    //


    SePublicDefaultSd = (PSECURITY_DESCRIPTOR)&SepPublicDefaultSd;
    Status = RtlCreateSecurityDescriptor(
                 SePublicDefaultSd,
                 SECURITY_DESCRIPTOR_REVISION1
                 );
    ASSERT( NT_SUCCESS(Status) );
    Status = RtlSetDaclSecurityDescriptor(
                 SePublicDefaultSd,
                 TRUE,                       // DaclPresent
                 SePublicDefaultDacl,
                 FALSE                       // DaclDefaulted
                 );
    ASSERT( NT_SUCCESS(Status) );


    SePublicDefaultUnrestrictedSd = (PSECURITY_DESCRIPTOR)&SepPublicDefaultUnrestrictedSd;
    Status = RtlCreateSecurityDescriptor(
                 SePublicDefaultUnrestrictedSd,
                 SECURITY_DESCRIPTOR_REVISION1
                 );
    ASSERT( NT_SUCCESS(Status) );
    Status = RtlSetDaclSecurityDescriptor(
                 SePublicDefaultUnrestrictedSd,
                 TRUE,                       // DaclPresent
                 SePublicDefaultUnrestrictedDacl,
                 FALSE                       // DaclDefaulted
                 );
    ASSERT( NT_SUCCESS(Status) );


    SePublicOpenSd = (PSECURITY_DESCRIPTOR)&SepPublicOpenSd;
    Status = RtlCreateSecurityDescriptor(
                 SePublicOpenSd,
                 SECURITY_DESCRIPTOR_REVISION1
                 );
    ASSERT( NT_SUCCESS(Status) );
    Status = RtlSetDaclSecurityDescriptor(
                 SePublicOpenSd,
                 TRUE,                       // DaclPresent
                 SePublicOpenDacl,
                 FALSE                       // DaclDefaulted
                 );
    ASSERT( NT_SUCCESS(Status) );


    SePublicOpenUnrestrictedSd = (PSECURITY_DESCRIPTOR)&SepPublicOpenUnrestrictedSd;
    Status = RtlCreateSecurityDescriptor(
                 SePublicOpenUnrestrictedSd,
                 SECURITY_DESCRIPTOR_REVISION1
                 );
    ASSERT( NT_SUCCESS(Status) );
    Status = RtlSetDaclSecurityDescriptor(
                 SePublicOpenUnrestrictedSd,
                 TRUE,                       // DaclPresent
                 SePublicOpenUnrestrictedDacl,
                 FALSE                       // DaclDefaulted
                 );
    ASSERT( NT_SUCCESS(Status) );


    SeSystemDefaultSd = (PSECURITY_DESCRIPTOR)&SepSystemDefaultSd;
    Status = RtlCreateSecurityDescriptor(
                 SeSystemDefaultSd,
                 SECURITY_DESCRIPTOR_REVISION1
                 );
    ASSERT( NT_SUCCESS(Status) );
    Status = RtlSetDaclSecurityDescriptor(
                 SeSystemDefaultSd,
                 TRUE,                       // DaclPresent
                 SeSystemDefaultDacl,
                 FALSE                       // DaclDefaulted
                 );
    ASSERT( NT_SUCCESS(Status) );

    SeLocalServicePublicSd = (PSECURITY_DESCRIPTOR)&SepLocalServicePublicSd;
    Status = RtlCreateSecurityDescriptor(
                 SeLocalServicePublicSd,
                 SECURITY_DESCRIPTOR_REVISION1
                 );
    ASSERT( NT_SUCCESS(Status) );
    Status = RtlSetDaclSecurityDescriptor(
                 SeLocalServicePublicSd,
                 TRUE,                       // DaclPresent
                 SeLocalServicePublicDacl,
                 FALSE                       // DaclDefaulted
                 );
    ASSERT( NT_SUCCESS(Status) );



    return;

}
Example #4
0
VOID
SepInitProcessAuditSd( VOID )
/*++

Routine Description:

    This function initializes SepProcessAuditSd -- a security descriptor
    that is used by SepAddSaclToProcess to add SACL to the existing
    security descriptor on a system process.

    A system process is defined as the one whose token has at least
    one of the following sids.
    -- SeLocalSystemSid
    -- SeLocalServiceSid
    -- SeNetworkServiceSid

Arguments:

    None.

Return Value:

    None.


--*/
{
#define PROCESS_ACCESSES_TO_AUDIT ( PROCESS_CREATE_THREAD   |\
                                    PROCESS_SET_INFORMATION |\
                                    PROCESS_SET_PORT        |\
                                    PROCESS_SUSPEND_RESUME )

    NTSTATUS Status = STATUS_SUCCESS;
    ULONG AclLength, TotalSdLength;
    PISECURITY_DESCRIPTOR Sd = NULL;
    PISECURITY_DESCRIPTOR Sd2 = NULL;
    PACL Acl = NULL;

    //
    // free earlier instance if present
    //

    if ( SepProcessAuditSd != NULL ) {

        ExFreePool( SepProcessAuditSd );
        SepProcessAuditSd = NULL;
    }

    //
    // Don't initialize SeProcessAuditSd if SepProcessAccessesToAudit is 0
    // This effectively disables process access auditing
    //

    if ( SepProcessAccessesToAudit == 0 ) {

        goto Cleanup;
    }

    AclLength = (ULONG)sizeof(ACL) +
        ((ULONG)sizeof(SYSTEM_AUDIT_ACE) - sizeof(ULONG)) +
        SeLengthSid( SeWorldSid );

    TotalSdLength = sizeof(SECURITY_DESCRIPTOR) + AclLength;

    Sd = (PSECURITY_DESCRIPTOR) ExAllocatePoolWithTag(
                                    NonPagedPool,
                                    TotalSdLength,
                                    'cAeS');

    if ( Sd == NULL ) {

        Status = STATUS_INSUFFICIENT_RESOURCES;
        goto Cleanup;
    }

    Acl = (PACL) (Sd + 1);

    Status = RtlCreateAcl( Acl, AclLength, ACL_REVISION2 );

    if ( NT_SUCCESS( Status )) {

        Status = RtlAddAuditAccessAce(
                     Acl,
                     ACL_REVISION2,
                     SepProcessAccessesToAudit,
                     SeWorldSid,
                     TRUE,
                     TRUE
                     );

        if ( NT_SUCCESS( Status )) {

            Status = RtlCreateSecurityDescriptor( Sd,
                                                  SECURITY_DESCRIPTOR_REVISION1 );
            if ( NT_SUCCESS( Status )) {

                Status = RtlSetSaclSecurityDescriptor( Sd,
                                                       TRUE, Acl, FALSE );
                if ( NT_SUCCESS( Status )) {

                    SepProcessAuditSd = Sd;
                }
            }
        }
    }

    ASSERT( NT_SUCCESS(Status) );

    if ( !NT_SUCCESS( Status )) {

        goto Cleanup;
    }

    //
    // create and initialize SepImportantProcessSd
    //

    AclLength = (ULONG)sizeof(ACL) +
        (3*((ULONG)sizeof(ACCESS_ALLOWED_ACE) - sizeof(ULONG))) +
        SeLengthSid( SeLocalSystemSid ) +
        SeLengthSid( SeLocalServiceSid ) +
        SeLengthSid( SeNetworkServiceSid );

    TotalSdLength = sizeof(SECURITY_DESCRIPTOR) + AclLength;

    Sd2 = (PSECURITY_DESCRIPTOR) ExAllocatePoolWithTag(
                                    NonPagedPool,
                                    TotalSdLength,
                                    'cAeS');

    if ( Sd2 == NULL ) {

        Status = STATUS_INSUFFICIENT_RESOURCES;
        goto Cleanup;
    }

    Acl = (PACL) (Sd2 + 1);

    Status = RtlCreateAcl( Acl, AclLength, ACL_REVISION2 );

    if ( NT_SUCCESS( Status )) {

        Status = RtlAddAccessAllowedAce(
                     Acl,
                     ACL_REVISION2,
                     SEP_QUERY_MEMBERSHIP,
                     SeLocalSystemSid
                     );

        if ( !NT_SUCCESS( Status )) {

            goto Cleanup;
        }

        Status = RtlAddAccessAllowedAce(
                     Acl,
                     ACL_REVISION2,
                     SEP_QUERY_MEMBERSHIP,
                     SeLocalServiceSid
                     );

        if ( !NT_SUCCESS( Status )) {

            goto Cleanup;
        }


        Status = RtlAddAccessAllowedAce(
                     Acl,
                     ACL_REVISION2,
                     SEP_QUERY_MEMBERSHIP,
                     SeNetworkServiceSid
                     );

        if ( !NT_SUCCESS( Status )) {

            goto Cleanup;
        }

        Status = RtlCreateSecurityDescriptor( Sd2, SECURITY_DESCRIPTOR_REVISION1 );

        if ( NT_SUCCESS( Status )) {

            Status = RtlSetDaclSecurityDescriptor( Sd2, TRUE, Acl, FALSE );

            if ( NT_SUCCESS( Status )) {

                SepImportantProcessSd = Sd2;
            }
        }
    }


 Cleanup:

    if ( !NT_SUCCESS( Status )) {

        ASSERT( FALSE && L"SepInitProcessAuditSd failed" );

        //
        // this will bugcheck if SepCrashOnAuditFail is TRUE
        //

        SepAuditFailed( Status );

        if ( Sd ) {

            ExFreePool( Sd );
            Sd = NULL;
            SepProcessAuditSd = NULL;
        }
        if ( Sd2 ) {

            ExFreePool( Sd2 );
            Sd2 = NULL;
            SepImportantProcessSd = NULL;
        }
    }
}
Example #5
0
BOOLEAN
SeRmInitPhase1(
    )

/*++

Routine Description:

    This function is called by Phase 1 System Initialization to initialize
    the Security Reference Monitor.  Note that initialization of the
    Reference Monitor Global State has already been performed in Phase 0
    initialization to allow access validation routines to operate without
    having to check that Reference Monitor Initialization is complete.

    The steps listed below are performed in this routine.  The remainder
    of Reference Monitor initialization requires the LSA subsystem to have run,
    so that initialization is performed in a separate thread (the RM Command
    Server Thread, see below), so that the present thread can create the
    Session Manager which execs the LSA.

    o Create the Reference Monitor Command LPC port.  The LSA subsystem sends
      commands (e.g. turn on auditing) which change the Reference Monitor
      Global State.
    o Create an Event for use in synchronizing with the LSA subsystem.  The
      LSA will signal the event when the portion of LSA initialization upon
      with the Reference Monitor depends is complete.  The Reference Monitor
      uses another LPC port, called the LSA Command Port to send commands
      to the LSA, so the RM must know that this port has been created before
      trying to connect to it.
    o Create the Reference Monitor Command Server Thread.  This thread is
      a permanent thread of the System Init process that fields the Reference
      Monitor State Change commands described above.


Arguments:

    None.

Return Value:

    BOOLEAN - TRUE if Rm Initialization (Phase 1) succeeded, else FALSE

--*/

{
    NTSTATUS Status;
    STRING RmCommandPortName;
    UNICODE_STRING UnicodeRmCommandPortName;
    OBJECT_ATTRIBUTES ObjectAttributes;
    STRING LsaInitEventName;
    UNICODE_STRING UnicodeLsaInitEventName;
    OBJECT_ATTRIBUTES LsaInitEventObjectAttributes;
    SECURITY_DESCRIPTOR LsaInitEventSecurityDescriptor;
    ULONG AclSize;

    PAGED_CODE();

    //
    // Create an LPC port called the Reference Monitor Command Port.
    // This will be used by the LSA to send commands to the Reference
    // Monitor to update its state data.
    //

    RtlInitString( &RmCommandPortName, "\\SeRmCommandPort" );
    Status = RtlAnsiStringToUnicodeString(
                 &UnicodeRmCommandPortName,
                 &RmCommandPortName,
                 TRUE );  ASSERT( NT_SUCCESS(Status) );
    InitializeObjectAttributes(
        &ObjectAttributes,
        &UnicodeRmCommandPortName,
        0,
        NULL,
        NULL
        );

    Status = ZwCreatePort(
                 &SepRmState.RmCommandPortHandle,
                 &ObjectAttributes,
                 sizeof(SEP_RM_CONNECT_INFO),
                 sizeof(RM_COMMAND_MESSAGE),
                 sizeof(RM_COMMAND_MESSAGE) * 32
                 );
    RtlFreeUnicodeString( &UnicodeRmCommandPortName );

    if( !NT_SUCCESS(Status) ) {

        KdPrint(("Security: Rm Create Command Port failed 0x%lx\n", Status));
        return FALSE;
    }

    //
    // Prepare to create an event for synchronizing with the LSA.
    // First, build the Security Descriptor for the Init Event Object
    //

    Status = RtlCreateSecurityDescriptor(
                 &LsaInitEventSecurityDescriptor,
                 SECURITY_DESCRIPTOR_REVISION
                 );

    if (!NT_SUCCESS(Status)) {

        KdPrint(("Security:  Creating Lsa Init Event Desc failed 0x%lx\n",
                  Status));
        return FALSE;
    }

    //
    // Allocate a temporary buffer from the paged pool.  It is a fatal
    // system error if the allocation fails since security cannot be
    // enabled.
    //

    AclSize = sizeof(ACL) +
              sizeof(ACCESS_ALLOWED_ACE) +
              SeLengthSid(SeLocalSystemSid);
    LsaInitEventSecurityDescriptor.Dacl =
        ExAllocatePoolWithTag(PagedPool, AclSize, 'cAeS');

    if (LsaInitEventSecurityDescriptor.Dacl == NULL) {

        KdPrint(("Security LSA:  Insufficient resources to initialize\n"));
        return FALSE;
    }

    //
    // Now create the Discretionary ACL within the Security Descriptor
    //

    Status = RtlCreateAcl(
                 LsaInitEventSecurityDescriptor.Dacl,
                 AclSize,
                 ACL_REVISION2
                 );

    if (!NT_SUCCESS(Status)) {

        KdPrint(("Security:  Creating Lsa Init Event Dacl failed 0x%lx\n",
                  Status));
        return FALSE;
    }

    //
    // Now add an ACE giving GENERIC_ALL access to the User ID
    //

    Status = RtlAddAccessAllowedAce(
                 LsaInitEventSecurityDescriptor.Dacl,
                 ACL_REVISION2,
                 GENERIC_ALL,
                 SeLocalSystemSid
                 );

    if (!NT_SUCCESS(Status)) {

        KdPrint(("Security:  Adding Lsa Init Event ACE failed 0x%lx\n",
                  Status));
        return FALSE;
    }

    //
    // Set up the Object Attributes for the Lsa Initialization Event
    //

    RtlInitString( &LsaInitEventName, "\\SeLsaInitEvent" );
    Status = RtlAnsiStringToUnicodeString(
                 &UnicodeLsaInitEventName,
                 &LsaInitEventName,
                 TRUE );  ASSERT( NT_SUCCESS(Status) );
    InitializeObjectAttributes(
        &LsaInitEventObjectAttributes,
        &UnicodeLsaInitEventName,
        0,
        NULL,
        &LsaInitEventSecurityDescriptor
        );

    //
    // Create an event for use in synchronizing with the LSA.  The LSA will
    // signal this event when LSA initialization has reached the point
    // where the LSA's Reference Monitor Server Port has been created.
    //

    Status = ZwCreateEvent(
                 &(SepRmState.LsaInitEventHandle),
                 EVENT_MODIFY_STATE,
                 &LsaInitEventObjectAttributes,
                 NotificationEvent,
                 FALSE);

    RtlFreeUnicodeString( &UnicodeLsaInitEventName );

    if (!NT_SUCCESS(Status)) {

        KdPrint(("Security: LSA init event creation failed.0x%xl\n",
            Status));
        return FALSE;
    }

    //
    // Deallocate the pool memory used for the Init Event DACL
    //

    ExFreePool( LsaInitEventSecurityDescriptor.Dacl );

    //
    // Create a permanent thread of the Sysinit Process, called the
    // Reference Monitor Server Thread.  This thread is dedicated to
    // receiving Reference Monitor commands and dispatching them.
    //

    Status = PsCreateSystemThread(
                 &SepRmState.SepRmThreadHandle,
                 THREAD_GET_CONTEXT |
                 THREAD_SET_CONTEXT |
                 THREAD_SET_INFORMATION,
                 NULL,
                 NULL,
                 NULL,
                 SepRmCommandServerThread,
                 NULL
                 );

    if (!NT_SUCCESS(Status)) {

        KdPrint(("Security: Rm Server Thread creation failed 0x%lx\n", Status));
        return FALSE;
    }

    //
    // Initialize data from the registry.  This must go here because all other
    // Se initialization takes place before the registry is initialized.
    //

    SepAdtInitializeCrashOnFail();
    SepAdtInitializePrivilegeAuditing();
    SepAdtInitializeAuditingOptions();
    
    //
    // Reference Monitor initialization is successful if we get to here.
    //

    ZwClose( SepRmState.SepRmThreadHandle );
    SepRmState.SepRmThreadHandle = NULL;
    return TRUE;
}
Example #6
0
PSECURITY_DESCRIPTOR
NTAPI
INIT_FUNCTION
CmpHiveRootSecurityDescriptor(VOID)
{
    NTSTATUS Status;
    PSECURITY_DESCRIPTOR SecurityDescriptor;
    PACL Acl, AclCopy;
    PSID Sid[4];
    SID_IDENTIFIER_AUTHORITY WorldAuthority = {SECURITY_WORLD_SID_AUTHORITY};
    SID_IDENTIFIER_AUTHORITY NtAuthority = {SECURITY_NT_AUTHORITY};
    ULONG AceLength, AclLength, SidLength;
    PACE_HEADER AceHeader;
    ULONG i;
    PAGED_CODE();

    /* Phase 1: Allocate SIDs */
    SidLength = RtlLengthRequiredSid(1);
    Sid[0] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM);
    Sid[1] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM);
    Sid[2] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM);
    SidLength = RtlLengthRequiredSid(2);
    Sid[3] = ExAllocatePoolWithTag(PagedPool, SidLength, TAG_CM);

    /* Make sure all SIDs were allocated */
    if (!(Sid[0]) || !(Sid[1]) || !(Sid[2]) || !(Sid[3]))
    {
        /* Bugcheck */
        KeBugCheckEx(REGISTRY_ERROR, 11, 1, 0, 0);
    }

    /* Phase 2: Initialize all SIDs */
    Status = RtlInitializeSid(Sid[0], &WorldAuthority, 1);
    Status |= RtlInitializeSid(Sid[1], &NtAuthority, 1);
    Status |= RtlInitializeSid(Sid[2], &NtAuthority, 1);
    Status |= RtlInitializeSid(Sid[3], &NtAuthority, 2);
    if (!NT_SUCCESS(Status)) KeBugCheckEx(REGISTRY_ERROR, 11, 2, 0, 0);

    /* Phase 2: Setup SID Sub Authorities */
    *RtlSubAuthoritySid(Sid[0], 0) = SECURITY_WORLD_RID;
    *RtlSubAuthoritySid(Sid[1], 0) = SECURITY_RESTRICTED_CODE_RID;
    *RtlSubAuthoritySid(Sid[2], 0) = SECURITY_LOCAL_SYSTEM_RID;
    *RtlSubAuthoritySid(Sid[3], 0) = SECURITY_BUILTIN_DOMAIN_RID;
    *RtlSubAuthoritySid(Sid[3], 1) = DOMAIN_ALIAS_RID_ADMINS;

    /* Make sure all SIDs are valid */
    ASSERT(RtlValidSid(Sid[0]));
    ASSERT(RtlValidSid(Sid[1]));
    ASSERT(RtlValidSid(Sid[2]));
    ASSERT(RtlValidSid(Sid[3]));

    /* Phase 3: Calculate ACL Length */
    AclLength = sizeof(ACL);
    for (i = 0; i < 4; i++)
    {
        /* This is what MSDN says to do */
        AceLength = FIELD_OFFSET(ACCESS_ALLOWED_ACE, SidStart);
        AceLength += SeLengthSid(Sid[i]);
        AclLength += AceLength;
    }

    /* Phase 3: Allocate the ACL */
    Acl = ExAllocatePoolWithTag(PagedPool, AclLength, TAG_CM);
    if (!Acl) KeBugCheckEx(REGISTRY_ERROR, 11, 3, 0, 0);

    /* Phase 4: Create the ACL */
    Status = RtlCreateAcl(Acl, AclLength, ACL_REVISION);
    if (!NT_SUCCESS(Status)) KeBugCheckEx(REGISTRY_ERROR, 11, 4, Status, 0);

    /* Phase 5: Build the ACL */
    Status = RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_ALL_ACCESS, Sid[0]);
    Status |= RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_ALL_ACCESS, Sid[1]);
    Status |= RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_READ, Sid[2]);
    Status |= RtlAddAccessAllowedAce(Acl, ACL_REVISION, KEY_READ, Sid[3]);
    if (!NT_SUCCESS(Status)) KeBugCheckEx(REGISTRY_ERROR, 11, 5, Status, 0);

    /* Phase 5: Make the ACEs inheritable */
    Status = RtlGetAce(Acl, 0,( PVOID*)&AceHeader);
    ASSERT(NT_SUCCESS(Status));
    AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;
    Status = RtlGetAce(Acl, 1, (PVOID*)&AceHeader);
    ASSERT(NT_SUCCESS(Status));
    AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;
    Status = RtlGetAce(Acl, 2, (PVOID*)&AceHeader);
    ASSERT(NT_SUCCESS(Status));
    AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;
    Status = RtlGetAce(Acl, 3, (PVOID*)&AceHeader);
    ASSERT(NT_SUCCESS(Status));
    AceHeader->AceFlags |= CONTAINER_INHERIT_ACE;

    /* Phase 6: Allocate the security descriptor and make space for the ACL */
    SecurityDescriptor = ExAllocatePoolWithTag(PagedPool,
                                               sizeof(SECURITY_DESCRIPTOR) +
                                               AclLength,
                                               TAG_CM);
    if (!SecurityDescriptor) KeBugCheckEx(REGISTRY_ERROR, 11, 6, 0, 0);

    /* Phase 6: Make a copy of the ACL */
    AclCopy = (PACL)((PISECURITY_DESCRIPTOR)SecurityDescriptor + 1);
    RtlCopyMemory(AclCopy, Acl, AclLength);

    /* Phase 7: Create the security descriptor */
    Status = RtlCreateSecurityDescriptor(SecurityDescriptor,
                                         SECURITY_DESCRIPTOR_REVISION);
    if (!NT_SUCCESS(Status)) KeBugCheckEx(REGISTRY_ERROR, 11, 7, Status, 0);

    /* Phase 8: Set the ACL as a DACL */
    Status = RtlSetDaclSecurityDescriptor(SecurityDescriptor,
                                          TRUE,
                                          AclCopy,
                                          FALSE);
    if (!NT_SUCCESS(Status)) KeBugCheckEx(REGISTRY_ERROR, 11, 8, Status, 0);

    /* Free the SIDs and original ACL */
    for (i = 0; i < 4; i++) ExFreePoolWithTag(Sid[i], TAG_CM);
    ExFreePoolWithTag(Acl, TAG_CM);

    /* Return the security descriptor */
    return SecurityDescriptor;
}
Example #7
0
NTSTATUS
RtlSelfRelativeToAbsoluteSD(
    IN OUT PSECURITY_DESCRIPTOR SelfRelativeSecurityDescriptor,
    OUT PSECURITY_DESCRIPTOR AbsoluteSecurityDescriptor,
    IN OUT PULONG AbsoluteSecurityDescriptorSize,
    IN OUT PACL Dacl,
    IN OUT PULONG DaclSize,
    IN OUT PACL Sacl,
    IN OUT PULONG SaclSize,
    IN OUT PSID Owner,
    IN OUT PULONG OwnerSize,
    IN OUT PSID PrimaryGroup,
    IN OUT PULONG PrimaryGroupSize
    )

/*++

Routine Description:

    Converts a security descriptor from self-relative format to absolute
    format

Arguments:

    SecurityDescriptor - Supplies a pointer to a security descriptor in
        Self-Relative format

    AbsoluteSecurityDescriptor - A pointer to a buffer in which will be
        placed the main body of the Absolute format security descriptor.

    Dacl - Supplies a pointer to a buffer that will contain the Dacl of the
        output descriptor.  This pointer will be referenced by, not copied
        into, the output descriptor.

    DaclSize - Supplies the size of the buffer pointed to by Dacl.  In case
        of error, it will return the minimum size necessary to contain the
        Dacl.

    Sacl - Supplies a pointer to a buffer that will contain the Sacl of the
        output descriptor.  This pointer will be referenced by, not copied
        into, the output descriptor.

    SaclSize - Supplies the size of the buffer pointed to by Sacl.  In case
        of error, it will return the minimum size necessary to contain the
        Sacl.

    Owner - Supplies a pointer to a buffer that will contain the Owner of
        the output descriptor.  This pointer will be referenced by, not
        copied into, the output descriptor.

    OwnerSize - Supplies the size of the buffer pointed to by Owner.  In
        case of error, it will return the minimum size necessary to contain
        the Owner.

    PrimaryGroup - Supplies a pointer to a buffer that will contain the
        PrimaryGroup of the output descriptor.  This pointer will be
        referenced by, not copied into, the output descriptor.

    PrimaryGroupSize - Supplies the size of the buffer pointed to by
        PrimaryGroup.  In case of error, it will return the minimum size
        necessary to contain the PrimaryGroup.


Return Value:

    STATUS_SUCCESS - Success

    STATUS_BUFFER_TOO_SMALL - One of the buffers passed was too small.

    STATUS_INVALID_OWNER - There was not a valid owner in the passed
        security descriptor.

--*/

{
    ULONG NewDaclSize;
    ULONG NewSaclSize;
    ULONG NewBodySize;
    ULONG NewOwnerSize;
    ULONG NewGroupSize;

    PSID NewOwner;
    PSID NewGroup;
    PACL NewDacl;
    PACL NewSacl;

    //
    // typecast security descriptors so we don't have to cast all over the place.
    //

    PISECURITY_DESCRIPTOR OutSD =
        AbsoluteSecurityDescriptor;

    PISECURITY_DESCRIPTOR InSD =
            (PISECURITY_DESCRIPTOR)SelfRelativeSecurityDescriptor;


    RTL_PAGED_CODE();

    if ( !RtlpAreControlBitsSet( InSD, SE_SELF_RELATIVE) ) {
        return( STATUS_BAD_DESCRIPTOR_FORMAT );
    }

    NewBodySize = sizeof(SECURITY_DESCRIPTOR);

    RtlpQuerySecurityDescriptor(
        InSD,
        &NewOwner,
        &NewOwnerSize,
        &NewGroup,
        &NewGroupSize,
        &NewDacl,
        &NewDaclSize,
        &NewSacl,
        &NewSaclSize
        );

    if ( (NewBodySize  > *AbsoluteSecurityDescriptorSize) ||
         (NewOwnerSize > *OwnerSize )                     ||
         (NewDaclSize  > *DaclSize )                      ||
         (NewSaclSize  > *SaclSize )                      ||
         (NewGroupSize > *PrimaryGroupSize ) ) {

         *AbsoluteSecurityDescriptorSize = sizeof(SECURITY_DESCRIPTOR);
         *PrimaryGroupSize               = NewGroupSize;
         *OwnerSize                      = NewOwnerSize;
         *SaclSize                       = NewSaclSize;
         *DaclSize                       = NewDaclSize;

         return( STATUS_BUFFER_TOO_SMALL );
    }


    RtlMoveMemory( OutSD,
                   InSD,
                   sizeof(SECURITY_DESCRIPTOR_RELATIVE) );

    OutSD->Owner = NULL;
    OutSD->Group = NULL;
    OutSD->Sacl  = NULL;
    OutSD->Dacl  = NULL;

    RtlpClearControlBits( OutSD, SE_SELF_RELATIVE );

    if (NewOwner != NULL) {
        RtlMoveMemory( Owner, NewOwner, SeLengthSid( NewOwner ));
        OutSD->Owner = Owner;
    }

    if (NewGroup != NULL) {
        RtlMoveMemory( PrimaryGroup, NewGroup, SeLengthSid( NewGroup ));
        OutSD->Group = PrimaryGroup;
    }

    if (NewSacl != NULL) {
        RtlMoveMemory( Sacl, NewSacl, NewSacl->AclSize );
        OutSD->Sacl  = Sacl;
    }

    if (NewDacl != NULL) {
        RtlMoveMemory( Dacl, NewDacl, NewDacl->AclSize );
        OutSD->Dacl  = Dacl;
    }

    return( STATUS_SUCCESS );
}
Example #8
0
VOID
RtlpQuerySecurityDescriptor(
    IN PISECURITY_DESCRIPTOR SecurityDescriptor,
    OUT PSID *Owner,
    OUT PULONG OwnerSize,
    OUT PSID *PrimaryGroup,
    OUT PULONG PrimaryGroupSize,
    OUT PACL *Dacl,
    OUT PULONG DaclSize,
    OUT PACL *Sacl,
    OUT PULONG SaclSize
    )
/*++

Routine Description:

    Returns the pieces of a security descriptor structure.

Arguments:


    SecurityDescriptor - Provides the security descriptor of interest.

    Owner - Returns a pointer to the owner information contained in the
        security descriptor.

    OwnerSize - Returns the size of the owner information.

    PrimaryGroup -  Returns a pointer to the primary group information.

    PrimaryGroupSize - Returns the size of the primary group information.

    Dacl - Returns a pointer to the Dacl.

    DaclSize - Returns the size of the Dacl.

    Sacl - Returns a pointer to the Sacl.

    SaclSize - Returns the size of the Sacl.

Return Value:

    None.

--*/
{

    RTL_PAGED_CODE();

    *Owner = RtlpOwnerAddrSecurityDescriptor( SecurityDescriptor );

    if (*Owner != NULL) {
        *OwnerSize = LongAlignSize(SeLengthSid(*Owner));
    } else {
        *OwnerSize = 0;
    }

    *Dacl = RtlpDaclAddrSecurityDescriptor ( SecurityDescriptor );

    if (*Dacl !=NULL) {
        *DaclSize = LongAlignSize((*Dacl)->AclSize);
    } else {
        *DaclSize = 0;
    }

    *PrimaryGroup = RtlpGroupAddrSecurityDescriptor( SecurityDescriptor );

    if (*PrimaryGroup != NULL) {
        *PrimaryGroupSize = LongAlignSize(SeLengthSid(*PrimaryGroup));
    } else {
         *PrimaryGroupSize = 0;
    }

    *Sacl = RtlpSaclAddrSecurityDescriptor( SecurityDescriptor );

    if (*Sacl != NULL) {
        *SaclSize = LongAlignSize((*Sacl)->AclSize);
    } else {
        *SaclSize = 0;
    }

}
Example #9
0
NTSTATUS
IopApplySystemPartitionProt(
    IN PLOADER_PARAMETER_BLOCK LoaderBlock
    )

/*++

Routine Description:

    This routine applies protection to the system partition that
    prevents all users except administrators from accessing the
    partition.


    This routine is only used during system initialization.
    As such, all memory allocations are expected to succeed.
    Success is tested only with assertions.


Arguments:

    LoaderBlock - Supplies a pointer to the loader parameter block that was
        created by the OS Loader.

Return Value:

    The function value is the final status from attempting to set the system
    partition protection.


--*/

{
    NTSTATUS status;
    PACL dacl;
    SECURITY_DESCRIPTOR securityDescriptor;
    OBJECT_ATTRIBUTES objectAttributes;
    ULONG length;
    CHAR ArcNameFmt[12];

    ArcNameFmt[0] = '\\';
    ArcNameFmt[1] = 'A';
    ArcNameFmt[2] = 'r';
    ArcNameFmt[3] = 'c';
    ArcNameFmt[4] = 'N';
    ArcNameFmt[5] = 'a';
    ArcNameFmt[6] = 'm';
    ArcNameFmt[7] = 'e';
    ArcNameFmt[8] = '\\';
    ArcNameFmt[9] = '%';
    ArcNameFmt[10] = 's';
    ArcNameFmt[11] = '\0';

    ASSERT( ARGUMENT_PRESENT( LoaderBlock ) );
    ASSERT( ARGUMENT_PRESENT( LoaderBlock->ArcHalDeviceName ) );

    //
    // Build an appropriate discretionary ACL.
    //

    length = (ULONG) sizeof( ACL ) +
             ( 2 * ((ULONG) sizeof( ACCESS_ALLOWED_ACE ))) +
             SeLengthSid( SeLocalSystemSid ) +
             SeLengthSid( SeAliasAdminsSid ) +
             8; // The 8 is just for good measure

    dacl = (PACL) ExAllocatePool( PagedPool, length );
    if (!dacl) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    status = RtlCreateAcl( dacl, length, ACL_REVISION2 );
    if (NT_SUCCESS( status )) {

        status = RtlAddAccessAllowedAce( dacl,
                                         ACL_REVISION2,
                                         GENERIC_ALL,
                                         SeLocalSystemSid );
        if (NT_SUCCESS( status )) {

            status = RtlAddAccessAllowedAce( dacl,
                                             ACL_REVISION2,
                                             GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | READ_CONTROL,
                                             SeAliasAdminsSid );
            if (NT_SUCCESS( status )) {

                //
                // Put it in a security descriptor so that it may be applied to
                // the system partition device.
                //

                status = RtlCreateSecurityDescriptor( &securityDescriptor,
                                                      SECURITY_DESCRIPTOR_REVISION );
                if (NT_SUCCESS( status )) {

                    status = RtlSetDaclSecurityDescriptor( &securityDescriptor,
                                                           TRUE,
                                                           dacl,
                                                           FALSE );
                }
            }
        }
    }

    if (!NT_SUCCESS( status )) {
        ExFreePool( dacl );
        return status;
    }

    //
    // Open the ARC boot device and apply the ACL.
    //

    {
        NTSTATUS tmpStatus;
        UCHAR deviceNameBuffer[256];
        STRING deviceNameString;
        UNICODE_STRING deviceNameUnicodeString;
        HANDLE deviceHandle;
        IO_STATUS_BLOCK ioStatusBlock;

        //
        // Begin by formulating the ARC name of the boot device in the ARC
        // name space.
        //

        sprintf( deviceNameBuffer,
                 ArcNameFmt,
                 LoaderBlock->ArcHalDeviceName );

        RtlInitAnsiString( &deviceNameString, deviceNameBuffer );

        status = RtlAnsiStringToUnicodeString( &deviceNameUnicodeString,
                                               &deviceNameString,
                                               TRUE );

        if (NT_SUCCESS( status )) {

            InitializeObjectAttributes( &objectAttributes,
                                        &deviceNameUnicodeString,
                                        OBJ_CASE_INSENSITIVE,
                                        NULL,
                                        NULL );

            status = ZwOpenFile( &deviceHandle,
                                 WRITE_DAC,
                                 &objectAttributes,
                                 &ioStatusBlock,
                                 TRUE,
                                 0 );

            RtlFreeUnicodeString( &deviceNameUnicodeString );

            if (NT_SUCCESS( status )) {


                //
                // Apply the ACL built above to the system partition device
                // object.
                //

                status = ZwSetSecurityObject( deviceHandle,
                                              DACL_SECURITY_INFORMATION,
                                              &securityDescriptor );

                tmpStatus = NtClose( deviceHandle );
            }
        }
    }

    //
    // Free the memory used to hold the ACL.
    //

    ExFreePool( dacl );

    return status;
}
Example #10
0
NTSTATUS
SepCreateImpersonationTokenDacl(
    IN PTOKEN Token,
    IN PACCESS_TOKEN PrimaryToken,
    OUT PACL *Acl
    )
/*++

Routine Description:

    This routine modifies the DACL protecting the passed token to allow
    the current user (described by the PrimaryToken parameter) full access.
    This permits callers of NtOpenThreadToken to call with OpenAsSelf==TRUE
    and succeed.

    The new DACL placed on the token is as follows:

    ACE 0 - Server gets TOKEN_ALL_ACCESS

    ACE 1 - Client gets TOKEN_ALL_ACCESS

    ACE 2 - Admins gets TOKEN_ALL_ACCESS

    ACE 3 - System gets TOKEN_ALL_ACCESS

    ACE 4 - Restricted gets TOKEN_ALL_ACCESS


Arguments:

    Token - The token whose protection is to be modified.

    PrimaryToken - Token representing the subject to be granted access.

    Acl - Returns the modified ACL, allocated out of PagedPool.


Return Value:


--*/

{
    PSID ServerUserSid;
    PSID ClientUserSid;
    NTSTATUS Status = STATUS_SUCCESS;
    ULONG AclLength;
    PACL NewDacl;
    PSECURITY_DESCRIPTOR OldDescriptor;
    BOOLEAN MemoryAllocated;
    PACL OldDacl;
    BOOLEAN DaclPresent;
    BOOLEAN DaclDefaulted;

    PAGED_CODE();

    ServerUserSid = ((PTOKEN)PrimaryToken)->UserAndGroups[0].Sid;

    ClientUserSid = Token->UserAndGroups[0].Sid;

    //
    // Compute how much space we'll need for the new DACL.
    //

    AclLength = 5 * sizeof( ACCESS_ALLOWED_ACE ) - 5 * sizeof( ULONG ) +
                SeLengthSid( ServerUserSid ) + SeLengthSid( SeLocalSystemSid ) +
                SeLengthSid( ClientUserSid ) + SeLengthSid( SeAliasAdminsSid ) +
                SeLengthSid( SeRestrictedSid ) + sizeof( ACL );

    NewDacl = ExAllocatePool( PagedPool, AclLength );

    if (NewDacl == NULL) {

        *Acl = NULL;
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    Status = RtlCreateAcl( NewDacl, AclLength, ACL_REVISION2 );
    ASSERT(NT_SUCCESS( Status ));

    Status = RtlAddAccessAllowedAce (
                 NewDacl,
                 ACL_REVISION2,
                 TOKEN_ALL_ACCESS,
                 ServerUserSid
                 );
    ASSERT( NT_SUCCESS( Status ));

    Status = RtlAddAccessAllowedAce (
                 NewDacl,
                 ACL_REVISION2,
                 TOKEN_ALL_ACCESS,
                 ClientUserSid
                 );
    ASSERT( NT_SUCCESS( Status ));

    Status = RtlAddAccessAllowedAce (
                 NewDacl,
                 ACL_REVISION2,
                 TOKEN_ALL_ACCESS,
                 SeAliasAdminsSid
                 );
    ASSERT( NT_SUCCESS( Status ));

    Status = RtlAddAccessAllowedAce (
                 NewDacl,
                 ACL_REVISION2,
                 TOKEN_ALL_ACCESS,
                 SeLocalSystemSid
                 );
    ASSERT( NT_SUCCESS( Status ));

    if(ARGUMENT_PRESENT(((PTOKEN)PrimaryToken)->RestrictedSids) ||
       ARGUMENT_PRESENT(Token->RestrictedSids)) {
        Status = RtlAddAccessAllowedAce (
                     NewDacl,
                     ACL_REVISION2,
                     TOKEN_ALL_ACCESS,
                     SeRestrictedSid
                     );
        ASSERT( NT_SUCCESS( Status ));
    }

    *Acl = NewDacl;
    return STATUS_SUCCESS;
}
Example #11
0
VOID
SepAppendDefaultDacl(
    IN PTOKEN Token,
    IN PACL PAcl
    )

/*++


Routine Description:

    Add a default discretionary ACL to the available space at the end of the
    dynamic part of the token.  It is the caller's responsibility to ensure
    that the default Dacl fits within the available space of the dynamic
    part of the token.

    The token is assumed to be locked for write access before calling
    this routine.

Arguments:

    Token - Pointer to the token.

    PAcl - Pointer to the ACL to add.

Return Value:

    None.

--*/
{
   ULONG NextFree;
   ULONG AclSize;

   PAGED_CODE();

    //
    // Add the size of the primary group to the
    // address of the Dynamic Part of the token to establish
    // where the primary group should be placed.
    //

    ASSERT(ARGUMENT_PRESENT(Token->PrimaryGroup));

    NextFree = (ULONG)(Token->DynamicPart) +
               SeLengthSid(Token->PrimaryGroup);

    //
    // Now copy the default Dacl
    //

    AclSize = (ULONG)(PAcl->AclSize);
//    ASSERT(AclSize == LongAlign(AclSize));

    RtlMoveMemory(
        (PVOID)NextFree,
        (PVOID)PAcl,
        AclSize
        );

    Token->DefaultDacl = (PACL)NextFree;

    //
    // And decrement the amount of the dynamic part that is available.
    //

    ASSERT( AclSize <= (Token->DynamicAvailable) );
    Token->DynamicAvailable -= AclSize;

    return;

}
Example #12
0
VOID
SepAppendPrimaryGroup(
    IN PTOKEN Token,
    IN PSID PSid
    )

/*++


Routine Description:

    Add a primary group SID to the available space at the end of the dynamic
    part of the token.  It is the caller's responsibility to ensure that the
    primary group SID fits within the available space of the dynamic part of
    the token.

    The token is assumed to be locked for write access before calling
    this routine.

Arguments:

    Token - Pointer to the token.

    PSid - Pointer to the SID to add.

Return Value:

    None.

--*/
{
   ULONG NextFree;
   ULONG SidSize;

   PAGED_CODE();

    //
    // Add the size of the Default Dacl (if there is one) to the
    // address of the Dynamic Part of the token to establish
    // where the primary group should be placed.
    //

    if (ARGUMENT_PRESENT(Token->DefaultDacl)) {

//        ASSERT( (ULONG)(Token->DefaultDacl->AclSize) ==
//                LongAlign(Token->DefaultDacl->AclSize) );

        NextFree = (ULONG)(Token->DynamicPart) +
                   Token->DefaultDacl->AclSize;

    } else {

        NextFree = (ULONG)(Token->DynamicPart);

    }

    //
    // Now copy the primary group SID.
    //


    SidSize = SeLengthSid( PSid );

    RtlMoveMemory(
        (PVOID)NextFree,
        (PVOID)PSid,
        SidSize
        );

    Token->PrimaryGroup = (PSID)NextFree;

    //
    // And decrement the amount of the dynamic part that is available.
    //

    ASSERT( SidSize <= (Token->DynamicAvailable) );
    Token->DynamicAvailable -= SidSize;

    return;

}
Example #13
0
VOID
SepFreeDefaultDacl(
    IN PTOKEN Token
    )

/*++


Routine Description:

    Free up the space in the dynamic part of the token take up by the default
    discretionary access control list.

    The token is assumed to be locked for write access before calling
    this routine.

Arguments:

    Token - Pointer to the token.

Return Value:

    None.

--*/
{
   ULONG PrimaryGroupSize;

   PAGED_CODE();

    //
    // Add the size of the Default Dacl (if there is one) to the
    // DynamicAvailable field.
    //
    if (ARGUMENT_PRESENT(Token->DefaultDacl)) {

        Token->DynamicAvailable += Token->DefaultDacl->AclSize;
        Token->DefaultDacl = NULL;

    }

    //
    // If it is not already at the beginning of the dynamic part, move
    // the primary group there (remember to update the pointer to it).
    //

    if (Token->DynamicPart != (PULONG)(Token->PrimaryGroup)) {

        PrimaryGroupSize = SeLengthSid( Token->PrimaryGroup );

        RtlMoveMemory(
            (PVOID)(Token->DynamicPart),
            (PVOID)(Token->PrimaryGroup),
            PrimaryGroupSize
            );

        Token->PrimaryGroup = (PSID)(Token->DynamicPart);
    }

    return;
}
Example #14
0
NTSTATUS
NtSetInformationToken (
    IN HANDLE TokenHandle,
    IN TOKEN_INFORMATION_CLASS TokenInformationClass,
    IN PVOID TokenInformation,
    IN ULONG TokenInformationLength
    )

/*++


Routine Description:

    Modify information in a specified token.

Arguments:

    TokenHandle - Provides a handle to the token to operate on.

    TokenInformationClass - The token information class being set.

    TokenInformation - The buffer containing the new values for the
        specified class of information.  The buffer must be aligned
        on at least a longword boundary.  The actual structures
        provided are dependent upon the information class specified,
        as defined in the TokenInformationClass parameter
        description.

        TokenInformation Format By Information Class:

           TokenUser => This value is not a valid value for this API.
           The User ID may not be replaced.

           TokenGroups => This value is not a valid value for this
           API.  The Group IDs may not be replaced.  However, groups
           may be enabled and disabled using NtAdjustGroupsToken().

           TokenPrivileges => This value is not a valid value for
           this API.  Privilege information may not be replaced.
           However, privileges may be explicitly enabled and disabled
           using the NtAdjustPrivilegesToken API.

           TokenOwner => TOKEN_OWNER data structure.
           TOKEN_ADJUST_DEFAULT access is needed to replace this
           information in a token.  The owner values that may be
           specified are restricted to the user and group IDs with an
           attribute indicating they may be assigned as the owner of
           objects.

           TokenPrimaryGroup => TOKEN_PRIMARY_GROUP data structure.
           TOKEN_ADJUST_DEFAULT access is needed to replace this
           information in a token.  The primary group values that may
           be specified are restricted to be one of the group IDs
           already in the token.

           TokenDefaultDacl => TOKEN_DEFAULT_DACL data structure.
           TOKEN_ADJUST_DEFAULT access is needed to replace this
           information in a token.  The ACL provided as a new default
           discretionary ACL is not validated for structural
           correctness or consistency.

           TokenSource => This value is not a valid value for this
           API.  The source name and context handle  may not be
           replaced.

           TokenStatistics => This value is not a valid value for this
           API.  The statistics of a token are read-only.

    TokenInformationLength - Indicates the length, in bytes, of the
        TokenInformation buffer.  This is only the length of the primary
        buffer.  All extensions of the primary buffer are self describing.

Return Value:

    STATUS_SUCCESS - The operation was successful.

    STATUS_INVALID_OWNER - The ID specified to be an owner (or
        default owner) is not one the caller may assign as the owner
        of an object.

    STATUS_INVALID_INFO_CLASS - The specified information class is
        not one that may be specified in this API.

    STATUS_ALLOTTED_SPACE_EXCEEDED - The space allotted for storage
        of the default discretionary access control and the primary
        group ID is not large enough to accept the new value of one
        of these fields.

--*/
{

    KPROCESSOR_MODE PreviousMode;
    NTSTATUS Status;

    PTOKEN Token;

    ULONG Index;
    BOOLEAN Found;
    BOOLEAN TokenModified = FALSE;

    ULONG NewLength;
    ULONG CurrentLength;

    PSID CapturedOwner;
    PSID CapturedPrimaryGroup;
    PACL CapturedDefaultDacl;

    PAGED_CODE();

    //
    // Get previous processor mode and probe input buffer if necessary.
    //

    PreviousMode = KeGetPreviousMode();
    if (PreviousMode != KernelMode) {
        try {

            //
            // This just probes the main part of the information buffer.
            // Any information class-specific data hung off the primary
            // buffer are self describing and must be probed separately
            // below.
            //

            ProbeForRead(
                TokenInformation,
                TokenInformationLength,
                sizeof(ULONG)
                );

        } except(EXCEPTION_EXECUTE_HANDLER) {
            return GetExceptionCode();
        }
    }

    //
    // Return error if not legal class
    //
    if ( (TokenInformationClass != TokenOwner)  &&
         (TokenInformationClass != TokenPrimaryGroup) &&
         (TokenInformationClass != TokenDefaultDacl) ) {

        return STATUS_INVALID_INFO_CLASS;

    }

    //
    // Check access rights and reference token
    //

    Status = ObReferenceObjectByHandle(
             TokenHandle,           // Handle
             TOKEN_ADJUST_DEFAULT,  // DesiredAccess
             SepTokenObjectType,    // ObjectType
             PreviousMode,          // AccessMode
             (PVOID *)&Token,       // Object
             NULL                   // GrantedAccess
             );

    if ( !NT_SUCCESS(Status) ) {
        return Status;
    }


    //
    // Case on information class.
    //

    switch ( TokenInformationClass ) {

    case TokenOwner:

        //
        //  Make sure the buffer is large enough to hold the
        //  necessary information class data structure.
        //

        if (TokenInformationLength < (ULONG)sizeof(TOKEN_OWNER)) {

            ObDereferenceObject( Token );
            return STATUS_INFO_LENGTH_MISMATCH;
        }

        //
        //  Capture and copy

        try {

            //
            //  Capture Owner SID
            //

            CapturedOwner = ((PTOKEN_OWNER)TokenInformation)->Owner;
            Status = SeCaptureSid(
                         CapturedOwner,
                         PreviousMode,
                         NULL, 0,
                         PagedPool,
                         TRUE,
                         &CapturedOwner
                         );

        } except(EXCEPTION_EXECUTE_HANDLER) {

            ObDereferenceObject( Token );
            return GetExceptionCode();
        }

        if (!NT_SUCCESS(Status)) {
            ObDereferenceObject( Token );
            return Status;
        }

        //
        //  Gain write access to the token.
        //

        SepAcquireTokenWriteLock( Token );

        //
        //  Walk through the list of user and group IDs looking
        //  for a match to the specified SID.  If one is found,
        //  make sure it may be assigned as an owner.  If it can,
        //  then set the index in the token's OwnerIndex field.
        //  Otherwise, return invalid owner error.
        //

        Index = 0;
        while (Index < Token->UserAndGroupCount) {

            try {

                Found = RtlEqualSid(
                            CapturedOwner,
                            Token->UserAndGroups[Index].Sid
                            );

                if ( Found ) {

                    if ( SepIdAssignableAsOwner(Token,Index) ){

                        Token->DefaultOwnerIndex = Index;
                        TokenModified = TRUE;
                        Status = STATUS_SUCCESS;

                    } else {

                        Status = STATUS_INVALID_OWNER;

                    } //endif assignable

                    SepReleaseTokenWriteLock( Token, TokenModified );
                    ObDereferenceObject( Token );
                    SeReleaseSid( CapturedOwner, PreviousMode, TRUE);
                    return Status;

                }  //endif Found

            } except(EXCEPTION_EXECUTE_HANDLER) {

                SepReleaseTokenWriteLock( Token, TokenModified );
                ObDereferenceObject( Token );
                SeReleaseSid( CapturedOwner, PreviousMode, TRUE);
                return GetExceptionCode();

            }  //endtry

            Index += 1;

        } //endwhile

        SepReleaseTokenWriteLock( Token, TokenModified );
        ObDereferenceObject( Token );
        SeReleaseSid( CapturedOwner, PreviousMode, TRUE);
        return STATUS_INVALID_OWNER;

    case TokenPrimaryGroup:

        //
        // Assuming everything works out, the strategy is to move everything
        // in the Dynamic part of the token (exept the primary group) to
        // the beginning of the dynamic part, freeing up the entire end of
        // the dynamic part for the new primary group.
        //

        //
        //  Make sure the buffer is large enough to hold the
        //  necessary information class data structure.
        //

        if (TokenInformationLength < (ULONG)sizeof(TOKEN_PRIMARY_GROUP)) {

            ObDereferenceObject( Token );
            return STATUS_INFO_LENGTH_MISMATCH;
        }

        //
        // Capture And Validate TOKEN_PRIMARY_GROUP and corresponding SID.
        //

        try {

            CapturedPrimaryGroup =
                ((PTOKEN_PRIMARY_GROUP)TokenInformation)->PrimaryGroup;

            Status = SeCaptureSid(
                         CapturedPrimaryGroup,
                         PreviousMode,
                         NULL, 0,
                         PagedPool,
                         TRUE,
                         &CapturedPrimaryGroup
                         );

        } except(EXCEPTION_EXECUTE_HANDLER) {

            ObDereferenceObject( Token );
            return GetExceptionCode();
        }

        if (!NT_SUCCESS(Status)) {
            ObDereferenceObject( Token );
            return Status;
        }

        //
        //  Gain write access to the token.
        //

        SepAcquireTokenWriteLock( Token );

        //
        // See if there is enough room in the dynamic part of the token
        // to replace the current Primary Group with the one specified.
        //

        NewLength = SeLengthSid( CapturedPrimaryGroup );
        CurrentLength = SeLengthSid( Token->PrimaryGroup );

        if (NewLength > (CurrentLength + Token->DynamicAvailable) ) {

            SepReleaseTokenWriteLock( Token, TokenModified );
            ObDereferenceObject( Token );
            SeReleaseSid( CapturedPrimaryGroup, PreviousMode, TRUE);
            return STATUS_ALLOTTED_SPACE_EXCEEDED;
        }

        //
        // Free up the existing primary group
        //

        SepFreePrimaryGroup( Token );

        //
        // And put the new SID in its place
        //

        SepAppendPrimaryGroup( Token, CapturedPrimaryGroup );

        TokenModified = TRUE;

        //
        // All done.
        //

        SepReleaseTokenWriteLock( Token, TokenModified );
        ObDereferenceObject( Token );
        SeReleaseSid( CapturedPrimaryGroup, PreviousMode, TRUE);
        return STATUS_SUCCESS;


    case TokenDefaultDacl:

        //
        // Assuming everything works out, the strategy is to move everything
        // in the Dynamic part of the token (exept the default Dacl) to
        // the beginning of the dynamic part, freeing up the entire end of
        // the dynamic part for the new default Dacl.
        //

        //
        //  Make sure the buffer is large enough to hold the
        //  necessary information class data structure.
        //

        if (TokenInformationLength < (ULONG)sizeof(TOKEN_DEFAULT_DACL)) {

            ObDereferenceObject( Token );
            return STATUS_INFO_LENGTH_MISMATCH;
        }

        //
        // Capture And Validate TOKEN_DEFAULT_DACL and corresponding ACL.
        //

        try {

            CapturedDefaultDacl =
                ((PTOKEN_DEFAULT_DACL)TokenInformation)->DefaultDacl;

            if (ARGUMENT_PRESENT(CapturedDefaultDacl)) {
                Status = SeCaptureAcl(
                             CapturedDefaultDacl,
                             PreviousMode,
                             NULL, 0,
                             PagedPool,
                             TRUE,
                             &CapturedDefaultDacl,
                             &NewLength
                             );

            } else {
                NewLength = 0;
                Status = STATUS_SUCCESS;
            }

        } except(EXCEPTION_EXECUTE_HANDLER) {

            ObDereferenceObject( Token );
            return GetExceptionCode();
        }

        if (!NT_SUCCESS(Status)) {
            ObDereferenceObject( Token );
            return Status;
        }

        //
        //  Gain write access to the token.
        //

        SepAcquireTokenWriteLock( Token );

        //
        // See if there is enough room in the dynamic part of the token
        // to replace the current Default Dacl with the one specified.
        //

        if (ARGUMENT_PRESENT(Token->DefaultDacl)) {
            CurrentLength = Token->DefaultDacl->AclSize;
        } else {
            CurrentLength = 0;
        }

        if (NewLength > (CurrentLength + Token->DynamicAvailable) ) {

            SepReleaseTokenWriteLock( Token, TokenModified );
            ObDereferenceObject( Token );
            if (ARGUMENT_PRESENT(CapturedDefaultDacl)) {
                SeReleaseAcl( CapturedDefaultDacl, PreviousMode, TRUE);
            }
            return STATUS_ALLOTTED_SPACE_EXCEEDED;
        }

        //
        // Free up the existing Default Dacl
        //

        SepFreeDefaultDacl( Token );

        //
        // And put the new ACL in its place
        //

        if (ARGUMENT_PRESENT(CapturedDefaultDacl)) {
            SepAppendDefaultDacl( Token, CapturedDefaultDacl );
        }

        TokenModified = TRUE;

        //
        // All done.
        //

        SepReleaseTokenWriteLock( Token, TokenModified );
        ObDereferenceObject( Token );
        if (ARGUMENT_PRESENT(CapturedDefaultDacl)) {
            SeReleaseAcl( CapturedDefaultDacl, PreviousMode, TRUE);
        }
        return STATUS_SUCCESS;

    } //endswitch

    ASSERT( TRUE == FALSE );  // Should never reach here.

}
Example #15
0
BOOLEAN
ObInitSystem(
    VOID
    )

/*++

Routine Description:

    This function performs the system initialization for the object
    manager.  The object manager data structures are self describing
    with the exception of the root directory, the type object type and
    the directory object type.  The initialization code then constructs
    these objects by hand to get the ball rolling.

Arguments:

    None.

Return Value:

    TRUE if successful and FALSE if an error occurred.

    The following errors can occur:

    - insufficient memory

--*/

{

    USHORT CreateInfoMaxDepth;
    USHORT NameBufferMaxDepth;
    ULONG RegionSegmentSize;
    OBJECT_TYPE_INITIALIZER ObjectTypeInitializer;
    UNICODE_STRING TypeTypeName;
    UNICODE_STRING SymbolicLinkTypeName;
    UNICODE_STRING DosDevicesDirectoryName;
    UNICODE_STRING DirectoryTypeName;
    UNICODE_STRING RootDirectoryName;
    UNICODE_STRING TypeDirectoryName;
    NTSTATUS Status;
    OBJECT_ATTRIBUTES ObjectAttributes;
    HANDLE RootDirectoryHandle;
    HANDLE TypeDirectoryHandle;
    PLIST_ENTRY Next, Head;
    POBJECT_HEADER ObjectTypeHeader;
    POBJECT_HEADER_CREATOR_INFO CreatorInfo;
    POBJECT_HEADER_NAME_INFO NameInfo;
    MM_SYSTEMSIZE SystemSize;
    SECURITY_DESCRIPTOR AuditSd;
    PSECURITY_DESCRIPTOR EffectiveSd;
    PACL    AuditAllAcl;
    UCHAR   AuditAllBuffer[250];  // Ample room for the ACL
    ULONG   AuditAllLength;
    PACE_HEADER Ace;

    //
    // PHASE 0 Initialization
    //

    if (InitializationPhase == 0) {

        //
        // Determine the the size of the object creation and the name buffer
        // lookaside lists.
        //

        SystemSize = MmQuerySystemSize();
        if (SystemSize == MmLargeSystem) {
            if (MmIsThisAnNtAsSystem()) {
                CreateInfoMaxDepth = 64;
                NameBufferMaxDepth = 32;

            } else {
                CreateInfoMaxDepth = 32;
                NameBufferMaxDepth = 16;
            }

        } else {
            CreateInfoMaxDepth = 3;
            NameBufferMaxDepth = 3;
        }

        //
        // Initialize the object creation lookaside list.
        //

        ExInitializeNPagedLookasideList(&ObpCreateInfoLookasideList,
                                        NULL,
                                        NULL,
                                        0,
                                        sizeof(OBJECT_CREATE_INFORMATION),
                                        'iCbO',
                                        CreateInfoMaxDepth);

        //
        // Initialize the name buffer lookaside list.
        //

        ExInitializeNPagedLookasideList(&ObpNameBufferLookasideList,
                                        NULL,
                                        NULL,
                                        0,
                                        OBJECT_NAME_BUFFER_SIZE,
                                        'mNbO',
                                        NameBufferMaxDepth);

        InitializeListHead( &ObpRemoveObjectQueue );

        //
        // Initialize security descriptor cache
        //

        ObpInitSecurityDescriptorCache();

        KeInitializeMutant( &ObpInitKillMutant, FALSE );
        KeInitializeEvent( &ObpDefaultObject, NotificationEvent, TRUE );
        KeInitializeSpinLock( &ObpLock );
        PsGetCurrentProcess()->GrantedAccess = PROCESS_ALL_ACCESS;
        PsGetCurrentThread()->GrantedAccess = THREAD_ALL_ACCESS;

        //
        // Initialize the quota block
        //

        KeInitializeSpinLock(&PspDefaultQuotaBlock.QuotaLock);
        PspDefaultQuotaBlock.ReferenceCount = 1;
        PspDefaultQuotaBlock.QuotaPoolLimit[PagedPool] = (ULONG)-1;
        PspDefaultQuotaBlock.QuotaPoolLimit[NonPagedPool] = (ULONG)-1;
        PspDefaultQuotaBlock.PagefileLimit = (ULONG)-1;

        PsGetCurrentProcess()->QuotaBlock = &PspDefaultQuotaBlock;

        PsGetCurrentProcess()->ObjectTable =
            ExCreateHandleTable( NULL,
                                 0,
                                 0
                               );

        RtlZeroMemory( &ObjectTypeInitializer, sizeof( ObjectTypeInitializer ) );
        ObjectTypeInitializer.Length = sizeof( ObjectTypeInitializer );
        ObjectTypeInitializer.InvalidAttributes = OBJ_OPENLINK;
        ObjectTypeInitializer.PoolType = NonPagedPool;

        RtlInitUnicodeString( &TypeTypeName, L"Type" );
        ObjectTypeInitializer.ValidAccessMask = OBJECT_TYPE_ALL_ACCESS;
        ObjectTypeInitializer.GenericMapping = ObpTypeMapping;
        ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof( OBJECT_TYPE );
        ObjectTypeInitializer.MaintainTypeList = TRUE;
        ObjectTypeInitializer.UseDefaultObject = TRUE;
        ObCreateObjectType( &TypeTypeName,
                            &ObjectTypeInitializer,
                            (PSECURITY_DESCRIPTOR)NULL,
                            &ObpTypeObjectType
                          );

        RtlInitUnicodeString( &DirectoryTypeName, L"Directory" );
        ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof( OBJECT_DIRECTORY );
        ObjectTypeInitializer.ValidAccessMask = DIRECTORY_ALL_ACCESS;
        ObjectTypeInitializer.GenericMapping = ObpDirectoryMapping;
        ObjectTypeInitializer.MaintainTypeList = FALSE;
        ObCreateObjectType( &DirectoryTypeName,
                            &ObjectTypeInitializer,
                            (PSECURITY_DESCRIPTOR)NULL,
                            &ObpDirectoryObjectType
                          );

        RtlInitUnicodeString( &SymbolicLinkTypeName, L"SymbolicLink" );
        ObjectTypeInitializer.DefaultNonPagedPoolCharge = sizeof( OBJECT_SYMBOLIC_LINK );
        ObjectTypeInitializer.ValidAccessMask = SYMBOLIC_LINK_ALL_ACCESS;
        ObjectTypeInitializer.GenericMapping = ObpSymbolicLinkMapping;
        ObjectTypeInitializer.DeleteProcedure = ObpDeleteSymbolicLink;
        ObjectTypeInitializer.ParseProcedure = ObpParseSymbolicLink;
        ObCreateObjectType( &SymbolicLinkTypeName,
                            &ObjectTypeInitializer,
                            (PSECURITY_DESCRIPTOR)NULL,
                            &ObpSymbolicLinkObjectType
                          );

        ExInitializeResourceLite( &ObpRootDirectoryMutex );

#if i386 && !FPO
        ObpCurCachedGrantedAccessIndex = 0;
        ObpMaxCachedGrantedAccessIndex = PAGE_SIZE / sizeof( ACCESS_MASK );
        ObpCachedGrantedAccesses = ExAllocatePoolWithTag( NonPagedPool, PAGE_SIZE, 'gAbO' );
#endif // i386 && !FPO

#if DBG
        ObpCreateObjectEventId = RtlCreateEventId( NULL,
                                                   0,
                                                   "CreateObject",
                                                   6,
                                                   RTL_EVENT_ULONG_PARAM, "Object", 0,
                                                   RTL_EVENT_PUNICODE_STRING_PARAM, "Type", 0,
                                                   RTL_EVENT_ULONG_PARAM, "PagedPool", 0,
                                                   RTL_EVENT_ULONG_PARAM, "NonPagedPool", 0,
                                                   RTL_EVENT_PUNICODE_STRING_PARAM, "Name", 0,
                                                   RTL_EVENT_FLAGS_PARAM, "", 5,
                                                     OBJ_INHERIT, "Inherit",
                                                     OBJ_PERMANENT, "Permanent",
                                                     OBJ_OPENIF, "OpenIf",
                                                     OBJ_CASE_INSENSITIVE, "CaseInsenitive",
                                                     OBJ_EXCLUSIVE, "Exclusive"
                                                 );
        ObpFreeObjectEventId = RtlCreateEventId( NULL,
                                                 0,
                                                 "FreeObject",
                                                 3,
                                                 RTL_EVENT_ULONG_PARAM, "Object", 0,
                                                 RTL_EVENT_ULONG_PARAM, "Type", 0,
                                                 RTL_EVENT_PUNICODE_STRING_PARAM, "Name", 0
                                               );
#endif // DBG

        }             // End of Phase 0 Initializtion


    //
    // PHASE 1 Initialization
    //

    if (InitializationPhase == 1) {


        EffectiveSd = SePublicDefaultSd;

        //
        // This code is only executed if base auditing is turned on.
        //

        if ((ObpAuditBaseDirectories != 0) || (ObpAuditBaseObjects != 0)) {

            //
            // build an SACL to audit
            //
            AuditAllAcl = (PACL)AuditAllBuffer;
            AuditAllLength = (ULONG)sizeof(ACL) +
                               ((ULONG)sizeof(SYSTEM_AUDIT_ACE)) +
                               SeLengthSid(SeWorldSid);
            ASSERT( sizeof(AuditAllBuffer)   >   AuditAllLength );
            Status = RtlCreateAcl( AuditAllAcl, AuditAllLength, ACL_REVISION2);
            ASSERT( NT_SUCCESS(Status) );
            Status = RtlAddAuditAccessAce (
                         AuditAllAcl,
                         ACL_REVISION2,
                         GENERIC_ALL,
                         SeWorldSid,
                         TRUE,  TRUE        //Audit success and failure
                         );
            ASSERT( NT_SUCCESS(Status) );

            Status = RtlGetAce( AuditAllAcl, 0,  (PVOID)&Ace );
            ASSERT( NT_SUCCESS(Status) );

            if (ObpAuditBaseDirectories != 0) {
                Ace->AceFlags |= (CONTAINER_INHERIT_ACE | INHERIT_ONLY_ACE);
                }

            if (ObpAuditBaseObjects != 0) {
                Ace->AceFlags |= (OBJECT_INHERIT_ACE    |
                                  CONTAINER_INHERIT_ACE |
                                  INHERIT_ONLY_ACE);
                }



            //
            // Now create a security descriptor that looks just like
            // the public default, but has auditing in it as well.

            EffectiveSd = (PSECURITY_DESCRIPTOR)&AuditSd;
            Status = RtlCreateSecurityDescriptor( EffectiveSd,
                                                  SECURITY_DESCRIPTOR_REVISION1 );
            ASSERT( NT_SUCCESS(Status) );

            Status = RtlSetDaclSecurityDescriptor( EffectiveSd,
                                                   TRUE,        // DaclPresent
                                                   SePublicDefaultDacl,
                                                   FALSE        // DaclDefaulted
                                                   );
            ASSERT( NT_SUCCESS(Status) );
            Status = RtlSetSaclSecurityDescriptor( EffectiveSd,
                                                   TRUE,        // DaclPresent
                                                   AuditAllAcl,
                                                   FALSE        // DaclDefaulted
                                                   );
            ASSERT( NT_SUCCESS(Status) );
            }


        //
        // We only need to use the EffectiveSd on the root.  The SACL
        // will be inherited by all other objects.
        //

        RtlInitUnicodeString( &RootDirectoryName, L"\\" );
        InitializeObjectAttributes( &ObjectAttributes,
                                    &RootDirectoryName,
                                    OBJ_CASE_INSENSITIVE |
                                    OBJ_PERMANENT,
                                    NULL,
                                    EffectiveSd
                                  );
        Status = NtCreateDirectoryObject( &RootDirectoryHandle,
                                          DIRECTORY_ALL_ACCESS,
                                          &ObjectAttributes
                                        );
        if (!NT_SUCCESS( Status )) {
            return( FALSE );
            }

        Status = ObReferenceObjectByHandle( RootDirectoryHandle,
                                            0,
                                            ObpDirectoryObjectType,
                                            KernelMode,
                                            (PVOID *)&ObpRootDirectoryObject,
                                            NULL
                                          );
        if (!NT_SUCCESS( Status )) {
            return( FALSE );
            }

        Status = NtClose( RootDirectoryHandle );
        if (!NT_SUCCESS( Status )) {
            return( FALSE );
            }

        RtlInitUnicodeString( &TypeDirectoryName, L"\\ObjectTypes" );
        InitializeObjectAttributes( &ObjectAttributes,
                                    &TypeDirectoryName,
                                    OBJ_CASE_INSENSITIVE |
                                    OBJ_PERMANENT,
                                    NULL,
                                    NULL
                                  );
        Status = NtCreateDirectoryObject( &TypeDirectoryHandle,
                                          DIRECTORY_ALL_ACCESS,
                                          &ObjectAttributes
                                        );
        if (!NT_SUCCESS( Status )) {
            return( FALSE );
            }

        Status = ObReferenceObjectByHandle( TypeDirectoryHandle,
                                            0,
                                            ObpDirectoryObjectType,
                                            KernelMode,
                                            (PVOID *)&ObpTypeDirectoryObject,
                                            NULL
                                          );
        if (!NT_SUCCESS( Status )) {
            return( FALSE );
            }

        Status = NtClose( TypeDirectoryHandle );
        if (!NT_SUCCESS( Status )) {
            return( FALSE );
            }

        ObpEnterRootDirectoryMutex();

        Head = &ObpTypeObjectType->TypeList;
        Next = Head->Flink;
        while (Next != Head) {
            CreatorInfo = CONTAINING_RECORD( Next,
                                             OBJECT_HEADER_CREATOR_INFO,
                                             TypeList
                                           );
            ObjectTypeHeader = (POBJECT_HEADER)(CreatorInfo+1);
            NameInfo = OBJECT_HEADER_TO_NAME_INFO( ObjectTypeHeader );
            if (NameInfo != NULL && NameInfo->Directory == NULL) {
                if (!ObpLookupDirectoryEntry( ObpTypeDirectoryObject,
                                              &NameInfo->Name,
                                              OBJ_CASE_INSENSITIVE
                                            )
                   ) {
                    ObpInsertDirectoryEntry( ObpTypeDirectoryObject,
                                             &ObjectTypeHeader->Body
                                           );
                    }
                }

            Next = Next->Flink;
            }

        ObpLeaveRootDirectoryMutex();

        //
        // Create \DosDevices object directory for drive letters and Win32 device names
        //
        Status = ObpCreateDosDevicesDirectory();
        if (!NT_SUCCESS( Status )) {
            return FALSE;
            }
        }

    return TRUE;
}
Example #16
0
VOID
NtfsInitializeNtfsData (
    IN PDRIVER_OBJECT DriverObject
    )

/*++

Routine Description:

    This routine initializes the global ntfs data record

Arguments:

    DriverObject - Supplies the driver object for NTFS

Return Value:

    None.

--*/

{
    USHORT FileLockMaxDepth;
    USHORT IoContextMaxDepth;
    USHORT IrpContextMaxDepth;
    USHORT KeventMaxDepth;
    USHORT ScbNonpagedMaxDepth;
    USHORT ScbSnapshotMaxDepth;

    USHORT CcbDataMaxDepth;
    USHORT CcbMaxDepth;
    USHORT DeallocatedRecordsMaxDepth;
    USHORT FcbDataMaxDepth;
    USHORT FcbIndexMaxDepth;
    USHORT IndexContextMaxDepth;
    USHORT LcbMaxDepth;
    USHORT NukemMaxDepth;
    USHORT ScbDataMaxDepth;

    PSECURITY_SUBJECT_CONTEXT SubjectContext = NULL;
    BOOLEAN CapturedSubjectContext = FALSE;

    PACL SystemDacl = NULL;
    ULONG SystemDaclLength;

    PSID AdminSid = NULL;
    PSID SystemSid = NULL;
    NTSTATUS Status = STATUS_SUCCESS;

    PAGED_CODE();

    DebugTrace( +1, Dbg, ("NtfsInitializeNtfsData\n") );

    //
    //  Zero the record and set its node type code and size
    //

    RtlZeroMemory( &NtfsData, sizeof(NTFS_DATA));

    NtfsData.NodeTypeCode = NTFS_NTC_DATA_HEADER;
    NtfsData.NodeByteSize = sizeof(NTFS_DATA);

    //
    //  Initialize the queue of mounted Vcbs
    //

    InitializeListHead(&NtfsData.VcbQueue);

    //
    //  This list head keeps track of closes yet to be done.
    //

    InitializeListHead( &NtfsData.AsyncCloseList );
    InitializeListHead( &NtfsData.DelayedCloseList );

    ExInitializeWorkItem( &NtfsData.NtfsCloseItem,
                          (PWORKER_THREAD_ROUTINE)NtfsFspClose,
                          NULL );

    //
    //  Set the driver object, device object, and initialize the global
    //  resource protecting the file system
    //

    NtfsData.DriverObject = DriverObject;

    ExInitializeResource( &NtfsData.Resource );

    //
    //  Now allocate and initialize the s-list structures used as our pool
    //  of IRP context records.  The size of the zone is based on the
    //  system memory size.  We also initialize the spin lock used to protect
    //  the zone.
    //

    KeInitializeSpinLock( &NtfsData.StrucSupSpinLock );
    {

        switch ( MmQuerySystemSize() ) {

        case MmSmallSystem:

            NtfsData.FreeEresourceTotal = 14;

            //
            //  Nonpaged Lookaside list maximum depths
            //

            FileLockMaxDepth           = 8;
            IoContextMaxDepth          = 8;
            IrpContextMaxDepth         = 4;
            KeventMaxDepth             = 8;
            ScbNonpagedMaxDepth        = 8;
            ScbSnapshotMaxDepth        = 8;

            //
            //  Paged Lookaside list maximum depths
            //

            CcbDataMaxDepth            = 4;
            CcbMaxDepth                = 4;
            DeallocatedRecordsMaxDepth = 8;
            FcbDataMaxDepth            = 8;
            FcbIndexMaxDepth           = 4;
            IndexContextMaxDepth       = 8;
            LcbMaxDepth                = 4;
            NukemMaxDepth              = 8;
            ScbDataMaxDepth            = 4;

            SetFlag( NtfsData.Flags, NTFS_FLAGS_SMALL_SYSTEM );
            NtfsMaxDelayedCloseCount = MAX_DELAYED_CLOSE_COUNT;

            break;

        case MmMediumSystem:

            NtfsData.FreeEresourceTotal = 30;

            //
            //  Nonpaged Lookaside list maximum depths
            //

            FileLockMaxDepth           = 8;
            IoContextMaxDepth          = 8;
            IrpContextMaxDepth         = 8;
            KeventMaxDepth             = 8;
            ScbNonpagedMaxDepth        = 30;
            ScbSnapshotMaxDepth        = 8;

            //
            //  Paged Lookaside list maximum depths
            //

            CcbDataMaxDepth            = 12;
            CcbMaxDepth                = 6;
            DeallocatedRecordsMaxDepth = 8;
            FcbDataMaxDepth            = 30;
            FcbIndexMaxDepth           = 12;
            IndexContextMaxDepth       = 8;
            LcbMaxDepth                = 12;
            NukemMaxDepth              = 8;
            ScbDataMaxDepth            = 12;

            SetFlag( NtfsData.Flags, NTFS_FLAGS_MEDIUM_SYSTEM );
            NtfsMaxDelayedCloseCount = 4 * MAX_DELAYED_CLOSE_COUNT;

            break;

        case MmLargeSystem:

            SetFlag( NtfsData.Flags, NTFS_FLAGS_LARGE_SYSTEM );
            NtfsMaxDelayedCloseCount = 16 * MAX_DELAYED_CLOSE_COUNT;

            if (MmIsThisAnNtAsSystem()) {

                NtfsData.FreeEresourceTotal = 256;

                //
                //  Nonpaged Lookaside list maximum depths
                //

                FileLockMaxDepth           = 8;
                IoContextMaxDepth          = 8;
                IrpContextMaxDepth         = 256;
                KeventMaxDepth             = 8;
                ScbNonpagedMaxDepth        = 128;
                ScbSnapshotMaxDepth        = 8;

                //
                //  Paged Lookaside list maximum depths
                //

                CcbDataMaxDepth            = 40;
                CcbMaxDepth                = 20;
                DeallocatedRecordsMaxDepth = 8;
                FcbDataMaxDepth            = 128;
                FcbIndexMaxDepth           = 40;
                IndexContextMaxDepth       = 8;
                LcbMaxDepth                = 40;
                NukemMaxDepth              = 8;
                ScbDataMaxDepth            = 40;

            } else {

                NtfsData.FreeEresourceTotal = 128;

                //
                //  Nonpaged Lookaside list maximum depths
                //

                FileLockMaxDepth           = 8;
                IoContextMaxDepth          = 8;
                IrpContextMaxDepth         = 64;
                KeventMaxDepth             = 8;
                ScbNonpagedMaxDepth        = 64;
                ScbSnapshotMaxDepth        = 8;

                //
                //  Paged Lookaside list maximum depths
                //

                CcbDataMaxDepth            = 20;
                CcbMaxDepth                = 10;
                DeallocatedRecordsMaxDepth = 8;
                FcbDataMaxDepth            = 64;
                FcbIndexMaxDepth           = 20;
                IndexContextMaxDepth       = 8;
                LcbMaxDepth                = 20;
                NukemMaxDepth              = 8;
                ScbDataMaxDepth            = 20;
            }

            break;
        }

        NtfsMinDelayedCloseCount = NtfsMaxDelayedCloseCount * 4 / 5;

    }

    //
    //  Initialize our various lookaside lists.  To make it a bit more readable we'll
    //  define two quick macros to do the initialization
    //

#if DBG && i386 && defined (NTFSPOOLCHECK)
#define NPagedInit(L,S,T,D) { ExInitializeNPagedLookasideList( (L), NtfsDebugAllocatePoolWithTag, NtfsDebugFreePool, POOL_RAISE_IF_ALLOCATION_FAILURE, S, T, D); }
#define PagedInit(L,S,T,D)  { ExInitializePagedLookasideList(  (L), NtfsDebugAllocatePoolWithTag, NtfsDebugFreePool, POOL_RAISE_IF_ALLOCATION_FAILURE, S, T, D); }
#else   //  DBG && i386
#define NPagedInit(L,S,T,D) { ExInitializeNPagedLookasideList( (L), NULL, NULL, POOL_RAISE_IF_ALLOCATION_FAILURE, S, T, D); }
#define PagedInit(L,S,T,D)  { ExInitializePagedLookasideList(  (L), NULL, NULL, POOL_RAISE_IF_ALLOCATION_FAILURE, S, T, D); }
#endif  //  DBG && i386

    NPagedInit( &NtfsFileLockLookasideList,    sizeof(FILE_LOCK),       'kftN', FileLockMaxDepth );
    NPagedInit( &NtfsIoContextLookasideList,   sizeof(NTFS_IO_CONTEXT), 'IftN', IoContextMaxDepth );
    NPagedInit( &NtfsIrpContextLookasideList,  sizeof(IRP_CONTEXT),     'iftN', IrpContextMaxDepth );
    NPagedInit( &NtfsKeventLookasideList,      sizeof(KEVENT),          'KftN', KeventMaxDepth );
    NPagedInit( &NtfsScbNonpagedLookasideList, sizeof(SCB_NONPAGED),    'nftN', ScbNonpagedMaxDepth );
    NPagedInit( &NtfsScbSnapshotLookasideList, sizeof(SCB_SNAPSHOT),    'TftN', ScbSnapshotMaxDepth );

    PagedInit(  &NtfsCcbLookasideList,                sizeof(CCB),                 'CftN', CcbMaxDepth );
    PagedInit(  &NtfsCcbDataLookasideList,            sizeof(CCB_DATA),            'cftN', CcbDataMaxDepth );
    PagedInit(  &NtfsDeallocatedRecordsLookasideList, sizeof(DEALLOCATED_RECORDS), 'DftN', DeallocatedRecordsMaxDepth );
    PagedInit(  &NtfsFcbDataLookasideList,            sizeof(FCB_DATA),            'fftN', FcbDataMaxDepth );
    PagedInit(  &NtfsFcbIndexLookasideList,           sizeof(FCB_INDEX),           'FftN', FcbIndexMaxDepth );
    PagedInit(  &NtfsIndexContextLookasideList,       sizeof(INDEX_CONTEXT),       'EftN', IndexContextMaxDepth );
    PagedInit(  &NtfsLcbLookasideList,                sizeof(LCB),                 'lftN', LcbMaxDepth );
    PagedInit(  &NtfsNukemLookasideList,              sizeof(NUKEM),               'NftN', NukemMaxDepth );
    PagedInit(  &NtfsScbDataLookasideList,            SIZEOF_SCB_DATA,             'sftN', ScbDataMaxDepth );

    //
    //  Initialize the cache manager callback routines,  First are the routines
    //  for normal file manipulations, followed by the routines for
    //  volume manipulations.
    //

    {
        PCACHE_MANAGER_CALLBACKS Callbacks = &NtfsData.CacheManagerCallbacks;

        Callbacks->AcquireForLazyWrite  = &NtfsAcquireScbForLazyWrite;
        Callbacks->ReleaseFromLazyWrite = &NtfsReleaseScbFromLazyWrite;
        Callbacks->AcquireForReadAhead  = &NtfsAcquireScbForReadAhead;
        Callbacks->ReleaseFromReadAhead = &NtfsReleaseScbFromReadAhead;
    }

    {
        PCACHE_MANAGER_CALLBACKS Callbacks = &NtfsData.CacheManagerVolumeCallbacks;

        Callbacks->AcquireForLazyWrite  = &NtfsAcquireVolumeFileForLazyWrite;
        Callbacks->ReleaseFromLazyWrite = &NtfsReleaseVolumeFileFromLazyWrite;
        Callbacks->AcquireForReadAhead  = NULL;
        Callbacks->ReleaseFromReadAhead = NULL;
    }

    //
    //  Initialize the queue of read ahead threads
    //

    InitializeListHead(&NtfsData.ReadAheadThreads);

    //
    //  Set up global pointer to our process.
    //

    NtfsData.OurProcess = PsGetCurrentProcess();

    //
    //  Use a try-finally to cleanup on errors.
    //

    try {

        SECURITY_DESCRIPTOR NewDescriptor;
        SID_IDENTIFIER_AUTHORITY Authority = SECURITY_NT_AUTHORITY;

        SubjectContext = NtfsAllocatePool( PagedPool, sizeof( SECURITY_SUBJECT_CONTEXT ));
        SeCaptureSubjectContext( SubjectContext );
        CapturedSubjectContext = TRUE;

        //
        //  Build the default security descriptor which gives full access to
        //  system and administrator.
        //

        AdminSid = (PSID) NtfsAllocatePool( PagedPool, RtlLengthRequiredSid( 2 ));
        RtlInitializeSid( AdminSid, &Authority, 2 );
        *(RtlSubAuthoritySid( AdminSid, 0 )) = SECURITY_BUILTIN_DOMAIN_RID;
        *(RtlSubAuthoritySid( AdminSid, 1 )) = DOMAIN_ALIAS_RID_ADMINS;

        SystemSid = (PSID) NtfsAllocatePool( PagedPool, RtlLengthRequiredSid( 1 ));
        RtlInitializeSid( SystemSid, &Authority, 1 );
        *(RtlSubAuthoritySid( SystemSid, 0 )) = SECURITY_LOCAL_SYSTEM_RID;

        SystemDaclLength = sizeof( ACL ) +
                           (2 * sizeof( ACCESS_ALLOWED_ACE )) +
                           SeLengthSid( AdminSid ) +
                           SeLengthSid( SystemSid ) +
                           8; // The 8 is just for good measure

        SystemDacl = NtfsAllocatePool( PagedPool, SystemDaclLength );

        Status = RtlCreateAcl( SystemDacl, SystemDaclLength, ACL_REVISION2 );

        if (!NT_SUCCESS( Status )) { leave; }

        Status = RtlAddAccessAllowedAce( SystemDacl,
                                         ACL_REVISION2,
                                         GENERIC_ALL,
                                         SystemSid );

        if (!NT_SUCCESS( Status )) { leave; }

        Status = RtlAddAccessAllowedAce( SystemDacl,
                                         ACL_REVISION2,
                                         GENERIC_ALL,
                                         AdminSid );

        if (!NT_SUCCESS( Status )) { leave; }

        Status = RtlCreateSecurityDescriptor( &NewDescriptor,
                                              SECURITY_DESCRIPTOR_REVISION1 );

        if (!NT_SUCCESS( Status )) { leave; }

        Status = RtlSetDaclSecurityDescriptor( &NewDescriptor,
                                               TRUE,
                                               SystemDacl,
                                               FALSE );

        if (!NT_SUCCESS( Status )) { leave; }

        Status = SeAssignSecurity( NULL,
                                   &NewDescriptor,
                                   &NtfsData.DefaultDescriptor,
                                   FALSE,
                                   SubjectContext,
                                   IoGetFileObjectGenericMapping(),
                                   PagedPool );

        if (!NT_SUCCESS( Status )) { leave; }

        NtfsData.DefaultDescriptorLength = RtlLengthSecurityDescriptor( NtfsData.DefaultDescriptor );

        ASSERT( SeValidSecurityDescriptor( NtfsData.DefaultDescriptorLength,
                                           NtfsData.DefaultDescriptor ));

    } finally {

        if (CapturedSubjectContext) {

            SeReleaseSubjectContext( SubjectContext );
        }

        if (SubjectContext != NULL) { NtfsFreePool( SubjectContext ); }

        if (SystemDacl != NULL) { NtfsFreePool( SystemDacl ); }

        if (AdminSid != NULL) { NtfsFreePool( AdminSid ); }

        if (SystemSid != NULL) { NtfsFreePool( SystemSid ); }
    }

    //
    //  Raise if we hit an error building the security descriptor.
    //

    if (!NT_SUCCESS( Status )) { ExRaiseStatus( Status ); }

    //
    //  And return to our caller
    //

    DebugTrace( -1, Dbg, ("NtfsInitializeNtfsData -> VOID\n") );

    return;
}
Example #17
0
BOOLEAN
SepValidateAce (
    IN PVOID Ace,
    IN PACL Dacl
    )

/*++

Routine Description:

    Performs rudimentary validation on an Ace.  Ace must be within the
    passed ACl, the SID must be within the Ace, and the Ace must be of at
    least a minimal size.

Arguments:

    Ace - Pointer to Ace to be examined

    Dacl - Pointer to Acl in which Ace is supposed to exist

Return Value:

    A value of TRUE indicates the Ace is well formed, FALSE otherwise.

--*/

{

    USHORT AceSize;
    USHORT AclSize;

    PAGED_CODE();

    //
    //  make sure ACE is within ACL
    //

    AceSize = ((PACE_HEADER)Ace)->AceSize;
    AclSize = Dacl->AclSize;

    if ( (PVOID)((PUCHAR)Ace + AceSize) > (PVOID)((PUSHORT)Dacl + AclSize)) {

        return(FALSE);

    }

    //
    //  make sure SID is within ACE
    //

    if (IsKnownAceType( Ace )) {
        if ( (PVOID) ( (ULONG)Ace + SeLengthSid(&(((PKNOWN_ACE)Ace)->SidStart)) ) >
             (PVOID) ( (PUCHAR)Ace + AceSize )
           ) {

            return(FALSE);

        }
    }

    //
    //  Make sure ACE is big enough for minimum grant ACE
    //

    if (AceSize < sizeof(KNOWN_ACE)) {

        return(FALSE);

    }


    return(TRUE);
}