/*++

Copyright (c) Microsoft Corporation. All rights reserved. 

You may only use this code if you agree to the terms of the Windows Research Kernel Source Code License agreement (see License.txt).
If you do not agree to the terms, do not use the code.


Module Name:

    seglobal.c

Abstract:

   This module contains the global variables used and exported by the security
   component.

--*/

#include "pch.h"

#pragma hdrstop

#include "adt.h"

VOID
SepInitializePrivilegeSets( VOID );


VOID
SepInitSystemDacls( VOID );

VOID
SepInitProcessAuditSd( VOID );


#ifdef ALLOC_PRAGMA
#pragma alloc_text(INIT,SepVariableInitialization)
#pragma alloc_text(INIT,SepInitSystemDacls)
#pragma alloc_text(INIT,SepInitializePrivilegeSets)
#pragma alloc_text(PAGE,SepAssemblePrivileges)
#pragma alloc_text(INIT,SepInitializeWorkList)
#endif

#ifdef ALLOC_DATA_PRAGMA
#pragma data_seg("PAGEDATA")
#pragma const_seg("PAGECONST")
#endif

#ifdef    SE_DIAGNOSTICS_ENABLED

//
// Used to control the active SE diagnostic support provided
//

ULONG SeGlobalFlag = 0;

#endif // SE_DIAGNOSTICS_ENABLED



////////////////////////////////////////////////////////////////////////
//                                                                    //
//           Global, READ ONLY, Security variables                    //
//                                                                    //
////////////////////////////////////////////////////////////////////////

//
//  Authentication ID and source name used for system processes
//

const TOKEN_SOURCE SeSystemTokenSource = {"*SYSTEM*", 0};
const LUID SeSystemAuthenticationId = SYSTEM_LUID;
const LUID SeAnonymousAuthenticationId = ANONYMOUS_LOGON_LUID;


//
// Universal well known SIDs
//

PSID  SeNullSid = NULL;
PSID  SeWorldSid = NULL;
PSID  SeLocalSid = NULL;
PSID  SeCreatorOwnerSid = NULL;
PSID  SeCreatorGroupSid = NULL;
PSID  SeCreatorGroupServerSid = NULL;
PSID  SeCreatorOwnerServerSid = NULL;

//
// Sids defined by NT
//

PSID SeNtAuthoritySid = NULL;

PSID SeDialupSid = NULL;
PSID SeNetworkSid = NULL;
PSID SeBatchSid = NULL;
PSID SeInteractiveSid = NULL;
PSID SeServiceSid = NULL;
PSID SePrincipalSelfSid = NULL;
PSID SeLocalSystemSid = NULL;
PSID SeAuthenticatedUsersSid = NULL;
PSID SeAliasAdminsSid = NULL;
PSID SeRestrictedSid = NULL;
PSID SeAliasUsersSid = NULL;
PSID SeAliasGuestsSid = NULL;
PSID SeAliasPowerUsersSid = NULL;
PSID SeAliasAccountOpsSid = NULL;
PSID SeAliasSystemOpsSid = NULL;
PSID SeAliasPrintOpsSid = NULL;
PSID SeAliasBackupOpsSid = NULL;
PSID SeAnonymousLogonSid = NULL;
PSID SeLocalServiceSid = NULL;
PSID SeNetworkServiceSid = NULL;

//
// Well known tokens
//

PACCESS_TOKEN SeAnonymousLogonToken = NULL;
PACCESS_TOKEN SeAnonymousLogonTokenNoEveryone = NULL;

//
// System default DACLs & Security Descriptors
//
//  SePublicDefaultDacl     - Protects objects so that WORLD:E, Admins:ALL, System: ALL.
//                            Not inherited by sub-objects.
//
//  SePublicDefaultUnrestrictedDacl - Protects objects so that WORLD:E, Admins:ALL, System: ALL, Restricted:E
//                            Not inherited by sub-objects.
//
//  SePublicOpenDacl        - Protects so that WORLD:RWE, Admins: All, System: ALL
//                            Not inherited by sub-objects.
//
//  SePublicOpenUnrestrictedDacl - Protects so that WORLD:RWE, Admins: All, System: ALL, Restricted:RE
//                            Not inherited by sub-objects.
//
//  SeSystemDefaultDacl     - Protects objects so that SYSTEM (All) & ADMIN (RE + ReadControl) can use them.
//                            Not inherited by subobjects.
//

PSECURITY_DESCRIPTOR SePublicDefaultSd = NULL;
SECURITY_DESCRIPTOR  SepPublicDefaultSd = {0};
PSECURITY_DESCRIPTOR SePublicDefaultUnrestrictedSd = NULL;
SECURITY_DESCRIPTOR  SepPublicDefaultUnrestrictedSd = {0};
PSECURITY_DESCRIPTOR SePublicOpenUnrestrictedSd = NULL;
SECURITY_DESCRIPTOR  SepPublicOpenUnrestrictedSd = {0};
PSECURITY_DESCRIPTOR SePublicOpenSd = NULL;
SECURITY_DESCRIPTOR  SepPublicOpenSd = {0};
PSECURITY_DESCRIPTOR SeSystemDefaultSd = NULL;
SECURITY_DESCRIPTOR  SepSystemDefaultSd = {0};
PSECURITY_DESCRIPTOR SeLocalServicePublicSd = NULL;
SECURITY_DESCRIPTOR  SepLocalServicePublicSd = {0};

