|
|
/*++
Copyright (c) 1996 Microsoft Corporation
Module Name:
security.c
Abstract:
This module provides security for the service.
Author:
Wesley Witt (wesw) 2-Dec-1996
Revision History:
--*/
#include "faxsvc.h"
#pragma hdrstop
//
// do this to avoid dragging in ntrtl.h since we already include some stuff
// from ntrtl.h
//
NTSYSAPI BOOLEAN NTAPI RtlValidRelativeSecurityDescriptor ( IN PSECURITY_DESCRIPTOR SecurityDescriptorInput, IN ULONG SecurityDescriptorLength, IN SECURITY_INFORMATION RequiredInformation );
//
// Number of ACEs currently defined for fax.
//
#define FAX_ACE_COUNT 26
typedef struct _FAX_SECURITY { LPCTSTR RegKey; PSECURITY_DESCRIPTOR SecurityDescriptor; PGENERIC_MAPPING GenericMapping; DWORD AceCount; DWORD AceIdx[FAX_ACE_COUNT]; DWORD StringResource; // Resource Id of friendly name
} FAX_SECURITY, *PFAX_SECURITY;
typedef struct _ACE_DATA { ACCESS_MASK AccessMask; PSID *Sid; UCHAR AceType; UCHAR AceFlags; } ACE_DATA, *PACE_DATA;
typedef struct _ACE { ACE_HEADER Header; ACCESS_MASK Mask; //
// The SID follows in the buffer
//
} ACE, *PACE;
//
// 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;
// Note - Georgeje
//
// The number of security descriptors has been reduced from six
// to one. The tables in security.c have been left in place in
// case we need to add more security descriptos later.
GENERIC_MAPPING FaxGenericMapping[] = { { STANDARD_RIGHTS_READ, STANDARD_RIGHTS_WRITE, STANDARD_RIGHTS_EXECUTE, STANDARD_RIGHTS_REQUIRED } };
//
// Indexes for the ACE Data Array:
//
// ACE 0 - unused
// ACE 1 - ADMIN Full
// ACE 2 - ADMIN Read
// ACE 3 - ADMIN Read Write
// ACE 4 - ADMIN Read Write Delete
// ACE 5 - Creator Full
// ACE 6 - Creator Read Write
// ACE 7 - World Full
// ACE 8 - World Read
// ACE 9 - World Read Write
// ACE 10 - World Read Write Delete
// ACE 11 - PowerUser Full
// ACE 12 - PowerUser Read Write
// ACE 13 - PowerUser Read Write Delete
// ACE 14 - System Ops Full
// ACE 15 - System Ops Read Write
// ACE 16 - System Ops Read Write Delete
// ACE 17 - System Full
// ACE 18 - System Read Write
// ACE 19 - System Read
// ACE 20 - ADMIN Read Write Execute
// ACE 21 - Interactive User Full
// ACE 22 - Interactive User Read
// ACE 23 - Interactive User Read Write
// ACE 24 - Interactive User Read Write Delete
// ACE 25 - Normal Users Read / Write
//
FAX_SECURITY FaxSecurity[] = { { REGVAL_CONFIG_SET, NULL, &FaxGenericMapping[0], 5, {1,5,9,11,17}, IDS_SET_CONFIG } };
#define FaxSecurityCount (sizeof(FaxSecurity)/sizeof(FAX_SECURITY))
//
// Array of ACEs to be applied to fax. They will be
// initialized during program startup based on the data in the
// FaxAceDataTable. The index of each element corresponds to the
// ordinals used in the [ACL] section of perms.inf.
//
PACE AcesForFax[FAX_ACE_COUNT];
//
// Array that contains the size of each ACE in the
// array AceSizesForFax. These sizes are needed
// in order to allocate a buffer of the right size
// when we build an ACL.
//
ULONG AceSizesForFax[FAX_ACE_COUNT];
//
// Table describing the data to put into each ACE for fax.
//
// This table will be read during initialization and used to construct a
// series of ACEs. The index of each ACE in the FaxAces array defined below
// corresponds to fax ordinals used in the ACL section of perms.inf
//
ACE_DATA AceDataTableForFax[FAX_ACE_COUNT] = {
//
// Index 0 is unused
//
{ 0,NULL,0,0 },
//
//
// ACE 1 - ADMIN Full
// (for fax)
//
{ FAX_ALL_ACCESS, &AliasAdminsSid, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE },
//
// ACE 2 - ADMIN Read
// (for fax)
//
{ FAX_READ, &AliasAdminsSid, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE },
//
// ACE 3 - ADMIN Read Write
// (for fax)
//
{ FAX_READ | FAX_WRITE, &AliasAdminsSid, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE },
//
// ACE 4 - ADMIN Read Write Delete
// (for fax)
//
{ FAX_READ | FAX_WRITE | FAX_JOB_MANAGE, &AliasAdminsSid, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE },
//
// ACE 5 - Creator Full
// (for fax)
//
{ FAX_ALL_ACCESS, &CreatorOwnerSid, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE },
//
// ACE 6 - Creator Read Write
// (for fax)
//
{ FAX_READ | FAX_WRITE, &CreatorOwnerSid, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE },
//
// ACE 7 - World Full
// (for fax)
//
{ FAX_ALL_ACCESS, &WorldSid, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE },
//
// ACE 8 - World Read
// (for fax)
//
{ FAX_READ, &WorldSid, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE },
//
// ACE 9 - World Read Write
// (for fax)
//
{ FAX_READ | FAX_WRITE, &WorldSid, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE },
//
// ACE 10 - World Read Write Delete
// (for fax)
//
{ FAX_READ | FAX_WRITE | FAX_JOB_MANAGE, &WorldSid, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE },
//
// ACE 11 - PowerUser Full
// (for fax)
//
{ FAX_ALL_ACCESS, &AliasPowerUsersSid, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE },
//
// ACE 12 - PowerUser Read Write
// (for fax)
//
{ FAX_READ | FAX_WRITE, &AliasPowerUsersSid, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE },
//
// ACE 13 - PowerUser Read Write Delete
// (for fax)
//
{ FAX_READ | FAX_WRITE | FAX_JOB_MANAGE, &AliasPowerUsersSid, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE },
//
// ACE 14 - System Ops Full
// (for fax)
//
{ FAX_ALL_ACCESS, &AliasSystemOpsSid, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE },
//
// ACE 15 - System Ops Read Write
// (for fax)
//
{ FAX_READ | FAX_WRITE, &AliasSystemOpsSid, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE },
//
// ACE 16 - System Ops Read Write Delete
// (for fax)
//
{ FAX_READ | FAX_WRITE | FAX_JOB_MANAGE, &AliasSystemOpsSid, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE },
//
// ACE 17 - System Full
// (for fax)
//
{ FAX_ALL_ACCESS, &LocalSystemSid, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE },
//
// ACE 18 - System Read Write
// (for fax)
//
{ FAX_READ | FAX_WRITE| FAX_JOB_MANAGE, &LocalSystemSid, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE },
//
// ACE 19 - System Read
// (for fax)
//
{ FAX_READ, &LocalSystemSid, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE },
//
// ACE 20 - ADMIN Read Write Execute
// (for fax)
//
{ FAX_READ | FAX_WRITE, &AliasAdminsSid, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE },
//
// ACE 21 - Interactive User Full
// (for fax)
//
{ FAX_ALL_ACCESS, &InteractiveSid, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE },
//
// ACE 22 - Interactive User Read
// (for fax)
//
{ FAX_READ, &InteractiveSid, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE },
//
// ACE 23 - Interactive User Read Write
// (for fax)
//
{ FAX_READ | FAX_WRITE, &InteractiveSid, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE },
//
// ACE 24 - Interactive User Read Write Delete
// (for fax)
//
{ FAX_READ | FAX_WRITE| FAX_JOB_MANAGE, &InteractiveSid, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE },
//
// ACE 25 - Normal Users Read / Write
// (for fax)
//
{ FAX_READ | FAX_WRITE, &AliasUsersSid, ACCESS_ALLOWED_ACE_TYPE, CONTAINER_INHERIT_ACE },
};
static CRITICAL_SECTION CsSecurity; static BOOL CsInit = FALSE;
DWORD InitializeSids( VOID );
VOID TearDownSids( VOID );
DWORD InitializeAces( IN OUT PACE_DATA DataTable, IN OUT PACE* AcesArray, IN OUT PULONG AceSizesArray, IN ULONG ArrayCount );
VOID TearDownAces( IN OUT PACE* AcesArray, IN ULONG ArrayCount );
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() ? GetLastError() : 1 ); }
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] = MemAlloc(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]) { MemFree(AcesArray[u]); } } }
BOOL FaxSvcAccessCheck( DWORD SecurityType, ACCESS_MASK DesiredAccess ) { DWORD rc; DWORD GrantedAccess; BOOL AccessStatus; HANDLE ClientToken = NULL; BYTE PrivilegeSet[512]; DWORD PrivilegeSetSize;
//
// sanity check
//
if (SecurityType >= FaxSecurityCount) { return FALSE; }
//
// Impersonate the client.
//
if ((rc = RpcImpersonateClient(NULL)) != RPC_S_OK) { return FALSE; }
EnterCriticalSection( &CsSecurity ); //
// Open the impersonated token.
//
if (!OpenThreadToken( GetCurrentThread(), TOKEN_QUERY, TRUE, &ClientToken )) { rc = GetLastError(); goto exit; }
//
// purify the access mask
//
MapGenericMask( &DesiredAccess, FaxSecurity[SecurityType].GenericMapping );
//
// Check if the client has the required access.
//
PrivilegeSetSize = sizeof(PrivilegeSet);
if (!AccessCheck( FaxSecurity[SecurityType].SecurityDescriptor, ClientToken, DesiredAccess, FaxSecurity[SecurityType].GenericMapping, (PPRIVILEGE_SET) PrivilegeSet, &PrivilegeSetSize, &GrantedAccess, &AccessStatus ) ) { rc = GetLastError(); goto exit; }
if (!AccessStatus) { rc = GetLastError(); goto exit; }
rc = 0;
exit: RpcRevertToSelf();
if (ClientToken) { CloseHandle( ClientToken ); }
if (rc != 0) { DebugPrint(( TEXT("FaxSvcAccessCheck() failed to authenticate, 0x%08x, 0x%08x\n"), SecurityType, DesiredAccess )); }
LeaveCriticalSection( &CsSecurity );
return rc == 0; }
PVOID MyGetTokenInformation( HANDLE hToken, TOKEN_INFORMATION_CLASS TokenInformationClass ) { PVOID TokenInformation = NULL; DWORD Size = 0;
if (!GetTokenInformation( hToken, TokenInformationClass, NULL, 0, &Size ) && GetLastError() == ERROR_INSUFFICIENT_BUFFER && (TokenInformation = MemAlloc( Size )) && GetTokenInformation( hToken, TokenInformationClass, TokenInformation, Size, &Size )) { return TokenInformation; }
MemFree( TokenInformation ); return NULL; }
DWORD InitializeFaxSecurityDescriptors( VOID ) { #define BUFFER_SIZE 4096
DWORD i,j; DWORD rc = ERROR_SUCCESS; DWORD Ace; DWORD Size; HKEY hKey = NULL; DWORD Disposition; LPBYTE Buffer = NULL; BYTE AclBuffer[512]; SECURITY_DESCRIPTOR SecurityDescriptor; DWORD Type; PACL Acl; HANDLE ServiceToken; PTOKEN_OWNER Owner; PTOKEN_GROUPS Groups; PSECURITY_DESCRIPTOR AbsSD; DWORD AbsSdSize = 0; DWORD DaclSize = 0; DWORD SaclSize = 0; DWORD OwnerSize = 0; DWORD GroupSize = 0; PACL pAbsDacl = NULL; PACL pAbsSacl = NULL; PSID pAbsOwner = NULL; PSID pAbsGroup = NULL;
if (!CsInit) { InitializeCriticalSection( &CsSecurity ); CsInit = TRUE; } //
// Initialize SIDs
//
rc = InitializeSids(); if (rc != NO_ERROR) { goto exit; }
//
// Initialize Fax ACEs
//
rc = InitializeAces( AceDataTableForFax, AcesForFax, AceSizesForFax, FAX_ACE_COUNT ); if (rc != NO_ERROR) { goto exit; }
if (!OpenProcessToken( GetCurrentProcess(), TOKEN_QUERY, &ServiceToken )) { rc = GetLastError(); goto exit; }
Owner = MyGetTokenInformation( ServiceToken, TokenOwner ); if (!Owner) { rc = ERROR_NOT_ENOUGH_MEMORY; goto exit; }
Groups = MyGetTokenInformation( ServiceToken, TokenGroups ); if (!Groups) { rc = ERROR_NOT_ENOUGH_MEMORY; goto exit; }
CloseHandle( ServiceToken );
rc = RegCreateKeyEx( HKEY_LOCAL_MACHINE, REGKEY_FAX_SECURITY, 0, TEXT(""), 0, KEY_ALL_ACCESS, NULL, &hKey, &Disposition ); if (rc != ERROR_SUCCESS) { goto exit; }
Buffer = (LPBYTE) MemAlloc( BUFFER_SIZE ); if (!Buffer) { rc = ERROR_NOT_ENOUGH_MEMORY; goto exit; }
for (i=0; i<FaxSecurityCount; i++) { Size = BUFFER_SIZE; ZeroMemory( Buffer, Size ); rc = RegQueryValueEx( hKey, FaxSecurity[i].RegKey, 0, &Type, Buffer, &Size ); if (rc == ERROR_SUCCESS) {
if (!IsValidSecurityDescriptor( (PSECURITY_DESCRIPTOR) Buffer )) { rc = GetLastError(); DebugPrint(( TEXT("IsValidSecurityDescriptor() failed, ec=%d"), rc )); goto exit; }
//
// the security descriptor needs to be converted to absolute format.
//
AbsSdSize = 0; DaclSize = 0; SaclSize = 0; OwnerSize = 0; GroupSize = 0;
rc = MakeAbsoluteSD( (PSECURITY_DESCRIPTOR) Buffer, NULL, &AbsSdSize, NULL, &DaclSize, NULL, &SaclSize, NULL, &OwnerSize, NULL, &GroupSize ); if (rc || GetLastError() != ERROR_INSUFFICIENT_BUFFER) { rc = GetLastError(); goto exit; }
AbsSD = MemAlloc(AbsSdSize); pAbsDacl = MemAlloc(DaclSize); pAbsSacl = MemAlloc(SaclSize); pAbsOwner = MemAlloc(OwnerSize); pAbsGroup = MemAlloc(GroupSize);
if (NULL == AbsSD || NULL == pAbsDacl || NULL == pAbsSacl || NULL == pAbsOwner || NULL == pAbsGroup) { rc = ERROR_NOT_ENOUGH_MEMORY; goto exit; }
MakeAbsoluteSD( (PSECURITY_DESCRIPTOR) Buffer, AbsSD, &AbsSdSize, pAbsDacl, &DaclSize, pAbsSacl, &SaclSize, pAbsOwner, &OwnerSize, pAbsGroup, &GroupSize );
FaxSecurity[i].SecurityDescriptor = AbsSD;
if (!IsValidSecurityDescriptor( FaxSecurity[i].SecurityDescriptor )) { rc = GetLastError(); DebugPrint(( TEXT("IsValidSecurityDescriptor() failed, ec=%d"), rc )); goto exit; }
continue; }
//
// Initialize a security descriptor and an ACL.
// We use a large static buffer to contain the ACL.
//
ZeroMemory( AclBuffer, sizeof(AclBuffer) );
Acl = (PACL)AclBuffer; if(!InitializeAcl( Acl, sizeof(AclBuffer), ACL_REVISION2) || !InitializeSecurityDescriptor( &SecurityDescriptor, SECURITY_DESCRIPTOR_REVISION )) { rc = GetLastError(); goto exit; }
//
// Build up the DACL from the indices
//
for (Ace=0; Ace<FaxSecurity[i].AceCount; Ace++) {
if (!AddAce( Acl, ACL_REVISION2, MAXDWORD, AcesForFax[FaxSecurity[i].AceIdx[Ace]], AcesForFax[FaxSecurity[i].AceIdx[Ace]]->Header.AceSize )) { rc = GetLastError(); goto exit; } }
//
// Add the ACL to the security descriptor as the DACL
//
if (!SetSecurityDescriptorDacl( &SecurityDescriptor, TRUE, Acl, FALSE )) { rc = GetLastError(); goto exit; }
//
// set the owner
//
if (!SetSecurityDescriptorOwner( &SecurityDescriptor, Owner->Owner, FALSE )) { rc = GetLastError(); goto exit; }
//
// set the groups
//
for (j=0; j<Groups->GroupCount; j++) { if (!SetSecurityDescriptorGroup( &SecurityDescriptor, Groups->Groups[j].Sid, FALSE )) { rc = GetLastError(); goto exit; } }
//
// make the security descriptor self relative
//
Size = BUFFER_SIZE; if (!MakeSelfRelativeSD( &SecurityDescriptor, (PSECURITY_DESCRIPTOR) Buffer, &Size )) { rc = GetLastError(); goto exit; }
//
// store the security descriptor in the registry
//
Size = GetSecurityDescriptorLength( (PSECURITY_DESCRIPTOR) Buffer );
FaxSecurity[i].SecurityDescriptor = (PSECURITY_DESCRIPTOR) MemAlloc( Size ); if (!FaxSecurity[i].SecurityDescriptor) { rc = ERROR_NOT_ENOUGH_MEMORY; goto exit; }
CopyMemory( FaxSecurity[i].SecurityDescriptor, Buffer, Size );
rc = RegSetValueEx( hKey, FaxSecurity[i].RegKey, 0, REG_BINARY, (LPBYTE) FaxSecurity[i].SecurityDescriptor, Size ); if (rc) { goto exit; } }
exit: if (hKey) { RegCloseKey( hKey ); } if (Buffer) { MemFree( Buffer ); } if (Owner) { MemFree( Owner ); } if (Groups) { MemFree( Groups ); } return rc; }
LPWSTR GetClientUserName( VOID ) { WCHAR UserName[128]; DWORD Size;
if (RpcImpersonateClient(NULL) != RPC_S_OK) { return NULL; }
Size = sizeof(UserName) / sizeof(WCHAR); if (!GetUserName( UserName, &Size )) { RpcRevertToSelf(); return NULL; }
RpcRevertToSelf();
return StringDup( UserName ); }
error_status_t FAX_GetSecurityDescriptorCount( IN handle_t FaxHandle, OUT LPDWORD Count )
/*++
Routine Description:
Arguments:
Return Value:
--*/
{ *Count = FaxSecurityCount; return ERROR_SUCCESS; }
error_status_t FAX_SetSecurityDescriptor( IN handle_t FaxHandle, IN const LPBYTE Buffer, IN DWORD BufferSize ) { DWORD rVal = ERROR_SUCCESS; PFAX_SECURITY_DESCRIPTOR FaxSecDesc = (PFAX_SECURITY_DESCRIPTOR) Buffer; HKEY hKey; DWORD Disposition; DWORD SecDescBufferSize;
if (!FaxSvcAccessCheck( SEC_CONFIG_SET, FAX_CONFIG_SET )) { return ERROR_ACCESS_DENIED; }
// Check that the buffer is large enough to hold a FAX_SECURITY_DESCRIPTOR
if (BufferSize < sizeof (FAX_SECURITY_DESCRIPTOR)) { return ERROR_INVALID_PARAMETER; }
if (FaxSecDesc->Id > FaxSecurityCount) { return ERROR_INVALID_CATEGORY; }
// Check that the offset is within the buffer.
if (PtrToUlong(FaxSecDesc->SecurityDescriptor) >= BufferSize) { return ERROR_INVALID_PARAMETER; }
// Calculate the size of the security descriptor buffer for validation
SecDescBufferSize = BufferSize - PtrToUlong(FaxSecDesc->SecurityDescriptor);
FaxSecDesc->SecurityDescriptor = (PSECURITY_DESCRIPTOR) FixupString(Buffer, FaxSecDesc->SecurityDescriptor);
// Validate the passed security descriptor.
if (!RtlValidRelativeSecurityDescriptor(FaxSecDesc->SecurityDescriptor, SecDescBufferSize, 0)) { return ERROR_INVALID_DATA; } rVal = RegCreateKeyEx( HKEY_LOCAL_MACHINE, REGKEY_FAX_SECURITY, 0, TEXT(""), 0, KEY_ALL_ACCESS, NULL, &hKey, &Disposition ); if (rVal != ERROR_SUCCESS) { return rVal; }
rVal = RegSetValueEx( hKey, FaxSecurity[FaxSecDesc->Id].RegKey, 0, REG_BINARY, (LPBYTE) FaxSecDesc->SecurityDescriptor, GetSecurityDescriptorLength( FaxSecDesc->SecurityDescriptor ) );
if (FaxSecurity[FaxSecDesc->Id].SecurityDescriptor) { MemFree( FaxSecurity[FaxSecDesc->Id].SecurityDescriptor ); } rVal = InitializeFaxSecurityDescriptors(); RegCloseKey( hKey );
return rVal; }
error_status_t FAX_GetSecurityDescriptor( IN handle_t FaxHandle, IN DWORD Id, OUT LPBYTE *Buffer, OUT LPDWORD BufferSize )
/*++
Routine Description:
Retrieves the FAX configuration from the FAX server. The SizeOfStruct in the FaxConfig argument MUST be set to a value == sizeof(FAX_CONFIGURATION). If the BufferSize is not big enough, return an error and set BytesNeeded to the required size.
Arguments:
FaxHandle - FAX handle obtained from FaxConnectFaxServer. Buffer - Pointer to a FAX_CONFIGURATION structure. BufferSize - Size of Buffer BytesNeeded - Number of bytes needed
Return Value:
TRUE - Success FALSE - Failure, call GetLastError() for more error information.
--*/
{ error_status_t rVal = ERROR_SUCCESS; PFAX_SECURITY_DESCRIPTOR FaxSecDesc; ULONG_PTR Offset; LPWSTR FriendlyName; DWORD DescLength; HKEY hKey; DWORD Type; DWORD Size; DWORD Disposition;
if (!FaxSvcAccessCheck( SEC_CONFIG_QUERY, FAX_CONFIG_QUERY )) { return ERROR_ACCESS_DENIED; }
if (Id > FaxSecurityCount) { return ERROR_INVALID_CATEGORY; } rVal = RegCreateKeyEx( HKEY_LOCAL_MACHINE, REGKEY_FAX_SECURITY, 0, TEXT(""), 0, KEY_ALL_ACCESS, NULL, &hKey, &Disposition ); if (rVal != ERROR_SUCCESS) { return rVal; }
FriendlyName = GetString( FaxSecurity[Id].StringResource ); //
// count up the number of bytes needed
//
rVal = RegQueryValueEx( hKey, FaxSecurity[Id].RegKey, 0, &Type, NULL, &DescLength ); if (rVal != ERROR_SUCCESS) { goto exit; } Offset = sizeof(FAX_SECURITY_DESCRIPTOR);
*BufferSize = (DWORD)(Offset + DescLength + (wcslen(FriendlyName) + 1) * sizeof(WCHAR));
*Buffer = MemAlloc( *BufferSize ); if (*Buffer == NULL) { rVal = ERROR_NOT_ENOUGH_MEMORY; goto exit; }
FaxSecDesc = (PFAX_SECURITY_DESCRIPTOR) *Buffer;
FaxSecDesc->Id = Id; StoreString( FriendlyName, (PULONG_PTR)&FaxSecDesc->FriendlyName, *Buffer, &Offset ); rVal = RegQueryValueEx( hKey, FaxSecurity[Id].RegKey, 0, &Type, *Buffer + Offset, &Size );
FaxSecDesc->SecurityDescriptor = (LPBYTE) Offset;
exit: RegCloseKey( hKey ); return rVal; }
BOOL PostClientMessage( PFAX_CLIENT_DATA ClientData, PFAX_EVENT FaxEvent )
/*++
Routine Description:
attempts to post a message to client on another windowstation and desktop
Arguments:
ClientData - pointer to a FAX_CLIENT_DATA structure. FaxEvent - pointer to a FAX_EVENT structure. Return Value:
TRUE - Success FALSE - Failure, call GetLastError() for more error information.
--*/
{ HWINSTA hWindowStation, hOldWindowStation=NULL; HDESK hDesktop, hOldDesktop=NULL; BOOL bStatus = FALSE;
//
// need to restore windowstation and desktop
//
if (! (hOldWindowStation = GetProcessWindowStation()) ) { DebugPrint(( TEXT("GetProcessWindowStation failed, ec = %d\n"), GetLastError() )); return FALSE; }
if (! (hOldDesktop = GetThreadDesktop( GetCurrentThreadId() )) ) { DebugPrint(( TEXT("GetThreadDesktop failed, ec = %d\n"), GetLastError() )); return FALSE; }
//
// impersonate the client
//
if (! SetThreadToken( NULL, ClientData->hClientToken ) ) { DebugPrint(( TEXT("SetThreadToken failed, ec = %d\n"), GetLastError() )); return FALSE; }
//
// get a handle to the windowstation, switch to new windowstation
//
if (! (hWindowStation = OpenWindowStation(ClientData->WindowStation, FALSE, //bInherit,
WINSTA_READATTRIBUTES | WINSTA_WRITEATTRIBUTES)) ) { DebugPrint(( TEXT("OpenWindowStation failed, ec = %d\n"), GetLastError() )); goto exit; }
if (! SetProcessWindowStation( hWindowStation ) ) { DebugPrint(( TEXT("SetProcessWindowStation failed, ec = %d\n"), GetLastError() )); goto exit; }
//
// get a handle to the desktop, switch to new desktop
//
if (! (hDesktop = OpenDesktop(ClientData->Desktop, 0, FALSE, DESKTOP_READOBJECTS | DESKTOP_WRITEOBJECTS)) ) { DebugPrint(( TEXT("OpenDesktop failed, ec = %d\n"), GetLastError() )); goto exit; }
if (! SetThreadDesktop( hDesktop ) ) { DebugPrint(( TEXT("SetThreadDesktop failed, ec = %d\n"), GetLastError() )); goto exit; }
//
// post the message to the proper window if it exits
//
if (! IsWindow( ClientData->hWnd )) { DebugPrint(( TEXT("Hwnd %x doesn't exist on current desktop\n"), ClientData->hWnd )); goto exit; }
if (! PostMessage( ClientData->hWnd, ClientData->MessageStart + FaxEvent->EventId, (WPARAM)FaxEvent->DeviceId, (LPARAM)FaxEvent->JobId )) { DebugPrint(( TEXT("PostMessage failed, ec = %d\n"), GetLastError() )); goto exit; }
bStatus = TRUE;
exit:
//
// revert to old thread context (NULL means stop impersonating)
//
SetThreadToken( NULL, NULL ); if (hOldWindowStation) { SetProcessWindowStation( hOldWindowStation ); CloseWindowStation( hWindowStation ); } if (hOldDesktop) { SetThreadDesktop( hOldDesktop ); CloseDesktop( hDesktop ); } return bStatus;
}
BOOL BuildSecureSD( OUT PSECURITY_DESCRIPTOR *SDIn ) /*++
Routine Description:
builds a secure security descriptor to be used in securing a globally named object. Our "secure" SD's DACL consists of the following permissions: Authenticated users get "generic read" access. Administrators get "generic all" access.
Arguments:
SDIn - pointer to the PSECURITY_DESCRIPTOR to be created. Return Value:
TRUE - Success, the SECURITY_DESCRIPTOR was created successfully. The caller is responsible for freeing the SECURITY_DESCRIPTOR
--*/ { SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY; PSID AuthenticatedUsers; PSID BuiltInAdministrators; PSECURITY_DESCRIPTOR Sd = NULL; ACL *Acl; ULONG AclSize; BOOL RetVal = TRUE; *SDIn = NULL;
//
// Allocate and initialize the required SIDs
//
if (!AllocateAndInitializeSid( &NtAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0,0,0,0,0,0, &BuiltInAdministrators)) { return(FALSE); }
if (!AllocateAndInitializeSid( &NtAuthority, 1, SECURITY_AUTHENTICATED_USER_RID, 0,0,0,0,0,0,0, &AuthenticatedUsers)) { RetVal = FALSE; goto e0; }
//
// "- sizeof (ULONG)" represents the SidStart field of the
// ACCESS_ALLOWED_ACE. Since we're adding the entire length of the
// SID, this field is counted twice.
//
AclSize = sizeof (ACL) + (2 * (sizeof (ACCESS_ALLOWED_ACE) - sizeof (ULONG))) + GetLengthSid(AuthenticatedUsers) + GetLengthSid(BuiltInAdministrators);
Sd = MemAlloc(SECURITY_DESCRIPTOR_MIN_LENGTH + AclSize);
if (!Sd) {
RetVal = FALSE; goto e1;
}
Acl = (ACL *)((BYTE *)Sd + SECURITY_DESCRIPTOR_MIN_LENGTH);
if (!InitializeAcl(Acl, AclSize, ACL_REVISION)) { RetVal = FALSE; goto e2;
} else if (!AddAccessAllowedAce(Acl, ACL_REVISION, SYNCHRONIZE | GENERIC_READ, AuthenticatedUsers)) {
// Failed to build the ACE granting "Authenticated users"
// (SYNCHRONIZE | GENERIC_READ) access.
RetVal = FALSE; goto e2;
} else if (!AddAccessAllowedAce(Acl, ACL_REVISION, GENERIC_ALL, BuiltInAdministrators)) {
// Failed to build the ACE granting "Built-in Administrators"
// GENERIC_ALL access.
RetVal = FALSE; goto e2;
} else if (!InitializeSecurityDescriptor(Sd, SECURITY_DESCRIPTOR_REVISION)) { RetVal = FALSE; goto e2;
} else if (!SetSecurityDescriptorDacl(Sd, TRUE, Acl, FALSE)) {
// error
RetVal = FALSE; goto e2; }
if (!IsValidSecurityDescriptor(Sd)) { DebugPrint(( TEXT("invalid security descriptor, ec = %d\n"), GetLastError() )); RetVal = FALSE; goto e2; }
//
// success
//
*SDIn = Sd; goto e1;
e2: MemFree(Sd); e1: FreeSid(AuthenticatedUsers); e0: FreeSid(BuiltInAdministrators);
return(RetVal); }
|