Leaked source code of windows server 2003
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.
 
 
 
 
 
 

798 lines
19 KiB

//////////////////////////////////////////////////////////////////////
// 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<IEnumWbemClassObject> srpEnum;
HRESULT hr = ::GetClassEnum(pNamespace, pszClassName, &srpEnum);
if (FAILED(hr))
{
return hr;
}
//
// go through all found classes
//
CComPtr<IWbemClassObject> 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;
}