//
// security descriptor with a SACL to be used for adding
// a SACL on system processes
//

PSECURITY_DESCRIPTOR SepProcessAuditSd = NULL;

//
// Access mask used for constructing the SACL in SepProcessAuditSd
//

ACCESS_MASK SepProcessAccessesToAudit = 0;

//
// security descriptor to check if a given token has any one of
// following sids in it:
// -- SeLocalSystemSid
// -- SeLocalServiceSid
// -- SeNetworkServiceSid
//

PSECURITY_DESCRIPTOR SepImportantProcessSd = NULL;

//
// used with SepImportantProcessSd
//

GENERIC_MAPPING GenericMappingForMembershipCheck = {
    STANDARD_RIGHTS_READ,
    STANDARD_RIGHTS_EXECUTE,
    STANDARD_RIGHTS_WRITE,
    STANDARD_RIGHTS_ALL };


PACL SePublicDefaultDacl = NULL;
PACL SePublicDefaultUnrestrictedDacl = NULL;
PACL SePublicOpenDacl = NULL;
PACL SePublicOpenUnrestrictedDacl = NULL;
PACL SeSystemDefaultDacl = NULL;
PACL SeLocalServicePublicDacl = NULL;


//
// Sid of primary domain, and admin account in that domain
//

PSID SepPrimaryDomainSid = NULL;
PSID SepPrimaryDomainAdminSid = NULL;



//
//  Well known privilege values
//


LUID SeCreateTokenPrivilege = {0};
LUID SeAssignPrimaryTokenPrivilege = {0};
LUID SeLockMemoryPrivilege = {0};
LUID SeIncreaseQuotaPrivilege = {0};
LUID SeUnsolicitedInputPrivilege = {0};
LUID SeTcbPrivilege = {0};
LUID SeSecurityPrivilege = {0};
LUID SeTakeOwnershipPrivilege = {0};
LUID SeLoadDriverPrivilege = {0};
LUID SeCreatePagefilePrivilege = {0};
LUID SeIncreaseBasePriorityPrivilege = {0};
LUID SeSystemProfilePrivilege = {0};
LUID SeSystemtimePrivilege = {0};
LUID SeProfileSingleProcessPrivilege = {0};
LUID SeCreatePermanentPrivilege = {0};
LUID SeBackupPrivilege = {0};
LUID SeRestorePrivilege = {0};
LUID SeShutdownPrivilege = {0};
LUID SeDebugPrivilege = {0};
LUID SeAuditPrivilege = {0};
LUID SeSystemEnvironmentPrivilege = {0};
LUID SeChangeNotifyPrivilege = {0};
LUID SeRemoteShutdownPrivilege = {0};
LUID SeUndockPrivilege = {0};
LUID SeSyncAgentPrivilege = {0};
LUID SeEnableDelegationPrivilege = {0};
LUID SeManageVolumePrivilege = { 0 };
LUID SeImpersonatePrivilege = { 0 };
LUID SeCreateGlobalPrivilege = { 0 };

//
// This is for optimizing SepAdtAuditThisEventWithContext and SeDetailedAuditingWithContext.
// If no per user policy for any token has been set in the system for a specific
// category then we never need to do the more expensive token policy checks.  This counter
// is incremented by NtSetInformationToken, SepDuplicateToken, and SepFilterToken.
// SepTokenDeleteMethod and NtSetInformationToken can decrement this counter.
//

LONG SepTokenPolicyCounter[POLICY_AUDIT_EVENT_TYPE_COUNT];

// Define the following structures for export from the kernel.
// This will allow us to export pointers to these structures
// rather than a pointer for each element in the structure.
//

PSE_EXPORTS  SeExports = NULL;
SE_EXPORTS SepExports = {0};


static const SID_IDENTIFIER_AUTHORITY    SepNullSidAuthority    = SECURITY_NULL_SID_AUTHORITY;
static const SID_IDENTIFIER_AUTHORITY    SepWorldSidAuthority   = SECURITY_WORLD_SID_AUTHORITY;
static const SID_IDENTIFIER_AUTHORITY    SepLocalSidAuthority   = SECURITY_LOCAL_SID_AUTHORITY;
static const SID_IDENTIFIER_AUTHORITY    SepCreatorSidAuthority = SECURITY_CREATOR_SID_AUTHORITY;
static const SID_IDENTIFIER_AUTHORITY    SepNtAuthority = SECURITY_NT_AUTHORITY;



//
// Some variables we are going to use to help speed up access
// checking.
//

static ULONG SinglePrivilegeSetSize = 0;
static ULONG DoublePrivilegeSetSize = 0;

