WindowsXP-SP1/admin/wmi/wbem/scripting/parsedn.cpp
2020-09-30 16:53:49 +02:00

1588 lines
43 KiB
C++

//***************************************************************************
//
// Copyright (c) 1998-2000 Microsoft Corporation
//
// File: parsedn.cxx
//
// Description :
// Parses CIM paths to objects and returns the requested object
//***************************************************************************
#include "precomp.h"
#define CURRENTSTR (lpszInputString + *pchEaten)
#define SKIPWHITESPACE \
while (*CURRENTSTR && _istspace( *CURRENTSTR ) ) \
(*pchEaten)++;
#define WBEMS_STR_OWNER L"O"
#define WBEMS_STR_GROUP L"G"
#define WBEMS_STR_DACL L"D"
#define WBEMS_STR_SACL L"S"
static void SecureProxy (bool authnSpecified, enum WbemAuthenticationLevelEnum eAuthLevel,
bool impSpecified, enum WbemImpersonationLevelEnum eImpersonLevel,
ISWbemServices *pService)
{
// Secure the proxy using the specified security settings (if any)
CComPtr<ISWbemSecurity> pSecurity;
if (authnSpecified || impSpecified)
{
if (SUCCEEDED(pService->get_Security_(&pSecurity)))
{
if (authnSpecified)
pSecurity->put_AuthenticationLevel (eAuthLevel);
if (impSpecified)
pSecurity->put_ImpersonationLevel (eImpersonLevel);
}
}
}
static void SecureProxy (bool authnSpecified, enum WbemAuthenticationLevelEnum eAuthLevel,
bool impSpecified, enum WbemImpersonationLevelEnum eImpersonLevel,
ISWbemObject *pObject)
{
// Secure the proxy using the specified security settings (if any)
CComPtr<ISWbemSecurity> pSecurity;
if (authnSpecified || impSpecified)
{
if (SUCCEEDED(pObject->get_Security_(&pSecurity)))
{
if (authnSpecified)
pSecurity->put_AuthenticationLevel (eAuthLevel);
if (impSpecified)
pSecurity->put_ImpersonationLevel (eImpersonLevel);
}
}
}
//***************************************************************************
//
// CWbemParseDN::CWbemParseDN
//
// DESCRIPTION:
//
// Constructor.
//
//***************************************************************************
CWbemParseDN::CWbemParseDN():
m_cRef(0)
{
InterlockedIncrement(&g_cObj);
}
//***************************************************************************
//
// CWbemParseDN::~CWbemParseDN
//
// DESCRIPTION:
//
// Destructor.
//
//***************************************************************************
CWbemParseDN::~CWbemParseDN(void)
{
InterlockedDecrement(&g_cObj);
}
//***************************************************************************
// HRESULT CWbemParseDN::QueryInterface
// long CWbemParseDN::AddRef
// long CWbemParseDN::Release
//
// DESCRIPTION:
//
// Standard Com IUNKNOWN functions.
//
//***************************************************************************
STDMETHODIMP CWbemParseDN::QueryInterface (
IN REFIID riid,
OUT LPVOID *ppv
)
{
*ppv=NULL;
if (IID_IUnknown==riid)
*ppv = (IUnknown *)this;
else if (IID_IParseDisplayName==riid)
*ppv = (IParseDisplayName *)this;
if (NULL!=*ppv)
{
((LPUNKNOWN)*ppv)->AddRef();
return NOERROR;
}
return E_NOINTERFACE;
}
STDMETHODIMP_(ULONG) CWbemParseDN::AddRef(void)
{
InterlockedIncrement(&m_cRef);
return m_cRef;
}
STDMETHODIMP_(ULONG) CWbemParseDN::Release(void)
{
InterlockedDecrement(&m_cRef);
if (0L!=m_cRef)
return m_cRef;
delete this;
return 0;
}
//***************************************************************************
//
// SCODE CWbemParseDN::ParseDisplayName
//
// DESCRIPTION:
//
// Take a CIM object path and return a suitable ISWbem... object
//
// PARAMETERS:
//
// pCtx The binding context (not used)
// szDisplayName The display name to be parsed
// pchEaten On return identifies how much of the DN has been
// consumed
// ppmk On return will address the moniker pointer
//
// RETURN VALUES:
//
// E_FAIL misery
//
// Other CreateMoniker codes are returned.
//
//***************************************************************************
STDMETHODIMP CWbemParseDN::ParseDisplayName(
IBindCtx* pCtx,
LPOLESTR szDisplayName,
ULONG* pchEaten,
IMoniker** ppmk)
{
HRESULT hr = E_FAIL;
LPUNKNOWN pUnknown = NULL;
ULONG lTemp = 0;
enum WbemAuthenticationLevelEnum eAuthLevel;
enum WbemImpersonationLevelEnum eImpersonLevel;
bool authnSpecified = false;
bool impSpecified = false;
BSTR bsAuthority = NULL;
//Check input parameters
*ppmk = NULL;
if (NULL != pchEaten)
*pchEaten = 0;
if (NULL == szDisplayName)
return E_FAIL;
/*
* moniker : wmiMoniker
*
* wmiMoniker : ["winmgmts:" | "wmi:"] securitySetting ["[" localeSetting "]"] ["!" objectPath]
* | ["winmgmts:" | "wmi:"] "[" localeSetting "]" ["!" objectPath]
* | ["winmgmts:" | "wmi:"] [objectPath]
* | [nativePath]
*
* localeSetting : "locale" <ows> "=" <ows> localeID
*
* localeID : a value of the form "ms_xxxx" where xxxx is a hex LCID value e.g. "ms_0x409".
*
* objectPath : a valid WMI Object Path
*
* securitySetting : "{" <ows> authAndImpersonSettings [<ows> "," <ows> privilegeOverrides]
* | "{" <ows> authAndImpersonSettings [<ows> "," <ows> privilegeOverrides] <ows> "}" <ows>
* | "{" <ows> privilegeOverrides <ows> "}" <ows>
*
*
* authAndImpersonSettings :
* authenticationLevel
* | impersonationLevel
* | authority
* | authenticationLevel <ows> "," <ows> impersonationLevel [<ows> "," <ows> authority]
* | authenticationLevel <ows> "," <ows> authority [<ows> "," <ows> impersonationLevel]
* | impersonationLevel <ows> "," <ows> authenticationLevel [<ows> "," <ows> authority]
* | impersonationLevel <ows> "," <ows> authority [<ows> "," <ows> authenticationLevel]
* | authority <ows> "," <ows> impersonationLevel [<ows> "," <ows> authenticationLevel]
* | authority <ows> "," <ows> authenticationLevel [<ows> "," <ows> impersonationLevel]
*
*
* authority : "authority" <ows> "=" <ows> authorityValue
*
* authorityValue : Any valid WMI authority string e.g. "kerberos:mydomain\server" or "ntlmdomain:mydomain". Note that backslashes need to be escaped in JScript.
*
* authenticationLevel : "authenticationLevel" <ows> "=" <ows> authenticationValue
*
* authenticationValue : "default" | "none" | "connect" | "call" | "pkt" | "pktIntegrity" | "pktPrivacy"
*
* impersonationLevel : "impersonationLevel" <ows> "=" <ows> impersonationValue
*
* impersonationValue : "anonymous" | "identify" | "impersonate" | "delegate"
*
* privilegeOverrides : "(" <ows> privileges <ows> ")"
*
* privileges : privilege [<ows> "," <ows> privileges <ows>]*
*
* privilege : ["!"] privilegeName
*
* privilegeName : "CreateToken" | "PrimaryToken" | "LockMemory" | "IncreaseQuota"
* | "MachineAccount" | "Tcb" | "Security" | "TakeOwnership"
* | "LoadDriver" | "SystemProfile" | "SystemTime"
* | "ProfileSingleProcess" | "IncreaseBasePriority"
* | "CreatePagefile" | "CreatePermanent" | "Backup" | "Restore"
* | "Shutdown" | "Debug" | "Audit" | "SystemEnvironment" | "ChangeNotify"
* | "RemoteShutdown"
*
*/
// It had better start with our scheme name
bool bCheckContext = false;
if (0 == _wcsnicmp (szDisplayName, WBEMS_PDN_SCHEME, wcslen (WBEMS_PDN_SCHEME)))
{
*pchEaten += wcslen (WBEMS_PDN_SCHEME);
bCheckContext = (pCtx && (wcslen (szDisplayName) == wcslen (WBEMS_PDN_SCHEME)));
}
else
return E_FAIL;
// One more check - if it was just the scheme and no more check for extra info in the context
if (bCheckContext)
{
IUnknown *pUnk = NULL;
if (SUCCEEDED (pCtx->GetObjectParam (L"WmiObject", &pUnk)) && pUnk)
{
// Is it an IWbemClassObject?
IWbemClassObject *pIWbemClassObject = NULL;
// Or is it an IWbemContext?
IWbemContext *pIWbemContext = NULL;
// Or is it an IWbemServices?
IWbemServices *pIWbemServices = NULL;
if (SUCCEEDED (pUnk->QueryInterface (IID_IWbemClassObject, (void **) &pIWbemClassObject)))
{
CSWbemObject *pSWbemObject = new CSWbemObject (NULL, pIWbemClassObject);
if (!pSWbemObject)
hr = E_OUTOFMEMORY;
else
{
CComPtr<ISWbemObjectEx> pISWbemObjectEx;
if (SUCCEEDED (pSWbemObject->QueryInterface (IID_ISWbemObjectEx, (void **) &pISWbemObjectEx)))
hr = CreatePointerMoniker (pISWbemObjectEx, ppmk);
}
pIWbemClassObject->Release ();
}
else if (SUCCEEDED (pUnk->QueryInterface (IID_IWbemContext, (void **) &pIWbemContext)))
{
CSWbemNamedValueSet *pSWbemNamedValueSet = new CSWbemNamedValueSet (NULL, pIWbemContext);
if (!pSWbemNamedValueSet)
hr = E_OUTOFMEMORY;
else
{
CComPtr<ISWbemNamedValueSet> pISWbemNamedValueSet;
if (SUCCEEDED (pSWbemNamedValueSet->QueryInterface (IID_ISWbemNamedValueSet,
(PPVOID)&pISWbemNamedValueSet)))
hr = CreatePointerMoniker (pISWbemNamedValueSet, ppmk);
}
pIWbemContext->Release ();
}
else if (SUCCEEDED (pUnk->QueryInterface (IID_IWbemServices, (void **) &pIWbemServices)))
{
// In this case we must get passed the object path as well
CComPtr<IUnknown> pUnkPath;
if (SUCCEEDED (pCtx->GetObjectParam (L"WmiObjectPath", &pUnkPath)) && pUnkPath)
{
CComPtr<ISWbemObjectPath> pISWbemObjectPath;
if (SUCCEEDED (pUnkPath->QueryInterface (IID_ISWbemObjectPath, (void **) &pISWbemObjectPath)))
{
// Dig the path out to initialize
CComBSTR bsNamespace = NULL;
pISWbemObjectPath->get_Path (&bsNamespace);
CSWbemServices *pSWbemServices = new CSWbemServices (pIWbemServices,
bsNamespace, (BSTR) NULL, NULL, NULL);
if (!pSWbemServices)
hr = E_OUTOFMEMORY;
else
{
CComQIPtr<ISWbemServicesEx>
pISWbemServicesEx (pSWbemServices);
if (pISWbemServicesEx)
hr = CreatePointerMoniker (pISWbemServicesEx, ppmk);
}
}
}
pIWbemServices->Release ();
}
pUnk->Release ();
}
// If this worked return now - o/w revert to regular parsing
if (SUCCEEDED (hr))
return hr;
}
// Check for the optional security info
CSWbemPrivilegeSet privilegeSet;
if (ParseSecurity(szDisplayName + *pchEaten, &lTemp, authnSpecified, &eAuthLevel,
impSpecified, &eImpersonLevel, privilegeSet,
bsAuthority))
*pchEaten += lTemp;
// If no impersonation level was specified, get the default from the registry
if (!impSpecified)
{
eImpersonLevel = CSWbemSecurity::GetDefaultImpersonationLevel ();
impSpecified = true;
}
// Create a locator
CSWbemLocator *pCSWbemLocator = new CSWbemLocator(&privilegeSet);
if (!pCSWbemLocator)
hr = E_OUTOFMEMORY;
else
{
CComQIPtr<ISWbemLocator> pISWbemLocator (pCSWbemLocator);
if (pISWbemLocator)
{
// Parse the locale information (if present)
lTemp = 0;
BSTR bsLocale = NULL;
if (ParseLocale (szDisplayName + *pchEaten, &lTemp, bsLocale))
{
*pchEaten += lTemp;
// Skip over the "!" separator if there is one
if(*(szDisplayName + *pchEaten) != NULL)
if (0 == _wcsnicmp (szDisplayName + *pchEaten, WBEMS_EXCLAMATION, wcslen (WBEMS_EXCLAMATION)))
*pchEaten += wcslen (WBEMS_EXCLAMATION);
// Now ready to parse the path - check if we have the degenerate cases
if (0 == wcslen (szDisplayName + *pchEaten))
{
// Need to return connection to default namespace on local machine
CComPtr<ISWbemServices> pISWbemServices;
if (SUCCEEDED( hr = pISWbemLocator->ConnectServer (NULL, NULL, NULL, NULL,
bsLocale, bsAuthority, 0, NULL, &pISWbemServices)) )
{
SecureProxy (authnSpecified, eAuthLevel, impSpecified, eImpersonLevel, pISWbemServices);
hr = CreatePointerMoniker(pISWbemServices, ppmk);
}
}
else
{
/*
* Check the path to see if we are dealing with a class or an instance.
* Note that we construct the parser with a flag indicating that relative
* namespace paths are OK (not the default behavior).
*/
CWbemPathCracker pathCracker (szDisplayName + *pchEaten);
if (CWbemPathCracker::WbemPathType::wbemPathTypeError != pathCracker.GetType ())
{
CComBSTR bsNamespacePath, bsServerPath;
if (pathCracker.GetNamespacePath (bsNamespacePath)
&& pathCracker.GetServer (bsServerPath))
{
// Success - begin by connecting to the namespace.
CComPtr<ISWbemServices> pISWbemServices;
if (SUCCEEDED( hr = pISWbemLocator->ConnectServer (bsServerPath,
bsNamespacePath, NULL, NULL, bsLocale, bsAuthority, 0, NULL, &pISWbemServices)) )
{
// Secure the proxy using the specified security settings (if any)
SecureProxy (authnSpecified, eAuthLevel, impSpecified, eImpersonLevel, pISWbemServices);
// Successful connection - now work out if we have a class or instance
// component.
if (pathCracker.IsClassOrInstance())
{
CComPtr<ISWbemObject> pISWbemObject;
// Now get it
CComBSTR bsRelPath;
if (pathCracker.GetPathText (bsRelPath, true))
{
long lFlags = 0;
// Note that when we retrieve the object we will retrieve
// the localized version if a locale was specified in the moniker
if ((NULL != bsLocale) && (0 < wcslen (bsLocale)))
lFlags |= wbemFlagUseAmendedQualifiers;
if (SUCCEEDED( hr = pISWbemServices->Get (bsRelPath,
lFlags, NULL, &pISWbemObject)) )
hr = CreatePointerMoniker (pISWbemObject, ppmk);
}
}
else
{
// Just a namespace
hr = CreatePointerMoniker(pISWbemServices, ppmk);
}
}
}
else
hr = WBEM_E_INVALID_SYNTAX; // Parse failure - abandon ship
}
else
hr = WBEM_E_INVALID_SYNTAX; // Parse failure - abandon ship
}
}
else
{
// Parse failure
hr = WBEM_E_INVALID_SYNTAX;
}
SysFreeString (bsLocale);
}
}
SysFreeString (bsAuthority);
if (FAILED (hr))
*pchEaten = 0;
else
*pchEaten = wcslen(szDisplayName);
return hr;
}
//***************************************************************************
//
// BOOLEAN CWbemParseDN::ParseSecurity
//
// DESCRIPTION:
//
// Take an authentication and impersonlation level string as described by the
// non-terminal authAndImpersonLevel and parse it into the authentication
// and impersonation levels
//
// PARAMETERS:
//
// lpszInputString The string to be parsed
// pchEaten On return identifies how much of the DN has been
// consumed
// authnSpecified Whether the Moniker specifies a non-default
// authn levl
// lpeAuthLevel The authentication level parsed. This is one of
// enum WbemAuthenticationLevelEnum.
// impSpecified Whether the Moniker specifies a non-default imp
// level
// lpeImpersonLevel The impersonation level parsed. This is one of
// enum WbemImpersonationLevelEnum.
// privilegeSet On return contains the specified privileges
// bsAuthority On return contains the specified authority
//
// RETURN VALUES:
//
// TRUE Parsing was successful. The lpeAuthLevel and
// lpeImpersonLevel arguments have valid data.
// FALSE Parsing failed.
//
//
//***************************************************************************
bool CWbemParseDN::ParseSecurity (
LPWSTR lpszInputString,
ULONG* pchEaten,
bool &authnSpecified,
enum WbemAuthenticationLevelEnum *lpeAuthLevel,
bool &impSpecified,
enum WbemImpersonationLevelEnum *lpeImpersonLevel,
CSWbemPrivilegeSet &privilegeSet,
BSTR &bsAuthority)
{
bool status = false;
// Set the default authentication and impersonation levels.
*lpeAuthLevel = wbemAuthenticationLevelNone;
*lpeImpersonLevel = wbemImpersonationLevelImpersonate;
// Initialize the number of consumed characters
*pchEaten = 0;
// Parse the contents
if (ParseAuthAndImpersonLevel (lpszInputString, pchEaten, authnSpecified, lpeAuthLevel,
impSpecified, lpeImpersonLevel, privilegeSet, bsAuthority))
status = true;
else
*pchEaten = 0;
return status;
}
//***************************************************************************
//
// BOOLEAN CWbemParseDN::ParseLocale
//
// DESCRIPTION:
//
// Take locale setting string as described by the non-terminal localeSetting
// and parse it.
//
// PARAMETERS:
//
// lpszInputString The string to be parsed
// pchEaten On return identifies how much of the DN has been
// consumed
// bsLocale Reference to BSTR to hold parsed locale setting
//
// RETURN VALUES:
//
// TRUE Parsing was successful.
// FALSE Parsing failed.
//
//
//***************************************************************************
bool CWbemParseDN::ParseLocale (
LPWSTR lpszInputString,
ULONG* pchEaten,
BSTR &bsLocale)
{
bool status = true;
// Initialize the number of consumed characters
*pchEaten = 0;
// The first character should be '[' - if not we are done
if (0 == _wcsnicmp (lpszInputString, WBEMS_LEFT_SQBRK, wcslen (WBEMS_LEFT_SQBRK)))
{
status = false;
*pchEaten += wcslen (WBEMS_LEFT_SQBRK);
// Parse the locale setting
SKIPWHITESPACE
// The next string should be "locale"
if(0 == _wcsnicmp(lpszInputString + *pchEaten, WBEMS_LOCALE, wcslen(WBEMS_LOCALE)))
{
*pchEaten += wcslen (WBEMS_LOCALE);
SKIPWHITESPACE
// Next should be "="
if(0 == _wcsnicmp(lpszInputString + *pchEaten, WBEMS_EQUALS, wcslen(WBEMS_EQUALS)))
{
*pchEaten += wcslen (WBEMS_EQUALS);
SKIPWHITESPACE
// Now we should have a character not equal to "]" (i.e. must specify locale ID string)
if (0 != _wcsnicmp (lpszInputString + *pchEaten, WBEMS_RIGHT_SQBRK, wcslen (WBEMS_RIGHT_SQBRK)))
{
// Consume everything up to the next space or "]"
LPWSTR cStr = CURRENTSTR;
ULONG lEaten = 0; // How many characters we consume
ULONG lLocale = 0; // The actual length of the locale ID
while (*(cStr + lEaten))
{
if (_istspace(*(cStr + lEaten)))
{
lEaten++;
// Hit white space - now skip until we find the "]"
SKIPWHITESPACE
// Now we must have a "]"
if (0 == _wcsnicmp
(cStr + lEaten, WBEMS_RIGHT_SQBRK, wcslen (WBEMS_RIGHT_SQBRK)))
{
// Success - we are done
lEaten += wcslen (WBEMS_RIGHT_SQBRK);
}
break;
}
else if (0 == _wcsnicmp (cStr + lEaten, WBEMS_RIGHT_SQBRK, wcslen (WBEMS_RIGHT_SQBRK)))
{
// Hit closing "]" - we are done
lEaten += wcslen (WBEMS_RIGHT_SQBRK);
break;
}
else // Consumed a locale character - keep on truckin'
{
lLocale++;
lEaten++;
}
}
// If we terminated correctly, save the locale setting
if ((lEaten > 1) && (lLocale > 0))
{
status = true;
LPWSTR pLocaleStr = new WCHAR [lLocale + 1];
if (pLocaleStr)
{
wcsncpy (pLocaleStr, lpszInputString + *pchEaten, lLocale);
pLocaleStr [lLocale] = NULL;
bsLocale = SysAllocString (pLocaleStr);
delete [] pLocaleStr;
*pchEaten += lEaten;
}
else
status = false;
}
}
}
}
}
if (!status)
*pchEaten = 0;
return status;
}
//***************************************************************************
//
// BOOLEAN CWbemParseDN::ParseAuthAndImpersonLevel
//
// DESCRIPTION:
//
// Take an authentication/impersonlation/authority level string as described by the
// non-terminal authAndImpersonLevel and parse it into the authentication
// and impersonation levels and the authority string
//
// PARAMETERS:
//
// lpszInputString The string to be parsed
// pchEaten On return identifies how much of the DN has been
// consumed
// authnSpecified Whether the Moniker specifies a non-default
// authn levl
// lpeAuthLevel The authentication level parsed. This is one of
// enum WbemAuthenticationLevelEnum.
// impSpecified Whether the Moniker specifies a non-default imp
// level
// lpeImpersonLevel The impersonation level parsed. This is one of
// enum WbemImpersonationLevelEnum.
// privilegeSet On return holds the privileges
// bsAuthority On retunr holds the authority string (if any)
//
// RETURN VALUES:
//
// TRUE Parsing was successful. The lpeAuthLevel and
// lpeImpersonLevel arguments have valid data.
// FALSE Parsing failed.
//
//
//***************************************************************************
bool CWbemParseDN::ParseAuthAndImpersonLevel (
LPWSTR lpszInputString,
ULONG* pchEaten,
bool &authnSpecified,
enum WbemAuthenticationLevelEnum *lpeAuthLevel,
bool &impSpecified,
enum WbemImpersonationLevelEnum *lpeImpersonLevel,
CSWbemPrivilegeSet &privilegeSet,
BSTR &bsAuthority)
{
// The first character should be '{'
if (0 != _wcsnicmp (lpszInputString, WBEMS_LEFT_CURLY, wcslen (WBEMS_LEFT_CURLY)))
return FALSE;
else
*pchEaten += wcslen (WBEMS_LEFT_CURLY);
bool authoritySpecified = false;
bool privilegeSpecified = false;
bool done = false;
bool error = false;
while (!done)
{
bool parsingAuthenticationLevel = false; // Which token are we parsing?
bool parsingPrivilegeSet = false;
bool parsingAuthority = false;
SKIPWHITESPACE
// The next string should be one of "authenticationLevel", "impersonationLevel",
// "authority", the privilege collection start marker "(", or the security
// descriptor start marker "<"
if(0 == _wcsnicmp(lpszInputString + *pchEaten, WBEMS_AUTH_LEVEL, wcslen(WBEMS_AUTH_LEVEL)))
{
// Error if we have already parsed this or have parsed privilege set
if (authnSpecified || privilegeSpecified)
{
error = true;
break;
}
else
{
parsingAuthenticationLevel = true;
*pchEaten += wcslen (WBEMS_AUTH_LEVEL);
}
}
else if (0 == _wcsnicmp(lpszInputString + *pchEaten, WBEMS_IMPERSON_LEVEL, wcslen(WBEMS_IMPERSON_LEVEL)))
{
// Error if we have already parsed this or have parsed privilege set
if (impSpecified || privilegeSpecified)
{
error = true;
break;
}
else
*pchEaten += wcslen (WBEMS_IMPERSON_LEVEL) ;
}
else if (0 == _wcsnicmp(lpszInputString + *pchEaten, WBEMS_AUTHORITY, wcslen(WBEMS_AUTHORITY)))
{
// Error if we have already parsed this or have parsed privilege set
if (authoritySpecified || privilegeSpecified)
{
error = true;
break;
}
else
{
parsingAuthority = true;
*pchEaten += wcslen (WBEMS_AUTHORITY) ;
}
}
else if (0 == _wcsnicmp(lpszInputString + *pchEaten, WBEMS_LEFT_PAREN, wcslen(WBEMS_LEFT_PAREN)))
{
// Error if we have already done this
if (privilegeSpecified)
{
error = true;
break;
}
else
{
parsingPrivilegeSet = true;
*pchEaten += wcslen (WBEMS_LEFT_PAREN);
}
}
else
{
// Unrecognized token or NULL
error = true;
break;
}
// Getting here means we have something to parse
SKIPWHITESPACE
if (parsingPrivilegeSet)
{
ULONG chEaten = 0;
if (ParsePrivilegeSet (lpszInputString + *pchEaten, &chEaten, privilegeSet))
{
privilegeSpecified = true;
*pchEaten += chEaten;
// If the next token is "}" we are done
if(0 == _wcsnicmp(lpszInputString + *pchEaten, WBEMS_RIGHT_CURLY, wcslen(WBEMS_RIGHT_CURLY)))
{
*pchEaten += wcslen (WBEMS_RIGHT_CURLY);
done = true;
}
}
else
{
error = true;
break;
}
}
else
{
// Parsing authentication, impersonation or authority. The next character should be '='
if(0 != _wcsnicmp(lpszInputString + *pchEaten, WBEMS_EQUALS, wcslen(WBEMS_EQUALS)))
{
error = true;
break;
}
else
{
*pchEaten += wcslen (WBEMS_EQUALS);
SKIPWHITESPACE
if (parsingAuthenticationLevel)
{
if (!ParseAuthenticationLevel (lpszInputString, pchEaten, lpeAuthLevel))
{
error = true;
break;
}
else
authnSpecified = true;
}
else if (parsingAuthority)
{
// Get the authority string
if (!ParseAuthority (lpszInputString, pchEaten, bsAuthority))
{
error = true;
break;
}
else
authoritySpecified = true;
}
else
{
// Must be parsing impersonation level
if (!ParseImpersonationLevel (lpszInputString, pchEaten, lpeImpersonLevel))
{
error = true;
break;
}
else
impSpecified = true;
}
SKIPWHITESPACE
// The next token should be "}" or ","
if(0 == _wcsnicmp(lpszInputString + *pchEaten, WBEMS_RIGHT_CURLY, wcslen(WBEMS_RIGHT_CURLY)))
{
*pchEaten += wcslen (WBEMS_RIGHT_CURLY);
done = true;
}
else if(0 == _wcsnicmp(lpszInputString + *pchEaten, WBEMS_COMMA, wcslen(WBEMS_COMMA)))
{
// If we have parsed all expected tokens this is an error
if (authnSpecified && impSpecified && authoritySpecified && privilegeSpecified)
{
error = true;
break;
}
else
{
*pchEaten += wcslen (WBEMS_COMMA);
// Loop round again for the next token
}
}
else
{
// Unrecognized token
error = true;
break;
}
}
}
}
if (error)
{
impSpecified = authnSpecified = false;
*pchEaten = 0;
return false;
}
return true; // success
}
//***************************************************************************
//
// BOOLEAN CWbemParseDN::ParseImpersonationLevel
//
// DESCRIPTION:
//
// Parse the string specification of an impersonation level into a
// symbolic constant value.
//
// PARAMETERS:
//
// lpszInputString The string to be parsed
// pchEaten On return identifies how much of the DN has been
// consumed
// lpeImpersonLevel The impersonation level parsed. This is one of
// enum WbemImpersonationLevelEnum.
//
// RETURN VALUES:
//
// TRUE Parsing was successful. The lpeImpersonLevel
// argument has valid data.
// FALSE Parsing failed.
//
//
//***************************************************************************
bool CWbemParseDN::ParseImpersonationLevel (
LPWSTR lpszInputString,
ULONG* pchEaten,
enum WbemImpersonationLevelEnum *lpeImpersonLevel
)
{
bool status = true;
if(0 == _wcsnicmp(lpszInputString + *pchEaten, WBEMS_IMPERSON_ANON, wcslen(WBEMS_IMPERSON_ANON)))
{
*lpeImpersonLevel = wbemImpersonationLevelAnonymous;
*pchEaten += wcslen (WBEMS_IMPERSON_ANON);
}
else if(0 == _wcsnicmp(lpszInputString + *pchEaten, WBEMS_IMPERSON_IDENTIFY, wcslen(WBEMS_IMPERSON_IDENTIFY)))
{
*lpeImpersonLevel = wbemImpersonationLevelIdentify;
*pchEaten += wcslen (WBEMS_IMPERSON_IDENTIFY);
}
else if(0 == _wcsnicmp(lpszInputString + *pchEaten, WBEMS_IMPERSON_IMPERSON, wcslen(WBEMS_IMPERSON_IMPERSON)))
{
*lpeImpersonLevel = wbemImpersonationLevelImpersonate;
*pchEaten += wcslen (WBEMS_IMPERSON_IMPERSON);
}
else if(0 == _wcsnicmp(lpszInputString + *pchEaten, WBEMS_IMPERSON_DELEGATE, wcslen(WBEMS_IMPERSON_DELEGATE)))
{
*lpeImpersonLevel = wbemImpersonationLevelDelegate;
*pchEaten += wcslen (WBEMS_IMPERSON_DELEGATE);
}
else
status = false;
return status;
}
//***************************************************************************
//
// BOOLEAN CWbemParseDN::ParseAuthenticationLevel
//
// DESCRIPTION:
//
// Parse the string specification of an authentication level into a
// symbolic constant value.
//
// PARAMETERS:
//
// lpszInputString The string to be parsed
// pchEaten On return identifies how much of the DN has been
// consumed
// lpeAuthLevel The authentication level parsed. This is one of
// enum WbemAuthenticationLevelEnum.
//
// RETURN VALUES:
//
// TRUE Parsing was successful. The lpeAuthLevel
// argument has valid data.
// FALSE Parsing failed.
//
//
//***************************************************************************
bool CWbemParseDN::ParseAuthenticationLevel (
LPWSTR lpszInputString,
ULONG* pchEaten,
enum WbemAuthenticationLevelEnum *lpeAuthLevel
)
{
bool status = true;
if(0 == _wcsnicmp(lpszInputString + *pchEaten, WBEMS_AUTH_DEFAULT, wcslen(WBEMS_AUTH_DEFAULT)))
{
*lpeAuthLevel = wbemAuthenticationLevelDefault;
*pchEaten += wcslen (WBEMS_AUTH_DEFAULT);
}
else if(0 == _wcsnicmp(lpszInputString + *pchEaten, WBEMS_AUTH_NONE, wcslen(WBEMS_AUTH_NONE)))
{
*lpeAuthLevel = wbemAuthenticationLevelNone;
*pchEaten += wcslen (WBEMS_AUTH_NONE);
}
else if(0 == _wcsnicmp(lpszInputString + *pchEaten, WBEMS_AUTH_CONNECT, wcslen(WBEMS_AUTH_CONNECT)))
{
*lpeAuthLevel = wbemAuthenticationLevelConnect;
*pchEaten += wcslen (WBEMS_AUTH_CONNECT);
}
else if(0 == _wcsnicmp(lpszInputString + *pchEaten, WBEMS_AUTH_CALL, wcslen(WBEMS_AUTH_CALL)))
{
*lpeAuthLevel = wbemAuthenticationLevelCall;
*pchEaten += wcslen (WBEMS_AUTH_CALL);
}
else if(0 == _wcsnicmp(lpszInputString + *pchEaten, WBEMS_AUTH_PKT_INT, wcslen(WBEMS_AUTH_PKT_INT)))
{
*lpeAuthLevel = wbemAuthenticationLevelPktIntegrity;
*pchEaten += wcslen (WBEMS_AUTH_PKT_INT);
}
else if(0 == _wcsnicmp(lpszInputString + *pchEaten, WBEMS_AUTH_PKT_PRIV, wcslen(WBEMS_AUTH_PKT_PRIV)))
{
*lpeAuthLevel = wbemAuthenticationLevelPktPrivacy;
*pchEaten += wcslen (WBEMS_AUTH_PKT_PRIV);
}
else if(0 == _wcsnicmp(lpszInputString + *pchEaten, WBEMS_AUTH_PKT, wcslen(WBEMS_AUTH_PKT)))
{
*lpeAuthLevel = wbemAuthenticationLevelPkt;
*pchEaten += wcslen (WBEMS_AUTH_PKT);
}
else
status = false;
return status;
}
//***************************************************************************
//
// BOOLEAN CWbemParseDN::ParseAuthority
//
// DESCRIPTION:
//
// Take authority setting string as described by the non-terminal localeSetting
// and parse it.
//
// PARAMETERS:
//
// lpszInputString The string to be parsed
// pchEaten On return identifies how much of the DN has been
// consumed
// bsAuthority Reference to BSTR to hold parsed authority string
//
// RETURN VALUES:
//
// TRUE Parsing was successful.
// FALSE Parsing failed.
//
//
//***************************************************************************
bool CWbemParseDN::ParseAuthority (
LPWSTR lpszInputString,
ULONG* pchEaten,
BSTR &bsAuthority)
{
bool status = false;
// Now we should have a character not equal to "," or "}" (i.e. must specify authority string)
if ((0 != _wcsnicmp (lpszInputString + *pchEaten, WBEMS_COMMA, wcslen (WBEMS_COMMA))) &&
(0 != _wcsnicmp (lpszInputString + *pchEaten, WBEMS_RIGHT_CURLY, wcslen (WBEMS_RIGHT_CURLY))))
{
// Consume everything up to the next space, "," or "]"
LPWSTR cStr = CURRENTSTR;
ULONG lEaten = 0; // Number of characters consumed
ULONG lAuthority = 0; // Actual length of the authority string
while (*(cStr + lEaten))
{
if (_istspace(*(cStr + lEaten)))
{
// Hit white space - stop now
break;
}
else if ((0 == _wcsnicmp (cStr + lEaten, WBEMS_RIGHT_CURLY, wcslen (WBEMS_RIGHT_CURLY))) ||
(0 == _wcsnicmp (cStr + lEaten, WBEMS_COMMA, wcslen (WBEMS_COMMA))))
{
// Hit closing "}" or "," - we are done; unpop the "}" or "," as that will be handled
// in the calling function
break;
}
else // Keep on truckin'
{
lAuthority++;
lEaten++;
}
}
// If we terminated correctly, save the locale setting
if ((lEaten > 1) && (lAuthority > 0))
{
status = true;
LPWSTR pAuthorityStr = new WCHAR [lAuthority + 1];
if (pAuthorityStr)
{
wcsncpy (pAuthorityStr, lpszInputString + *pchEaten, lAuthority);
pAuthorityStr [lAuthority] = NULL;
bsAuthority = SysAllocString (pAuthorityStr);
delete [] pAuthorityStr;
*pchEaten += lEaten;
}
else
status = false;
}
}
if (!status)
*pchEaten = 0;
return status;
}
//***************************************************************************
//
// BOOLEAN CWbemParseDN::ParsePrivilegeSet
//
// DESCRIPTION:
//
// Parse the string specification of privilege settings.
//
// PARAMETERS:
//
// lpszInputString The string to be parsed
// pchEaten On return identifies how much of the DN has been
// consumed
// privilegeSet The container into which the parsed privileges
// are stored.
//
// RETURN VALUES:
//
// TRUE Parsing was successful.
// FALSE Parsing failed.
//
//
//***************************************************************************
bool CWbemParseDN::ParsePrivilegeSet (
LPWSTR lpszInputString,
ULONG *pchEaten,
CSWbemPrivilegeSet &privilegeSet
)
{
// We have consumed the initial "(". Now we are looking for
// a list of privileges, followed by a final ")"
bool status = true;
ULONG chEaten = *pchEaten; // In case we need to roll back
bool done = false;
bool firstPrivilege = true;
SKIPWHITESPACE
while (!done)
{
VARIANT_BOOL bEnabled = VARIANT_TRUE;
// If not the first privilege we are expecting a ","
if (!firstPrivilege)
{
if (0 == _wcsnicmp(lpszInputString + *pchEaten, WBEMS_COMMA, wcslen(WBEMS_COMMA)))
{
*pchEaten += wcslen (WBEMS_COMMA);
SKIPWHITESPACE
}
else
{
status = false;
break;
}
}
// Next token may be a "!" to indicate a disabled privilege
if (0 == _wcsnicmp(lpszInputString + *pchEaten, WBEMS_EXCLAMATION, wcslen(WBEMS_EXCLAMATION)))
{
*pchEaten += wcslen (WBEMS_EXCLAMATION);
bEnabled = VARIANT_FALSE;
SKIPWHITESPACE
}
// Next token must be a valid privilege moniker name
WbemPrivilegeEnum iPrivilege;
if (CSWbemPrivilege::GetIdFromMonikerName (lpszInputString + *pchEaten, iPrivilege))
{
ISWbemPrivilege *pDummy = NULL;
if (SUCCEEDED (privilegeSet.Add (iPrivilege, bEnabled, &pDummy)))
{
*pchEaten += wcslen (CSWbemPrivilege::GetMonikerNameFromId (iPrivilege));
pDummy->Release ();
}
else
{
status = false;
break;
}
}
else
{
// Didn't recognize the privilege name
status = false;
break;
}
SKIPWHITESPACE
// Finally if we meet a ")" we are truly done with no error
if (0 == _wcsnicmp(lpszInputString + *pchEaten, WBEMS_RIGHT_PAREN, wcslen(WBEMS_RIGHT_PAREN)))
{
*pchEaten += wcslen (WBEMS_RIGHT_PAREN);
done = true;
SKIPWHITESPACE
}
firstPrivilege = false;
SKIPWHITESPACE
}
if (!status)
{
// Misery - blow away any privileges we might have accrued
*pchEaten = chEaten;
privilegeSet.DeleteAll ();
}
return status;
}
//***************************************************************************
//
// BOOLEAN CWbemParseDN::GetSecurityString
//
// DESCRIPTION:
//
// Take an authentication and impersonlation level and convert it into
// a security specifier string.
//
// PARAMETERS:
//
// authnSpecified Whether a nondefault authn levl is specified.
// authnLevel The authentication level.
// impSpecified Whether a non-default imp level is specified.
// impLevel The impersonation level.
// privilegeSet Privileges
// bsAuthority Authority
//
//
// RETURN VALUES:
// the newly created string (which the caller must free) or NULL
//
//***************************************************************************
wchar_t *CWbemParseDN::GetSecurityString (
bool authnSpecified,
enum WbemAuthenticationLevelEnum authnLevel,
bool impSpecified,
enum WbemImpersonationLevelEnum impLevel,
CSWbemPrivilegeSet &privilegeSet,
BSTR &bsAuthority
)
{
wchar_t *pResult = NULL;
long lPrivilegeCount = 0;
privilegeSet.get_Count (&lPrivilegeCount);
ULONG lNumDisabled = privilegeSet.GetNumberOfDisabledElements ();
PrivilegeMap privMap = privilegeSet.GetPrivilegeMap ();
bool authoritySpecified = ((NULL != bsAuthority) && (0 < wcslen (bsAuthority)));
// Degenerate case - no security info
if (!authnSpecified && !impSpecified && (0 == lPrivilegeCount)
&& !authoritySpecified)
return NULL;
// Must have at least these 2 tokens
size_t len = wcslen (WBEMS_LEFT_CURLY) + wcslen (WBEMS_RIGHT_CURLY);
if (authnSpecified)
{
len += wcslen(WBEMS_AUTH_LEVEL) + wcslen (WBEMS_EQUALS);
switch (authnLevel)
{
case wbemAuthenticationLevelDefault:
len += wcslen (WBEMS_AUTH_DEFAULT);
break;
case wbemAuthenticationLevelNone:
len += wcslen (WBEMS_AUTH_NONE);
break;
case wbemAuthenticationLevelConnect:
len += wcslen (WBEMS_AUTH_CONNECT);
break;
case wbemAuthenticationLevelCall:
len += wcslen (WBEMS_AUTH_CALL);
break;
case wbemAuthenticationLevelPkt:
len += wcslen (WBEMS_AUTH_PKT);
break;
case wbemAuthenticationLevelPktIntegrity:
len += wcslen (WBEMS_AUTH_PKT_INT);
break;
case wbemAuthenticationLevelPktPrivacy:
len += wcslen (WBEMS_AUTH_PKT_PRIV);
break;
default:
return NULL; // Bad level
}
if (impSpecified || authoritySpecified)
len += wcslen (WBEMS_COMMA);
}
if (impSpecified)
{
len += wcslen(WBEMS_IMPERSON_LEVEL) + wcslen (WBEMS_EQUALS);
switch (impLevel)
{
case wbemImpersonationLevelAnonymous:
len += wcslen (WBEMS_IMPERSON_ANON);
break;
case wbemImpersonationLevelIdentify:
len += wcslen (WBEMS_IMPERSON_IDENTIFY);
break;
case wbemImpersonationLevelImpersonate:
len += wcslen (WBEMS_IMPERSON_IMPERSON);
break;
case wbemImpersonationLevelDelegate:
len += wcslen (WBEMS_IMPERSON_DELEGATE);
break;
default:
return NULL; // Bad level
}
if (authoritySpecified)
len += wcslen (WBEMS_COMMA);
}
if (authoritySpecified)
len += wcslen(WBEMS_AUTHORITY) + wcslen (WBEMS_EQUALS) + wcslen (bsAuthority);
if (0 < lPrivilegeCount)
{
// If imp, authn or authority also specified, we need another separator
if (authnSpecified || impSpecified || authoritySpecified)
len += wcslen (WBEMS_COMMA);
// Need these boundary tokens
len += wcslen (WBEMS_LEFT_PAREN) + wcslen (WBEMS_RIGHT_PAREN);
// Need a separator between each privilege
if (1 < lPrivilegeCount)
len += (lPrivilegeCount - 1) * wcslen (WBEMS_COMMA);
// Need to specify false values with "!"
if (lNumDisabled)
len += lNumDisabled * wcslen (WBEMS_EXCLAMATION);
// Now add the privilege strings
PrivilegeMap::iterator next = privMap.begin ();
while (next != privMap.end ())
{
OLECHAR *sMonikerName = CSWbemPrivilege::GetMonikerNameFromId ((*next).first);
if (sMonikerName)
len += wcslen (sMonikerName);
next++;
}
}
pResult = new wchar_t [len + 1];
if (pResult)
{
// Now build the string
wcscpy (pResult, WBEMS_LEFT_CURLY);
if (authnSpecified)
{
wcscat (pResult, WBEMS_AUTH_LEVEL);
wcscat (pResult, WBEMS_EQUALS);
switch (authnLevel)
{
case wbemAuthenticationLevelDefault:
wcscat (pResult, WBEMS_AUTH_DEFAULT);
break;
case wbemAuthenticationLevelNone:
wcscat (pResult, WBEMS_AUTH_NONE);
break;
case wbemAuthenticationLevelConnect:
wcscat (pResult, WBEMS_AUTH_CONNECT);
break;
case wbemAuthenticationLevelCall:
wcscat (pResult, WBEMS_AUTH_CALL);
break;
case wbemAuthenticationLevelPkt:
wcscat (pResult, WBEMS_AUTH_PKT);
break;
case wbemAuthenticationLevelPktIntegrity:
wcscat (pResult, WBEMS_AUTH_PKT_INT);
break;
case wbemAuthenticationLevelPktPrivacy:
wcscat (pResult, WBEMS_AUTH_PKT_PRIV);
break;
}
if (impSpecified || authoritySpecified || (0 < lPrivilegeCount))
wcscat (pResult, WBEMS_COMMA);
}
if (impSpecified)
{
wcscat (pResult, WBEMS_IMPERSON_LEVEL);
wcscat (pResult, WBEMS_EQUALS);
switch (impLevel)
{
case wbemImpersonationLevelAnonymous:
wcscat (pResult, WBEMS_IMPERSON_ANON);
break;
case wbemImpersonationLevelIdentify:
wcscat (pResult, WBEMS_IMPERSON_IDENTIFY);
break;
case wbemImpersonationLevelImpersonate:
wcscat (pResult, WBEMS_IMPERSON_IMPERSON);
break;
case wbemImpersonationLevelDelegate:
wcscat (pResult, WBEMS_IMPERSON_DELEGATE);
break;
default:
return NULL; // Bad level
}
if (authoritySpecified || (0 < lPrivilegeCount))
wcscat (pResult, WBEMS_COMMA);
}
if (authoritySpecified)
{
wcscat (pResult, WBEMS_AUTHORITY);
wcscat (pResult, WBEMS_EQUALS);
wcscat (pResult, bsAuthority);
if ((0 < lPrivilegeCount))
wcscat (pResult, WBEMS_COMMA);
}
if (lPrivilegeCount)
{
wcscat (pResult, WBEMS_LEFT_PAREN);
// Now add the privilege strings
PrivilegeMap::iterator next = privMap.begin ();
bool firstPrivilege = true;
while (next != privMap.end ())
{
if (!firstPrivilege)
wcscat (pResult, WBEMS_COMMA);
firstPrivilege = false;
CSWbemPrivilege *pPrivilege = (*next).second;
VARIANT_BOOL bValue;
if (SUCCEEDED (pPrivilege->get_IsEnabled (&bValue)) &&
(VARIANT_FALSE == bValue))
wcscat (pResult, WBEMS_EXCLAMATION);
OLECHAR *sMonikerName = CSWbemPrivilege::GetMonikerNameFromId ((*next).first);
wcscat (pResult, sMonikerName);
next++;
}
wcscat (pResult, WBEMS_RIGHT_PAREN);
}
wcscat (pResult, WBEMS_RIGHT_CURLY);
pResult [len] = NULL;
}
return pResult;
}
//***************************************************************************
//
// BOOLEAN CWbemParseDN::GetLocaleString
//
// DESCRIPTION:
//
// Take a locale value and convert it into a locale specifier string.
//
// PARAMETERS:
//
// bsLocale The value (if any)
//
// RETURN VALUES:
// the newly created string (which the caller must free) or NULL
//
//***************************************************************************
wchar_t *CWbemParseDN::GetLocaleString (
BSTR bsLocale
)
{
wchar_t *pResult = NULL;
// Degenerate case - no locale info
if (!bsLocale || (0 == wcslen (bsLocale)))
return NULL;
// Calculate length of string
size_t len = wcslen (WBEMS_LEFT_SQBRK) + wcslen (WBEMS_LOCALE) +
wcslen (WBEMS_EQUALS) + wcslen (bsLocale) + wcslen (WBEMS_RIGHT_SQBRK);
pResult = new wchar_t [len + 1];
if (pResult)
{
// Now build the string
wcscpy (pResult, WBEMS_LEFT_SQBRK);
wcscat (pResult, WBEMS_LOCALE);
wcscat (pResult, WBEMS_EQUALS);
wcscat (pResult, bsLocale);
wcscat (pResult, WBEMS_RIGHT_SQBRK);
pResult [len] = NULL;
}
return pResult;
}
#undef CURRENTSTR
#undef SKIPWHITESPACE