/*++

Copyright (c) 1989  Microsoft Corporation

Module Name:

    seinit.c

Abstract:

    Executive security components Initialization.

Author:

    Jim Kelly (JimK) 10-May-1990

Revision History:

--*/

#include "pch.h"

#pragma hdrstop

#include "adt.h"
#include <string.h>

//
// Security Database Constants
//

#define SEP_INITIAL_KEY_COUNT 15
#define SEP_INITIAL_LEVEL_COUNT 6L

#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT,SeInitSystem)
#pragma alloc_text(INIT,SepInitializationPhase0)
#pragma alloc_text(INIT,SepInitializationPhase1)
#endif

BOOLEAN
SeInitSystem( VOID )

/*++

Routine Description:

    Perform security related system initialization functions.

Arguments:

    None.

Return Value:

    TRUE - Initialization succeeded.

    FALSE - Initialization failed.

--*/

{
    PAGED_CODE();

    switch ( InitializationPhase ) {

    case 0 :
        return SepInitializationPhase0();
    case 1 :
        return SepInitializationPhase1();
    default:
        KeBugCheckEx(UNEXPECTED_INITIALIZATION_CALL, 0, InitializationPhase, 0, 0);
    }
}

VOID
SepInitProcessAuditSd( VOID );


BOOLEAN
SepInitializationPhase0( VOID )

/*++

Routine Description:

    Perform phase 0 security initialization.

    This includes:

        - Initialize LUID allocation
        - Initialize security global variables
        - initialize the token object.
        - Initialize the necessary security components of the boot thread/process


Arguments:

    None.

Return Value:

    TRUE - Initialization was successful.

    FALSE - Initialization Failed.

--*/

{

    PAGED_CODE();

    //
    //  LUID allocation services are needed by security prior to phase 0
    //  Executive initialization.  So, LUID initialization is performed
    //  here
    //

    if (ExLuidInitialization() == FALSE) {
        KdPrint(("Security: Locally Unique ID initialization failed.\n"));
        return FALSE;
    }

    //
    // Initialize security global variables
    //

    if (!SepVariableInitialization()) {
        KdPrint(("Security: Global variable initialization failed.\n"));
        return FALSE;
    }

    //
    // Perform Phase 0 Reference Monitor Initialization.
    //

    if (!SepRmInitPhase0()) {
        KdPrint(("Security: Ref Mon state initialization failed.\n"));
        return FALSE;
    }

    //
    // Initialize the token object type.
    //

    if (!SepTokenInitialization()) {
        KdPrint(("Security: Token object initialization failed.\n"));
        return FALSE;
    }

//    //
//    // Initialize auditing structures
//    //
//
//    if (!SepAdtInitializePhase0()) {
//        KdPrint(("Security: Auditing initialization failed.\n"));
//        return FALSE;
//    }
//
    //
    // Initialize SpinLock and list for the LSA worker thread
    //

    //
    // Initialize the work queue spinlock, list head, and semaphore
    // for each of the work queues.
    //

    if (!SepInitializeWorkList()) {
        KdPrint(("Security: Unable to initialize work queue\n"));
        return FALSE;
    }

    //
    // Initialize the security fields of the boot thread.
    //
    PsGetCurrentThread()->ImpersonationInfo = NULL;
    PS_CLEAR_BITS (&PsGetCurrentThread()->CrossThreadFlags, PS_CROSS_THREAD_FLAGS_IMPERSONATING);
    ObInitializeFastReference (&PsGetCurrentProcess()->Token, NULL);

    ObInitializeFastReference (&PsGetCurrentProcess()->Token, SeMakeSystemToken());

    return ( !ExFastRefObjectNull (PsGetCurrentProcess()->Token) );
}


BOOLEAN
SepInitializationPhase1( VOID )

/*++

Routine Description:

    Perform phase 1 security initialization.

    This includes:

        - Create an object directory for security related objects.
          (\Security).

        - Create an event to be signalled after the LSA has initialized.
          (\Security\LSA_Initialized)




Arguments:

    None.

Return Value:

    TRUE - Initialization was successful.

    FALSE - Initialization Failed.

--*/