static PPRIVILEGE_SET SepSystemSecurityPrivilegeSet = NULL;
static PPRIVILEGE_SET SepTakeOwnershipPrivilegeSet = NULL;
static PPRIVILEGE_SET SepDoublePrivilegeSet = NULL;


//
// Array containing information describing what is to be audited
//

SE_AUDITING_STATE SeAuditingState[POLICY_AUDIT_EVENT_TYPE_COUNT] =
    {
        { FALSE, FALSE },
        { FALSE, FALSE },
        { FALSE, FALSE },
        { FALSE, FALSE },
        { FALSE, FALSE },
        { FALSE, FALSE },
        { FALSE, FALSE },
        { FALSE, FALSE },
        { FALSE, FALSE }
    };

//
// Boolean indicating whether or not auditing is enabled for the system
//

BOOLEAN SepAdtAuditingEnabled = FALSE;

//
// Boolean to hold whether or not the user wants the system to crash when
// an audit fails.
//

BOOLEAN SepCrashOnAuditFail = FALSE;

//
// Handle to the LSA process
//

HANDLE SepLsaHandle = NULL;

#define SE_SUBSYSTEM_NAME L"Security"
const UNICODE_STRING SeSubsystemName = {
    sizeof(SE_SUBSYSTEM_NAME) - sizeof(WCHAR),
    sizeof(SE_SUBSYSTEM_NAME),
    SE_SUBSYSTEM_NAME
};


//
// Doubly linked list of work items queued to worker threads.
//

LIST_ENTRY SepLsaQueue = {NULL};

//
// Count to tell us how long the queue gets in SepRmCallLsa
//

ULONG SepLsaQueueLength = 0;

#ifdef ALLOC_DATA_PRAGMA
#pragma data_seg()
#endif

//
// Mutex protecting the queue of work being passed to LSA
//

ERESOURCE SepLsaQueueLock = {0};

SEP_WORK_ITEM SepExWorkItem = {0};

#if DBG || TOKEN_LEAK_MONITOR
LONG    SepTokenLeakMethodCount = 0;
LONG    SepTokenLeakBreakCount  = 0;
LONG    SepTokenLeakMethodWatch = 0;
PVOID   SepTokenLeakToken       = NULL;
HANDLE  SepTokenLeakProcessCid  = NULL;
BOOLEAN SepTokenLeakTracking    = FALSE;
#endif


////////////////////////////////////////////////////////////////////////
//                                                                    //
//           Variable Initialization Routines                         //
//                                                                    //
////////////////////////////////////////////////////////////////////////

