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.
1048 lines
28 KiB
1048 lines
28 KiB
/*++
|
|
|
|
Copyright (C) 1998-2001 Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
OLDSEC.CPP
|
|
|
|
Abstract:
|
|
|
|
contains various routines and classes used providing backward security support.
|
|
|
|
History:
|
|
|
|
a-davj 02-sept-99 Created.
|
|
|
|
--*/
|
|
|
|
#include "precomp.h"
|
|
#include <wbemcore.h>
|
|
#include <oleauto.h>
|
|
#include <genutils.h>
|
|
#include <safearry.h>
|
|
#include <oahelp.inl>
|
|
#include "secure.h"
|
|
#include <flexarry.h>
|
|
#include <secure.h>
|
|
#include <objpath.h>
|
|
#include "oldsec.h"
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CreateTheInstance
|
|
//
|
|
// Takes a class object, and a CCombined entry and creates an instance.
|
|
//
|
|
// PARAMETERS:
|
|
///
|
|
// ppObj used to pass back the created instance
|
|
// pClass Class object used for spawning
|
|
// pCombinedEntry Has the combined values for all the aces which mach
|
|
// the user or group.
|
|
// RETURN VALUES:
|
|
//
|
|
// S_OK if all is well, else an error code
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CreateTheInstance(IWbemClassObject ** ppObj, IWbemClassObject * pClass,
|
|
CCombinedAce * pCombinedEntry)
|
|
{
|
|
|
|
if(ppObj == NULL || pCombinedEntry == NULL || pClass == NULL)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
// spawn the instance
|
|
|
|
SCODE sc = pClass->SpawnInstance(0, ppObj);
|
|
if(FAILED(sc))
|
|
return sc;
|
|
CReleaseMe rm(*ppObj); // we addref at end if all is well
|
|
|
|
// populate the instance
|
|
|
|
bool bEnabled=false, bEditSecurity=false, bExecMethods=false;
|
|
|
|
DWORD dwMask = pCombinedEntry->m_dwDeny;
|
|
if(dwMask == 0)
|
|
dwMask = pCombinedEntry->m_dwAllow;
|
|
|
|
if( (dwMask & WBEM_ENABLE) &&
|
|
(dwMask & WBEM_REMOTE_ACCESS) &&
|
|
(dwMask & WBEM_WRITE_PROVIDER) &&
|
|
pCombinedEntry->m_dwAllow)
|
|
bEnabled = true;
|
|
|
|
if(dwMask & READ_CONTROL)
|
|
bEditSecurity = true;
|
|
|
|
if(dwMask & WBEM_METHOD_EXECUTE)
|
|
bExecMethods = true;
|
|
|
|
DWORD dwPermission = 0; // start at read
|
|
|
|
if(dwMask & WBEM_PARTIAL_WRITE_REP)
|
|
dwPermission = 1;
|
|
|
|
if(dwMask & WBEM_FULL_WRITE_REP)
|
|
dwPermission = 2;
|
|
|
|
VARIANT var;
|
|
var.vt = VT_I4;
|
|
|
|
var.lVal = dwPermission;
|
|
sc = (*ppObj)->Put(L"Permissions", 0, &var, 0);
|
|
|
|
var.vt = VT_BOOL;
|
|
|
|
var.boolVal = (bEnabled) ? VARIANT_TRUE : VARIANT_FALSE;
|
|
sc = (*ppObj)->Put(L"Enabled", 0, &var, 0);
|
|
|
|
var.boolVal = (bEditSecurity) ? VARIANT_TRUE : VARIANT_FALSE;
|
|
sc = (*ppObj)->Put(L"EditSecurity", 0, &var, 0);
|
|
|
|
var.boolVal = (bExecMethods) ? VARIANT_TRUE : VARIANT_FALSE;
|
|
sc = (*ppObj)->Put(L"ExecuteMethods", 0, &var, 0);
|
|
|
|
// Get the account and domain info
|
|
|
|
LPWSTR pwszAccount = NULL;
|
|
LPWSTR pwszDomain = NULL;
|
|
|
|
sc = pCombinedEntry->GetNames(pwszAccount, pwszDomain);
|
|
if(FAILED(sc))
|
|
return sc;
|
|
|
|
CDeleteMe<WCHAR> dm1(pwszAccount);
|
|
CDeleteMe<WCHAR> dm2(pwszDomain);
|
|
|
|
var.vt = VT_BSTR;
|
|
if(pwszAccount && wcslen(pwszAccount) > 0) // SEC:REVIEWED 2002-03-22 : OK, <->GetNames() call assures valid strings>
|
|
{
|
|
BSTR bstr = SysAllocString(pwszAccount); // SEC:REVIEWED 2002-03-22 : OK
|
|
if(bstr == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
var.bstrVal = bstr;
|
|
sc = (*ppObj)->Put(L"Name", 0, &var, 0);
|
|
SysFreeString(bstr);
|
|
}
|
|
if(pwszDomain && wcslen(pwszDomain)) // SEC:REVIEWED 2002-03-22 : OK
|
|
{
|
|
BSTR bstr = SysAllocString(pwszDomain); // SEC:REVIEWED 2002-03-22 : OK
|
|
if(bstr == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
var.bstrVal = bstr;
|
|
sc = (*ppObj)->Put(L"Authority", 0, &var, 0);
|
|
SysFreeString(bstr);
|
|
}
|
|
(*ppObj)->AddRef(); // make up for the releaseme
|
|
return S_OK;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// GetAceStylePath
|
|
//
|
|
// Takes a parsed object path and converts it into "authority|name"
|
|
// format.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pOutput parsed path object
|
|
// pToBeDeleted Set to newly allocated string. Call must free if
|
|
// this routine return S_OK
|
|
//
|
|
// RETURN VALUES:
|
|
//
|
|
// S_OK if all is well, else an error code
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT GetAceStylePath(ParsedObjectPath* pOutput, LPWSTR *pToBeDeleted)
|
|
{
|
|
LPWSTR pRet;
|
|
int iLen;
|
|
int iAuthLen = 0;
|
|
int iNameLen = 0;
|
|
KeyRef* pAuth;
|
|
KeyRef* pName;
|
|
|
|
if(pOutput == NULL || pToBeDeleted == NULL)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
if(wbem_wcsicmp(pOutput->m_pClass, L"__ntlmuser") &&
|
|
wbem_wcsicmp(pOutput->m_pClass, L"__ntlmgroup"))
|
|
return WBEM_E_INVALID_OBJECT_PATH;
|
|
|
|
if(pOutput->m_bSingletonObj || pOutput->m_dwNumKeys < 1 ||
|
|
pOutput->m_dwNumKeys > 2)
|
|
return WBEM_E_INVALID_OBJECT_PATH;
|
|
|
|
// The authority key is optional
|
|
|
|
if(pOutput->m_dwNumKeys == 1)
|
|
{
|
|
pAuth = NULL;
|
|
pName = pOutput->m_paKeys[0];
|
|
|
|
}
|
|
else
|
|
{
|
|
|
|
// Determine which order the keys are in
|
|
|
|
pAuth = pOutput->m_paKeys[0];
|
|
pName = pOutput->m_paKeys[1];
|
|
if(wbem_wcsicmp(pAuth->m_pName, L"Authority"))
|
|
{
|
|
pAuth = pOutput->m_paKeys[1];
|
|
pName = pOutput->m_paKeys[0];
|
|
}
|
|
}
|
|
// do some more checking
|
|
|
|
if((pAuth && wbem_wcsicmp(pAuth->m_pName, L"Authority")) ||
|
|
wbem_wcsicmp(pName->m_pName, L"Name"))
|
|
return WBEM_E_INVALID_OBJECT_PATH;
|
|
|
|
if(pAuth && pAuth->m_vValue.vt == VT_BSTR && pAuth->m_vValue.bstrVal != 0)
|
|
iAuthLen = wcslen(pAuth->m_vValue.bstrVal); // SEC:REVIEWED 2002-03-22 : OK, prior logic assures NULL
|
|
else
|
|
iAuthLen = 1; // assume a "."
|
|
if(pName->m_vValue.vt == VT_BSTR && pName->m_vValue.bstrVal != 0)
|
|
iNameLen = wcslen(pName->m_vValue.bstrVal); // SEC:REVIEWED 2002-03-22 : OK, prior logic assures NULL
|
|
|
|
if(iNameLen == 0 || iAuthLen == 0)
|
|
return WBEM_E_INVALID_OBJECT_PATH;
|
|
|
|
// allocate some memory
|
|
|
|
iLen = 2 + iNameLen + iAuthLen;
|
|
|
|
pRet = new WCHAR[iLen];
|
|
if(pRet == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
|
|
if(pAuth && pAuth->m_vValue.vt == VT_BSTR && pAuth->m_vValue.bstrVal != 0)
|
|
StringCchCopyW(pRet, iLen, pAuth->m_vValue.bstrVal);
|
|
else
|
|
StringCchCopyW(pRet, iLen, L".");
|
|
StringCchCatW(pRet, iLen, L"|");
|
|
StringCchCatW(pRet, iLen, pName->m_vValue.bstrVal);
|
|
*pToBeDeleted = pRet;
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CCombinedAce::CCombinedAce
|
|
//
|
|
// Constructor. Since there might be several ACEs for a single user or
|
|
// group in the ACL, this structure is used to combine all the aces for a
|
|
// sid into one.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pwszName User/group name.
|
|
//
|
|
//***************************************************************************
|
|
|
|
CCombinedAce::CCombinedAce(WCHAR *pwszName)
|
|
{
|
|
m_dwAllow = 0;
|
|
m_dwDeny = 0;
|
|
m_BadAce = false;
|
|
m_wcFullName = NULL;
|
|
if(pwszName)
|
|
{
|
|
DUP_STRING_NEW(m_wcFullName, pwszName);
|
|
}
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CCombinedAce::AddToMasks
|
|
//
|
|
// Since this class is used to combine possibly many ACEs into a single
|
|
// entry, this is called each time an ACE needs to be "OR"ed in.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pAce Pointer to the ace to be combined.
|
|
//
|
|
//***************************************************************************
|
|
|
|
void CCombinedAce::AddToMasks(CBaseAce * pAce)
|
|
{
|
|
if(pAce == NULL)
|
|
return;
|
|
|
|
// Only aces with the container inherit bit can
|
|
// be translated back.
|
|
|
|
if(pAce->GetFlags() != CONTAINER_INHERIT_ACE)
|
|
m_BadAce = true;
|
|
if(pAce->GetType() == ACCESS_ALLOWED_ACE_TYPE)
|
|
m_dwAllow |= pAce->GetAccessMask();
|
|
else
|
|
m_dwDeny |= pAce->GetAccessMask();
|
|
return;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CCombinedAce::IsValidOldEntry
|
|
//
|
|
// Checks a combined ace and determines if it could be converted into
|
|
// an old style object.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// bIsGroup Set to true if the entry is for a group.
|
|
//
|
|
// RETURN VALUES:
|
|
//
|
|
// TRUE if the entry would make a valid instance
|
|
//
|
|
//***************************************************************************
|
|
|
|
bool CCombinedAce::IsValidOldEntry(bool bIsGroup)
|
|
{
|
|
// If we have detected incompatible flags, all is done!
|
|
|
|
if(m_BadAce)
|
|
return false;
|
|
if(bIsGroup && m_dwDeny)
|
|
return false; // group denies were not supported
|
|
if(m_dwDeny && m_dwAllow)
|
|
return false; // can not mix allows and denies in old system
|
|
|
|
if(m_dwDeny)
|
|
{
|
|
return true;
|
|
}
|
|
DWORD dwOldAllow = WBEM_ENABLE | WBEM_REMOTE_ACCESS | WBEM_WRITE_PROVIDER;
|
|
DWORD dwMask = m_dwDeny;
|
|
if(dwMask == 0)
|
|
dwMask = m_dwAllow;
|
|
|
|
// all these must be set if it is an allow.
|
|
|
|
DWORD dwTemp = dwMask;
|
|
dwTemp &= dwOldAllow;
|
|
if(m_dwAllow != 0 && dwTemp != dwOldAllow)
|
|
return false;
|
|
|
|
// cant have full repository write without partial
|
|
|
|
if((dwMask & WBEM_FULL_WRITE_REP) != 0 && (dwMask & WBEM_PARTIAL_WRITE_REP) == 0)
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CCombinedAce::GetNames
|
|
//
|
|
// Retrieves the account name and authority
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pwszAccount Set to newly allocated string, Caller must free if success
|
|
// pwszDomain Set to newly allocated string, Caller must free if success
|
|
//
|
|
// RETURN VALUES:
|
|
//
|
|
// S_OK if all is well, else an error code
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CCombinedAce::GetNames(LPWSTR & pwszAccount, LPWSTR &pwszDomain)
|
|
{
|
|
pwszAccount = 0;
|
|
pwszDomain = 0;
|
|
|
|
// find the position of the '|'
|
|
|
|
if(m_wcFullName == 0)
|
|
return WBEM_E_FAILED;
|
|
|
|
WCHAR * pwcSeparator;
|
|
try
|
|
{
|
|
for(pwcSeparator = m_wcFullName; *pwcSeparator && *pwcSeparator != L'|'; pwcSeparator++); // SEC:REVIEWED 2002-03-22 : OK
|
|
}
|
|
catch(...)
|
|
{
|
|
return WBEM_E_FAILED;
|
|
}
|
|
|
|
DWORD dwLenDomain;
|
|
DWORD dwLenUser;
|
|
bool bUseDotDomain = false;
|
|
|
|
if(*pwcSeparator == 0)
|
|
{
|
|
return WBEM_E_FAILED;
|
|
}
|
|
if(pwcSeparator == m_wcFullName)
|
|
{
|
|
bUseDotDomain = true;
|
|
dwLenDomain = 2;
|
|
}
|
|
else
|
|
{
|
|
dwLenDomain = pwcSeparator - m_wcFullName + 1;
|
|
}
|
|
dwLenUser = wcslen(pwcSeparator); // SEC:REVIEWED 2002-03-22 : OK; prior logic assures NULL
|
|
if(dwLenUser == 0)
|
|
return WBEM_E_INVALID_OBJECT_PATH;
|
|
|
|
// Allocate space for the two strings
|
|
|
|
pwszAccount = new WCHAR[dwLenUser];
|
|
if(pwszAccount == NULL)
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
StringCchCopyW(pwszAccount, dwLenUser, pwcSeparator+1);
|
|
|
|
pwszDomain = new WCHAR[dwLenDomain];
|
|
if(pwszDomain == NULL)
|
|
{
|
|
delete pwszAccount;
|
|
pwszAccount = 0;
|
|
return WBEM_E_OUT_OF_MEMORY;
|
|
}
|
|
if(bUseDotDomain)
|
|
StringCchCopyW(pwszDomain, dwLenDomain, L".");
|
|
else
|
|
{
|
|
StringCchCopyW(pwszDomain, dwLenDomain, m_wcFullName);
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// RootSD::RootSD
|
|
//
|
|
// Constructor. This class contains a pointer to the root namespace and the
|
|
// flex array of aces.
|
|
//
|
|
//***************************************************************************
|
|
|
|
RootSD::RootSD()
|
|
{
|
|
m_bOK = false;
|
|
m_pFlex = NULL;
|
|
m_pRoot = CWbemNamespace::CreateInstance();
|
|
|
|
if(m_pRoot == NULL)
|
|
return;
|
|
HRESULT hRes = m_pRoot->Initialize(L"root", L"Administrator",
|
|
0 ,
|
|
FULL_RIGHTS, true, false, NULL, 0xFFFFFFFF,
|
|
FALSE, NULL);
|
|
|
|
if (FAILED(hRes))
|
|
{
|
|
m_pRoot->Release();
|
|
m_pRoot = NULL;
|
|
return;
|
|
}
|
|
else if (m_pRoot->GetStatus() != 0)
|
|
{
|
|
m_pRoot->Release();
|
|
m_pRoot = NULL;
|
|
return;
|
|
}
|
|
m_pRoot->AddRef();
|
|
|
|
// Get the security descriptor
|
|
|
|
m_pFlex = NULL;
|
|
SCODE sc = m_pRoot->GetAceList(&m_pFlex);
|
|
if(!FAILED(sc))
|
|
m_bOK = true;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// RootSD::~RootSD
|
|
//
|
|
// Destructor.
|
|
//
|
|
//***************************************************************************
|
|
|
|
RootSD::~RootSD()
|
|
{
|
|
if(m_pRoot)
|
|
m_pRoot->Release();
|
|
if(m_pFlex)
|
|
delete m_pFlex;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// RootSD::StoreAceList()
|
|
//
|
|
// Stores the Ace list back into the db.
|
|
//
|
|
// RETURN VALUES:
|
|
//
|
|
// S_OK if all is well, else an error code
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT RootSD::StoreAceList()
|
|
{
|
|
if(m_bOK && m_pFlex && m_pRoot)
|
|
m_pRoot->PutAceList(m_pFlex);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
//***************************************************************************
|
|
//
|
|
// RootSD::RemoveMatchingEntries
|
|
//
|
|
// Goes through the ACE list and removes all entries that match the name
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pwszAccountName Name of the account to be deleted
|
|
//
|
|
// RETURN VALUES:
|
|
//
|
|
// S_OK if all is well, else an error code
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT RootSD::RemoveMatchingEntries(LPWSTR pwszAccountName)
|
|
{
|
|
|
|
if(!m_bOK || m_pFlex == NULL)
|
|
return WBEM_E_FAILED;
|
|
|
|
for(int iPos = m_pFlex->Size()-1; iPos >= 0; iPos--)
|
|
{
|
|
CBaseAce * pListAce = (CBaseAce *)m_pFlex->GetAt(iPos);
|
|
WCHAR * pwszAceListUserName;
|
|
if(pListAce == NULL)
|
|
continue;
|
|
HRESULT hr = pListAce->GetFullUserName2(&pwszAceListUserName);
|
|
if(FAILED(hr))
|
|
return hr;
|
|
CDeleteMe<WCHAR> dm1(pwszAceListUserName);
|
|
|
|
if(wbem_wcsicmp(pwszAceListUserName, pwszAccountName) == 0)
|
|
{
|
|
delete pListAce;
|
|
m_pFlex->RemoveAt(iPos);
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// OldSecList::OldSecList
|
|
//
|
|
// Constructor. This class contains the list of combined entries for the
|
|
// aces in the root namespace. Note that the list is of just the users,
|
|
// or just the groups.
|
|
//
|
|
//***************************************************************************
|
|
|
|
OldSecList::OldSecList(bool bGroups)
|
|
{
|
|
|
|
// Attach up to the root namespace
|
|
|
|
RootSD rsd;
|
|
if(!rsd.IsOK())
|
|
return; // empty list
|
|
|
|
// Get the Security namespace
|
|
|
|
CFlexAceArray * pRootNsAceList = rsd.GetAceList();
|
|
|
|
if(pRootNsAceList == NULL)
|
|
return;
|
|
|
|
// For each ACE in the root namespace list
|
|
|
|
for(int iAce = 0; iAce < pRootNsAceList->Size(); iAce++)
|
|
{
|
|
|
|
// Search the entries in the combined list to see if there is already one for
|
|
// this ace
|
|
|
|
CBaseAce * pAce = (CBaseAce *)pRootNsAceList->GetAt(iAce);
|
|
|
|
WCHAR * pwszAceListUserName;
|
|
if(pAce == NULL)
|
|
continue;
|
|
|
|
CNtAce * pNtAce = (CNtAce *)pAce;
|
|
CNtSid sid;
|
|
pNtAce->GetSid(sid);
|
|
DWORD dwUsage;
|
|
LPWSTR pAccount = NULL;
|
|
LPWSTR pDomain = NULL;
|
|
if(sid.GetInfo(&pAccount, &pDomain, &dwUsage))
|
|
continue;
|
|
delete pAccount;
|
|
delete pDomain;
|
|
if(dwUsage == SidTypeUser && bGroups)
|
|
continue;
|
|
if(dwUsage != SidTypeUser && !bGroups)
|
|
continue;
|
|
|
|
|
|
HRESULT hr = pAce->GetFullUserName2(&pwszAceListUserName);
|
|
if(FAILED(hr))
|
|
continue;
|
|
CDeleteMe<WCHAR> dm1(pwszAceListUserName);
|
|
|
|
bool bExisting = false;
|
|
for(int iMergedEntry = 0; iMergedEntry < m_MergedAceList.Size(); iMergedEntry++)
|
|
{
|
|
CCombinedAce * pCombinedEntry = (CCombinedAce *)m_MergedAceList.GetAt(iMergedEntry);
|
|
if(pCombinedEntry)
|
|
{
|
|
if(wbem_wcsicmp(pwszAceListUserName, pCombinedEntry->m_wcFullName) == 0 )
|
|
{
|
|
bExisting = true;
|
|
pCombinedEntry->AddToMasks(pAce);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// If necessary add a new entry
|
|
|
|
if(!bExisting)
|
|
{
|
|
CCombinedAce * pCombinedEntry = new CCombinedAce(pwszAceListUserName);
|
|
if(pCombinedEntry == NULL)
|
|
return;
|
|
pCombinedEntry->AddToMasks(pAce);
|
|
if (CFlexArray::no_error != m_MergedAceList.Add((void *)pCombinedEntry))
|
|
{
|
|
//throw CX_Exception();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// OldSecList::~OldSecList()
|
|
//
|
|
// Destructor.
|
|
//
|
|
//***************************************************************************
|
|
|
|
OldSecList::~OldSecList()
|
|
{
|
|
|
|
// Delete the stuff used in the entry list.
|
|
|
|
for(int iCnt = m_MergedAceList.Size() - 1; iCnt >= 0; iCnt--)
|
|
{
|
|
CCombinedAce * pCombinedEntry = (CCombinedAce *)m_MergedAceList.GetAt(iCnt);
|
|
delete pCombinedEntry;
|
|
}
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// OldSecList::GetValidCombined
|
|
//
|
|
// Returns a combined entry at the specified index, but only if it is valid.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// iIndex Index into the array, 0 is the first
|
|
// bGroup true if a group entry is desired.
|
|
//
|
|
// RETURN VALUES:
|
|
//
|
|
// If all is well, a pointer to the combined entry. NULL indicates failure.
|
|
//
|
|
//***************************************************************************
|
|
|
|
CCombinedAce * OldSecList::GetValidCombined(int iIndex, bool bGroup)
|
|
{
|
|
|
|
if(iIndex < 0 || iIndex >= m_MergedAceList.Size())
|
|
return NULL;
|
|
|
|
// Get the entry
|
|
|
|
CCombinedAce * pCombinedEntry = (CCombinedAce *)m_MergedAceList.GetAt(iIndex);
|
|
if(pCombinedEntry == NULL)
|
|
return NULL;
|
|
|
|
// verify that the entry can be translated back into an old security setting
|
|
|
|
if(pCombinedEntry->IsValidOldEntry(bGroup))
|
|
return pCombinedEntry;
|
|
else
|
|
{
|
|
DEBUGTRACE((LOG_WBEMCORE, "Invalid ace entry combination encountered, name = %S, "
|
|
"allow=0x%x, deny=0x%x, flag validity=&d", pCombinedEntry->m_wcFullName,
|
|
pCombinedEntry->m_dwAllow, pCombinedEntry->m_dwDeny, pCombinedEntry->m_BadAce));
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// OldSecList::GetValidCombined
|
|
//
|
|
// Returns a combined entry which matches the name, but only if it is valid.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pName Name to be found. It is of the format "authority|name"
|
|
// bGroup true if a group entry is desired.
|
|
//
|
|
// RETURN VALUES:
|
|
//
|
|
// If all is well, a pointer to the combined entry. NULL indicates failure.
|
|
//
|
|
//***************************************************************************
|
|
|
|
CCombinedAce * OldSecList::GetValidCombined(LPWSTR pName, bool bGroup)
|
|
{
|
|
|
|
if(pName == NULL)
|
|
return NULL;
|
|
|
|
// Go through the list and look for the matching entry
|
|
|
|
int iCnt;
|
|
CCombinedAce * pCombinedEntry;
|
|
for(iCnt = 0; iCnt < m_MergedAceList.Size(); iCnt++)
|
|
{
|
|
pCombinedEntry = (CCombinedAce *)m_MergedAceList.GetAt(iCnt);
|
|
if(pCombinedEntry && !wbem_wcsicmp(pCombinedEntry->m_wcFullName, pName))
|
|
break;
|
|
}
|
|
|
|
if(iCnt == m_MergedAceList.Size())
|
|
return NULL;
|
|
|
|
// verify that the entry can be translated back into an old security setting
|
|
|
|
if(pCombinedEntry->IsValidOldEntry(bGroup))
|
|
return pCombinedEntry;
|
|
else
|
|
{
|
|
DEBUGTRACE((LOG_WBEMCORE, "Invalid ace entry combination encountered, name = %S, "
|
|
"allow=0x%x, deny=0x%x, flag validity=&d", pCombinedEntry->m_wcFullName,
|
|
pCombinedEntry->m_dwAllow, pCombinedEntry->m_dwDeny, pCombinedEntry->m_BadAce));
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CWbemNamespace::EnumerateSecurityClassInstances
|
|
//
|
|
// Equivalent the a CreateInstanceEnumAsync call.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// wszClassName class name
|
|
// pSink Where to indicate the value
|
|
// pContext pointer to the context object.
|
|
// lFlags flags.
|
|
//
|
|
// RETURN VALUES:
|
|
//
|
|
// S_OK if all is well, else an error code
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CWbemNamespace::EnumerateSecurityClassInstances(LPWSTR wszClassName,
|
|
IWbemObjectSink* pSink, IWbemContext* pContext, long lFlags)
|
|
{
|
|
|
|
SCODE sc = WBEM_E_FAILED;
|
|
IWbemClassObject FAR* pObj = NULL;
|
|
|
|
// Do sanity check of arguments.
|
|
|
|
if(pSink == NULL || wszClassName == NULL ) // Should not happen
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
// Get the class object
|
|
|
|
IWbemClassObject * pClass = NULL;
|
|
sc = GetObject(wszClassName, 0, pContext, &pClass, NULL);
|
|
if(sc != S_OK)
|
|
{
|
|
return sc;
|
|
}
|
|
|
|
CReleaseMe rm(pClass);
|
|
|
|
|
|
bool bGroup = false;
|
|
if(wbem_wcsicmp(L"__ntlmgroup", wszClassName) == 0)
|
|
bGroup = true;
|
|
|
|
OldSecList osl(bGroup);
|
|
sc = S_OK;
|
|
for(int i = 0; i < osl.Size(); i++)
|
|
{
|
|
IWbemClassObject * pObj = NULL;
|
|
CCombinedAce * pCombinedEntry = osl.GetValidCombined(i, bGroup);
|
|
if(pCombinedEntry)
|
|
{
|
|
sc = CreateTheInstance(&pObj, pClass, pCombinedEntry);
|
|
if(sc == S_OK)
|
|
{
|
|
if (SUCCEEDED(sc = DecorateObject(pObj)))
|
|
{
|
|
pSink->Indicate(1,&pObj);
|
|
}
|
|
pObj->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Set status, all done
|
|
return sc;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CWbemNamespace::PutSecurityClassInstances
|
|
//
|
|
// Equivalent to a PutInstanceAsync call.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// wszClassName class name
|
|
// pObj Object to be "put"
|
|
// pSink where to SetStatus
|
|
// pContext pointer to the context object
|
|
// lFlags flags
|
|
//
|
|
// RETURN VALUES:
|
|
//
|
|
// S_OK if all is well, else an error code
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CWbemNamespace::PutSecurityClassInstances(LPWSTR wszClassName, IWbemClassObject * pObj,
|
|
IWbemObjectSink* pSink, IWbemContext* pContext, long lFlags)
|
|
{
|
|
// Check the args
|
|
|
|
if(wszClassName == NULL || pObj == NULL || pSink == NULL)
|
|
{
|
|
pSink->SetStatus(0,WBEM_E_INVALID_PARAMETER,NULL,NULL);
|
|
return S_OK;
|
|
}
|
|
|
|
RootSD rsd;
|
|
if(!rsd.IsOK())
|
|
{
|
|
pSink->SetStatus(0,WBEM_E_FAILED,NULL,NULL);
|
|
return S_OK;
|
|
}
|
|
|
|
// Get the Security namespace
|
|
|
|
CFlexAceArray * pRootNsAceList = rsd.GetAceList();
|
|
bool bGroup = false;
|
|
if(wbem_wcsicmp(L"__ntlmgroup", wszClassName) == 0)
|
|
bGroup = true;
|
|
|
|
// Convert to new sid
|
|
|
|
CBaseAce * pAce = ConvertOldObjectToAce(pObj, bGroup);
|
|
if(pAce == NULL)
|
|
{
|
|
pSink->SetStatus(0,WBEM_E_INVALID_OBJECT,NULL,NULL);
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
// Delete all entries with the same name
|
|
|
|
WCHAR * pwszAccountName;
|
|
HRESULT hr = pAce->GetFullUserName2(&pwszAccountName);
|
|
if(FAILED(hr))
|
|
{
|
|
pSink->SetStatus(0,hr,NULL,NULL);
|
|
return S_OK;
|
|
}
|
|
|
|
CDeleteMe<WCHAR> dm1(pwszAccountName);
|
|
|
|
rsd.RemoveMatchingEntries(pwszAccountName);
|
|
|
|
// Add the new entries
|
|
|
|
pRootNsAceList->Add(pAce);
|
|
|
|
// Put Sid back
|
|
|
|
hr = rsd.StoreAceList();
|
|
pSink->SetStatus(0,hr,NULL,NULL);
|
|
return S_OK;
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CWbemNamespace::DeleteSecurityClassInstances
|
|
//
|
|
// Equivalent to a DeleteInstanceAsync routine
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pParsedPath parsed object path
|
|
// pSink where to SetStatus
|
|
// pContext pointer to the context object
|
|
// lFlags flags
|
|
//
|
|
// RETURN VALUES:
|
|
//
|
|
// S_OK if all is well, else an error code
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CWbemNamespace::DeleteSecurityClassInstances(ParsedObjectPath* pParsedPath,
|
|
IWbemObjectSink* pSink, IWbemContext* pContext, long lFlags)
|
|
{
|
|
// Check the args
|
|
|
|
if(pParsedPath == NULL || pSink == NULL || pSink == NULL)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
// Parse the path and contruct the domain|user string
|
|
|
|
LPWSTR pAcePath = NULL;
|
|
HRESULT hr = GetAceStylePath(pParsedPath, &pAcePath);
|
|
if(FAILED(hr))
|
|
{
|
|
pSink->SetStatus(0,hr,NULL,NULL);
|
|
return S_OK;
|
|
}
|
|
|
|
CDeleteMe<WCHAR> dm(pAcePath);
|
|
|
|
// Delete the entries
|
|
|
|
RootSD rsd;
|
|
if(!rsd.IsOK())
|
|
hr = WBEM_E_FAILED;
|
|
else
|
|
{
|
|
CFlexAceArray * pRootNsAceList = rsd.GetAceList();
|
|
int iOriginalSize = pRootNsAceList->Size();
|
|
|
|
// Delete all entries with the same name
|
|
|
|
rsd.RemoveMatchingEntries(pAcePath);
|
|
|
|
int iNewSize = pRootNsAceList->Size();
|
|
if(iNewSize < iOriginalSize)
|
|
hr = rsd.StoreAceList();
|
|
else
|
|
hr = WBEM_E_NOT_FOUND;
|
|
}
|
|
pSink->SetStatus(0,hr,NULL,NULL);
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
//***************************************************************************
|
|
//
|
|
// CWbemNamespace::GetSecurityClassInstances
|
|
//
|
|
// Equivalent to a GetObjectAsync call.
|
|
//
|
|
// PARAMETERS:
|
|
//
|
|
// pParsedPath parsed object path
|
|
// pSink where to SetStatus
|
|
// pContext pointer to the context object
|
|
// lFlags flags
|
|
//
|
|
// RETURN VALUES:
|
|
//
|
|
// S_OK if all is well, else an error code
|
|
//
|
|
//***************************************************************************
|
|
|
|
HRESULT CWbemNamespace::GetSecurityClassInstances(ParsedObjectPath* pParsedPath, CBasicObjectSink* pSink,
|
|
IWbemContext* pContext,long lFlags)
|
|
{
|
|
// Check the args
|
|
|
|
if(pParsedPath == NULL|| pSink == NULL)
|
|
return WBEM_E_INVALID_PARAMETER;
|
|
|
|
// Parse the path and contruct the domain|user string
|
|
|
|
LPWSTR pAcePath = NULL;
|
|
HRESULT hr = GetAceStylePath(pParsedPath, &pAcePath);
|
|
if(FAILED(hr))
|
|
{
|
|
pSink->SetStatus(0,hr,NULL,NULL);
|
|
return S_OK;
|
|
}
|
|
|
|
CDeleteMe<WCHAR> dm(pAcePath);
|
|
|
|
IWbemClassObject * pClass = NULL;
|
|
SCODE sc = GetObject(pParsedPath->m_pClass, 0, pContext, &pClass, NULL);
|
|
if(sc != S_OK)
|
|
{
|
|
pSink->SetStatus(0,sc,NULL, NULL);
|
|
return S_OK;
|
|
}
|
|
|
|
CReleaseMe rm(pClass);
|
|
|
|
|
|
bool bGroup = false;
|
|
if(wbem_wcsicmp(L"__ntlmgroup", pParsedPath->m_pClass) == 0)
|
|
bGroup = true;
|
|
OldSecList osl(bGroup);
|
|
|
|
IWbemClassObject * pObj = NULL;
|
|
CCombinedAce * pCombinedEntry = osl.GetValidCombined(pAcePath, bGroup);
|
|
if(pCombinedEntry == NULL)
|
|
{
|
|
pSink->SetStatus(0, WBEM_E_INVALID_OBJECT_PATH, NULL, NULL);
|
|
return S_OK;
|
|
}
|
|
sc = CreateTheInstance(&pObj, pClass, pCombinedEntry);
|
|
if(sc == S_OK) // not all entries make for valid old entries, so failure is common
|
|
{
|
|
if (SUCCEEDED(sc = DecorateObject(pObj)))
|
|
{
|
|
pSink->Indicate(1,&pObj);
|
|
}
|
|
pObj->Release();
|
|
}
|
|
|
|
// Set status, all done
|
|
|
|
pSink->SetStatus(0,sc,NULL, NULL);
|
|
return S_OK;
|
|
|
|
}
|
|
|
|
|