|
|
//****************************************************************************
//
// Copyright (C) 1999 Microsoft Corporation
//
// GROUPSFORUSER.CPP
//
//****************************************************************************
// This is done in the sources file: WIN32_WIN32_WINNT=0x0400
//#define _WIN32_WINNT 0x0400
#include "precomp.h"
#include <wbemcomn.h>
#include "wmiauthz.h"
#include "GroupsForUser.h"
//
// Store the error status of CWmiAuthzWrapper and CAdminSID class initialization.
// They are set to ERROR_INVALID_ACCESS error status initially.
//
static DWORD g_dwWmiAuthzError = ERROR_INVALID_ACCESS; static DWORD g_dwAdminSIDError = ERROR_INVALID_ACCESS;
//
// Class definition of CWmiAuthzWrapper class.
// This class wraps CWmiAuthz class:
// - It creates an instance of CWmiAuthz class in its
// constructor and deletes it in descrutor.
// - Sets g_dwWmiAuthzError global in case of error otherwise
// sets it to 0 ( ERROR_SUCCESS )
//
class CWmiAuthzWrapper { // Private member variables
CWmiAuthz *m_pWmiAuthz;
public: // Constructor
CWmiAuthzWrapper( ) { m_pWmiAuthz = new CWmiAuthz( NULL ); if ( NULL == m_pWmiAuthz ) { g_dwWmiAuthzError = ERROR_OUTOFMEMORY; } else { m_pWmiAuthz->AddRef( ); g_dwWmiAuthzError = ERROR_SUCCESS; } }
// Destructor
~CWmiAuthzWrapper( ) { if ( m_pWmiAuthz ) { m_pWmiAuthz->Release( ); } }
// Accessor method to CWmiClass instance
CWmiAuthz * GetWmiAuthz( ) const { return m_pWmiAuthz; }
};
//
// Class definition of CAdminSID class.
// - Allocates Admin SID in its constructor and
// frees it in destructor.
// - Sets g_dwAdminSIDError global in case of error otherwise
// sets it to 0 ( ERROR_SUCCESS )
//
class CAdminSID { PSID m_pSIDAdmin;
public: // Constructor
CAdminSID( ) { //
// Create a System Identifier for the Admin group.
//
SID_IDENTIFIER_AUTHORITY SystemSidAuthority = SECURITY_NT_AUTHORITY;
if ( FALSE == AllocateAndInitializeSid ( &SystemSidAuthority, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0, &m_pSIDAdmin ) ) { g_dwAdminSIDError = GetLastError( ); ERRORTRACE( ( LOG_ESS, "AllocateAndInitializeSid failed, error 0x%X\n", g_dwAdminSIDError ) ); m_pSIDAdmin = NULL; } else { g_dwAdminSIDError = ERROR_SUCCESS; } }
// Destructor
~CAdminSID( ) { if ( m_pSIDAdmin ) { FreeSid ( m_pSIDAdmin ); } }
// Accessor method to Admin SID
PSID GetAdminSID( ) const { return m_pSIDAdmin; } };
//
// Static glabal declaration of CWmiAuthsWrapper class.
//
static CWmiAuthzWrapper g_wmiAuthzWrapper;
//
// Static glabal declaration of CAdminSID class.
//
static CAdminSID g_adminSID;
//
// Returns SD and DACL with a given Access Mask and SID
//
DWORD GetSDAndACLFromSID( DWORD dwAccessMask, PSID pSID, BYTE **ppNewDACL, BYTE **ppNewSD ) { DWORD dwError = 0, dwDACLLength = sizeof ( ACL ) + sizeof ( ACCESS_ALLOWED_ACE ) - sizeof ( DWORD ) + GetLengthSid ( pSID ); //
// Get memory needed for new DACL
//
*ppNewDACL = new BYTE[ dwDACLLength ]; if ( !*ppNewDACL ) { *ppNewSD = NULL; return E_OUTOFMEMORY; }
//
// Get memory for new SD
//
*ppNewSD = new BYTE[ sizeof( SECURITY_DESCRIPTOR ) ]; if ( !*ppNewSD ) { delete[] *ppNewDACL; *ppNewDACL = NULL; return E_OUTOFMEMORY; }
do { //
// Initialize new SD
//
if ( FALSE == InitializeSecurityDescriptor ( ( PSECURITY_DESCRIPTOR )*ppNewSD, SECURITY_DESCRIPTOR_REVISION ) ) { dwError = GetLastError( ); break; }
//
// Initialize new DACL
//
if ( FALSE == InitializeAcl ( ( PACL )*ppNewDACL, dwDACLLength, ACL_REVISION ) ) { dwError = GetLastError( ); break; }
//
// Get DACL using Access Mask and SID
//
if ( FALSE == AddAccessAllowedAce ( ( PACL )*ppNewDACL, ACL_REVISION, dwAccessMask, pSID ) ) { dwError = GetLastError( ); break; }
//
// Check if everything went OK
//
if ( FALSE == IsValidAcl ( ( PACL )*ppNewDACL ) ) { dwError = GetLastError( ); break; }
//
// Set DACL to the SD
//
if ( FALSE == SetSecurityDescriptorDacl ( ( PSECURITY_DESCRIPTOR )*ppNewSD, TRUE, ( PACL )*ppNewDACL, FALSE ) ) { dwError = GetLastError( ); break; }
//
// Set Group to the SD
//
if ( FALSE == SetSecurityDescriptorGroup ( ( PSECURITY_DESCRIPTOR )*ppNewSD, pSID, TRUE ) ) { dwError = GetLastError( ); break; }
//
// Set Owner to the SD
//
if ( FALSE == SetSecurityDescriptorOwner ( ( PSECURITY_DESCRIPTOR )*ppNewSD, pSID, TRUE ) ) { dwError = GetLastError( ); break; }
//
// Check if everything went OK
//
if ( FALSE == IsValidSecurityDescriptor ( ( PSECURITY_DESCRIPTOR )*ppNewSD ) ) { dwError = GetLastError( ); break; } } while( FALSE );
//
// Delete the stuff in case of error
//
if ( dwError ) { delete[] *ppNewDACL; delete[] *ppNewSD; *ppNewDACL = NULL; *ppNewSD = NULL; }
return dwError; }
//
// Returns SD with a given DACL
//
DWORD GetSDFromACL( PACL pNewDACL, BYTE **ppNewSD ) { //
// Return if error occured during initialization of Admin SID
// in CAdminSID static global class declaration;
//
_DBG_ASSERT( !g_dwAdminSIDError );
if ( g_dwAdminSIDError ) { *ppNewSD = NULL; return g_dwAdminSIDError; }
//
// Get memory for new SD
//
*ppNewSD = new BYTE[ sizeof( SECURITY_DESCRIPTOR ) ]; if ( !*ppNewSD ) { return E_OUTOFMEMORY; }
DWORD dwError = 0;
do { //
// Initialize new SD
//
if ( FALSE == InitializeSecurityDescriptor ( ( PSECURITY_DESCRIPTOR )*ppNewSD, SECURITY_DESCRIPTOR_REVISION ) ) { dwError = GetLastError( ); break; }
//
// Set DACL to the SD
//
if ( FALSE == SetSecurityDescriptorDacl ( ( PSECURITY_DESCRIPTOR )*ppNewSD, TRUE, pNewDACL, FALSE ) ) { dwError = GetLastError( ); break; }
//
// Set Group to the SD with Admin SID
//
if ( FALSE == SetSecurityDescriptorGroup ( ( PSECURITY_DESCRIPTOR )*ppNewSD, g_adminSID.GetAdminSID( ), TRUE ) ) { dwError = GetLastError( ); break; }
//
// Set Owner to the SD
//
if ( FALSE == SetSecurityDescriptorOwner ( ( PSECURITY_DESCRIPTOR )*ppNewSD, g_adminSID.GetAdminSID( ), TRUE ) ) { dwError = GetLastError( ); break; } //
// Check if everything went OK
//
if ( FALSE == IsValidSecurityDescriptor ( ( PSECURITY_DESCRIPTOR )*ppNewSD ) ) { dwError = GetLastError( ); break; } } while( FALSE );
//
// Delete the security descriptor in case of error
//
if ( dwError ) { delete[] *ppNewSD; *ppNewSD = NULL; }
return dwError; }
//
// Returns STATUS_SUCCESS if user is in group
// STATUS_ACCESS_DENIED if not
// some error code or other on error
//
NTSTATUS IsUserInGroup( PSID pSidUser, PSID pSidGroup ) { _DBG_ASSERT( IsValidSid( pSidUser ) ); _DBG_ASSERT( IsValidSid( pSidGroup ) );
//
// Return if error occured during creation of CWmiAuthz class
// in static global CWmiAuthzWrapper class declaration.
//
_DBG_ASSERT( !g_dwWmiAuthzError );
if ( g_dwWmiAuthzError ) { return g_dwWmiAuthzError; }
IWbemToken *pToken = NULL; HRESULT hr = g_wmiAuthzWrapper.GetWmiAuthz( )->GetToken( ( BYTE * )pSidUser, &pToken );
if ( FAILED( hr ) ) { return hr; } BYTE *pDACL = NULL; BYTE *pSD = NULL; DWORD dwAccess = 0; NTSTATUS stat = GetSDAndACLFromSID( STANDARD_RIGHTS_EXECUTE, pSidGroup, &pDACL, &pSD );
if ( stat ) { pToken->Release( ); return stat; }
hr = pToken->AccessCheck( STANDARD_RIGHTS_EXECUTE, pSD, &dwAccess );
pToken->Release( );
//
// Delete allocated memory in GetSDAndACLFromSID
//
delete[] pSD; delete[] pDACL;
if ( FAILED( hr ) ) { return hr; }
if ( STANDARD_RIGHTS_EXECUTE & dwAccess ) { return STATUS_SUCCESS; }
return STATUS_ACCESS_DENIED; }
//
// Returns STATUS_SUCCESS if user is in admin group
// STATUS_ACCESS_DENIED if not
// some error code or other on error
//
NTSTATUS IsUserAdministrator( PSID pSidUser ) { _DBG_ASSERT( IsValidSid( pSidUser ) );
//
// Return if error occured during initialization of Admin SID
// in CAdminSID static global class declaration;
//
_DBG_ASSERT( !g_dwAdminSIDError );
if ( g_dwAdminSIDError ) { return g_dwAdminSIDError; }
//
// Call IsUserInGroup with Administrators group SID
//
return IsUserInGroup( pSidUser, g_adminSID.GetAdminSID( ) ); }
//
// Retireves access mask corresponding to permissions granted
// by dacl to account denoted in pSid
// only deals with the ACCESS_ALLOWED/DENIED type aces
// including the ACCESS_ALLOWED/DENIED_OBJECT_ACEs
// - will error out if it finds a SYSTEM_AUDIT or unrecognized type.
//
NTSTATUS GetAccessMask( PSID pSid, PACL pDacl, DWORD *pdwAccessMask ) { if ( NULL == pDacl ) { *pdwAccessMask = 0xFFFFFFFF; return STATUS_SUCCESS; } _DBG_ASSERT( IsValidSid( pSid ) ); _DBG_ASSERT( IsValidAcl( pDacl ) );
*pdwAccessMask = NULL;
//
// Return if error occured during creation of CWmiAuthz class
// in static global CWmiAuthzWrapper class declaration.
//
_DBG_ASSERT( !g_dwWmiAuthzError );
if ( g_dwWmiAuthzError ) { return g_dwWmiAuthzError; }
IWbemToken *pToken = NULL; HRESULT hr = g_wmiAuthzWrapper.GetWmiAuthz( )->GetToken( ( BYTE * )pSid, &pToken );
if ( FAILED( hr ) ) { return hr; } BYTE *pSD = NULL; NTSTATUS stat = GetSDFromACL( pDacl, &pSD );
if ( stat ) { pToken->Release( ); return stat; }
//
// Requested DesiredAccessMask should be MAXIMUM_ALLOWED
// to be able to retrieve all the accesses with replied
// access mask
//
hr = pToken->AccessCheck( MAXIMUM_ALLOWED, pSD, pdwAccessMask );
pToken->Release( );
//
// Delete allocated memory in GetSDFromACL
//
delete[] pSD;
if ( FAILED( hr ) ) { return hr; }
return STATUS_SUCCESS; }
|