BOOLEAN
SepVariableInitialization()
/*++

Routine Description:

    This function initializes the global variables used by and exposed
    by security.

Arguments:

    None.

Return Value:

    TRUE if variables successfully initialized.
    FALSE if not successfully initialized.

--*/
{

    ULONG SidWithZeroSubAuthorities;
    ULONG SidWithOneSubAuthority;
    ULONG SidWithTwoSubAuthorities;
    ULONG SidWithThreeSubAuthorities;

    SID_IDENTIFIER_AUTHORITY NullSidAuthority;
    SID_IDENTIFIER_AUTHORITY WorldSidAuthority;
    SID_IDENTIFIER_AUTHORITY LocalSidAuthority;
    SID_IDENTIFIER_AUTHORITY CreatorSidAuthority;
    SID_IDENTIFIER_AUTHORITY SeNtAuthority;

    PAGED_CODE();

    NullSidAuthority         = SepNullSidAuthority;
    WorldSidAuthority        = SepWorldSidAuthority;
    LocalSidAuthority        = SepLocalSidAuthority;
    CreatorSidAuthority      = SepCreatorSidAuthority;
    SeNtAuthority            = SepNtAuthority;


    //
    //  The following SID sizes need to be allocated
    //

    SidWithZeroSubAuthorities  = RtlLengthRequiredSid( 0 );
    SidWithOneSubAuthority     = RtlLengthRequiredSid( 1 );
    SidWithTwoSubAuthorities   = RtlLengthRequiredSid( 2 );
    SidWithThreeSubAuthorities = RtlLengthRequiredSid( 3 );

    //
    //  Allocate and initialize the universal SIDs
    //

    SeNullSid         = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithOneSubAuthority,'iSeS');
    SeWorldSid        = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithOneSubAuthority,'iSeS');
    SeLocalSid        = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithOneSubAuthority,'iSeS');
    SeCreatorOwnerSid = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithOneSubAuthority,'iSeS');
    SeCreatorGroupSid = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithOneSubAuthority,'iSeS');
    SeCreatorOwnerServerSid = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithOneSubAuthority,'iSeS');
    SeCreatorGroupServerSid = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithOneSubAuthority,'iSeS');

    //
    // Fail initialization if we didn't get enough memory for the universal
    // SIDs.
    //

    if ( (SeNullSid         == NULL)        ||
         (SeWorldSid        == NULL)        ||
         (SeLocalSid        == NULL)        ||
         (SeCreatorOwnerSid == NULL)        ||
         (SeCreatorGroupSid == NULL)        ||
         (SeCreatorOwnerServerSid == NULL ) ||
         (SeCreatorGroupServerSid == NULL )
       ) {

        return( FALSE );
    }

    RtlInitializeSid( SeNullSid,         &NullSidAuthority, 1 );
    RtlInitializeSid( SeWorldSid,        &WorldSidAuthority, 1 );
    RtlInitializeSid( SeLocalSid,        &LocalSidAuthority, 1 );
    RtlInitializeSid( SeCreatorOwnerSid, &CreatorSidAuthority, 1 );
    RtlInitializeSid( SeCreatorGroupSid, &CreatorSidAuthority, 1 );
    RtlInitializeSid( SeCreatorOwnerServerSid, &CreatorSidAuthority, 1 );
    RtlInitializeSid( SeCreatorGroupServerSid, &CreatorSidAuthority, 1 );

    *(RtlSubAuthoritySid( SeNullSid, 0 ))         = SECURITY_NULL_RID;
    *(RtlSubAuthoritySid( SeWorldSid, 0 ))        = SECURITY_WORLD_RID;
    *(RtlSubAuthoritySid( SeLocalSid, 0 ))        = SECURITY_LOCAL_RID;
    *(RtlSubAuthoritySid( SeCreatorOwnerSid, 0 )) = SECURITY_CREATOR_OWNER_RID;
    *(RtlSubAuthoritySid( SeCreatorGroupSid, 0 )) = SECURITY_CREATOR_GROUP_RID;
    *(RtlSubAuthoritySid( SeCreatorOwnerServerSid, 0 )) = SECURITY_CREATOR_OWNER_SERVER_RID;
    *(RtlSubAuthoritySid( SeCreatorGroupServerSid, 0 )) = SECURITY_CREATOR_GROUP_SERVER_RID;

    //
    // Allocate and initialize the NT defined SIDs
    //

    SeNtAuthoritySid  = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithZeroSubAuthorities,'iSeS');
    SeDialupSid       = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithOneSubAuthority,'iSeS');
    SeNetworkSid      = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithOneSubAuthority,'iSeS');
    SeBatchSid        = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithOneSubAuthority,'iSeS');
    SeInteractiveSid  = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithOneSubAuthority,'iSeS');
    SeServiceSid      = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithOneSubAuthority,'iSeS');
    SePrincipalSelfSid = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithOneSubAuthority,'iSeS');
    SeLocalSystemSid  = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithOneSubAuthority,'iSeS');
    SeAuthenticatedUsersSid  = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithOneSubAuthority,'iSeS');
    SeRestrictedSid   = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithOneSubAuthority,'iSeS');
    SeAnonymousLogonSid = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithOneSubAuthority,'iSeS');
    SeLocalServiceSid = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithOneSubAuthority,'iSeS');
    SeNetworkServiceSid = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithOneSubAuthority,'iSeS');

    SeAliasAdminsSid     = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithTwoSubAuthorities,'iSeS');
    SeAliasUsersSid      = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithTwoSubAuthorities,'iSeS');
    SeAliasGuestsSid     = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithTwoSubAuthorities,'iSeS');
    SeAliasPowerUsersSid = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithTwoSubAuthorities,'iSeS');
    SeAliasAccountOpsSid = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithTwoSubAuthorities,'iSeS');
    SeAliasSystemOpsSid  = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithTwoSubAuthorities,'iSeS');
    SeAliasPrintOpsSid   = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithTwoSubAuthorities,'iSeS');
    SeAliasBackupOpsSid  = (PSID)ExAllocatePoolWithTag(PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE,SidWithTwoSubAuthorities,'iSeS');

    //
    // Fail initialization if we didn't get enough memory for the NT SIDs.
    //

    if ( (SeNtAuthoritySid          == NULL) ||
         (SeDialupSid               == NULL) ||
         (SeNetworkSid              == NULL) ||
         (SeBatchSid                == NULL) ||
         (SeInteractiveSid          == NULL) ||
         (SeServiceSid              == NULL) ||
         (SePrincipalSelfSid        == NULL) ||
         (SeLocalSystemSid          == NULL) ||
         (SeAuthenticatedUsersSid   == NULL) ||
         (SeRestrictedSid           == NULL) ||
         (SeAnonymousLogonSid       == NULL) ||
         (SeLocalServiceSid         == NULL) ||
         (SeNetworkServiceSid       == NULL) ||
         (SeAliasAdminsSid          == NULL) ||
         (SeAliasUsersSid           == NULL) ||
         (SeAliasGuestsSid          == NULL) ||
         (SeAliasPowerUsersSid      == NULL) ||
         (SeAliasAccountOpsSid      == NULL) ||
         (SeAliasSystemOpsSid       == NULL) ||
         (SeAliasPrintOpsSid        == NULL) ||
         (SeAliasBackupOpsSid       == NULL)
       ) {

        return( FALSE );
    }

    RtlInitializeSid( SeNtAuthoritySid,         &SeNtAuthority, 0 );
    RtlInitializeSid( SeDialupSid,              &SeNtAuthority, 1 );
    RtlInitializeSid( SeNetworkSid,             &SeNtAuthority, 1 );
    RtlInitializeSid( SeBatchSid,               &SeNtAuthority, 1 );
    RtlInitializeSid( SeInteractiveSid,         &SeNtAuthority, 1 );
    RtlInitializeSid( SeServiceSid,             &SeNtAuthority, 1 );
    RtlInitializeSid( SePrincipalSelfSid,       &SeNtAuthority, 1 );
    RtlInitializeSid( SeLocalSystemSid,         &SeNtAuthority, 1 );
    RtlInitializeSid( SeAuthenticatedUsersSid,  &SeNtAuthority, 1 );
    RtlInitializeSid( SeRestrictedSid,          &SeNtAuthority, 1 );
    RtlInitializeSid( SeAnonymousLogonSid,      &SeNtAuthority, 1 );
    RtlInitializeSid( SeLocalServiceSid,        &SeNtAuthority, 1 );
    RtlInitializeSid( SeNetworkServiceSid,      &SeNtAuthority, 1 );

    RtlInitializeSid( SeAliasAdminsSid,     &SeNtAuthority, 2);
    RtlInitializeSid( SeAliasUsersSid,      &SeNtAuthority, 2);
    RtlInitializeSid( SeAliasGuestsSid,     &SeNtAuthority, 2);
    RtlInitializeSid( SeAliasPowerUsersSid, &SeNtAuthority, 2);
    RtlInitializeSid( SeAliasAccountOpsSid, &SeNtAuthority, 2);
    RtlInitializeSid( SeAliasSystemOpsSid,  &SeNtAuthority, 2);
    RtlInitializeSid( SeAliasPrintOpsSid,   &SeNtAuthority, 2);
    RtlInitializeSid( SeAliasBackupOpsSid,  &SeNtAuthority, 2);

    *(RtlSubAuthoritySid( SeDialupSid,              0 )) = SECURITY_DIALUP_RID;
    *(RtlSubAuthoritySid( SeNetworkSid,             0 )) = SECURITY_NETWORK_RID;
    *(RtlSubAuthoritySid( SeBatchSid,               0 )) = SECURITY_BATCH_RID;
    *(RtlSubAuthoritySid( SeInteractiveSid,         0 )) = SECURITY_INTERACTIVE_RID;
    *(RtlSubAuthoritySid( SeServiceSid,             0 )) = SECURITY_SERVICE_RID;
    *(RtlSubAuthoritySid( SePrincipalSelfSid,       0 )) = SECURITY_PRINCIPAL_SELF_RID;
    *(RtlSubAuthoritySid( SeLocalSystemSid,         0 )) = SECURITY_LOCAL_SYSTEM_RID;
    *(RtlSubAuthoritySid( SeAuthenticatedUsersSid,  0 )) = SECURITY_AUTHENTICATED_USER_RID;
    *(RtlSubAuthoritySid( SeRestrictedSid,          0 )) = SECURITY_RESTRICTED_CODE_RID;
    *(RtlSubAuthoritySid( SeAnonymousLogonSid,      0 )) = SECURITY_ANONYMOUS_LOGON_RID;
    *(RtlSubAuthoritySid( SeLocalServiceSid,        0 )) = SECURITY_LOCAL_SERVICE_RID;
    *(RtlSubAuthoritySid( SeNetworkServiceSid,      0 )) = SECURITY_NETWORK_SERVICE_RID;


    *(RtlSubAuthoritySid( SeAliasAdminsSid,     0 )) = SECURITY_BUILTIN_DOMAIN_RID;
    *(RtlSubAuthoritySid( SeAliasUsersSid,      0 )) = SECURITY_BUILTIN_DOMAIN_RID;
    *(RtlSubAuthoritySid( SeAliasGuestsSid,     0 )) = SECURITY_BUILTIN_DOMAIN_RID;
    *(RtlSubAuthoritySid( SeAliasPowerUsersSid, 0 )) = SECURITY_BUILTIN_DOMAIN_RID;
    *(RtlSubAuthoritySid( SeAliasAccountOpsSid, 0 )) = SECURITY_BUILTIN_DOMAIN_RID;
    *(RtlSubAuthoritySid( SeAliasSystemOpsSid,  0 )) = SECURITY_BUILTIN_DOMAIN_RID;
    *(RtlSubAuthoritySid( SeAliasPrintOpsSid,   0 )) = SECURITY_BUILTIN_DOMAIN_RID;
    *(RtlSubAuthoritySid( SeAliasBackupOpsSid,  0 )) = SECURITY_BUILTIN_DOMAIN_RID;

    *(RtlSubAuthoritySid( SeAliasAdminsSid,     1 )) = DOMAIN_ALIAS_RID_ADMINS;
    *(RtlSubAuthoritySid( SeAliasUsersSid,      1 )) = DOMAIN_ALIAS_RID_USERS;
    *(RtlSubAuthoritySid( SeAliasGuestsSid,     1 )) = DOMAIN_ALIAS_RID_GUESTS;
    *(RtlSubAuthoritySid( SeAliasPowerUsersSid, 1 )) = DOMAIN_ALIAS_RID_POWER_USERS;
    *(RtlSubAuthoritySid( SeAliasAccountOpsSid, 1 )) = DOMAIN_ALIAS_RID_ACCOUNT_OPS;
    *(RtlSubAuthoritySid( SeAliasSystemOpsSid,  1 )) = DOMAIN_ALIAS_RID_SYSTEM_OPS;
    *(RtlSubAuthoritySid( SeAliasPrintOpsSid,   1 )) = DOMAIN_ALIAS_RID_PRINT_OPS;
    *(RtlSubAuthoritySid( SeAliasBackupOpsSid,  1 )) = DOMAIN_ALIAS_RID_BACKUP_OPS;



    //
    // Initialize system default dacl
    //

    SepInitSystemDacls();


    //
    // Initialize the well known privilege values
    //

    SeCreateTokenPrivilege =
        RtlConvertLongToLuid(SE_CREATE_TOKEN_PRIVILEGE);
    SeAssignPrimaryTokenPrivilege =
        RtlConvertLongToLuid(SE_ASSIGNPRIMARYTOKEN_PRIVILEGE);
    SeLockMemoryPrivilege =
        RtlConvertLongToLuid(SE_LOCK_MEMORY_PRIVILEGE);
    SeIncreaseQuotaPrivilege =
        RtlConvertLongToLuid(SE_INCREASE_QUOTA_PRIVILEGE);
    SeUnsolicitedInputPrivilege =
        RtlConvertLongToLuid(SE_UNSOLICITED_INPUT_PRIVILEGE);
    SeTcbPrivilege =
        RtlConvertLongToLuid(SE_TCB_PRIVILEGE);
    SeSecurityPrivilege =
        RtlConvertLongToLuid(SE_SECURITY_PRIVILEGE);
    SeTakeOwnershipPrivilege =
        RtlConvertLongToLuid(SE_TAKE_OWNERSHIP_PRIVILEGE);
    SeLoadDriverPrivilege =
        RtlConvertLongToLuid(SE_LOAD_DRIVER_PRIVILEGE);
    SeCreatePagefilePrivilege =
        RtlConvertLongToLuid(SE_CREATE_PAGEFILE_PRIVILEGE);
    SeIncreaseBasePriorityPrivilege =
        RtlConvertLongToLuid(SE_INC_BASE_PRIORITY_PRIVILEGE);
    SeSystemProfilePrivilege =
        RtlConvertLongToLuid(SE_SYSTEM_PROFILE_PRIVILEGE);
    SeSystemtimePrivilege =
        RtlConvertLongToLuid(SE_SYSTEMTIME_PRIVILEGE);
    SeProfileSingleProcessPrivilege =
        RtlConvertLongToLuid(SE_PROF_SINGLE_PROCESS_PRIVILEGE);
    SeCreatePermanentPrivilege =
        RtlConvertLongToLuid(SE_CREATE_PERMANENT_PRIVILEGE);
    SeBackupPrivilege =
        RtlConvertLongToLuid(SE_BACKUP_PRIVILEGE);
    SeRestorePrivilege =
        RtlConvertLongToLuid(SE_RESTORE_PRIVILEGE);
    SeShutdownPrivilege =
        RtlConvertLongToLuid(SE_SHUTDOWN_PRIVILEGE);
    SeDebugPrivilege =
        RtlConvertLongToLuid(SE_DEBUG_PRIVILEGE);
    SeAuditPrivilege =
        RtlConvertLongToLuid(SE_AUDIT_PRIVILEGE);
    SeSystemEnvironmentPrivilege =
        RtlConvertLongToLuid(SE_SYSTEM_ENVIRONMENT_PRIVILEGE);
    SeChangeNotifyPrivilege =
        RtlConvertLongToLuid(SE_CHANGE_NOTIFY_PRIVILEGE);
    SeRemoteShutdownPrivilege =
        RtlConvertLongToLuid(SE_REMOTE_SHUTDOWN_PRIVILEGE);
    SeUndockPrivilege =
        RtlConvertLongToLuid(SE_UNDOCK_PRIVILEGE);
    SeSyncAgentPrivilege =
        RtlConvertLongToLuid(SE_SYNC_AGENT_PRIVILEGE);
    SeEnableDelegationPrivilege =
        RtlConvertLongToLuid(SE_ENABLE_DELEGATION_PRIVILEGE);
    SeManageVolumePrivilege =
        RtlConvertLongToLuid(SE_MANAGE_VOLUME_PRIVILEGE);
    SeImpersonatePrivilege = 
        RtlConvertLongToLuid(SE_IMPERSONATE_PRIVILEGE);
    SeCreateGlobalPrivilege =
        RtlConvertLongToLuid(SE_CREATE_GLOBAL_PRIVILEGE);


    //
    // Initialize the SeExports structure for exporting all
    // of the information we've created out of the kernel.
    //

    //
    // Package these together for export
    //


    SepExports.SeNullSid         = SeNullSid;
    SepExports.SeWorldSid        = SeWorldSid;
    SepExports.SeLocalSid        = SeLocalSid;
    SepExports.SeCreatorOwnerSid = SeCreatorOwnerSid;
    SepExports.SeCreatorGroupSid = SeCreatorGroupSid;


    SepExports.SeNtAuthoritySid         = SeNtAuthoritySid;
    SepExports.SeDialupSid              = SeDialupSid;
    SepExports.SeNetworkSid             = SeNetworkSid;
    SepExports.SeBatchSid               = SeBatchSid;
    SepExports.SeInteractiveSid         = SeInteractiveSid;
    SepExports.SeLocalSystemSid         = SeLocalSystemSid;
    SepExports.SeAuthenticatedUsersSid  = SeAuthenticatedUsersSid;
    SepExports.SeRestrictedSid          = SeRestrictedSid;
    SepExports.SeAnonymousLogonSid      = SeAnonymousLogonSid;
    SepExports.SeLocalServiceSid        = SeLocalServiceSid;
    SepExports.SeNetworkServiceSid      = SeNetworkServiceSid;
    SepExports.SeAliasAdminsSid         = SeAliasAdminsSid;
    SepExports.SeAliasUsersSid          = SeAliasUsersSid;
    SepExports.SeAliasGuestsSid         = SeAliasGuestsSid;
    SepExports.SeAliasPowerUsersSid     = SeAliasPowerUsersSid;
    SepExports.SeAliasAccountOpsSid     = SeAliasAccountOpsSid;
    SepExports.SeAliasSystemOpsSid      = SeAliasSystemOpsSid;
    SepExports.SeAliasPrintOpsSid       = SeAliasPrintOpsSid;
    SepExports.SeAliasBackupOpsSid      = SeAliasBackupOpsSid;



    SepExports.SeCreateTokenPrivilege          = SeCreateTokenPrivilege;
    SepExports.SeAssignPrimaryTokenPrivilege   = SeAssignPrimaryTokenPrivilege;
    SepExports.SeLockMemoryPrivilege           = SeLockMemoryPrivilege;
    SepExports.SeIncreaseQuotaPrivilege        = SeIncreaseQuotaPrivilege;
    SepExports.SeUnsolicitedInputPrivilege     = SeUnsolicitedInputPrivilege;
    SepExports.SeTcbPrivilege                  = SeTcbPrivilege;
    SepExports.SeSecurityPrivilege             = SeSecurityPrivilege;
    SepExports.SeTakeOwnershipPrivilege        = SeTakeOwnershipPrivilege;
    SepExports.SeLoadDriverPrivilege           = SeLoadDriverPrivilege;
    SepExports.SeCreatePagefilePrivilege       = SeCreatePagefilePrivilege;
    SepExports.SeIncreaseBasePriorityPrivilege = SeIncreaseBasePriorityPrivilege;
    SepExports.SeSystemProfilePrivilege        = SeSystemProfilePrivilege;
    SepExports.SeSystemtimePrivilege           = SeSystemtimePrivilege;
    SepExports.SeProfileSingleProcessPrivilege = SeProfileSingleProcessPrivilege;
    SepExports.SeCreatePermanentPrivilege      = SeCreatePermanentPrivilege;
    SepExports.SeBackupPrivilege               = SeBackupPrivilege;
    SepExports.SeRestorePrivilege              = SeRestorePrivilege;
    SepExports.SeShutdownPrivilege             = SeShutdownPrivilege;
    SepExports.SeDebugPrivilege                = SeDebugPrivilege;
    SepExports.SeAuditPrivilege                = SeAuditPrivilege;
    SepExports.SeSystemEnvironmentPrivilege    = SeSystemEnvironmentPrivilege;
    SepExports.SeChangeNotifyPrivilege         = SeChangeNotifyPrivilege;
    SepExports.SeRemoteShutdownPrivilege       = SeRemoteShutdownPrivilege;
    SepExports.SeUndockPrivilege               = SeUndockPrivilege;
    SepExports.SeSyncAgentPrivilege            = SeSyncAgentPrivilege;
    SepExports.SeEnableDelegationPrivilege     = SeEnableDelegationPrivilege;
    SepExports.SeManageVolumePrivilege         = SeManageVolumePrivilege;
    SepExports.SeImpersonatePrivilege          = SeImpersonatePrivilege ;
    SepExports.SeCreateGlobalPrivilege         = SeCreateGlobalPrivilege;


    SeExports = &SepExports;

    //
    // Initialize frequently used privilege sets to speed up access
    // validation.
    //

    SepInitializePrivilegeSets();

    return TRUE;

}


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;
        }
    }
}



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;

}


