Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1723 lines
41 KiB

/*++
Copyright (c) 1997 Microsoft Corporation
Module Name:
security.cpp
Abstract:
Initializes security descriptor object for STI services
access validation
Author:
Vlad Sadovsky (vlads) 09-28-97
Environment:
User Mode - Win32
Revision History:
28-Sep-1997 VladS created
--*/
//
// Include Headers
//
#include "precomp.h"
#include "stiexe.h"
#include <stisvc.h>
#ifdef DEBUG
#define STATIC
#else
#define STATIC static
#endif
#ifdef WINNT
//
// Globals
//
//
// NT well-known SIDs
//
PSID psidNull = NULL; // No members SID
PSID psidWorld = NULL; // All users SID
PSID psidLocal = NULL; // NT local users SID
PSID psidLocalSystem= NULL; // NT system processes SID
PSID psidNetwork = NULL; // NT remote users SID
PSID psidAdmins = NULL;
PSID psidServerOps = NULL;
PSID psidPowerUsers = NULL;
PSID psidGuestUser = NULL;
PSID psidProcessUser= NULL;
PSID psidBuiltinDomain = NULL; // Domain Id of the Builtin Domain
//
// Well Known Aliases.
//
// These are aliases that are relative to the built-in domain.
//
PSID psidLocalAdmin = NULL; // NT local admins
PSID psidAliasAdmins = NULL;
PSID psidAliasUsers = NULL;
PSID psidAliasGuests = NULL;
PSID psidAliasPowerUsers = NULL;
PSID psidAliasAccountOps = NULL;
PSID psidAliasSystemOps = NULL;
PSID psidAliasPrintOps = NULL;
PSID psidAliasBackupOps = NULL;
//
// List of well-known SID data structures we use to initialize globals
//
struct _SID_DATA {
PSID *Sid;
SID_IDENTIFIER_AUTHORITY IdentifierAuthority;
ULONG SubAuthority;
} SidData[] = {
{&psidNull, SECURITY_NULL_SID_AUTHORITY, SECURITY_NULL_RID},
{&psidWorld, SECURITY_WORLD_SID_AUTHORITY, SECURITY_WORLD_RID},
{&psidLocal, SECURITY_LOCAL_SID_AUTHORITY, SECURITY_LOCAL_RID},
{&psidNetwork, SECURITY_NT_AUTHORITY, SECURITY_NETWORK_RID},
{&psidLocalSystem, SECURITY_NT_AUTHORITY, SECURITY_LOCAL_SYSTEM_RID},
{&psidBuiltinDomain, SECURITY_NT_AUTHORITY, SECURITY_BUILTIN_DOMAIN_RID}
};
#define NUM_SIDS (sizeof(SidData) / sizeof(SidData[0]))
STATIC
struct _BUILTIN_DOMAIN_SID_DATA {
PSID *Sid;
ULONG RelativeId;
} psidBuiltinDomainData[] = {
{ &psidLocalAdmin, DOMAIN_ALIAS_RID_ADMINS},
{ &psidAliasAdmins, DOMAIN_ALIAS_RID_ADMINS },
{ &psidAliasUsers, DOMAIN_ALIAS_RID_USERS },
{ &psidAliasGuests, DOMAIN_ALIAS_RID_GUESTS },
{ &psidAliasPowerUsers, DOMAIN_ALIAS_RID_POWER_USERS },
{ &psidAliasAccountOps, DOMAIN_ALIAS_RID_ACCOUNT_OPS },
{ &psidAliasSystemOps, DOMAIN_ALIAS_RID_SYSTEM_OPS },
{ &psidAliasPrintOps, DOMAIN_ALIAS_RID_PRINT_OPS },
{ &psidAliasBackupOps, DOMAIN_ALIAS_RID_BACKUP_OPS }
};
#define NUM_DOMAIN_SIDS (sizeof(psidBuiltinDomainData) / sizeof(psidBuiltinDomainData[0]))
//
// List of ACEs definitions to initialize our security descriptor
//
typedef struct {
BYTE AceType;
BYTE InheritFlags;
BYTE AceFlags;
ACCESS_MASK Mask;
PSID *Sid;
} ACE_DATA, *PACE_DATA;
STATIC
ACE_DATA AcesData[] =
{
{
ACCESS_ALLOWED_ACE_TYPE,
0,
0,
STI_ALL_ACCESS,
&psidLocalSystem
},
{
ACCESS_ALLOWED_ACE_TYPE,
0,
0,
STI_ALL_ACCESS,
&psidAliasAdmins
},
{
ACCESS_ALLOWED_ACE_TYPE,
0,
0,
STI_ALL_ACCESS,
&psidAliasSystemOps
},
{
ACCESS_ALLOWED_ACE_TYPE,
0,
0,
STI_ALL_ACCESS,
&psidAliasPowerUsers
},
{
ACCESS_ALLOWED_ACE_TYPE,
0,
0,
STI_ALL_ACCESS, // BUGBUG only need to syncronize
// STI_GENERIC_EXECUTE | SYNCHRONIZE,
&psidWorld
},
{
ACCESS_ALLOWED_ACE_TYPE,
0,
0,
STI_ALL_ACCESS, // BUGBUG only need to syncronize
&psidLocal
},
// {
// ACCESS_ALLOWED_ACE_TYPE,
// 0,
// 0,
// STI_GENERIC_EXECUTE,
// &psidProcessUser
// },
};
#define NUM_ACES (sizeof(AcesData) / sizeof(AcesData[0]))
//
// Local variables and types definitions
//
//
// The API security object. Client access STI Server APIs
// are validated against this object.
//
PSECURITY_DESCRIPTOR sdApiObject;
//
// This table maps generic rights (like GENERIC_READ) to
// specific rights (like STI_QUERY_SECURITY).
//
GENERIC_MAPPING ApiObjectMapping = {
STI_GENERIC_READ, // generic read
STI_GENERIC_WRITE, // generic write
STI_GENERIC_EXECUTE, // generic execute
STI_ALL_ACCESS // generic all
};
//
// Private prototypes.
//
DWORD
CreateWellKnownSids(
VOID
);
VOID
FreeWellKnownSids(
VOID
);
DWORD
CreateSecurityObject(
IN PACE_DATA AceData,
IN ULONG AceCount,
IN PSID psidOwner,
IN PSID psidGroup,
IN PGENERIC_MAPPING GenericMapping,
OUT PSECURITY_DESCRIPTOR *NewDescriptor
);
DWORD
DeleteSecurityObject(
IN PSECURITY_DESCRIPTOR *Descriptor
);
//
// Code
//
DWORD
AllocateAndInitializeSid(
OUT PSID *Sid,
IN PSID_IDENTIFIER_AUTHORITY IdentifierAuthority,
IN ULONG SubAuthorityCount
)
/*++
Routine Description:
This function allocates memory for a SID and initializes it.
Arguments:
None.
Return Value:
WIN32 Error Code.
--*/
{
*Sid = (PSID)
LocalAlloc(LPTR,
GetSidLengthRequired( (BYTE)SubAuthorityCount) );
if (*Sid == NULL) {
return ERROR_NOT_ENOUGH_MEMORY;
}
InitializeSid( *Sid, IdentifierAuthority, (BYTE)SubAuthorityCount );
return( NOERROR );
}
DWORD
DomainIdToSid(
IN PSID DomainId,
IN ULONG RelativeId,
OUT PSID *Sid
)
/*++
Routine Description:
Given a domain Id and a relative ID create a SID
Arguments:
DomainId - The template SID to use.
RelativeId - The relative Id to append to the DomainId.
Sid - Returns a pointer to an allocated buffer containing the resultant Sid.
Return Value:
WIN32 Error Code.
--*/
{
DWORD dwError;
BYTE DomainIdSubAuthorityCount; // Number of sub authorities in domain ID
UINT SidLength; // Length of newly allocated SID
//
// Allocate a Sid which has one more sub-authority than the domain ID.
//
DomainIdSubAuthorityCount = *(GetSidSubAuthorityCount( DomainId ));
SidLength = GetSidLengthRequired( (BYTE)(DomainIdSubAuthorityCount+1) );
if ((*Sid = (PSID) LocalAlloc(LPTR, SidLength )) == NULL ) {
return ERROR_NOT_ENOUGH_MEMORY;
}
//
// Initialize the new SID to have the same inital value as the
// domain ID.
//
if( CopySid(SidLength, *Sid, DomainId) == FALSE ) {
dwError = GetLastError();
LocalFree( *Sid );
return( dwError );
}
//
// Adjust the sub-authority count and
// add the relative Id unique to the newly allocated SID
//
(*(GetSidSubAuthorityCount( *Sid ))) ++;
*GetSidSubAuthority( *Sid, DomainIdSubAuthorityCount ) = RelativeId;
return( NOERROR );
}
DWORD
WINAPI
CreateWellKnownSids(
VOID
)
/*++
Routine Description:
This function creates some well-known SIDs and store them in global
variables.
Arguments:
none.
Return Value:
WIN32 Error Code.
--*/
{
DWORD dwError;
DWORD i;
//
// Allocate and initialize well-known SIDs which aren't relative to
// the Domain Id.
//
for (i = 0; i< NUM_SIDS ; i++) {
dwError = AllocateAndInitializeSid(
SidData[i].Sid,
&(SidData[i].IdentifierAuthority),
1);
if ( dwError != NOERROR ) {
return dwError;
}
*(GetSidSubAuthority(*(SidData[i].Sid), 0)) = SidData[i].SubAuthority;
}
//
// Build each SID which is relative to the Builtin Domain Id.
//
for ( i = 0;i < NUM_DOMAIN_SIDS; i++) {
dwError = DomainIdToSid(
psidBuiltinDomain,
psidBuiltinDomainData[i].RelativeId,
psidBuiltinDomainData[i].Sid );
if ( dwError != NOERROR ) {
return dwError;
}
}
return NOERROR;
} // CreateWellKnownSids
VOID
WINAPI
FreeWellKnownSids(
VOID
)
/*++
Routine Description:
This function frees up the dynamic memory consumed by the well-known
SIDs.
Arguments:
none.
Return Value:
none
--*/
{
DWORD i;
//
// free up memory allocated for well-known SIDs
//
for (i = 0; i < NUM_SIDS ; i++) {
if( *SidData[i].Sid != NULL ) {
LocalFree( *SidData[i].Sid );
*SidData[i].Sid = NULL;
}
}
//
// free up memory allocated for Builtin Domain SIDs
//
for (i = 0; i < NUM_DOMAIN_SIDS; i++) {
if( *psidBuiltinDomainData[i].Sid != NULL ) {
LocalFree( *psidBuiltinDomainData[i].Sid );
*psidBuiltinDomainData[i].Sid = NULL;
}
}
} //FreeWellKnownSids
DWORD
WINAPI
InitializeAllowedAce(
IN PACCESS_ALLOWED_ACE AllowedAce,
IN USHORT AceSize,
IN BYTE InheritFlags,
IN BYTE AceFlags,
IN ACCESS_MASK Mask,
IN PSID AllowedSid
)
/*++
Routine Description:
This function assigns the specified ACE values into an allowed type ACE.
Arguments:
AllowedAce - Supplies a pointer to the ACE that is initialized.
AceSize - Supplies the size of the ACE in bytes.
InheritFlags - Supplies ACE inherit flags.
AceFlags - Supplies ACE type specific control flags.
Mask - Supplies the allowed access masks.
AllowedSid - Supplies the pointer to the SID of user/group which is allowed
the specified access.
Return Value:
WIN32 Error Code.
--*/
{
AllowedAce->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
AllowedAce->Header.AceSize = AceSize;
AllowedAce->Header.AceFlags = AceFlags | InheritFlags;
AllowedAce->Mask = Mask;
if( CopySid(
GetLengthSid(AllowedSid), // should be valid SID ??
&(AllowedAce->SidStart),
AllowedSid ) == FALSE ) {
return( GetLastError() );
}
return( NOERROR );
}
DWORD
WINAPI
InitializeDeniedAce(
IN PACCESS_DENIED_ACE DeniedAce,
IN USHORT AceSize,
IN BYTE InheritFlags,
IN BYTE AceFlags,
IN ACCESS_MASK Mask,
IN PSID DeniedSid
)
/*++
Routine Description:
This function assigns the specified ACE values into a denied type ACE.
Arguments:
DeniedAce - Supplies a pointer to the ACE that is initialized.
AceSize - Supplies the size of the ACE in bytes.
InheritFlags - Supplies ACE inherit flags.
AceFlags - Supplies ACE type specific control flags.
Mask - Supplies the denied access masks.
AllowedSid - Supplies the pointer to the SID of user/group which is denied
the specified access.
Return Value:
WIN32 Error Code.
--*/
{
DeniedAce->Header.AceType = ACCESS_DENIED_ACE_TYPE;
DeniedAce->Header.AceSize = AceSize;
DeniedAce->Header.AceFlags = AceFlags | InheritFlags;
DeniedAce->Mask = Mask;
if( CopySid(
GetLengthSid(DeniedSid), // should be valid SID ??
&(DeniedAce->SidStart),
DeniedSid ) == FALSE ) {
return( GetLastError() );
}
return( NOERROR );
}
DWORD
WINAPI
InitializeAuditAce(
IN PACCESS_ALLOWED_ACE AuditAce,
IN USHORT AceSize,
IN BYTE InheritFlags,
IN BYTE AceFlags,
IN ACCESS_MASK Mask,
IN PSID AuditSid
)
/*++
Routine Description:
This function assigns the specified ACE values into an audit type ACE.
Arguments:
AuditAce - Supplies a pointer to the ACE that is initialized.
AceSize - Supplies the size of the ACE in bytes.
InheritFlags - Supplies ACE inherit flags.
AceFlags - Supplies ACE type specific control flags.
Mask - Supplies the allowed access masks.
AuditSid - Supplies the pointer to the SID of user/group which is to be
audited.
Return Value:
WIN32 Error Code.
--*/
{
AuditAce->Header.AceType = SYSTEM_AUDIT_ACE_TYPE;
AuditAce->Header.AceSize = AceSize;
AuditAce->Header.AceFlags = AceFlags | InheritFlags;
AuditAce->Mask = Mask;
if( CopySid(
GetLengthSid(AuditSid),
&(AuditAce->SidStart),
AuditSid ) == FALSE ) {
return( GetLastError() );
}
return( NOERROR );
}
DWORD
WINAPI
CreateSecurityDescriptorHelper(
IN PACE_DATA AceData,
IN ULONG AceCount,
IN PSID psidOwner OPTIONAL,
IN PSID psidGroup OPTIONAL,
OUT PSECURITY_DESCRIPTOR *NewDescriptor
)
/*++
Routine Description:
This function creates an absolute security descriptor containing
the supplied ACE information.
A sample usage of this function:
//
// Order matters! These ACEs are inserted into the DACL in the
// following order. Security access is granted or denied based on
// the order of the ACEs in the DACL.
//
ACE_DATA AceData[4] = {
{ACCESS_ALLOWED_ACE_TYPE, 0, 0,
GENERIC_ALL, &psidLocalAdmin},
{ACCESS_DENIED_ACE_TYPE, 0, 0,
GENERIC_ALL, &psidNetwork},
{ACCESS_ALLOWED_ACE_TYPE, 0, 0,
WKSTA_CONFIG_GUEST_INFO_GET |
WKSTA_CONFIG_USER_INFO_GET, &DomainUsersSid},
{ACCESS_ALLOWED_ACE_TYPE, 0, 0,
WKSTA_CONFIG_GUEST_INFO_GET, &DomainGuestsSid}
};
return CreateSecurityDescriptor(
AceData,
4,
psidNull,
psidLocalSystem,
&ConfigurationInfoSd
);
Arguments:
AceData - Supplies the structure of information that describes the DACL.
AceCount - Supplies the number of entries in AceData structure.
psidOwner - Supplies the pointer to the SID of the security descriptor
owner. If not specified, a security descriptor with no owner
will be created.
psidGroup - Supplies the pointer to the SID of the security descriptor
primary group. If not specified, a security descriptor with no primary
group will be created.
NewDescriptor - Returns a pointer to the absolute secutiry descriptor
allocated using MemoryAllocate.
Return Value:
WIN32 Error Code.
--*/
{
DWORD dwError = 0;
DWORD i;
//
// Pointer to memory dynamically allocated by this routine to hold
// the absolute security descriptor, the DACL, the SACL, and all the ACEs.
//
// +---------------------------------------------------------------+
// | Security Descriptor |
// +-------------------------------+-------+---------------+-------+
// | DACL | ACE 1 | . . . | ACE n |
// +-------------------------------+-------+---------------+-------+
// | SACL | ACE 1 | . . . | ACE n |
// +-------------------------------+-------+---------------+-------+
//
PSECURITY_DESCRIPTOR AbsoluteSd = NULL;
PACL Dacl = NULL; // Pointer to the DACL portion of above buffer
PACL Sacl = NULL; // Pointer to the SACL portion of above buffer
DWORD DaclSize = sizeof(ACL);
DWORD SaclSize = sizeof(ACL);
DWORD MaxAceSize = 0;
PVOID MaxAce = NULL;
LPBYTE CurrentAvailable;
DWORD Size;
// ASSERT( AceCount > 0 );
//
// Compute the total size of the DACL and SACL ACEs and the maximum
// size of any ACE.
//
for (i = 0; i < AceCount; i++) {
DWORD AceSize;
AceSize = GetLengthSid( *(AceData[i].Sid) );
switch (AceData[i].AceType) {
case ACCESS_ALLOWED_ACE_TYPE:
AceSize += sizeof(ACCESS_ALLOWED_ACE);
DaclSize += AceSize;
break;
case ACCESS_DENIED_ACE_TYPE:
AceSize += sizeof(ACCESS_DENIED_ACE);
DaclSize += AceSize;
break;
case SYSTEM_AUDIT_ACE_TYPE:
AceSize += sizeof(SYSTEM_AUDIT_ACE);
SaclSize += AceSize;
break;
default:
return( ERROR_INVALID_PARAMETER );
}
MaxAceSize = max( MaxAceSize, AceSize );
}
//
// Allocate a chunk of memory large enough the security descriptor
// the DACL, the SACL and all ACEs.
//
// A security descriptor is of opaque data type but
// SECURITY_DESCRIPTOR_MIN_LENGTH is the right size.
//
__try {
Size = SECURITY_DESCRIPTOR_MIN_LENGTH;
if ( DaclSize != sizeof(ACL) ) {
Size += DaclSize;
}
if ( SaclSize != sizeof(ACL) ) {
Size += SaclSize;
}
if ((AbsoluteSd = LocalAlloc(LPTR, Size )) == NULL) {
dwError = ERROR_NOT_ENOUGH_MEMORY;
__leave;
}
//
// Initialize the Dacl and Sacl
//
CurrentAvailable = (LPBYTE)AbsoluteSd + SECURITY_DESCRIPTOR_MIN_LENGTH;
if ( DaclSize != sizeof(ACL) ) {
Dacl = (PACL)CurrentAvailable;
CurrentAvailable += DaclSize;
if( InitializeAcl( Dacl, DaclSize, ACL_REVISION ) == FALSE ) {
dwError = GetLastError();
__leave;
}
}
if ( SaclSize != sizeof(ACL) ) {
Sacl = (PACL)CurrentAvailable;
CurrentAvailable += SaclSize;
if( InitializeAcl( Sacl, SaclSize, ACL_REVISION ) == FALSE ) {
dwError = GetLastError();
__leave;
}
}
//
// Allocate a temporary buffer big enough for the biggest ACE.
//
if ((MaxAce = LocalAlloc(LPTR, MaxAceSize )) == NULL ) {
dwError = ERROR_NOT_ENOUGH_MEMORY;
__leave;
}
//
// Initialize each ACE, and append it into the end of the DACL or SACL.
//
for (i = 0; i < AceCount; i++) {
DWORD AceSize;
PACL CurrentAcl = NULL;
AceSize = GetLengthSid( *(AceData[i].Sid) );
switch (AceData[i].AceType) {
case ACCESS_ALLOWED_ACE_TYPE:
AceSize += sizeof(ACCESS_ALLOWED_ACE);
CurrentAcl = Dacl;
dwError = InitializeAllowedAce(
(PACCESS_ALLOWED_ACE)MaxAce,
(USHORT) AceSize,
AceData[i].InheritFlags,
AceData[i].AceFlags,
AceData[i].Mask,
*(AceData[i].Sid) );
break;
case ACCESS_DENIED_ACE_TYPE:
AceSize += sizeof(ACCESS_DENIED_ACE);
CurrentAcl = Dacl;
dwError = InitializeDeniedAce(
(PACCESS_DENIED_ACE)MaxAce,
(USHORT) AceSize,
AceData[i].InheritFlags,
AceData[i].AceFlags,
AceData[i].Mask,
*(AceData[i].Sid) );
break;
case SYSTEM_AUDIT_ACE_TYPE:
AceSize += sizeof(SYSTEM_AUDIT_ACE);
CurrentAcl = Sacl;
dwError = InitializeAuditAce(
(PACCESS_ALLOWED_ACE)MaxAce,
(USHORT) AceSize,
AceData[i].InheritFlags,
AceData[i].AceFlags,
AceData[i].Mask,
*(AceData[i].Sid) );
break;
}
if ( dwError != NOERROR ) {
__leave;
}
//
// Append the initialized ACE to the end of DACL or SACL
//
if ( AddAce(
CurrentAcl,
ACL_REVISION,
MAXDWORD,
MaxAce,
AceSize ) == FALSE ) {
dwError = GetLastError();
__leave;
}
}
//
// Create the security descriptor with absolute pointers to SIDs
// and ACLs.
//
// Owner = psidOwner
// Group = psidGroup
// Dacl = Dacl
// Sacl = Sacl
//
if ( InitializeSecurityDescriptor(
AbsoluteSd,
SECURITY_DESCRIPTOR_REVISION ) == FALSE ) {
dwError = GetLastError();
__leave;
}
if ( SetSecurityDescriptorOwner(
AbsoluteSd,
psidOwner,
FALSE ) == FALSE ) {
dwError = GetLastError();
__leave;
}
if ( SetSecurityDescriptorGroup(
AbsoluteSd,
psidGroup,
FALSE ) == FALSE ) {
dwError = GetLastError();
__leave;
}
if ( SetSecurityDescriptorDacl(
AbsoluteSd,
TRUE,
Dacl,
FALSE ) == FALSE ) {
dwError = GetLastError();
__leave;
}
if ( SetSecurityDescriptorSacl(
AbsoluteSd,
FALSE,
Sacl,
FALSE ) == FALSE ) {
dwError = GetLastError();
__leave;
}
//
// Done
//
*NewDescriptor = AbsoluteSd;
AbsoluteSd = NULL;
dwError = NOERROR;
}
__finally {
// Cleanup
if( AbsoluteSd != NULL ) {
//
// delete the partially made SD if we are not completely
// successful
//
LocalFree( AbsoluteSd );
AbsoluteSd = NULL;
}
//
// Delete the temporary ACE
//
if ( MaxAce != NULL ) {
LocalFree( MaxAce );
MaxAce = NULL;
}
}
return( dwError );
}
DWORD
WINAPI
CreateSecurityObject(
IN PACE_DATA AceData,
IN ULONG AceCount,
IN PSID psidOwner,
IN PSID psidGroup,
IN PGENERIC_MAPPING GenericMapping,
OUT PSECURITY_DESCRIPTOR *NewDescriptor
)
/*++
Routine Description:
This function creates the DACL for the security descriptor based on
on the ACE information specified, and creates the security descriptor
which becomes the user-mode security object.
Arguments:
AceData - Supplies the structure of information that describes the DACL.
AceCount - Supplies the number of entries in AceData structure.
psidOwner - Supplies the pointer to the SID of the security descriptor
owner.
psidGroup - Supplies the pointer to the SID of the security descriptor
primary group.
GenericMapping - Supplies the pointer to a generic mapping array denoting
the mapping between each generic right to specific rights.
NewDescriptor - Returns a pointer to the self-relative security descriptor
which represents the user-mode object.
Return Value:
WIN32 Error Code.
NOTE : the security object created by calling this function may be
freed up by calling DeleteSecurityObject().
--*/
{
DWORD dwError;
PSECURITY_DESCRIPTOR AbsoluteSd = NULL;
HANDLE hTokenHandle = NULL;
__try {
dwError = CreateSecurityDescriptorHelper(
AceData,
AceCount,
psidOwner,
psidGroup,
&AbsoluteSd
);
if( dwError != NOERROR ) {
__leave;
}
if( OpenProcessToken(
GetCurrentProcess(),
TOKEN_QUERY,
&hTokenHandle ) == FALSE ) {
hTokenHandle = INVALID_HANDLE_VALUE;
dwError = GetLastError();
__leave;
}
//
// Create the security object (a user-mode object is really a pseudo-
// object represented by a security descriptor that have relative
// pointers to SIDs and ACLs). This routine allocates the memory to
// hold the relative security descriptor so the memory allocated for the
// DACL, ACEs, and the absolute descriptor can be freed.
//
if( CreatePrivateObjectSecurity(
NULL, // Parent descriptor
AbsoluteSd, // Creator descriptor
NewDescriptor, // Pointer to new descriptor
FALSE, // Is directory object
hTokenHandle, // Token
GenericMapping // Generic mapping
) == FALSE ) {
dwError = GetLastError();
__leave;
}
dwError = NOERROR;
}
__finally {
//
// Finally clean up used resources
if( hTokenHandle != NULL ) {
CloseHandle( hTokenHandle );
}
//
// Free dynamic memory before returning
//
if( AbsoluteSd != NULL ) {
LocalFree( AbsoluteSd );
}
}
return( dwError );
}
DWORD
WINAPI
DeleteSecurityObject(
IN PSECURITY_DESCRIPTOR *Descriptor
)
/*++
Routine Description:
This function deletes a security object that was created by calling
CreateSecurityObject() function.
Arguments:
Descriptor - Returns a pointer to the self-relative security descriptor
which represents the user-mode object.
Return Value:
WIN32 Error Code.
--*/
{
if( DestroyPrivateObjectSecurity( Descriptor ) == FALSE ) {
return( GetLastError() );
}
return( NOERROR );
}
DWORD
WINAPI
StiAccessCheckAndAuditW(
IN LPCWSTR SubsystemName,
IN LPWSTR ObjectTypeName,
IN PSECURITY_DESCRIPTOR SecurityDescriptor,
IN ACCESS_MASK DesiredAccess,
IN PGENERIC_MAPPING GenericMapping
)
/*++
Routine Description:
This function impersonates the caller so that it can perform access
validation using NtAccessCheckAndAuditAlarm; and reverts back to
itself before returning.
Arguments:
SubsystemName - Supplies a name string identifying the subsystem
calling this routine.
ObjectTypeName - Supplies the name of the type of the object being
accessed.
SecurityDescriptor - A pointer to the Security Descriptor against which
acccess is to be checked.
DesiredAccess - Supplies desired acccess mask. This mask must have been
previously mapped to contain no generic accesses.
GenericMapping - Supplies a pointer to the generic mapping associated
with this object type.
Return Value:
WIN32 Error - NOERROR or reason for failure.
--*/
{
DWORD dwError;
ACCESS_MASK GrantedAccess;
BOOL GenerateOnClose;
BOOL AccessStatus;
dwError = RpcImpersonateClient( NULL ) ;
if( dwError != NOERROR ) {
return( dwError );
}
__try {
if( AccessCheckAndAuditAlarmW(
SubsystemName,
NULL, // No handle for object
ObjectTypeName,
NULL,
SecurityDescriptor,
DesiredAccess,
GenericMapping,
FALSE, // open existing object.
&GrantedAccess,
&AccessStatus,
&GenerateOnClose ) == FALSE ) {
dwError = GetLastError();
__leave;
}
if ( AccessStatus == FALSE ) {
dwError = ERROR_ACCESS_DENIED;
__leave;
}
dwError = NOERROR;
}
__finally {
DWORD dwTemp = RpcRevertToSelf(); // We don't care about the return here
}
return( dwError );
}
DWORD
WINAPI
StiAccessCheckAndAuditA(
IN LPCSTR SubsystemName,
IN LPSTR ObjectTypeName,
IN PSECURITY_DESCRIPTOR SecurityDescriptor,
IN ACCESS_MASK DesiredAccess,
IN PGENERIC_MAPPING GenericMapping
)
/*++
Routine Description:
This function impersonates the caller so that it can perform access
validation using NtAccessCheckAndAuditAlarm; and reverts back to
itself before returning.
Arguments:
SubsystemName - Supplies a name string identifying the subsystem
calling this routine.
ObjectTypeName - Supplies the name of the type of the object being
accessed.
SecurityDescriptor - A pointer to the Security Descriptor against which
acccess is to be checked.
DesiredAccess - Supplies desired acccess mask. This mask must have been
previously mapped to contain no generic accesses.
GenericMapping - Supplies a pointer to the generic mapping associated
with this object type.
Return Value:
WIN32 Error - NOERROR or reason for failure.
--*/
{
DWORD dwError;
ACCESS_MASK GrantedAccess;
BOOL GenerateOnClose;
BOOL AccessStatus;
dwError = RpcImpersonateClient( NULL ) ;
if( dwError != NOERROR ) {
return( dwError );
}
__try {
if( AccessCheckAndAuditAlarmA(
SubsystemName,
NULL, // No handle for object
ObjectTypeName,
NULL,
SecurityDescriptor,
DesiredAccess,
GenericMapping,
FALSE, // open existing object.
&GrantedAccess,
&AccessStatus,
&GenerateOnClose ) == FALSE ) {
dwError = GetLastError();
__leave;
}
if ( AccessStatus == FALSE ) {
dwError = ERROR_ACCESS_DENIED;
__leave;
}
dwError = NOERROR;
}
__finally {
DWORD dwTemp = RpcRevertToSelf(); // We don't care about the return here
}
return( dwError );
}
DWORD
WINAPI
StiAccessCheck(
IN PSECURITY_DESCRIPTOR SecurityDescriptor,
IN ACCESS_MASK DesiredAccess,
IN PGENERIC_MAPPING GenericMapping
)
/*++
Routine Description:
This function impersonates the caller so that it can perform access
validation using AccessCheck; and reverts back to
itself before returning.
This routine differs from AccessCheckAndAudit in that it doesn't require
the caller to have SE_AUDIT_PRIVILEGE nor does it generate audits.
That is typically fine since the passed in security descriptor typically doesn't
have a SACL requesting an audit.
Arguments:
SecurityDescriptor - A pointer to the Security Descriptor against which
acccess is to be checked.
DesiredAccess - Supplies desired acccess mask. This mask must have been
previously mapped to contain no generic accesses.
GenericMapping - Supplies a pointer to the generic mapping associated
with this object type.
Return Value:
WINAPI_STATUS - NOERROR or reason for failure.
--*/
{
DWORD dwError;
HANDLE hClientToken = NULL;
DWORD GrantedAccess;
BOOL AccessStatus;
BYTE PrivilegeSet[500]; // Large buffer
DWORD PrivilegeSetSize;
//
// Impersonate the client.
//
dwError = RpcImpersonateClient(NULL);
if ( dwError != NOERROR ) {
return( dwError );
}
__try {
//
// Open the impersonated token.
//
if ( OpenThreadToken(
GetCurrentThread(),
TOKEN_QUERY,
TRUE, // use process security context to open token
&hClientToken ) == FALSE ) {
dwError = GetLastError();
__leave;
}
//
// Check if the client has the required access.
//
PrivilegeSetSize = sizeof(PrivilegeSet);
if ( AccessCheck(
SecurityDescriptor,
hClientToken,
DesiredAccess,
GenericMapping,
(PPRIVILEGE_SET)PrivilegeSet,
&PrivilegeSetSize,
&GrantedAccess,
&AccessStatus ) == FALSE ) {
dwError = GetLastError();
__leave;
}
if ( AccessStatus == FALSE ) {
dwError = ERROR_ACCESS_DENIED;
__leave;
}
//
// Success
//
dwError = NOERROR;
}
__finally {
DWORD dwTemp = RpcRevertToSelf(); // We don't care about the return here
if ( hClientToken != NULL ) {
CloseHandle( hClientToken );
}
}
return( dwError );
}
DWORD
WINAPI
StiApiAccessCheck(
IN ACCESS_MASK DesiredAccess
)
/*++
Routine Description:
Arguments:
DesiredAccess - Supplies desired acccess mask. This mask must have been
previously mapped to contain no generic accesses.
Return Value:
WINAPI_STATUS - NOERROR or reason for failure.
--*/
{
return StiAccessCheck(
sdApiObject,
DesiredAccess,
&ApiObjectMapping
);
}
BOOL
WINAPI
AdjustSecurityDescriptorForSync(
HANDLE hObject
)
/*++
Routine Description:
Arguments:
None
Return Value:
--*/
{
#define SD_SIZE (65536 + SECURITY_DESCRIPTOR_MIN_LENGTH)
BOOL fRet;
BYTE *bSDbuf = NULL;
PSECURITY_DESCRIPTOR pProcessSD;
DWORD dwSDLengthNeeded;
PACL pACL;
BOOL bDaclPresent;
BOOL bDaclDefaulted;
ACL_SIZE_INFORMATION AclInfo;
PACL pNewACL = NULL;
DWORD dwNewACLSize;
UCHAR NewSD[SECURITY_DESCRIPTOR_MIN_LENGTH];
PSECURITY_DESCRIPTOR psdNewSD=(PSECURITY_DESCRIPTOR)NewSD;
PVOID pTempAce;
UINT CurrentAceIndex;
fRet = FALSE;
bSDbuf = (BYTE*) LocalAlloc(LPTR, SD_SIZE);
if (!bSDbuf) {
DBG_ERR(("AdjustSecurityDescriptorForSync, Out of memory!"));
return FALSE;
}
pProcessSD = (PSECURITY_DESCRIPTOR)bSDbuf;
__try {
if (!GetKernelObjectSecurity(hObject,
DACL_SECURITY_INFORMATION,
pProcessSD,
SD_SIZE,
(LPDWORD)&dwSDLengthNeeded)) {
__leave;
}
// Initialize new SD
if(!InitializeSecurityDescriptor(psdNewSD,SECURITY_DESCRIPTOR_REVISION)) {
fRet = FALSE;
__leave;
}
// Get DACL from SD
if (!GetSecurityDescriptorDacl(pProcessSD,&bDaclPresent,&pACL,&bDaclDefaulted)) {
fRet = FALSE;
__leave;
}
// Get file ACL size information
if(!GetAclInformation(pACL,&AclInfo,sizeof(ACL_SIZE_INFORMATION),AclSizeInformation)) {
fRet = FALSE;
__leave;
}
// Compute size needed for the new ACL
dwNewACLSize = AclInfo.AclBytesInUse +
sizeof(ACCESS_ALLOWED_ACE) +
GetLengthSid(psidLocal) - sizeof(DWORD);
// Allocate memory for new ACL
pNewACL = (PACL)LocalAlloc(LPTR, dwNewACLSize);
if (!pNewACL) {
fRet = FALSE;
__leave;
}
// Initialize the new ACL
if(!InitializeAcl(pNewACL, dwNewACLSize, ACL_REVISION2)) {
fRet = FALSE;
__leave;
}
// If DACL is present, copy it to a new DACL
if(bDaclPresent) {
if(AclInfo.AceCount) {
for(CurrentAceIndex = 0;
CurrentAceIndex < AclInfo.AceCount;
CurrentAceIndex++) {
if(!GetAce(pACL,CurrentAceIndex,&pTempAce)) {
fRet = FALSE;
__leave;
}
// Add the ACE to the new ACL
if(!AddAce(pNewACL, ACL_REVISION, MAXDWORD, pTempAce,((PACE_HEADER)pTempAce)->AceSize)){
fRet = FALSE;
__leave;
}
}
}
}
// Add the access-allowed ACE to the new DACL
if(!AddAccessAllowedAce(pNewACL,ACL_REVISION2, READ_CONTROL | SYNCHRONIZE,psidLocal)) {
fRet = FALSE;
__leave;
}
// Set our new DACL to the file SD
if (!SetSecurityDescriptorDacl(psdNewSD,TRUE,pNewACL,FALSE)) {
fRet = FALSE;
__leave;
}
if (!SetKernelObjectSecurity(hObject,DACL_SECURITY_INFORMATION,psdNewSD)) {
fRet = FALSE;
__leave;
}
fRet = TRUE;
}
__finally {
if (bSDbuf) {
LocalFree(bSDbuf);
bSDbuf = NULL;
}
if (pNewACL) {
LocalFree((HLOCAL) pNewACL);
pNewACL = NULL;
}
}
return(fRet);
}
BOOL
WINAPI
InitializeNTSecurity(
VOID
)
/*++
Routine Description:
Creates and initializes security related data
Arguments:
None
Return Value:
TRUE if successful
--*/
{
DWORD dwError = NOERROR;
HANDLE hProcess = NULL;
DBG_FN(InitializeNTSecurity);
CreateWellKnownSids();
//
// Set proper process and thread security descriptor
//
hProcess = OpenProcess(PROCESS_ALL_ACCESS,FALSE,GetCurrentProcessId());
if (IS_VALID_HANDLE(hProcess)) {
AdjustSecurityDescriptorForSync(hProcess);
CloseHandle(hProcess);
}
else {
dwError = GetLastError();
return FALSE;
}
AdjustSecurityDescriptorForSync(GetCurrentThread());
dwError = CreateSecurityObject( AcesData,
NUM_ACES,
NULL,
NULL,
&ApiObjectMapping,
&sdApiObject );
return (dwError == NOERROR) ? TRUE : FALSE;
} // InitializeNTSecurity
BOOL
WINAPI
TerminateNTSecurity(
VOID
)
/*++
Routine Description:
Cleans up security related data
Arguments:
None
Return Value:
TRUE if successful
--*/
{
DeleteSecurityObject(&sdApiObject);
FreeWellKnownSids();
return TRUE;
} //TerminateNTSecurity
#else
//
// We don't support security on non-NT platforms
//
DWORD
WINAPI
StiApiAccessCheck(
IN ACCESS_MASK DesiredAccess
)
/*++
Routine Description:
Arguments:
DesiredAccess - Supplies desired acccess mask. This mask must have been
previously mapped to contain no generic accesses.
Return Value:
WINAPI_STATUS - NOERROR or reason for failure.
--*/
{
return NOERROR;
}
#endif