////////////////////////////////////////////////////////////////////// // globals.cpp : Implementation for the globals // Copyright (c)1997-2001 Microsoft Corporation // // Original Create Date: 2/21/2001 // Original Author: shawnwu ////////////////////////////////////////////////////////////////////// #include "globals.h" LPCWSTR pszRollbackAll = L"RollbackAll"; LPCWSTR pszEmptyRollbackToken = L"EmptyRollbackToken"; LPCWSTR pszCreateDefaultPolicy = L"CreateDefaultPolicy"; LPCWSTR pszGetDefaultPolicyName = L"GetDefaultPolicyName"; // // these are WMI class names to support IPSec // LPCWSTR pszNspGeneral = L"Nsp_GeneralSettings"; LPCWSTR pszNspTcp = L"Nsp_TcpSettings"; LPCWSTR pszNspIPConfigure = L"Nsp_IPConfigSettings"; LPCWSTR pszNspFilter = L"Nsp_FilterSettings"; LPCWSTR pszNspTransportFilter = L"Nsp_TransportFilterSettings"; LPCWSTR pszNspTunnelFilter = L"Nsp_TunnelFilterSettings"; LPCWSTR pszNspMMFilter = L"Nsp_MMFilterSettings"; LPCWSTR pszNspQMPolicy = L"Nsp_QMPolicySettings"; LPCWSTR pszNspMMPolicy = L"Nsp_MMPolicySettings"; LPCWSTR pszNspMMAuth = L"Nsp_MMAuthSettings"; LPCWSTR pszNspExceptionPorts = L"Nsp_ExceptionPorts"; LPCWSTR pszNspRollbackFilter = L"Nsp_RollbackFilter"; LPCWSTR pszNspRollbackPolicy = L"Nsp_RollbackPolicy"; LPCWSTR pszNspRollbackMMAuth = L"Nsp_RollbackMMAuth"; LPCWSTR pszNspTranxManager = L"Nsp_TranxManager"; // // These are WMI class names to support SCW (Security Configuration Wizard) // LPCWSTR pszScwActiveSocket = L"SCW_ActiveSocket"; // // these are WMI class property names for IPSec // LPCWSTR g_pszFilterName = L"FilterName"; LPCWSTR g_pszDirection = L"Direction"; LPCWSTR g_pszFilterType = L"FilterType"; LPCWSTR g_pszInterfaceType = L"InterfaceType"; //LPCWSTR g_pszGenericFilter = L"GenericFilter"; LPCWSTR g_pszCreateMirror = L"CreateMirror"; LPCWSTR g_pszSrcAddr = L"SrcAddr"; LPCWSTR g_pszSrcSubnetMask = L"SrcSubnetMask"; LPCWSTR g_pszSrcAddrType = L"SrcAddrType"; LPCWSTR g_pszDestAddr = L"DestAddr"; LPCWSTR g_pszDestSubnetMask = L"DestSubnetMask"; LPCWSTR g_pszDestAddrType = L"DestAddrType"; LPCWSTR g_pszMMPolicyName = L"MMPolicyName"; LPCWSTR g_pszMMAuthName = L"MMAuthName"; LPCWSTR g_pszInboundFlag = L"InboundFilterFlag"; LPCWSTR g_pszOutboundFlag = L"OutboundFilterFlag"; LPCWSTR g_pszProtocol = L"Protocol"; LPCWSTR g_pszSrcPort = L"SrcPort"; LPCWSTR g_pszDestPort = L"DestPort"; LPCWSTR g_pszQMPolicyName = L"QMPolicyName"; LPCWSTR g_pszTunnelSrcAddr = L"TunnelSrcAddr"; LPCWSTR g_pszTunnelSrcSubnetMask = L"TunnelSrcSubnetMask"; LPCWSTR g_pszTunnelSrcAddrType = L"TunnelSrcAddrType"; LPCWSTR g_pszTunnelDestAddr = L"TunnelDestAddr"; LPCWSTR g_pszTunnelDestSubnetMask = L"TunnelDestSubnetMask"; LPCWSTR g_pszTunnelDestAddrType = L"TunnelDestAddrType"; LPCWSTR g_pszPolicyName = L"PolicyName"; LPCWSTR g_pszPolicyFlag = L"Flag"; LPCWSTR g_pszOfferCount = L"OfferCount"; LPCWSTR g_pszKeyLifeTime = L"KeyLifeTime"; LPCWSTR g_pszKeyLifeTimeKBytes = L"KeyLifeTimeKBytes"; LPCWSTR g_pszSoftSAExpTime = L"SoftSAExpTime"; LPCWSTR g_pszQMLimit = L"QMLimit"; LPCWSTR g_pszDHGroup = L"DHGroup"; LPCWSTR g_pszEncryptID = L"EncryptID"; LPCWSTR g_pszHashID = L"HashID"; LPCWSTR g_pszPFSRequired = L"PFSRequired"; LPCWSTR g_pszPFSGroup = L"PFSGroup"; LPCWSTR g_pszNumAlgos = L"NumAlgos"; LPCWSTR g_pszAlgoOp = L"AlgoOp"; LPCWSTR g_pszAlgoID = L"AlgoID"; LPCWSTR g_pszAlgoSecID = L"AlgoSecID"; LPCWSTR g_pszAuthMethodID = L"AuthMethodID"; LPCWSTR g_pszNumAuthInfos = L"NumAuthInfos"; LPCWSTR g_pszAuthMethod = L"AuthMethod"; LPCWSTR g_pszAuthInfoSize = L"AuthInfoSize"; LPCWSTR g_pszAuthInfo = L"AuthInfo"; LPCWSTR g_pszTokenGuid = L"TokenGuid"; LPCWSTR g_pszAction = L"Action"; LPCWSTR g_pszPreviousData = L"PreviousData"; LPCWSTR g_pszFilterGuid = L"FilterGuid"; LPCWSTR g_pszPolicyType = L"PolicyType"; LPCWSTR g_pszRollback = L"Rollback"; LPCWSTR g_pszClearAll = L"ClearAll"; LPCWSTR g_pszEncryption = L"Encryption"; // // constant strings for SPD data // LPCWSTR g_pszIP_ADDRESS_ME = L"IP_ADDRESS_ME"; LPCWSTR g_pszIP_ADDRESS_MASK_NONE = L"IP_ADDRESS_MASK_NONE"; LPCWSTR g_pszSUBNET_ADDRESS_ANY = L"SUBNET_ADDRESS_ANY"; LPCWSTR g_pszSUBNET_MASK_ANY = L"SUBNET_MASK_ANY"; // // these are WMI class property names for SCW // LPCWSTR g_pszPort = L"Port"; //LPCWSTR g_pszProtocol = L"Protocol"; LPCWSTR g_pszAddress = L"Address"; LPCWSTR g_pszForeignAddress = L"ForeignAddress"; LPCWSTR g_pszForeignPort = L"ForeignPort"; LPCWSTR g_pszState = L"State"; //Listening, Established, TIME_WAIT LPCWSTR g_pszProcessID = L"ProcessID"; LPCWSTR g_pszImageName = L"ImageName"; LPCWSTR g_pszImageTitleBar = L"ImageTitleBar"; LPCWSTR g_pszNTService = L"NTService"; // // these are default quick mode policy names // LPCWSTR g_pszDefQMPolicyNegNone = L"SSR_DEFAULT_QM_POLICY_NEG_NONE"; LPCWSTR g_pszDefQMPolicyNegRequest = L"SSR_DEFAULT_QM_POLICY_NEG_REQUEST"; LPCWSTR g_pszDefQMPolicyNegRequire = L"SSR_DEFAULT_QM_POLICY_NEG_REQUIRE"; LPCWSTR g_pszDefQMPolicyNegMax = L"SSR_DEFAULT_QM_POLICY_NEG_MAX"; /* Routine Description: Name: CheckImpersonationLevel Functionality: Check the impersonation level of the thread to see if the level is at least SecurityImpersonation. Virtual: No. Arguments: None. Return Value: Success: WBEM_NO_ERROR if the impersonation level is at least SecurityImpersonation. Failure: (1) WBEM_E_ACCESS_DENIED. (2) WBEM_E_FAILED if somehow the thread token can't opened or the token information can't be queried. Notes: Make sure that you call this function at the begining of each provider's public interface function. $undone:shawnwu, is there a performance concern? */ HRESULT CheckImpersonationLevel () { HRESULT hr = WBEM_E_ACCESS_DENIED; if (SUCCEEDED(::CoImpersonateClient())) { // // Now, let's check the impersonation level. First, get the thread token // HANDLE hThreadTok; DWORD dwImp, dwBytesReturned; if(!::OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hThreadTok )) { hr = WBEM_E_FAILED; } else { if(::GetTokenInformation(hThreadTok, TokenImpersonationLevel, &dwImp, sizeof(DWORD), &dwBytesReturned)) { // // Is the impersonation level Impersonate? // if (dwImp >= SecurityImpersonation) { hr = WBEM_NO_ERROR; } else { hr = WBEM_E_ACCESS_DENIED; } } else { hr = WBEM_E_FAILED; } ::CloseHandle(hThreadTok); } } return hr; } /* Routine Description: Name: CheckSafeArraySize Functionality: Check to see if the variant has really what the caller wants: a safearray with given count of elements. Virtual: No. Arguments: pVar - The variant. lCount - The claimed size of the variant's array. plLB - Receives the lower bound of the variant's array. plUB - Receives the upper bound of the variant's array. Return Value: Success: WBEM_NO_ERROR. Failure: (1) WBEM_E_VALUE_OUT_OF_RANGE if the claimed size for the variant doesn't match what it really holds. (2) WBEM_E_INVALID_PARAMETER if input parameters are not valid. Notes: */ HRESULT CheckSafeArraySize ( IN VARIANT * pVar, IN long lCount, OUT long * plLB, OUT long * plUB ) { // // we must have a valid variant, and its type must be an array, // and its array value must not be null. // if (pVar == NULL || (pVar->vt & VT_ARRAY) != VT_ARRAY || pVar->parray == NULL || plLB == NULL || plUB == NULL) { return WBEM_E_INVALID_PARAMETER; } *plLB = 0; *plUB = 0; HRESULT hr = ::SafeArrayGetLBound(pVar->parray, 1, plLB); if (SUCCEEDED(hr)) { hr = ::SafeArrayGetUBound(pVar->parray, 1, plUB); } if (SUCCEEDED(hr) && lCount != (*plUB - *plLB + 1) ) { hr = WBEM_E_VALUE_OUT_OF_RANGE; } return SUCCEEDED(hr) ? WBEM_NO_ERROR : hr; } /* Routine Description: Name: GetDWORDSafeArrayElements Functionality: Get all DWORD safearray elements from the variant to the provided DWORD array buffer. Virtual: No. Arguments: pVar - The variant. lCount - The count the caller wants. ppValArray - Receives the wanted number of DWORD from the variant. Return Value: Success: WBEM_NO_ERROR. Failure: (1) WBEM_E_VALUE_OUT_OF_RANGE if the claimed size for the variant doesn't match what it really holds. (2) WBEM_E_INVALID_PARAMETER if input parameters are not valid. Notes: (1) Caller should call CheckSafeArraySize to make sure that this variant does have that many elements. (2) Caller is resonsible for making sure that pValArray has enough room for the dwords */ HRESULT GetDWORDSafeArrayElements ( IN VARIANT * pVar, IN long lCount, OUT DWORD * pValArray ) { // // sanity check // if (pVar == NULL || (pVar->vt & VT_ARRAY) != VT_ARRAY || pVar->parray == NULL || (lCount > 0 && pValArray == NULL) ) { return WBEM_E_INVALID_PARAMETER; } long lLB; HRESULT hr = ::SafeArrayGetLBound(pVar->parray, 1, &lLB); long lIndexes[1]; // // get the values from the safearray. Since safearray's index may not be 0-based, // we have to start from its lower bound. But our out parameter (array) is 0-based. // Be aware of this offset! // for (long l = lLB; l < lLB + lCount; l++) { lIndexes[0] = l; hr = ::SafeArrayGetElement(pVar->parray, lIndexes, &(pValArray[l - lLB])); // // we don't try to continue if we can't get one of them // if (FAILED(hr)) { break; } } return hr; } /* Routine Description: Name: FindMMAuthMethodsByID Functionality: Given a guid, we will try to find all the main mode auth methods using the resume handle, which is a opaque data. Virtual: No. Arguments: pszGuid - The Main Mode Authentication Method's ID. This should be represent a guid. ppAuthMethod - Receives the MM_AUTH_METHODS data. pdwResumeHandle - In-bound: the current handle for this call. Out-bound: the next handle for the call. Return Value: Success: Various success codes. Use SUCCEEDED(hr) to test. Failure: Various error codes. Notes: */ HRESULT FindMMAuthMethodsByID ( IN LPCWSTR pszGuid, OUT PMM_AUTH_METHODS * ppAuthMethod, IN OUT DWORD * pdwResumeHandle ) { GUID gID = GUID_NULL; // // We allow pssGuid to be invalid, in that case, we simply return any mm auth method. // HRESULT hr = WBEM_NO_ERROR; *ppAuthMethod = NULL; if (pszGuid != NULL && *pszGuid != L'\0') { hr = ::CLSIDFromString((LPWSTR)pszGuid, &gID); } if (SUCCEEDED(hr)) { DWORD dwCount = 0; // // Enumerate all mm auth methods in a hope to find a matching one. // DWORD dwResult = ::EnumMMAuthMethods(NULL, ppAuthMethod, 1, &dwCount, pdwResumeHandle); hr = WBEM_E_NOT_FOUND; while (dwResult == ERROR_SUCCESS && dwCount > 0) { if (gID == GUID_NULL || (*ppAuthMethod)->gMMAuthID == gID) { hr = WBEM_NO_ERROR; break; } else { // // not this one, then release this one and find the next // ::SPDApiBufferFree(*ppAuthMethod); *ppAuthMethod = NULL; dwCount = 0; dwResult = ::EnumMMAuthMethods(NULL, ppAuthMethod, 1, &dwCount, pdwResumeHandle); } } } return hr; } /* Routine Description: Name: GetClassEnum Functionality: A helper function to create a class numeration object for the given name. Virtual: No. Arguments: pNamespace - The namespace where the enum object is requested. pszClassName - The class we want to enumerate. ppEnum - Receives the enumerator. Return Value: Other than WBEM_E_INVALID_PARAMETER and WBEM_E_OUT_OF_MEMORY, it returns whatever pNamespace->ExecQuery returns. Notes: */ HRESULT GetClassEnum ( IN IWbemServices * pNamespace, IN LPCWSTR pszClassName, OUT IEnumWbemClassObject ** ppEnum ) { if ( NULL == pNamespace || NULL == ppEnum || NULL == pszClassName || L'\0' == *pszClassName ) { return WBEM_E_INVALID_PARAMETER; } *ppEnum = NULL; // // format the query // LPCWSTR pszQueryFmt = L"SELECT * FROM %s"; DWORD dwLength = wcslen(pszQueryFmt) + wcslen(pszClassName) + 1; CComBSTR bstrQuery; bstrQuery.m_str = ::SysAllocStringLen(NULL, dwLength); if (bstrQuery.m_str == NULL) { return WBEM_E_OUT_OF_MEMORY; } swprintf(bstrQuery.m_str, pszQueryFmt, pszClassName); // // execute the query // return pNamespace->ExecQuery(L"WQL", bstrQuery, WBEM_FLAG_RETURN_IMMEDIATELY | WBEM_FLAG_FORWARD_ONLY, NULL, ppEnum ); } /* Routine Description: Name: DeleteRollbackObjects Functionality: Given the class name for rollback objects, we will delete all such rollback objects from WMI. Virtual: No. Arguments: pNamespace - The namespace the objects belong. pszClassName - The name of the class of the objects to be deleted. Return Value: Success: WBEM_NO_ERROR Failure: Various error codes. Notes: If during deletion we see an error, the deletion will continue, but we will return the first such error. */ HRESULT DeleteRollbackObjects ( IN IWbemServices * pNamespace, IN LPCWSTR pszClassName ) { if ( NULL == pNamespace || NULL == pszClassName || L'\0' == *pszClassName ) { return WBEM_E_INVALID_PARAMETER; } CComPtr srpEnum; HRESULT hr = ::GetClassEnum(pNamespace, pszClassName, &srpEnum); if (FAILED(hr)) { return hr; } // // go through all found classes // CComPtr srpObj; ULONG nEnum = 0; // // This will keep track of the first error // HRESULT hrError = WBEM_NO_ERROR; // // srpEnum->Next returns WBEM_S_FALSE once the end has reached. // hr = srpEnum->Next(WBEM_INFINITE, 1, &srpObj, &nEnum); while (SUCCEEDED(hr) && hr != WBEM_S_FALSE && srpObj) { CComVariant varPath; if (SUCCEEDED(srpObj->Get(L"__RelPath", 0, &varPath, NULL, NULL)) && varPath.vt == VT_BSTR) { // // now delete the instance // hr = pNamespace->DeleteInstance(varPath.bstrVal, 0, NULL, NULL); if (FAILED(hr) && SUCCEEDED(hrError)) { hrError = hr; } } // // so that we can reuse it // srpObj.Release(); // // next object // hr = srpEnum->Next(WBEM_INFINITE, 1, &srpObj, &nEnum); } // // make our return code easy since we are not going to pass different success codes // if (SUCCEEDED(hr)) { hr = WBEM_NO_ERROR; } // // we will return the first error // return FAILED(hrError) ? hrError : hr; } /* Routine Description: Name: IPSecErrorToWbemError Functionality: Translate IPSec error into Wbem error Virtual: No. Arguments: dwErr - Error code from IPSec APIs Return Value: various Wbem error code Notes: WMI team simply can't give us enough information as how we can provide our own error text. This is not a good translation. Need more support from WMI team in order for us to support custom error information. */ HRESULT IPSecErrorToWbemError ( IN DWORD dwErr ) { // // this is the last resort, not a good code at all // HRESULT hr = WBEM_E_FAILED; switch (dwErr) { case ERROR_IPSEC_QM_POLICY_EXISTS: case ERROR_IPSEC_MM_POLICY_EXISTS: case ERROR_IPSEC_MM_FILTER_EXISTS: case ERROR_IPSEC_TRANSPORT_FILTER_EXISTS: case ERROR_IPSEC_MM_AUTH_EXISTS: case ERROR_IPSEC_TUNNEL_FILTER_EXISTS: hr = WBEM_E_ALREADY_EXISTS; break; case ERROR_IPSEC_QM_POLICY_NOT_FOUND: case ERROR_IPSEC_MM_POLICY_NOT_FOUND: case ERROR_IPSEC_MM_FILTER_NOT_FOUND: case ERROR_IPSEC_TRANSPORT_FILTER_NOT_FOUND: case ERROR_IPSEC_MM_AUTH_NOT_FOUND: case ERROR_IPSEC_DEFAULT_MM_POLICY_NOT_FOUND: case ERROR_IPSEC_DEFAULT_MM_AUTH_NOT_FOUND: case ERROR_IPSEC_DEFAULT_QM_POLICY_NOT_FOUND: case ERROR_IPSEC_TUNNEL_FILTER_NOT_FOUND: hr = WBEM_E_NOT_FOUND; break; case ERROR_IPSEC_QM_POLICY_IN_USE: case ERROR_IPSEC_MM_POLICY_IN_USE: case ERROR_IPSEC_MM_AUTH_IN_USE: hr = WBEM_E_OVERRIDE_NOT_ALLOWED; } return hr; }