VOID
SepInitializePrivilegeSets( VOID )
/*++

Routine Description:

    This routine is called once during system initialization to pre-allocate
    and initialize some commonly used privilege sets.

Arguments:

    None

Return Value:

    None.

--*/
{
    PAGED_CODE();

    SinglePrivilegeSetSize = sizeof( PRIVILEGE_SET );
    DoublePrivilegeSetSize = sizeof( PRIVILEGE_SET ) +
                                (ULONG)sizeof( LUID_AND_ATTRIBUTES );

    SepSystemSecurityPrivilegeSet = ExAllocatePoolWithTag( PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, SinglePrivilegeSetSize, 'rPeS' );
    SepTakeOwnershipPrivilegeSet  = ExAllocatePoolWithTag( PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, SinglePrivilegeSetSize, 'rPeS' );
    SepDoublePrivilegeSet         = ExAllocatePoolWithTag( PagedPool | POOL_RAISE_IF_ALLOCATION_FAILURE, DoublePrivilegeSetSize, 'rPeS' );

    SepSystemSecurityPrivilegeSet->PrivilegeCount = 1;
    SepSystemSecurityPrivilegeSet->Control = 0;
    SepSystemSecurityPrivilegeSet->Privilege[0].Luid = SeSecurityPrivilege;
    SepSystemSecurityPrivilegeSet->Privilege[0].Attributes = SE_PRIVILEGE_USED_FOR_ACCESS;

    SepTakeOwnershipPrivilegeSet->PrivilegeCount = 1;
    SepTakeOwnershipPrivilegeSet->Control = 0;
    SepTakeOwnershipPrivilegeSet->Privilege[0].Luid = SeTakeOwnershipPrivilege;
    SepTakeOwnershipPrivilegeSet->Privilege[0].Attributes = SE_PRIVILEGE_USED_FOR_ACCESS;

    SepDoublePrivilegeSet->PrivilegeCount = 2;
    SepDoublePrivilegeSet->Control = 0;

    SepDoublePrivilegeSet->Privilege[0].Luid = SeSecurityPrivilege;
    SepDoublePrivilegeSet->Privilege[0].Attributes = SE_PRIVILEGE_USED_FOR_ACCESS;

    SepDoublePrivilegeSet->Privilege[1].Luid = SeTakeOwnershipPrivilege;
    SepDoublePrivilegeSet->Privilege[1].Attributes = SE_PRIVILEGE_USED_FOR_ACCESS;

}



