//*************************************************************************** // // 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 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 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) { LONG cRef = InterlockedDecrement(&m_cRef); if (0 != cRef) { _ASSERT(cRef > 0); return 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" "=" 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 : "{" authAndImpersonSettings [ "," privilegeOverrides] * | "{" authAndImpersonSettings [ "," privilegeOverrides] "}" * | "{" privilegeOverrides "}" * * * authAndImpersonSettings : * authenticationLevel * | impersonationLevel * | authority * | authenticationLevel "," impersonationLevel [ "," authority] * | authenticationLevel "," authority [ "," impersonationLevel] * | impersonationLevel "," authenticationLevel [ "," authority] * | impersonationLevel "," authority [ "," authenticationLevel] * | authority "," impersonationLevel [ "," authenticationLevel] * | authority "," authenticationLevel [ "," impersonationLevel] * * * authority : "authority" "=" 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" "=" authenticationValue * * authenticationValue : "default" | "none" | "connect" | "call" | "pkt" | "pktIntegrity" | "pktPrivacy" * * impersonationLevel : "impersonationLevel" "=" impersonationValue * * impersonationValue : "anonymous" | "identify" | "impersonate" | "delegate" * * privilegeOverrides : "(" privileges ")" * * privileges : privilege [ "," privileges ]* * * 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 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 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 pUnkPath; if (SUCCEEDED (pCtx->GetObjectParam (L"WmiObjectPath", &pUnkPath)) && pUnkPath) { CComPtr 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 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 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 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 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 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