964 lines
20 KiB
C
964 lines
20 KiB
C
/*++
|
|
|
|
Copyright (c) 1996 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
applyacl.c
|
|
|
|
Abstract:
|
|
|
|
Routines to apply default ACLs to system files and directories
|
|
during setup.
|
|
|
|
Author:
|
|
|
|
Ted Miller (tedm) 16-Feb-1996
|
|
|
|
Revision History:
|
|
|
|
--*/
|
|
|
|
#include "setupp.h"
|
|
#pragma hdrstop
|
|
|
|
#define MAXULONG 0xffffffff
|
|
|
|
//
|
|
// Universal well known SIDs
|
|
//
|
|
PSID NullSid;
|
|
PSID WorldSid;
|
|
PSID LocalSid;
|
|
PSID CreatorOwnerSid;
|
|
PSID CreatorGroupSid;
|
|
|
|
//
|
|
// SIDs defined by NT
|
|
//
|
|
PSID DialupSid;
|
|
PSID NetworkSid;
|
|
PSID BatchSid;
|
|
PSID InteractiveSid;
|
|
PSID ServiceSid;
|
|
PSID LocalSystemSid;
|
|
PSID AliasAdminsSid;
|
|
PSID AliasUsersSid;
|
|
PSID AliasGuestsSid;
|
|
PSID AliasPowerUsersSid;
|
|
PSID AliasAccountOpsSid;
|
|
PSID AliasSystemOpsSid;
|
|
PSID AliasPrintOpsSid;
|
|
PSID AliasBackupOpsSid;
|
|
PSID AliasReplicatorSid;
|
|
|
|
|
|
typedef struct _ACE_DATA {
|
|
ACCESS_MASK AccessMask;
|
|
PSID *Sid;
|
|
UCHAR AceType;
|
|
UCHAR AceFlags;
|
|
} ACE_DATA, *PACE_DATA;
|
|
|
|
//
|
|
// This structure is valid for access allowed, access denied, audit,
|
|
// and alarm ACEs.
|
|
//
|
|
typedef struct _ACE {
|
|
ACE_HEADER Header;
|
|
ACCESS_MASK Mask;
|
|
//
|
|
// The SID follows in the buffer
|
|
//
|
|
} ACE, *PACE;
|
|
|
|
|
|
//
|
|
// Number of ACEs currently defined for files and directories.
|
|
//
|
|
#define DIRS_AND_FILES_ACE_COUNT 19
|
|
|
|
//
|
|
// Table describing the data to put into each ACE.
|
|
//
|
|
// This table will be read during initialization and used to construct a
|
|
// series of ACEs. The index of each ACE in the Aces array defined below
|
|
// corresponds to the ordinals used in the ACL section of perms.inf
|
|
//
|
|
ACE_DATA AceDataTableForDirsAndFiles[DIRS_AND_FILES_ACE_COUNT] = {
|
|
|
|
//
|
|
// Index 0 is unused
|
|
//
|
|
{ 0,NULL,0,0 },
|
|
|
|
//
|
|
// ACE 1
|
|
// (for files and directories)
|
|
//
|
|
{
|
|
GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | DELETE,
|
|
&AliasAccountOpsSid,
|
|
ACCESS_ALLOWED_ACE_TYPE,
|
|
CONTAINER_INHERIT_ACE
|
|
},
|
|
|
|
//
|
|
// ACE 2
|
|
// (for files and directories)
|
|
//
|
|
{
|
|
GENERIC_ALL,
|
|
&AliasAdminsSid,
|
|
ACCESS_ALLOWED_ACE_TYPE,
|
|
CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE
|
|
},
|
|
|
|
//
|
|
// ACE 3
|
|
// (for files and directories)
|
|
//
|
|
{
|
|
GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | DELETE,
|
|
&AliasAdminsSid,
|
|
ACCESS_ALLOWED_ACE_TYPE,
|
|
CONTAINER_INHERIT_ACE
|
|
},
|
|
|
|
//
|
|
// ACE 4
|
|
// (for files and directories)
|
|
//
|
|
{
|
|
GENERIC_ALL,
|
|
&CreatorOwnerSid,
|
|
ACCESS_ALLOWED_ACE_TYPE,
|
|
CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE
|
|
},
|
|
|
|
//
|
|
// ACE 5
|
|
// (for files and directories)
|
|
//
|
|
{
|
|
GENERIC_ALL,
|
|
&NetworkSid,
|
|
ACCESS_DENIED_ACE_TYPE,
|
|
CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE
|
|
},
|
|
|
|
//
|
|
// ACE 6
|
|
// (for files and directories)
|
|
//
|
|
{
|
|
GENERIC_ALL,
|
|
&AliasPrintOpsSid,
|
|
ACCESS_ALLOWED_ACE_TYPE,
|
|
CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE
|
|
},
|
|
|
|
//
|
|
// ACE 7
|
|
// (for files and directories)
|
|
//
|
|
{
|
|
GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | DELETE,
|
|
&AliasReplicatorSid,
|
|
ACCESS_ALLOWED_ACE_TYPE,
|
|
CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE
|
|
},
|
|
|
|
//
|
|
// ACE 8
|
|
// (for files and directories)
|
|
//
|
|
{
|
|
GENERIC_READ | GENERIC_EXECUTE,
|
|
&AliasReplicatorSid,
|
|
ACCESS_ALLOWED_ACE_TYPE,
|
|
CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE
|
|
},
|
|
|
|
//
|
|
// ACE 9
|
|
// (for files and directories)
|
|
//
|
|
{
|
|
GENERIC_ALL,
|
|
&AliasSystemOpsSid,
|
|
ACCESS_ALLOWED_ACE_TYPE,
|
|
CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE
|
|
},
|
|
|
|
//
|
|
// ACE 10
|
|
// (for files and directories)
|
|
//
|
|
{
|
|
GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | DELETE,
|
|
&AliasSystemOpsSid,
|
|
ACCESS_ALLOWED_ACE_TYPE,
|
|
OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE
|
|
},
|
|
|
|
//
|
|
// ACE 11
|
|
// (for files and directories)
|
|
//
|
|
{
|
|
GENERIC_ALL,
|
|
&WorldSid,
|
|
ACCESS_ALLOWED_ACE_TYPE,
|
|
CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE
|
|
},
|
|
|
|
//
|
|
// ACE 12
|
|
// (for files and directories)
|
|
//
|
|
{
|
|
GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE,
|
|
&WorldSid,
|
|
ACCESS_ALLOWED_ACE_TYPE,
|
|
CONTAINER_INHERIT_ACE
|
|
},
|
|
|
|
//
|
|
// ACE 13
|
|
// (for files and directories)
|
|
//
|
|
{
|
|
GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | DELETE,
|
|
&WorldSid,
|
|
ACCESS_ALLOWED_ACE_TYPE,
|
|
OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE
|
|
},
|
|
|
|
//
|
|
// ACE 14
|
|
// (for files and directories)
|
|
//
|
|
{
|
|
GENERIC_READ | GENERIC_EXECUTE,
|
|
&WorldSid,
|
|
ACCESS_ALLOWED_ACE_TYPE,
|
|
CONTAINER_INHERIT_ACE
|
|
},
|
|
|
|
//
|
|
// ACE 15
|
|
// (for files and directories)
|
|
//
|
|
{
|
|
GENERIC_READ | GENERIC_EXECUTE,
|
|
&WorldSid,
|
|
ACCESS_ALLOWED_ACE_TYPE,
|
|
OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE
|
|
},
|
|
|
|
//
|
|
// ACE 16
|
|
// (for files and directories)
|
|
//
|
|
{
|
|
GENERIC_READ | GENERIC_EXECUTE | GENERIC_WRITE,
|
|
&WorldSid,
|
|
ACCESS_ALLOWED_ACE_TYPE,
|
|
OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE
|
|
},
|
|
|
|
//
|
|
// ACE 17
|
|
// (for files and directories)
|
|
//
|
|
{
|
|
GENERIC_ALL,
|
|
&LocalSystemSid,
|
|
ACCESS_ALLOWED_ACE_TYPE,
|
|
CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE
|
|
},
|
|
|
|
//
|
|
// ACE 18
|
|
// (for files and directories)
|
|
//
|
|
{
|
|
GENERIC_READ | GENERIC_WRITE | GENERIC_EXECUTE | DELETE,
|
|
&AliasPowerUsersSid,
|
|
ACCESS_ALLOWED_ACE_TYPE,
|
|
CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE
|
|
}
|
|
};
|
|
|
|
|
|
//
|
|
// Array of ACEs to be applied to the objects (files and directories).
|
|
// They will be initialized during program startup based on the data in the
|
|
// AceDataTable. The index of each element corresponds to the
|
|
// ordinals used in the [ACL] section of perms.inf.
|
|
//
|
|
PACE AcesForDirsAndFiles[DIRS_AND_FILES_ACE_COUNT];
|
|
|
|
//
|
|
// Array that contains the size of each ACE in the
|
|
// array AcesForDirsAndFiles. These sizes are needed
|
|
// in order to allocate a buffer of the right size
|
|
// when we build an ACL.
|
|
//
|
|
ULONG AceSizesForDirsAndFiles[DIRS_AND_FILES_ACE_COUNT];
|
|
|
|
|
|
|
|
VOID
|
|
TearDownAces(
|
|
IN OUT PACE* AcesArray,
|
|
IN ULONG ArrayCount
|
|
);
|
|
|
|
|
|
VOID
|
|
TearDownSids(
|
|
VOID
|
|
);
|
|
|
|
|
|
DWORD
|
|
InitializeSids(
|
|
VOID
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function initializes the global variables used by and exposed
|
|
by security.
|
|
|
|
Arguments:
|
|
|
|
None.
|
|
|
|
Return Value:
|
|
|
|
Win32 error indicating outcome.
|
|
|
|
--*/
|
|
|
|
{
|
|
SID_IDENTIFIER_AUTHORITY NullSidAuthority = SECURITY_NULL_SID_AUTHORITY;
|
|
SID_IDENTIFIER_AUTHORITY WorldSidAuthority = SECURITY_WORLD_SID_AUTHORITY;
|
|
SID_IDENTIFIER_AUTHORITY LocalSidAuthority = SECURITY_LOCAL_SID_AUTHORITY;
|
|
SID_IDENTIFIER_AUTHORITY CreatorSidAuthority = SECURITY_CREATOR_SID_AUTHORITY;
|
|
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
|
|
|
|
BOOL b = TRUE;
|
|
|
|
//
|
|
// Ensure the SIDs are in a well-known state
|
|
//
|
|
NullSid = NULL;
|
|
WorldSid = NULL;
|
|
LocalSid = NULL;
|
|
CreatorOwnerSid = NULL;
|
|
CreatorGroupSid = NULL;
|
|
DialupSid = NULL;
|
|
NetworkSid = NULL;
|
|
BatchSid = NULL;
|
|
InteractiveSid = NULL;
|
|
ServiceSid = NULL;
|
|
LocalSystemSid = NULL;
|
|
AliasAdminsSid = NULL;
|
|
AliasUsersSid = NULL;
|
|
AliasGuestsSid = NULL;
|
|
AliasPowerUsersSid = NULL;
|
|
AliasAccountOpsSid = NULL;
|
|
AliasSystemOpsSid = NULL;
|
|
AliasPrintOpsSid = NULL;
|
|
AliasBackupOpsSid = NULL;
|
|
AliasReplicatorSid = NULL;
|
|
|
|
//
|
|
// Allocate and initialize the universal SIDs
|
|
//
|
|
b = b && AllocateAndInitializeSid(
|
|
&NullSidAuthority,
|
|
1,
|
|
SECURITY_NULL_RID,
|
|
0,0,0,0,0,0,0,
|
|
&NullSid
|
|
);
|
|
|
|
b = b && AllocateAndInitializeSid(
|
|
&WorldSidAuthority,
|
|
1,
|
|
SECURITY_WORLD_RID,
|
|
0,0,0,0,0,0,0,
|
|
&WorldSid
|
|
);
|
|
|
|
b = b && AllocateAndInitializeSid(
|
|
&LocalSidAuthority,
|
|
1,
|
|
SECURITY_LOCAL_RID,
|
|
0,0,0,0,0,0,0,
|
|
&LocalSid
|
|
);
|
|
|
|
b = b && AllocateAndInitializeSid(
|
|
&CreatorSidAuthority,
|
|
1,
|
|
SECURITY_CREATOR_OWNER_RID,
|
|
0,0,0,0,0,0,0,
|
|
&CreatorOwnerSid
|
|
);
|
|
|
|
b = b && AllocateAndInitializeSid(
|
|
&CreatorSidAuthority,
|
|
1,
|
|
SECURITY_CREATOR_GROUP_RID,
|
|
0,0,0,0,0,0,0,
|
|
&CreatorGroupSid
|
|
);
|
|
|
|
//
|
|
// Allocate and initialize the NT defined SIDs
|
|
//
|
|
b = b && AllocateAndInitializeSid(
|
|
&NtAuthority,
|
|
1,
|
|
SECURITY_DIALUP_RID,
|
|
0,0,0,0,0,0,0,
|
|
&DialupSid
|
|
);
|
|
|
|
b = b && AllocateAndInitializeSid(
|
|
&NtAuthority,
|
|
1,
|
|
SECURITY_NETWORK_RID,
|
|
0,0,0,0,0,0,0,
|
|
&NetworkSid
|
|
);
|
|
|
|
b = b && AllocateAndInitializeSid(
|
|
&NtAuthority,
|
|
1,
|
|
SECURITY_BATCH_RID,
|
|
0,0,0,0,0,0,0,
|
|
&BatchSid
|
|
);
|
|
|
|
b = b && AllocateAndInitializeSid(
|
|
&NtAuthority,
|
|
1,
|
|
SECURITY_INTERACTIVE_RID,
|
|
0,0,0,0,0,0,0,
|
|
&InteractiveSid
|
|
);
|
|
|
|
b = b && AllocateAndInitializeSid(
|
|
&NtAuthority,
|
|
1,
|
|
SECURITY_SERVICE_RID,
|
|
0,0,0,0,0,0,0,
|
|
&ServiceSid
|
|
);
|
|
|
|
b = b && AllocateAndInitializeSid(
|
|
&NtAuthority,
|
|
1,
|
|
SECURITY_LOCAL_SYSTEM_RID,
|
|
0,0,0,0,0,0,0,
|
|
&LocalSystemSid
|
|
);
|
|
|
|
b = b && AllocateAndInitializeSid(
|
|
&NtAuthority,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ADMINS,
|
|
0,0,0,0,0,0,
|
|
&AliasAdminsSid
|
|
);
|
|
|
|
b = b && AllocateAndInitializeSid(
|
|
&NtAuthority,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_USERS,
|
|
0,0,0,0,0,0,
|
|
&AliasUsersSid
|
|
);
|
|
|
|
b = b && AllocateAndInitializeSid(
|
|
&NtAuthority,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_GUESTS,
|
|
0,0,0,0,0,0,
|
|
&AliasGuestsSid
|
|
);
|
|
|
|
b = b && AllocateAndInitializeSid(
|
|
&NtAuthority,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_POWER_USERS,
|
|
0,0,0,0,0,0,
|
|
&AliasPowerUsersSid
|
|
);
|
|
|
|
b = b && AllocateAndInitializeSid(
|
|
&NtAuthority,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_ACCOUNT_OPS,
|
|
0,0,0,0,0,0,
|
|
&AliasAccountOpsSid
|
|
);
|
|
|
|
b = b && AllocateAndInitializeSid(
|
|
&NtAuthority,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_SYSTEM_OPS,
|
|
0,0,0,0,0,0,
|
|
&AliasSystemOpsSid
|
|
);
|
|
|
|
b = b && AllocateAndInitializeSid(
|
|
&NtAuthority,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_PRINT_OPS,
|
|
0,0,0,0,0,0,
|
|
&AliasPrintOpsSid
|
|
);
|
|
|
|
b = b && AllocateAndInitializeSid(
|
|
&NtAuthority,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_BACKUP_OPS,
|
|
0,0,0,0,0,0,
|
|
&AliasBackupOpsSid
|
|
);
|
|
|
|
b = b && AllocateAndInitializeSid(
|
|
&NtAuthority,
|
|
2,
|
|
SECURITY_BUILTIN_DOMAIN_RID,
|
|
DOMAIN_ALIAS_RID_REPLICATOR,
|
|
0,0,0,0,0,0,
|
|
&AliasReplicatorSid
|
|
);
|
|
|
|
if(!b) {
|
|
TearDownSids();
|
|
}
|
|
|
|
return(b ? NO_ERROR : GetLastError());
|
|
}
|
|
|
|
|
|
VOID
|
|
TearDownSids(
|
|
VOID
|
|
)
|
|
{
|
|
if(NullSid) {
|
|
FreeSid(NullSid);
|
|
}
|
|
if(WorldSid) {
|
|
FreeSid(WorldSid);
|
|
}
|
|
if(LocalSid) {
|
|
FreeSid(LocalSid);
|
|
}
|
|
if(CreatorOwnerSid) {
|
|
FreeSid(CreatorOwnerSid);
|
|
}
|
|
if(CreatorGroupSid) {
|
|
FreeSid(CreatorGroupSid);
|
|
}
|
|
if(DialupSid) {
|
|
FreeSid(DialupSid);
|
|
}
|
|
if(NetworkSid) {
|
|
FreeSid(NetworkSid);
|
|
}
|
|
if(BatchSid) {
|
|
FreeSid(BatchSid);
|
|
}
|
|
if(InteractiveSid) {
|
|
FreeSid(InteractiveSid);
|
|
}
|
|
if(ServiceSid) {
|
|
FreeSid(ServiceSid);
|
|
}
|
|
if(LocalSystemSid) {
|
|
FreeSid(LocalSystemSid);
|
|
}
|
|
if(AliasAdminsSid) {
|
|
FreeSid(AliasAdminsSid);
|
|
}
|
|
if(AliasUsersSid) {
|
|
FreeSid(AliasUsersSid);
|
|
}
|
|
if(AliasGuestsSid) {
|
|
FreeSid(AliasGuestsSid);
|
|
}
|
|
if(AliasPowerUsersSid) {
|
|
FreeSid(AliasPowerUsersSid);
|
|
}
|
|
if(AliasAccountOpsSid) {
|
|
FreeSid(AliasAccountOpsSid);
|
|
}
|
|
if(AliasSystemOpsSid) {
|
|
FreeSid(AliasSystemOpsSid);
|
|
}
|
|
if(AliasPrintOpsSid) {
|
|
FreeSid(AliasPrintOpsSid);
|
|
}
|
|
if(AliasBackupOpsSid) {
|
|
FreeSid(AliasBackupOpsSid);
|
|
}
|
|
if(AliasReplicatorSid) {
|
|
FreeSid(AliasReplicatorSid);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
InitializeAces(
|
|
IN OUT PACE_DATA DataTable,
|
|
IN OUT PACE* AcesArray,
|
|
IN OUT PULONG AceSizesArray,
|
|
IN ULONG ArrayCount
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initializes the array of ACEs as described in the DataTable
|
|
|
|
Arguments:
|
|
|
|
DataTable - Pointer to the array that contains the data
|
|
describing each ACE.
|
|
AcesArray - Array that will contain the ACEs.
|
|
|
|
AceSizesArray - Array that contains the sizes for each ACE.
|
|
|
|
ArrayCount - Number of elements in each array.
|
|
|
|
Return Value:
|
|
|
|
Win32 error code indicating outcome.
|
|
|
|
--*/
|
|
|
|
{
|
|
unsigned u;
|
|
DWORD Length;
|
|
DWORD rc;
|
|
BOOL b;
|
|
DWORD SidLength;
|
|
|
|
//
|
|
// Initialize to a known state.
|
|
//
|
|
ZeroMemory(AcesArray,ArrayCount*sizeof(PACE));
|
|
|
|
//
|
|
// Create ACEs for each item in the data table.
|
|
// This involves merging the ace data with the SID data, which
|
|
// are initialized in an earlier step.
|
|
//
|
|
for(u=1; u<ArrayCount; u++) {
|
|
|
|
SidLength = GetLengthSid(*(DataTable[u].Sid));
|
|
Length = SidLength + sizeof(ACE) + sizeof(ACCESS_MASK)- sizeof(ULONG);
|
|
AceSizesArray[u] = Length;
|
|
|
|
AcesArray[u] = malloc(Length);
|
|
if(!AcesArray[u]) {
|
|
TearDownAces(AcesArray, ArrayCount);
|
|
return(ERROR_NOT_ENOUGH_MEMORY);
|
|
}
|
|
|
|
AcesArray[u]->Header.AceType = DataTable[u].AceType;
|
|
AcesArray[u]->Header.AceFlags = DataTable[u].AceFlags;
|
|
AcesArray[u]->Header.AceSize = (WORD)Length;
|
|
|
|
AcesArray[u]->Mask = DataTable[u].AccessMask;
|
|
|
|
b = CopySid(
|
|
SidLength, // Length - sizeof(ACE) + sizeof(ULONG),
|
|
(PUCHAR)AcesArray[u] + sizeof(ACE),
|
|
*(DataTable[u].Sid)
|
|
);
|
|
|
|
if(!b) {
|
|
rc = GetLastError();
|
|
TearDownAces(AcesArray, ArrayCount);
|
|
return(rc);
|
|
}
|
|
}
|
|
|
|
return(NO_ERROR);
|
|
}
|
|
|
|
|
|
|
|
VOID
|
|
TearDownAces(
|
|
IN OUT PACE* AcesArray,
|
|
IN ULONG ArrayCount
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Destroys the array of ACEs as described in the DataTable
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
|
|
{
|
|
unsigned u;
|
|
|
|
|
|
for(u=1; u<ArrayCount; u++) {
|
|
|
|
if(AcesArray[u]) {
|
|
free(AcesArray[u]);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
ULONG
|
|
ApplyAclToDirOrFile(
|
|
IN PCWSTR FullPath,
|
|
IN PULONG AcesToApply,
|
|
IN ULONG ArraySize
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Applies an ACL to a specified file or directory.
|
|
|
|
Arguments:
|
|
|
|
FullPath - supplies full win32 path to the file or directory
|
|
to receive the ACL
|
|
|
|
AcesIndexArray - Array that contains the index to the ACEs to be used in the ACL.
|
|
|
|
ArraySize - Number of elements in the array.
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD AceCount;
|
|
DWORD Ace;
|
|
INT AceIndex;
|
|
DWORD rc;
|
|
SECURITY_DESCRIPTOR SecurityDescriptor;
|
|
PACL Acl;
|
|
UCHAR AclBuffer[2048];
|
|
BOOL b;
|
|
PCWSTR AclSection;
|
|
ACL_SIZE_INFORMATION AclSizeInfo;
|
|
|
|
//
|
|
// Initialize a security descriptor and an ACL.
|
|
// We use a large static buffer to contain the ACL.
|
|
//
|
|
Acl = (PACL)AclBuffer;
|
|
if(!InitializeAcl(Acl,sizeof(AclBuffer),ACL_REVISION2)
|
|
|| !InitializeSecurityDescriptor(&SecurityDescriptor,SECURITY_DESCRIPTOR_REVISION)) {
|
|
return(GetLastError());
|
|
}
|
|
|
|
|
|
//
|
|
// Build up the DACL from the indices on the list we just looked up
|
|
// in the ACL section.
|
|
//
|
|
rc = NO_ERROR;
|
|
AceCount = ArraySize;
|
|
for(Ace=0; Ace < AceCount; Ace++) {
|
|
AceIndex = AcesToApply[ Ace ];
|
|
if((AceIndex == 0) || (AceIndex >= DIRS_AND_FILES_ACE_COUNT)) {
|
|
return(ERROR_INVALID_DATA);
|
|
}
|
|
|
|
b = AddAce(
|
|
Acl,
|
|
ACL_REVISION2,
|
|
MAXULONG,
|
|
AcesForDirsAndFiles[AceIndex],
|
|
AcesForDirsAndFiles[AceIndex]->Header.AceSize
|
|
);
|
|
|
|
//
|
|
// Track first error we encounter.
|
|
//
|
|
if(!b) {
|
|
rc = GetLastError();
|
|
}
|
|
}
|
|
|
|
if(rc != NO_ERROR) {
|
|
return(rc);
|
|
}
|
|
|
|
//
|
|
// Truncate the ACL, since only a fraction of the size we originally
|
|
// allocated for it is likely to be in use.
|
|
//
|
|
if(!GetAclInformation(Acl,&AclSizeInfo,sizeof(ACL_SIZE_INFORMATION),AclSizeInformation)) {
|
|
return(GetLastError());
|
|
}
|
|
Acl->AclSize = (WORD)AclSizeInfo.AclBytesInUse;
|
|
|
|
//
|
|
// Add the ACL to the security descriptor as the DACL
|
|
//
|
|
if(!SetSecurityDescriptorDacl(&SecurityDescriptor,TRUE,Acl,FALSE)) {
|
|
return(GetLastError());
|
|
}
|
|
|
|
//
|
|
// Finally, apply the security descriptor.
|
|
//
|
|
rc = SetFileSecurity(FullPath,DACL_SECURITY_INFORMATION,&SecurityDescriptor)
|
|
? NO_ERROR
|
|
: GetLastError();
|
|
|
|
return(rc);
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
ApplySecurityToRepairInfo(
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
--*/
|
|
|
|
{
|
|
DWORD d, TempError;
|
|
WCHAR Directory[MAX_PATH];
|
|
BOOL SetAclsNt;
|
|
DWORD FsFlags;
|
|
DWORD Result;
|
|
BOOL b;
|
|
ULONG Count;
|
|
PWSTR Files[] = {
|
|
L"sam",
|
|
L"security",
|
|
L"software",
|
|
L"system",
|
|
L"default",
|
|
L"ntuser.dat",
|
|
L"sam._",
|
|
L"security._",
|
|
L"software._",
|
|
L"system._",
|
|
L"default._",
|
|
L"ntuser.da_"
|
|
};
|
|
|
|
//
|
|
// Get the file system of the system drive.
|
|
// On x86 get the file system of the system partition.
|
|
//
|
|
d = NO_ERROR;
|
|
SetAclsNt = FALSE;
|
|
Result = GetWindowsDirectory(Directory,MAX_PATH);
|
|
if(Result == 0) {
|
|
MYASSERT(FALSE);
|
|
return( GetLastError());
|
|
}
|
|
Directory[3] = 0;
|
|
|
|
|
|
//
|
|
// ApplySecurity to directories and files, if needed
|
|
//
|
|
|
|
b = GetVolumeInformation(Directory,NULL,0,NULL,NULL,&FsFlags,NULL,0);
|
|
if(b && (FsFlags & FS_PERSISTENT_ACLS)) {
|
|
SetAclsNt = TRUE;
|
|
}
|
|
|
|
if(SetAclsNt) {
|
|
//
|
|
// Initialize SIDs
|
|
//
|
|
d = InitializeSids();
|
|
if(d != NO_ERROR) {
|
|
return(d);
|
|
}
|
|
//
|
|
// Initialize ACEs
|
|
//
|
|
d = InitializeAces(AceDataTableForDirsAndFiles, AcesForDirsAndFiles, AceSizesForDirsAndFiles, DIRS_AND_FILES_ACE_COUNT);
|
|
if(d != NO_ERROR) {
|
|
TearDownSids();
|
|
return(d);
|
|
}
|
|
//
|
|
// Go do the real work.
|
|
//
|
|
for( Count = 0; Count < sizeof( Files ) / sizeof( PWSTR ); Count++ ) {
|
|
ULONG AcesToApply[] = { 2,
|
|
17
|
|
};
|
|
|
|
GetWindowsDirectory(Directory,MAX_PATH);
|
|
wcscat( Directory, L"\\repair\\" );
|
|
wcscat( Directory, Files[ Count ] );
|
|
TempError = ApplyAclToDirOrFile( Directory, AcesToApply, sizeof( AcesToApply) / sizeof( ULONG ) );
|
|
if( TempError != NO_ERROR ) {
|
|
if( d == NO_ERROR ) {
|
|
d = TempError;
|
|
}
|
|
}
|
|
}
|
|
|
|
//
|
|
// Clean up.
|
|
//
|
|
TearDownAces(AcesForDirsAndFiles, DIRS_AND_FILES_ACE_COUNT);
|
|
TearDownSids();
|
|
}
|
|
return(d);
|
|
}
|
|
|