VOID
SepAssemblePrivileges(
    IN ULONG PrivilegeCount,
    IN BOOLEAN SystemSecurity,
    IN BOOLEAN WriteOwner,
    OUT PPRIVILEGE_SET *Privileges
    )
/*++

Routine Description:

    This routine takes the results of the various privilege checks
    in SeAccessCheck and returns an appropriate privilege set.

Arguments:

    PrivilegeCount - The number of privileges granted.

    SystemSecurity - Provides a boolean indicating whether to put
        SeSecurityPrivilege into the output privilege set.

    WriteOwner - Provides a boolean indicating whether to put
        SeTakeOwnershipPrivilege into the output privilege set.

    Privileges - Supplies a pointer that will return the privilege
        set.  Should be freed with ExFreePool when no longer needed.

Return Value:

    None.

--*/
{
    PPRIVILEGE_SET PrivilegeSet;
    ULONG SizeRequired;

    PAGED_CODE();

    ASSERT( (PrivilegeCount != 0) && (PrivilegeCount <= 2) );

    if ( !ARGUMENT_PRESENT( Privileges ) ) {
        return;
    }

    if ( PrivilegeCount == 1 ) {

        SizeRequired = SinglePrivilegeSetSize;

        if ( SystemSecurity ) {

            PrivilegeSet = SepSystemSecurityPrivilegeSet;

        } else {

            ASSERT( WriteOwner );

            PrivilegeSet = SepTakeOwnershipPrivilegeSet;
        }

    } else {

        SizeRequired = DoublePrivilegeSetSize;
        PrivilegeSet = SepDoublePrivilegeSet;
    }

    *Privileges = ExAllocatePoolWithTag( PagedPool, SizeRequired, 'rPeS' );

    if ( *Privileges != NULL ) {

        RtlCopyMemory (
           *Privileges,
           PrivilegeSet,
           SizeRequired
           );
    }
}





BOOLEAN
SepInitializeWorkList(
    VOID
    )

/*++

Routine Description:

    Initializes the mutex and list head used to queue work from the
    Executive to LSA.  This mechanism operates on top of the normal ExWorkerThread
    mechanism by capturing the first thread to perform LSA work and keeping it
    until all the current work is done.

    The reduces the number of worker threads that are blocked on I/O to LSA.

Arguments:

    None.


Return Value:

    TRUE if successful, FALSE otherwise.

--*/

{
    PAGED_CODE();

    ExInitializeResourceLite(&SepLsaQueueLock);
    InitializeListHead(&SepLsaQueue);
    return( TRUE );
}

#ifdef ALLOC_DATA_PRAGMA
#pragma const_seg()
#endif