{

    NTSTATUS Status;
    STRING Name;
    UNICODE_STRING UnicodeName;
    OBJECT_ATTRIBUTES ObjectAttributes;
    HANDLE SecurityRoot, TemporaryHandle;
    PSECURITY_DESCRIPTOR SD ;
    UCHAR SDBuffer[ SECURITY_DESCRIPTOR_MIN_LENGTH ];
    PACL Dacl ;

    PAGED_CODE();

    //
    // Insert the system token
    //

    Status = ObInsertObject( ExFastRefGetObject (PsGetCurrentProcess()->Token),
                             NULL,
                             0,
                             0,
                             NULL,
                             NULL );

    ASSERT( NT_SUCCESS(Status) );

    SeAnonymousLogonToken = SeMakeAnonymousLogonToken();
    ASSERT(SeAnonymousLogonToken != NULL);

    SeAnonymousLogonTokenNoEveryone = SeMakeAnonymousLogonTokenNoEveryone();
    ASSERT(SeAnonymousLogonTokenNoEveryone != NULL);

    //
    // Create the security object directory.
    //

    RtlInitString( &Name, "\\Security" );
    Status = RtlAnsiStringToUnicodeString(
                 &UnicodeName,
                 &Name,
                 TRUE );
    ASSERT( NT_SUCCESS(Status) );

    //
    // Build up the security descriptor
    //

    SD = (PSECURITY_DESCRIPTOR) SDBuffer ;

    RtlCreateSecurityDescriptor( SD,
                                 SECURITY_DESCRIPTOR_REVISION );

    Dacl = ExAllocatePool(
                NonPagedPool,
                256 );

    if ( !Dacl )
    {
        return FALSE ;
    }

    RtlCreateAcl( Dacl, 256, ACL_REVISION );

    RtlAddAccessAllowedAce( Dacl,
                            ACL_REVISION,
                            DIRECTORY_ALL_ACCESS,
                            SeLocalSystemSid );

    RtlAddAccessAllowedAce( Dacl,
                            ACL_REVISION,
                            DIRECTORY_QUERY | DIRECTORY_TRAVERSE |
                                READ_CONTROL,
                            SeAliasAdminsSid );

    RtlAddAccessAllowedAce( Dacl,
                            ACL_REVISION,
                            DIRECTORY_TRAVERSE,
                            SeWorldSid );

    RtlSetDaclSecurityDescriptor(
                            SD,
                            TRUE,
                            Dacl,
                            FALSE );

    InitializeObjectAttributes(
        &ObjectAttributes,
        &UnicodeName,
        (OBJ_PERMANENT | OBJ_CASE_INSENSITIVE),
        NULL,
        SD
        );

    Status = NtCreateDirectoryObject(
                 &SecurityRoot,
                 DIRECTORY_ALL_ACCESS,
                 &ObjectAttributes
                 );
    RtlFreeUnicodeString( &UnicodeName );
    ASSERTMSG("Security root object directory creation failed.",NT_SUCCESS(Status));

    ExFreePool( Dacl );

    //
    // Create an event in the security directory
    //

    RtlInitString( &Name, "LSA_AUTHENTICATION_INITIALIZED" );
    Status = RtlAnsiStringToUnicodeString(
                 &UnicodeName,
                 &Name,
                 TRUE );  ASSERT( NT_SUCCESS(Status) );
    InitializeObjectAttributes(
        &ObjectAttributes,
        &UnicodeName,
        (OBJ_PERMANENT | OBJ_CASE_INSENSITIVE),
        SecurityRoot,
        SePublicDefaultSd
        );

    Status = NtCreateEvent(
                 &TemporaryHandle,
                 GENERIC_WRITE,
                 &ObjectAttributes,
                 NotificationEvent,
                 FALSE
                 );
    RtlFreeUnicodeString( &UnicodeName );
    ASSERTMSG("LSA Initialization Event Creation Failed.",NT_SUCCESS(Status));

    Status = NtClose( SecurityRoot );
    ASSERTMSG("Security object directory handle closure Failed.",NT_SUCCESS(Status));
    Status = NtClose( TemporaryHandle );
    ASSERTMSG("LSA Initialization Event handle closure Failed.",NT_SUCCESS(Status));

    //
    // Initialize the default SACL to use for auditing
    // accesses to system processes. This initializes SepProcessSacl
    //

    SepInitProcessAuditSd();
    
#ifndef SETEST

    return TRUE;

#else

    return SepDevelopmentTest();

#endif  //SETEST

}
