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.
 
 
 
 
 
 

2309 lines
78 KiB

/*++
Copyright (C) 1996-2000 Microsoft Corporation
Module Name:
IMPORT.CPP
Abstract:
History:
--*/
#include "precomp.h"
#include <StdIo.h>
#include <ConIo.h>
#include <wbemint.h>
#include <WbemUtil.h>
#include <corex.h>
#include "upgrade.h"
#include "Import.h"
#include "export.h"
#include "reg.h"
template <class T> class CMyRelMe
{
T m_p;
public:
CMyRelMe(T p) : m_p(p) {};
~CMyRelMe() { if (m_p) m_p->Release(); }
void Set(T p) { m_p = p; }
};
class CSysFreeMe
{
protected:
BSTR m_str;
public:
CSysFreeMe(BSTR str) : m_str(str){}
~CSysFreeMe() {SysFreeString(m_str);}
};
bool CRepImporter::CheckOldSecurityClass(const wchar_t* wszClass)
{
// check whether it is an old security class
bool bOldSecurityClass = false;
if(m_bSecurityMode)
{
if(!_wcsicmp(wszClass, L"__SecurityRelatedClass"))
bOldSecurityClass = true;
else if(!_wcsicmp(wszClass, L"__Subject"))
bOldSecurityClass = true;
else if(!_wcsicmp(wszClass, L"__User"))
bOldSecurityClass = true;
else if(!_wcsicmp(wszClass, L"__NTLMUser"))
bOldSecurityClass = true;
else if(!_wcsicmp(wszClass, L"__Group"))
bOldSecurityClass = true;
else if(!_wcsicmp(wszClass, L"__NTLMGroup"))
bOldSecurityClass = true;
}
return bOldSecurityClass;
}
void CRepImporter::DecodeTrailer()
{
DWORD dwTrailerSize = 0;
DWORD dwTrailer[4];
DWORD dwSize = 0;
if ((ReadFile(m_hFile, &dwTrailerSize, 4, &dwSize, NULL) == 0) || (dwSize != 4))
{
LogMessage(MSG_ERROR, "Failed to read a block trailer size.");
throw FAILURE_READ;
}
if (dwTrailerSize != REP_EXPORT_END_TAG_SIZE)
{
LogMessage(MSG_ERROR, "Block trailer size is invalid.");
throw FAILURE_INVALID_TRAILER;
}
if ((ReadFile(m_hFile, dwTrailer, REP_EXPORT_END_TAG_SIZE, &dwSize, NULL) == 0) || (dwSize != REP_EXPORT_END_TAG_SIZE))
{
LogMessage(MSG_ERROR, "Failed to read a block trailer.");
throw FAILURE_READ;
}
for (int i = 0; i < 4; i++)
{
if (dwTrailer[i] != REP_EXPORT_FILE_END_TAG)
{
LogMessage(MSG_ERROR, "Block trailer has invalid contents.");
throw FAILURE_INVALID_TRAILER;
}
}
}
void CRepImporter::DecodeInstanceInt(IWbemServices* pNamespace, const wchar_t *wszFullPath, const wchar_t *pszParentClass, _IWmiObject* pOldParentClass, _IWmiObject *pNewParentClass)
{
char szMsg[MAX_MSG_TEXT_LENGTH];
//Read the key and object size
INT_PTR dwKey = 0;
DWORD dwSize = 0;
if ((ReadFile(m_hFile, &dwKey, sizeof(INT_PTR), &dwSize, NULL) == 0) || (dwSize != sizeof(INT_PTR)))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve instance key for class %S. (i)", pszParentClass);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_READ;
}
DWORD dwHeader;
if ((ReadFile(m_hFile, &dwHeader, 4, &dwSize, NULL) == 0) || (dwSize != 4))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve instance object size for class %S. (i)", pszParentClass);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_READ;
}
char *pObjectBlob = new char[dwHeader];
if (pObjectBlob == 0)
{
throw FAILURE_OUT_OF_MEMORY;
}
CVectorDeleteMe<char> delMe(pObjectBlob);
//Read the blob
if ((ReadFile(m_hFile, pObjectBlob, dwHeader, &dwSize, NULL) == 0) || (dwSize != dwHeader))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve instance information for class %S. (i)", pszParentClass);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_READ;
}
if (pNewParentClass == (_IWmiObject*)-1)
{
//We are working with a class which has problems... we need to ignore this instance...
return;
}
// create old Nova-style instance
HRESULT hr;
_IWmiObject* pOldInstance = 0;
CMyRelMe<_IWmiObject*> relMe(pOldInstance);
_IWmiObject* pNewInstance = 0;
CMyRelMe<_IWmiObject*> relMe2(pNewInstance);
hr = pOldParentClass->Merge(WMIOBJECT_MERGE_FLAG_INSTANCE, dwSize, pObjectBlob, &pOldInstance);
if (FAILED(hr))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Unable to merge old instance (i); HRESULT = %#lx", hr);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_CANNOT_MERGE_INSTANCE;
}
if (pOldInstance == 0)
{
throw FAILURE_OUT_OF_MEMORY;
}
relMe.Set(pOldInstance);
// put the new instance into the repository
hr = pNamespace->PutInstance(pOldInstance, WBEM_FLAG_CREATE_OR_UPDATE, NULL, NULL);
if (FAILED(hr))
{
// Original put failed, so we will try to upgrade the instance and retry the put
// upgrade to new Whistler instance
hr = pOldInstance->Upgrade(pNewParentClass, 0L, &pNewInstance);
if (FAILED(hr))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Unable to upgrade to new instance (i); HRESULT = %#lx", hr);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_CANNOT_UPGRADE_INSTANCE;
}
if (pNewInstance == 0)
{
throw FAILURE_OUT_OF_MEMORY;
}
relMe2.Set(pNewInstance);
hr = pNamespace->PutInstance(pNewInstance, WBEM_FLAG_CREATE_OR_UPDATE, NULL, NULL);
if ( FAILED(hr))
{
if (!CheckOldSecurityClass(pszParentClass))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to create instance %S.%d in repository. (i); HRESULT = %#lx", pszParentClass, dwKey, hr);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_CANNOT_CREATE_INSTANCE;
}
else
{
// This is an old Win9x security class, but it can't be put yet because the win9x users haven't been migrated at this point in setup.
// Instead, write it out to the win9x security blob file so it can be processed later after setup is completed
if (!AppendWin9xBlobFile(wszFullPath, pszParentClass, pNewInstance))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Unable to write Win9x security class to file for instance %S.%d", pszParentClass, dwKey);
LogMessage(MSG_ERROR, szMsg);
}
}
}
}
}
void CRepImporter::DecodeInstanceString(IWbemServices* pNamespace, const wchar_t *wszFullPath, const wchar_t *pszParentClass, _IWmiObject* pOldParentClass, _IWmiObject *pNewParentClass)
{
char szMsg[MAX_MSG_TEXT_LENGTH];
//Read the key and object size
DWORD dwKeySize;
DWORD dwSize = 0;
if ((ReadFile(m_hFile, &dwKeySize, 4, &dwSize, NULL) == 0) || (dwSize != 4))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve instance key size for class %S. (s)", pszParentClass);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_READ;
}
wchar_t *wszKey = new wchar_t[dwKeySize];
if (wszKey == NULL)
{
throw FAILURE_OUT_OF_MEMORY;
}
CVectorDeleteMe<wchar_t> delMe(wszKey);
if ((ReadFile(m_hFile, wszKey, dwKeySize, &dwSize, NULL) == 0) || (dwSize != dwKeySize))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve instance key for class %S. (s)", pszParentClass);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_READ;
}
DWORD dwBlobSize;
if ((ReadFile(m_hFile, &dwBlobSize, 4, &dwSize, NULL) == 0) || (dwSize != 4))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve instance object size for %S.%S from import file. (s)", pszParentClass, wszKey);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_READ;
}
char *pObjectBlob = new char[dwBlobSize];
if (pObjectBlob == NULL)
{
throw FAILURE_OUT_OF_MEMORY;
}
CVectorDeleteMe<char> delMe2(pObjectBlob);
//Read the blob
if ((ReadFile(m_hFile, pObjectBlob, dwBlobSize, &dwSize, NULL) == 0) || (dwSize != dwBlobSize))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve instance %S.%S from import file. (s)", pszParentClass, wszKey);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_READ;
}
if (pNewParentClass == (_IWmiObject*)-1)
{
//We are working with a class which has problems... we need to ignore this instance...
return;
}
// create old Nova-style instance
HRESULT hr;
_IWmiObject* pOldInstance = 0;
CMyRelMe<_IWmiObject*> relMe(pOldInstance);
_IWmiObject* pNewInstance = 0;
CMyRelMe<_IWmiObject*> relMe2(pNewInstance);
hr = pOldParentClass->Merge(WMIOBJECT_MERGE_FLAG_INSTANCE, dwSize, pObjectBlob, &pOldInstance);
if (FAILED(hr))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Unable to merge old instance (s); HRESULT = %#lx", hr);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_CANNOT_MERGE_INSTANCE;
}
if (pOldInstance == 0)
{
throw FAILURE_OUT_OF_MEMORY;
}
relMe.Set(pOldInstance);
// put the instance into the repository
// if this fails, upgrade and retry
hr = pNamespace->PutInstance(pOldInstance, WBEM_FLAG_CREATE_OR_UPDATE, NULL, NULL);
if (FAILED(hr))
{
// upgrade to new Whistler instance
hr = pOldInstance->Upgrade(pNewParentClass, 0L, &pNewInstance);
if (FAILED(hr))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Unable to upgrade to new instance (s); HRESULT = %#lx", hr);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_CANNOT_UPGRADE_INSTANCE;
}
if (pNewInstance == 0)
{
throw FAILURE_OUT_OF_MEMORY;
}
relMe2.Set(pNewInstance);
hr = pNamespace->PutInstance(pNewInstance, WBEM_FLAG_CREATE_OR_UPDATE, NULL, NULL);
if ( FAILED(hr))
{
if (!CheckOldSecurityClass(pszParentClass))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to create instance %S.%S in repository. (s); HRESULT = %#lx", pszParentClass, wszKey, hr);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_CANNOT_CREATE_INSTANCE;
}
else
{
// This is an old Win9x security class, but it can't be put yet because the win9x users haven't been migrated at this point in setup.
// Instead, write it out to the win9x security blob file so it can be processed later after setup is completed
if (!AppendWin9xBlobFile(wszFullPath, pszParentClass, pNewInstance))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Unable to write Win9x security class to file for instance %S.%S", pszParentClass, wszKey);
LogMessage(MSG_ERROR, szMsg);
}
}
}
}
}
void CRepImporter::DecodeClass(IWbemServices* pNamespace, const wchar_t *wszFullPath, const wchar_t *wszParentClass, _IWmiObject* pOldParentClass, _IWmiObject *pNewParentClass)
{
char szMsg[MAX_MSG_TEXT_LENGTH];
//Read our current class from the file...
HRESULT hr;
DWORD dwClassSize = 0;
DWORD dwSize = 0;
_IWmiObject* pOldClass = 0;
CMyRelMe<_IWmiObject*> relMe(pOldClass);
_IWmiObject* pNewClass = 0;
CMyRelMe<_IWmiObject*> relMe2(pNewClass);
if ((ReadFile(m_hFile, &dwClassSize, 4, &dwSize, NULL) == 0) || (dwSize != 4))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve class size for class with parent class %S.", wszParentClass);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_READ;
}
wchar_t *wszClass = new wchar_t[dwClassSize];
if (wszClass == NULL)
{
throw FAILURE_OUT_OF_MEMORY;
}
CVectorDeleteMe<wchar_t> delMe(wszClass);
if ((ReadFile(m_hFile, wszClass, dwClassSize, &dwSize, NULL) == 0) || (dwSize != dwClassSize))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve class information for class with parent class %S.", wszParentClass);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_READ;
}
//Now we have the class blob...
if ((ReadFile(m_hFile, &dwClassSize, 4, &dwSize, NULL) == 0) || (dwSize != 4))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve class size for class %S.", wszClass);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_READ;
}
if (dwClassSize)
{
char *pClassBlob = new char[dwClassSize];
if (pClassBlob == NULL)
{
throw FAILURE_OUT_OF_MEMORY;
}
CVectorDeleteMe<char> delMe2(pClassBlob);
if ((ReadFile(m_hFile, pClassBlob, dwClassSize, &dwSize, NULL) == 0) || (dwSize != dwClassSize))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve class information for class %S.", wszClass);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_READ;
}
if (pNewParentClass == (_IWmiObject*)-1)
{
// parent class was bad, so don't process this class
pNewClass = (_IWmiObject*)-1;
}
else
{
// create old Nova-style class
hr = pOldParentClass->Merge(WMIOBJECT_MERGE_FLAG_CLASS, dwSize, pClassBlob, &pOldClass);
if (FAILED(hr))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Unable to merge old class; HRESULT = %#lx", hr);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_CANNOT_MERGE_CLASS;
}
if (pOldClass == 0)
{
throw FAILURE_OUT_OF_MEMORY;
}
relMe.Set(pOldClass);
//If the class is a system class then we do not write it... it may have changed for starters,
//but also we create all system classes when a new database/namespace is created...
if (_wcsnicmp(wszClass, L"__", 2) != 0)
{
// put the class into the repository
// if this fails, upgrade it and retry
hr = pNamespace->PutClass(pOldClass, WBEM_FLAG_CREATE_OR_UPDATE | WBEM_FLAG_UPDATE_FORCE_MODE, NULL, NULL);
if (FAILED(hr))
{
// upgrade to new Whistler class (note: pNewParentClass will be NULL for base classes)
hr = pOldClass->Upgrade(pNewParentClass, 0L, &pNewClass);
if (FAILED(hr))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Unable to upgrade to new class; HRESULT = %#lx", hr);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_CANNOT_UPGRADE_CLASS;
}
if (pNewClass == 0)
{
throw FAILURE_OUT_OF_MEMORY;
}
relMe2.Set(pNewClass);
// retry the put
hr = pNamespace->PutClass(pNewClass, WBEM_FLAG_CREATE_OR_UPDATE | WBEM_FLAG_UPDATE_FORCE_MODE, NULL, NULL);
if ( FAILED(hr) )
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to create class for class %S; HRESULT = %#lx", wszClass, hr);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_CANNOT_CREATE_CLASS;
}
}
}
// We need to re-get the class as class comparisons may fail to see
// that this class is in fact the same as the one in the database!
if ( NULL != pNewClass )
{
pNewClass->Release();
pNewClass = 0;
relMe2.Set(NULL);
}
BSTR bstrClassName = SysAllocString(wszClass);
if (!bstrClassName)
throw FAILURE_OUT_OF_MEMORY;
CSysFreeMe fm(bstrClassName);
hr = pNamespace->GetObject(bstrClassName, 0L, NULL, (IWbemClassObject**) &pNewClass, NULL);
if (FAILED(hr))
{
if (_wcsnicmp(wszClass, L"__", 2) != 0)
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve class %S from the repository after creating it; HRESULT = %#lx", wszClass, hr);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_CANNOT_GET_PARENT_CLASS;
}
else
{
if (_wcsicmp(wszClass, L"__CIMOMIdentification") != 0) // we don't want to warn about failures to retrieve this class
{
// couldn't get the system class
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve system class %S from the repository; HRESULT = %#lx", wszClass, hr);
LogMessage(MSG_WARNING, szMsg);
}
// set pointer to -1 and continue processing file
// old comment said: If this does not exist then it cannot be important!
pNewClass = (_IWmiObject*)-1;
}
}
else
relMe2.Set(pNewClass);
}
}
else
{
// This is a situation where we have a class in the export file,
// but the size is zero, so we just get the class from the repository.
// ***** So what do we do about pOldClass? At this point it is NULL. *****
// ***** We need the old class to be able to upgrade child classes properly. *****
if (pNewParentClass == (_IWmiObject*)-1)
{
// parent class was bad, so don't process this class
pNewClass = (_IWmiObject*)-1;
}
else
{
// get the class from the repository
BSTR bstrClassName = SysAllocString(wszClass);
if (!bstrClassName)
throw FAILURE_OUT_OF_MEMORY;
CSysFreeMe fm(bstrClassName);
hr = pNamespace->GetObject(bstrClassName, 0L, NULL, (IWbemClassObject**) &pNewClass, NULL);
if (FAILED(hr))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve class %S from the repository; HRESULT = %#lx", wszClass, hr);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_CANNOT_GET_PARENT_CLASS;
}
relMe2.Set(pNewClass);
}
}
//Now we iterate through all child classes and instances until we get an end of class marker...
while (1)
{
DWORD dwType = 0;
if ((ReadFile(m_hFile, &dwType, 4, &dwSize, NULL) == 0) || (dwSize != 4))
{
LogMessage(MSG_ERROR, "Failed to read next block type from import file.");
throw FAILURE_READ;
}
if (dwType == REP_EXPORT_CLASS_TAG)
{
DecodeClass(pNamespace, wszFullPath, wszClass, pOldClass, pNewClass);
}
else if (dwType == REP_EXPORT_INST_INT_TAG)
{
DecodeInstanceInt(pNamespace, wszFullPath, wszClass, pOldClass, pNewClass);
}
else if (dwType == REP_EXPORT_INST_STR_TAG)
{
DecodeInstanceString(pNamespace, wszFullPath, wszClass, pOldClass, pNewClass);
}
else if (dwType == REP_EXPORT_CLASS_END_TAG)
{
//That's the end of this class...
DecodeTrailer();
break;
}
else
{
LogMessage(MSG_ERROR, "Next block type in import file is invalid.");
throw FAILURE_INVALID_TYPE;
}
}
}
void CRepImporter::DecodeNamespace(IWbemServices* pParentNamespace, const wchar_t *wszParentNamespace)
{
char szMsg[MAX_MSG_TEXT_LENGTH];
//Read our current namespace from the file...
DWORD dwNsSize = 0;
DWORD dwSize = 0;
if ((ReadFile(m_hFile, &dwNsSize, 4, &dwSize, NULL) == 0) || (dwSize != 4))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve a namespace whose parent namespace is %S.", wszParentNamespace);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_READ;
}
wchar_t *wszNs = new wchar_t[dwNsSize];
if (wszNs == NULL)
{
throw FAILURE_OUT_OF_MEMORY;
}
CVectorDeleteMe<wchar_t> delMe(wszNs);
if ((ReadFile(m_hFile, wszNs, dwNsSize, &dwSize, NULL) == 0) || (dwSize != dwNsSize))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve a namespace whose parent namespace is %S.", wszParentNamespace);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_READ;
}
if (wbem_wcsicmp(wszNs, L"security") == 0)
{
m_bSecurityMode = true;
}
wchar_t *wszFullPath = new wchar_t[wcslen(wszParentNamespace) + 1 + wcslen(wszNs) + 1];
if (wszFullPath == NULL)
{
throw FAILURE_OUT_OF_MEMORY;
}
CVectorDeleteMe<wchar_t> delMe2(wszFullPath);
StringCchCopyW(wszFullPath, MAX_MSG_TEXT_LENGTH, wszParentNamespace);
if (wcslen(wszParentNamespace) != 0)
{
StringCchCatW(wszFullPath, MAX_MSG_TEXT_LENGTH, L"\\");
}
StringCchCatW(wszFullPath, MAX_MSG_TEXT_LENGTH, wszNs);
// open the namespace
IWbemServices* pNamespace = NULL;
CMyRelMe<IWbemServices*> relMe2(pNamespace);
HRESULT hr;
if (pParentNamespace)
{
BSTR bstrNamespace = SysAllocString(wszNs);
if (!bstrNamespace)
throw FAILURE_OUT_OF_MEMORY;
CSysFreeMe fm(bstrNamespace);
hr = pParentNamespace->OpenNamespace(bstrNamespace, WBEM_FLAG_CONNECT_REPOSITORY_ONLY, NULL, &pNamespace, NULL);
if (FAILED(hr))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve namespace %S from the repository; HRESULT = %#lx", wszFullPath, hr);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_CANNOT_FIND_NAMESPACE;
}
}
else // special start case for root
{
IWbemLocator* pLocator = NULL;
CMyRelMe<IWbemLocator*> relMe(pLocator);
hr = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_IWbemLocator, (void**) &pLocator);
if(FAILED(hr))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to create instance of IWbemLocator; HRESULT = %#lx", hr);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_CANNOT_CREATE_IWBEMLOCATOR;
}
else
{
relMe.Set(pLocator);
BSTR bstrNamespace = SysAllocString(L"root");
if (!bstrNamespace)
throw FAILURE_OUT_OF_MEMORY;
CSysFreeMe fm(bstrNamespace);
hr = pLocator->ConnectServer(bstrNamespace, NULL, NULL, NULL, WBEM_FLAG_CONNECT_REPOSITORY_ONLY, NULL, NULL, &pNamespace);
if (FAILED(hr))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to connect server; HRESULT = %#lx", hr);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_CANNOT_CONNECT_SERVER;
}
}
}
if (pNamespace == NULL)
{
throw FAILURE_OUT_OF_MEMORY;
}
relMe2.Set(pNamespace);
//Get and set the namespace security...
DWORD dwBuffer[2];
if ((ReadFile(m_hFile, dwBuffer, 8, &dwSize, NULL) == 0) || (dwSize != 8))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve a namespace security header for namespace %S.", wszFullPath);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_READ;
}
if (dwBuffer[0] != REP_EXPORT_NAMESPACE_SEC_TAG)
{
LogMessage(MSG_ERROR, "Expecting a namespace security blob and did not find it.");
throw FAILURE_INVALID_TYPE;
}
if (dwBuffer[1] != 0)
{
char *pNsSecurity = new char[dwBuffer[1]];
CVectorDeleteMe<char> delMe3(pNsSecurity);
if (pNsSecurity == NULL)
{
throw FAILURE_OUT_OF_MEMORY;
}
if ((ReadFile(m_hFile, pNsSecurity, dwBuffer[1], &dwSize, NULL) == 0) || (dwSize != dwBuffer[1]))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to retrieve a namespace security blob for namespace %S.", wszFullPath);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_READ;
}
// we have the security blob, now set the SECURITY_DESCRIPTOR property in the namespace
DecodeNamespaceSecurity(pNamespace, pParentNamespace, pNsSecurity, dwBuffer[1], wszFullPath);
}
// create empty Nova-style class object for use in decoding base classes
_IWmiObjectFactory* pObjFactory = NULL;
CMyRelMe<_IWmiObjectFactory*> relMe3(pObjFactory);
hr = CoCreateInstance(CLSID__WmiObjectFactory, NULL, CLSCTX_ALL, IID__IWmiObjectFactory, (void**) &pObjFactory);
if(FAILED(hr))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to create instance of IWmiObjectFactory; HRESULT = %#lx", hr);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_CANNOT_CREATE_OBJECTFACTORY;
}
if (pObjFactory == NULL)
{
throw FAILURE_OUT_OF_MEMORY;
}
relMe3.Set(pObjFactory);
_IWmiObject* pBaseObject = NULL;
CMyRelMe<_IWmiObject*> relMe4(pBaseObject);
hr = pObjFactory->Create(NULL, 0L, CLSID__WbemEmptyClassObject, IID__IWmiObject, (void**) &pBaseObject);
if(FAILED(hr))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to create instance of IWmiObject; HRESULT = %#lx", hr);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_CANNOT_CREATE_IWMIOBJECT;
}
if (pBaseObject == NULL)
{
throw FAILURE_OUT_OF_MEMORY;
}
relMe4.Set(pBaseObject);
//Now we need to iterate through the next set of blocks of namespace or class
//until we get to an end of NS marker
while (1)
{
DWORD dwType = 0;
if ((ReadFile(m_hFile, &dwType, 4, &dwSize, NULL) == 0) || (dwSize != 4))
{
LogMessage(MSG_ERROR, "Failed to read next block type (namespace/class) from import file.");
throw FAILURE_READ;
}
if (dwType == REP_EXPORT_NAMESPACE_TAG)
{
DecodeNamespace(pNamespace, wszFullPath);
}
else if (dwType == REP_EXPORT_CLASS_TAG)
{
DecodeClass(pNamespace, wszFullPath, L"", pBaseObject, NULL);
}
else if (dwType == REP_EXPORT_NAMESPACE_END_TAG)
{
//That's the end of this namespace...
DecodeTrailer();
break;
}
else
{
LogMessage(MSG_ERROR, "Next block type (namespace/class) in import file is invalid.");
throw FAILURE_INVALID_TYPE;
}
}
m_bSecurityMode = false;
}
void CRepImporter::DecodeNamespaceSecurity(IWbemServices* pNamespace, IWbemServices* pParentNamespace, const char* pNsSecurity, DWORD dwSize, const wchar_t* wszFullPath)
{
char szMsg[MAX_MSG_TEXT_LENGTH];
// determine whether we have an old Win9x pseudo-blob
DWORD dwStoredAsNT = 0;
if (pNsSecurity)
{
DWORD* pdwData = (DWORD*)pNsSecurity;
DWORD dwBlobSize = *pdwData;
pdwData++;
DWORD dwVersion = *pdwData;
if(dwVersion != 1 || dwBlobSize == 0 || dwBlobSize > 64000)
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Invalid namespace security blob header for namespace %S.", wszFullPath);
LogMessage(MSG_ERROR, szMsg);
return;
}
pdwData++;
dwStoredAsNT = *pdwData;
}
if (!dwStoredAsNT)
{
// Do not process Win9x security blobs, because Win9x users haven't been migrated over yet at this point in setup.
// Instead, write them out to a file to be processed after setup is complete.
if (!AppendWin9xBlobFile(wszFullPath, dwSize, pNsSecurity))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Unable to write Win9x security blob to file for namespace %S.", wszFullPath);
LogMessage(MSG_ERROR, szMsg);
}
return;
}
// now transform the old security blob that consisted of a header and array of ACE's
// into a proper Security Descriptor that can be stored in the property
CNtSecurityDescriptor mmfNsSD;
if (!TransformBlobToSD(pParentNamespace, pNsSecurity, dwStoredAsNT, mmfNsSD))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to convert security blob to SD for namespace %S.", wszFullPath);
LogMessage(MSG_ERROR, szMsg);
return;
}
// now set the security
if (!SetNamespaceSecurity(pNamespace, mmfNsSD))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to set namespace security for namespace %S.", wszFullPath);
LogMessage(MSG_ERROR, szMsg);
return;
}
}
void CRepImporter::Decode()
{
char pszBuff[7];
DWORD dwSize = 0;
if ((ReadFile(m_hFile, pszBuff, 7, &dwSize, NULL) == 0) || (dwSize != 7))
{
LogMessage(MSG_ERROR, "Failed to retrieve the import file header information.");
throw FAILURE_READ;
}
if (strncmp(pszBuff, REP_EXPORT_FILE_START_TAG, 7) != 0)
{
LogMessage(MSG_ERROR, "The import file specified is not an import file.");
throw FAILURE_INVALID_FILE;
}
//We should have a tag for a namespace...
DWORD dwType = 0;
if ((ReadFile(m_hFile, &dwType, 4, &dwSize, NULL) == 0) || (dwSize != 4))
{
LogMessage(MSG_ERROR, "Failed to read next block type from import file.");
throw FAILURE_READ;
}
if (dwType != REP_EXPORT_NAMESPACE_TAG)
{
LogMessage(MSG_ERROR, "Next block type in import file is invalid.");
throw FAILURE_INVALID_TYPE;
}
DecodeNamespace(NULL, L"");
// if we opened a Win9x security blob upgrade file, close it
CloseWin9xBlobFile();
// force ROOT\DEFAULT and ROOT\SECURITY namespaces to inherit their inheritable security settings
ForceInherit();
//Now we should have the file trailer
if ((ReadFile(m_hFile, &dwType, 4, &dwSize, NULL) == 0) || (dwSize != 4))
{
LogMessage(MSG_ERROR, "Failed to read next block type (trailer) from import file.");
throw FAILURE_READ;
}
if (dwType != REP_EXPORT_FILE_END_TAG)
{
LogMessage(MSG_ERROR, "Next block type (trailer) in import file is invalid.");
throw FAILURE_INVALID_TYPE;
}
DecodeTrailer();
}
int CRepImporter::ImportRepository(const TCHAR *pszFromFile)
{
LogMessage(MSG_INFO, "Beginning ImportRepository");
int nRet = no_error;
m_hFile = CreateFile(pszFromFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (m_hFile != INVALID_HANDLE_VALUE)
{
try
{
Decode();
}
catch (CX_MemoryException)
{
LogMessage(MSG_ERROR, "Memory Exception.");
nRet = out_of_memory;
}
catch (...)
{
LogMessage(MSG_ERROR, "Traversal of import file failed.");
nRet = critical_error;
}
CloseHandle(m_hFile);
}
else
{
char szMsg[MAX_MSG_TEXT_LENGTH];
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Could not open the import file \"%s\" for reading.", pszFromFile);
LogMessage(MSG_ERROR, szMsg);
nRet = critical_error;
}
if (nRet == no_error)
LogMessage(MSG_INFO, "ImportRepository completed successfully.");
else
LogMessage(MSG_ERROR, "ImportRepository failed to complete.");
return nRet;
}
//***************************************************************************
//***************************************************************************
//
// Helper functions for DecodeNamespaceSecurity
//
//***************************************************************************
//***************************************************************************
bool CRepImporter::TransformBlobToSD(IWbemServices* pParentNamespace, const char* pNsSecurity, DWORD dwStoredAsNT, CNtSecurityDescriptor& mmfNsSD)
{
// now transform the old security blob that consisted of a header and array of ACE's
// into a proper Security Descriptor that can be stored in the property
// build up an ACL from our blob, if we have one
CNtAcl acl;
if (pNsSecurity)
{
DWORD* pdwData = (DWORD*) pNsSecurity;
pdwData += 3;
int iAceCount = (int)*pdwData;
pdwData += 2;
BYTE* pAceData = (BYTE*)pdwData;
PGENERIC_ACE pAce = NULL;
for (int iCnt = 0; iCnt < iAceCount; iCnt++)
{
pAce = (PGENERIC_ACE)pAceData;
if (!pAce)
{
LogMessage(MSG_ERROR, "Failed to access GENERIC_ACE within security blob");
return false;
}
CNtAce ace(pAce);
if(ace.GetStatus() != 0)
{
LogMessage(MSG_ERROR, "Failed to construct CNtAce from GENERIC_ACE");
return false;
}
acl.AddAce(&ace);
if (acl.GetStatus() != 0)
{
LogMessage(MSG_ERROR, "Failed to add ACE to ACL");
return false;
}
pAceData += ace.GetSize();
}
}
// a real SD was constructed and passed in by reference, now set it up properly
SetOwnerAndGroup(mmfNsSD);
mmfNsSD.SetDacl(&acl);
if (mmfNsSD.GetStatus() != 0)
{
LogMessage(MSG_ERROR, "Failed to convert namespace security blob to SD");
return false;
}
// add in the parent's inheritable aces, if this is not ROOT
if (pParentNamespace)
{
if (!GetParentsInheritableAces(pParentNamespace, mmfNsSD))
{
LogMessage(MSG_ERROR, "Failed to inherit parent's inheritable ACE's");
return false;
}
}
return true;
}
bool CRepImporter::SetNamespaceSecurity(IWbemServices* pNamespace, CNtSecurityDescriptor& mmfNsSD)
{
// now set the security
if (!pNamespace)
return false;
IWbemClassObject* pThisNamespace = NULL;
BSTR bstrNamespace = SysAllocString(L"__thisnamespace=@");
if (!bstrNamespace)
throw FAILURE_OUT_OF_MEMORY;
CSysFreeMe fm(bstrNamespace);
HRESULT hr = pNamespace->GetObject(bstrNamespace, 0, NULL, &pThisNamespace, NULL);
if (FAILED(hr))
{
LogMessage(MSG_ERROR, "Failed to get singleton namespace object");
return false;
}
CMyRelMe<IWbemClassObject*> relMe(pThisNamespace);
//
// Check to see if namespace contains any ALLOW or DENY ACEs for NETWORK/LOCAL SERVICE
// If they do exist, we leave them as is, otherwise we want to add them to the SD.
//
if ( CheckNetworkLocalService ( mmfNsSD ) == false )
{
LogMessage(MSG_ERROR, "Failed to add NETWORK/LOCAL service ACEs");
return false;
}
SAFEARRAY FAR* psa;
SAFEARRAYBOUND rgsabound[1];
rgsabound[0].lLbound = 0;
rgsabound[0].cElements = mmfNsSD.GetSize();
psa = SafeArrayCreate( VT_UI1, 1 , rgsabound );
if (!psa)
throw FAILURE_OUT_OF_MEMORY;
char* pData = NULL;
hr = SafeArrayAccessData(psa, (void HUGEP* FAR*)&pData);
if (FAILED(hr))
{
LogMessage(MSG_ERROR, "Failed SafeArrayAccessData");
return false;
}
memcpy(pData, mmfNsSD.GetPtr(), mmfNsSD.GetSize());
hr = SafeArrayUnaccessData(psa);
if (FAILED(hr))
{
LogMessage(MSG_ERROR, "Failed SafeArrayUnaccessData");
return false;
}
pData = NULL;
VARIANT var;
var.vt = VT_UI1|VT_ARRAY;
var.parray = psa;
hr = pThisNamespace->Put(L"SECURITY_DESCRIPTOR" , 0, &var, 0);
VariantClear(&var);
if (FAILED(hr))
{
if (hr == WBEM_E_OUT_OF_MEMORY)
throw FAILURE_OUT_OF_MEMORY;
else
{
LogMessage(MSG_ERROR, "Failed to put SECURITY_DESCRIPTOR property");
return false;
}
}
hr = pNamespace->PutInstance(pThisNamespace, WBEM_FLAG_CREATE_OR_UPDATE, NULL, NULL);
if (FAILED(hr))
{
if (hr == WBEM_E_OUT_OF_MEMORY)
throw FAILURE_OUT_OF_MEMORY;
else
{
LogMessage(MSG_ERROR, "Failed to put back singleton instance");
return false;
}
}
return true;
}
/*
--------------------------------------------------------------------------
|
| Checks to see if the namespace had a previous ACE with NETWORK or LOCAL
| service accounts. If so, it simply leaves them, otherwise, it adds a
| ACE with default settings for these accounts. The default settings are:
| WBEM_ENABLE | WBEM_METHOD_EXECUTE | WBEM_WRITE_PROVIDER
| The characteristics of the ACE is irrelevant. Only SID comparison applies.
|
--------------------------------------------------------------------------
*/
bool CRepImporter::CheckNetworkLocalService ( CNtSecurityDescriptor& mmfNsSD )
{
DWORD dwAccessMaskNetworkLocalService = WBEM_ENABLE | WBEM_METHOD_EXECUTE | WBEM_WRITE_PROVIDER ;
PSID pRawSid = NULL ;
SID_IDENTIFIER_AUTHORITY id = SECURITY_NT_AUTHORITY;
BOOL bStatus = TRUE ;
BYTE flags = 0 ;
CNtAcl* pAcl = mmfNsSD.GetDacl ( ) ;
CDeleteMe<CNtAcl> AclDelete ( pAcl ) ;
//
// Start with NETWORK_SERVICE account
//
if(AllocateAndInitializeSid( &id, 1,
SECURITY_NETWORK_SERVICE_RID,0,0,0,0,0,0,0,&pRawSid))
{
CNtSid SidNetworkService (pRawSid);
FreeSid(pRawSid);
{
CNtAce * pace = new CNtAce(dwAccessMaskNetworkLocalService,
ACCESS_ALLOWED_ACE_TYPE,
CONTAINER_INHERIT_ACE,
SidNetworkService );
if ( NULL == pace )
{
bStatus = FALSE ;
}
else
{
CDeleteMe<CNtAce> dm(pace);
pAcl->AddAce(pace);
}
}
}
//
// Next, LOCAL_SERVICE account
//
if ( bStatus == TRUE )
{
pRawSid = NULL ;
if(AllocateAndInitializeSid( &id, 1,
SECURITY_LOCAL_SERVICE_RID,0,0,0,0,0,0,0,&pRawSid))
{
CNtSid SidLocalService (pRawSid);
FreeSid(pRawSid);
{
CNtAce * pace = new CNtAce(dwAccessMaskNetworkLocalService,
ACCESS_ALLOWED_ACE_TYPE,
CONTAINER_INHERIT_ACE,
SidLocalService );
if ( NULL == pace )
{
bStatus = FALSE ;
}
else
{
CDeleteMe<CNtAce> dm(pace);
pAcl->AddAce(pace);
}
}
}
}
if ( bStatus == TRUE )
{
mmfNsSD.SetDacl ( pAcl ) ;
}
return bStatus ? true : false ;
}
bool CRepImporter::GetParentsInheritableAces(IWbemServices* pParentNamespace, CNtSecurityDescriptor &sd)
{
if (!pParentNamespace)
return false;
// Get the parent namespace's SD
CNtSecurityDescriptor sdParent;
if (!GetSDFromNamespace(pParentNamespace, sdParent))
return false;
// strip out the inherited aces so we have a consistent SD
if (!StripOutInheritedAces(sd))
return false;
// Go through the parents dacl and add any inheritable aces to ours.
if (!CopyInheritAces(sd, sdParent))
return false;
return true;
}
bool CRepImporter::GetSDFromNamespace(IWbemServices* pNamespace, CNtSecurityDescriptor& sd)
{
if (!pNamespace)
return false;
// get the singleton object
IWbemClassObject* pThisNamespace = NULL;
BSTR bstrNamespace = SysAllocString(L"__thisnamespace=@");
if (!bstrNamespace)
throw FAILURE_OUT_OF_MEMORY;
CSysFreeMe fm(bstrNamespace);
HRESULT hr = pNamespace->GetObject(bstrNamespace, 0, NULL, &pThisNamespace, NULL);
if (FAILED(hr))
{
LogMessage(MSG_ERROR, "Failed to get singleton namespace object");
return false;
}
CMyRelMe<IWbemClassObject*> relMe(pThisNamespace);
// Get the security descriptor argument
VARIANT var;
VariantInit(&var);
hr = pThisNamespace->Get(L"SECURITY_DESCRIPTOR", 0, &var, NULL, NULL);
if (FAILED(hr))
{
VariantClear(&var);
LogMessage(MSG_ERROR, "Failed to get SECURITY_DESCRIPTOR property");
return false;
}
if(var.vt != (VT_ARRAY | VT_UI1))
{
VariantClear(&var);
LogMessage(MSG_ERROR, "Failed to get SECURITY_DESCRIPTOR property due to incorrect variant type");
return false;
}
SAFEARRAY* psa = var.parray;
PSECURITY_DESCRIPTOR pSD;
hr = SafeArrayAccessData(psa, (void HUGEP* FAR*)&pSD);
if (FAILED(hr))
{
VariantClear(&var);
LogMessage(MSG_ERROR, "GetSDFromNamespace failed SafeArrayAccessData");
return false;
}
BOOL bValid = IsValidSecurityDescriptor(pSD);
if (!bValid)
{
VariantClear(&var);
LogMessage(MSG_ERROR, "GetSDFromNamespace retrieved an invalid security descriptor");
return false;
}
CNtSecurityDescriptor sdNew(pSD);
// Check to make sure the owner and group is not NULL!!!!
CNtSid *pTmpSid = sdNew.GetOwner();
if (pTmpSid == NULL)
{
LogMessage(MSG_ERROR, "Security descriptor was retrieved and it had no owner");
}
delete pTmpSid;
pTmpSid = sdNew.GetGroup();
if (pTmpSid == NULL)
{
LogMessage(MSG_ERROR, "Security descriptor was retrieved and it had no group");
}
delete pTmpSid;
sd = sdNew;
SafeArrayUnaccessData(psa);
VariantClear(&var);
return true;
}
bool CRepImporter::StripOutInheritedAces(CNtSecurityDescriptor &sd)
{
// Get the DACL
CNtAcl* pAcl;
pAcl = sd.GetDacl();
if(!pAcl)
return false;
CDeleteMe<CNtAcl> dm(pAcl);
// enumerate through the aces
DWORD dwNumAces = pAcl->GetNumAces();
BOOL bChanged = FALSE;
for(long nIndex = (long)dwNumAces-1; nIndex >= 0; nIndex--)
{
CNtAce *pAce = pAcl->GetAce(nIndex);
if(pAce)
{
long lFlags = pAce->GetFlags();
if(lFlags & INHERITED_ACE)
{
pAcl->DeleteAce(nIndex);
bChanged = TRUE;
}
}
}
if(bChanged)
sd.SetDacl(pAcl);
return true;
}
bool CRepImporter::CopyInheritAces(CNtSecurityDescriptor& sd, CNtSecurityDescriptor& sdParent)
{
// Get the acl list for both SDs
CNtAcl * pacl = sd.GetDacl();
if(pacl == NULL)
return false;
CDeleteMe<CNtAcl> dm0(pacl);
CNtAcl * paclParent = sdParent.GetDacl();
if(paclParent == NULL)
return false;
CDeleteMe<CNtAcl> dm1(paclParent);
int iNumParent = paclParent->GetNumAces();
for(int iCnt = 0; iCnt < iNumParent; iCnt++)
{
CNtAce *pParentAce = paclParent->GetAce(iCnt);
CDeleteMe<CNtAce> dm2(pParentAce);
long lFlags = pParentAce->GetFlags();
if(lFlags & CONTAINER_INHERIT_ACE)
{
if(lFlags & NO_PROPAGATE_INHERIT_ACE)
lFlags ^= CONTAINER_INHERIT_ACE;
lFlags |= INHERITED_ACE;
// If this is an inherit only ace we need to clear this
// in the children.
// NT RAID: 161761 [marioh]
if ( lFlags & INHERIT_ONLY_ACE )
lFlags ^= INHERIT_ONLY_ACE;
pParentAce->SetFlags(lFlags);
pacl->AddAce(pParentAce);
}
}
sd.SetDacl(pacl);
return true;
}
BOOL CRepImporter::SetOwnerAndGroup(CNtSecurityDescriptor &sd)
{
PSID pRawSid;
BOOL bRet = FALSE;
SID_IDENTIFIER_AUTHORITY id = SECURITY_NT_AUTHORITY;
if(AllocateAndInitializeSid( &id, 2,
SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS,
0,0,0,0,0,0,&pRawSid))
{
CNtSid SidAdmins(pRawSid);
bRet = sd.SetGroup(&SidAdmins); // Access check doesn't really care what you put,
// so long as you put something for the owner
if(bRet)
bRet = sd.SetOwner(&SidAdmins);
FreeSid(pRawSid);
return bRet;
}
return bRet;
}
void CRepImporter::ForceInherit()
{
// force ROOT\DEFAULT and ROOT\SECURITY namespaces to inherit their inheritable security settings
char szMsg[MAX_MSG_TEXT_LENGTH];
IWbemLocator* pLocator = NULL;
HRESULT hr = CoCreateInstance(CLSID_WbemLocator, NULL, CLSCTX_ALL, IID_IWbemLocator, (void**) &pLocator);
if(FAILED(hr))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to create instance of IWbemLocator; HRESULT = %#lx", hr);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_CANNOT_CREATE_IWBEMLOCATOR;
}
CMyRelMe<IWbemLocator*> relMe1(pLocator);
IWbemServices* pRootNamespace = NULL;
ConnectNamespace(pLocator, L"root", &pRootNamespace);
CMyRelMe<IWbemServices*> relMe2(pRootNamespace);
if (!InheritSecurity(pLocator, pRootNamespace, L"root\\default"))
LogMessage(MSG_ERROR, "Failed to force inherit for root\\default");
if (!InheritSecurity(pLocator, pRootNamespace, L"root\\security"))
LogMessage(MSG_ERROR, "Failed to force inherit for root\\security");
}
bool CRepImporter::InheritSecurity(IWbemLocator* pLocator, IWbemServices* pRootNamespace, const wchar_t* wszNamespace)
{
IWbemServices* pNamespace = NULL;
ConnectNamespace(pLocator, wszNamespace, &pNamespace);
CMyRelMe<IWbemServices*> relMe(pNamespace);
CNtSecurityDescriptor sdNamespace;
if (!GetSDFromNamespace(pNamespace, sdNamespace))
return false;
if (!GetParentsInheritableAces(pRootNamespace, sdNamespace))
return false;
if (!SetNamespaceSecurity(pNamespace, sdNamespace))
return false;
return true;
}
void CRepImporter::ConnectNamespace(IWbemLocator* pLocator, const wchar_t* wszNamespaceName, IWbemServices** ppNamespace)
{
char szMsg[MAX_MSG_TEXT_LENGTH];
// get the namespace
BSTR bstrNamespace = SysAllocString(wszNamespaceName);
if (!bstrNamespace)
throw FAILURE_OUT_OF_MEMORY;
CSysFreeMe fm(bstrNamespace);
HRESULT hres = pLocator->ConnectServer(bstrNamespace, NULL, NULL, NULL, WBEM_FLAG_CONNECT_REPOSITORY_ONLY, NULL, NULL, ppNamespace);
if (FAILED(hres))
{
StringCchPrintfA(szMsg, MAX_MSG_TEXT_LENGTH, "Failed to connect server for namespace %S; HRESULT = %#lx", wszNamespaceName, hres);
LogMessage(MSG_ERROR, szMsg);
throw FAILURE_CANNOT_CONNECT_SERVER;
}
if (!*ppNamespace)
{
throw FAILURE_OUT_OF_MEMORY;
}
}
//***************************************************************************
//***************************************************************************
//
// Helper functions for Win9x security processing
//
//***************************************************************************
//***************************************************************************
bool CRepImporter::AppendWin9xBlobFile(const wchar_t* wszFullPath, DWORD dwBlobSize, const char* pNsSecurity)
{
// check whether we need to create the blob file
if (m_h9xBlobFile == INVALID_HANDLE_VALUE)
{
if (!CreateWin9xBlobFile())
return false;
}
// write the blob header containing the type, namespace name size, and blob size to the file
BLOB9X_SPACER header;
header.dwSpacerType = BLOB9X_TYPE_SECURITY_BLOB;
header.dwNamespaceNameSize = (wcslen(wszFullPath)+1)*sizeof(wchar_t);
header.dwParentClassNameSize = 0;
header.dwBlobSize = dwBlobSize;
DWORD dwSize = 0;
if (WriteFile(m_h9xBlobFile, &header, sizeof(header), &dwSize, NULL) && (dwSize == sizeof(header)))
{
// write the namespace name to the file
dwSize = 0;
if (WriteFile(m_h9xBlobFile, wszFullPath, header.dwNamespaceNameSize, &dwSize, NULL) && (dwSize == header.dwNamespaceNameSize))
{
// write the blob to the file
dwSize = 0;
if (WriteFile(m_h9xBlobFile, pNsSecurity, dwBlobSize, &dwSize, NULL) && (dwSize == dwBlobSize))
return true;
}
}
// if we failed to write to the file, something is wrong with the file, so close and delete it
DeleteWin9xBlobFile();
return false;
}
bool CRepImporter::AppendWin9xBlobFile(const wchar_t* wszFullPath, const wchar_t* wszParentClass, _IWmiObject* pInstance)
{
// check whether we need to create the blob file
if (m_h9xBlobFile == INVALID_HANDLE_VALUE)
{
if (!CreateWin9xBlobFile())
return false;
}
//Get the size of the object
DWORD dwObjPartLen = 0;
HRESULT hRes = pInstance->Unmerge(0, 0, &dwObjPartLen, 0);
//Allocate the size of the object
BYTE *pObjPart = NULL;
if (hRes == WBEM_E_BUFFER_TOO_SMALL)
{
hRes = WBEM_S_NO_ERROR;
pObjPart = new BYTE[dwObjPartLen];
}
if (pObjPart)
{
CVectorDeleteMe<BYTE> delMe(pObjPart);
//retrieve the object blob
if (SUCCEEDED(hRes))
{
DWORD dwLen;
hRes = pInstance->Unmerge(0, dwObjPartLen, &dwLen, pObjPart);
}
if (SUCCEEDED(hRes))
{
// write the blob header containing the type, namespace name size, parent class name size, and blob size to the file
BLOB9X_SPACER header;
header.dwSpacerType = BLOB9X_TYPE_SECURITY_INSTANCE;
header.dwNamespaceNameSize = (wcslen(wszFullPath)+1)*sizeof(wchar_t);
header.dwParentClassNameSize = (wcslen(wszParentClass)+1)*sizeof(wchar_t);
header.dwBlobSize = dwObjPartLen;
DWORD dwSize = 0;
if (WriteFile(m_h9xBlobFile, &header, sizeof(header), &dwSize, NULL) && (dwSize == sizeof(header)))
{
// write the namespace name to the file
dwSize = 0;
if (WriteFile(m_h9xBlobFile, wszFullPath, header.dwNamespaceNameSize, &dwSize, NULL) && (dwSize == header.dwNamespaceNameSize))
{
// write the parent class name to the file
dwSize = 0;
if (WriteFile(m_h9xBlobFile, wszParentClass, header.dwParentClassNameSize, &dwSize, NULL) && (dwSize == header.dwParentClassNameSize))
{
// write the blob to the file
dwSize = 0;
if (WriteFile(m_h9xBlobFile, pObjPart, dwObjPartLen, &dwSize, NULL) && (dwSize == dwObjPartLen))
return true;
}
}
}
}
}
// if we failed to write to the file, something is wrong with the file, so close and delete it
DeleteWin9xBlobFile();
return false;
}
bool CRepImporter::CreateWin9xBlobFile()
{
// get the root directory of the repository
wchar_t wszFilePath[MAX_PATH+1];
if (!GetRepositoryDirectory(wszFilePath))
return false;
// append blob file name
StringCchCatW(wszFilePath, MAX_PATH+1, BLOB9X_FILENAME);
// create a new file in which to store blob info
m_h9xBlobFile = CreateFileW(wszFilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (m_h9xBlobFile == INVALID_HANDLE_VALUE)
return false;
// write the blob file header
BLOB9X_HEADER header;
StringCchCopyA(header.szSignature, sizeof(header.szSignature)/sizeof(char), BLOB9X_SIGNATURE);
DWORD dwSize = 0;
if (WriteFile(m_h9xBlobFile, &header, sizeof(header), &dwSize, NULL) && (dwSize == sizeof(header)))
return true;
// if we failed to write to the file we should close the handle and delete the file
CloseHandle(m_h9xBlobFile);
DeleteFileW(wszFilePath);
m_h9xBlobFile = INVALID_HANDLE_VALUE;
return false;
}
void CRepImporter::DeleteWin9xBlobFile()
{
// close and invalidate the handle if necessary
if (m_h9xBlobFile != INVALID_HANDLE_VALUE)
{
CloseHandle(m_h9xBlobFile);
m_h9xBlobFile = INVALID_HANDLE_VALUE;
}
// delete the file
wchar_t wszFilePath[MAX_PATH+1];
if (GetRepositoryDirectory(wszFilePath))
{
StringCchCatW(wszFilePath, MAX_PATH+1, BLOB9X_FILENAME);
DeleteFileW(wszFilePath);
}
}
bool CRepImporter::GetRepositoryDirectory(wchar_t wszRepositoryDirectory[MAX_PATH+1])
{
HKEY hKey;
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\WBEM\\CIMOM", 0, KEY_READ, &hKey))
return false;
wchar_t wszTmp[MAX_PATH + 1];
DWORD dwLen = (MAX_PATH + 1) * sizeof(wchar_t);
long lRes = RegQueryValueExW(hKey, L"Repository Directory", NULL, NULL, (LPBYTE)wszTmp, &dwLen);
RegCloseKey(hKey);
if(lRes)
return false;
if (ExpandEnvironmentStringsW(wszTmp,wszRepositoryDirectory, MAX_PATH + 1) == 0)
return false;
return true;
}
bool CRepImporter::CloseWin9xBlobFile()
{
// if no valid handle, then we don't have a file to close, return success
if (m_h9xBlobFile == INVALID_HANDLE_VALUE)
return true;
// write the end of blob file marker
BLOB9X_SPACER trailer;
trailer.dwSpacerType = BLOB9X_TYPE_END_OF_FILE;
trailer.dwNamespaceNameSize = 0;
trailer.dwParentClassNameSize = 0;
trailer.dwBlobSize = 0;
DWORD dwSize = 0;
if ((WriteFile(m_h9xBlobFile, &trailer, sizeof(trailer), &dwSize, NULL) == 0) || (dwSize != sizeof(trailer)))
{
// if we failed to write the trailer, something is wrong with the file, so close and delete it
DeleteWin9xBlobFile();
return false;
}
CloseHandle(m_h9xBlobFile);
m_h9xBlobFile = INVALID_HANDLE_VALUE;
return true;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
extern HRESULT Traverse (
IWbemServices *a_Service ,
BSTR a_Namespace
) ;
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
PSID g_NetworkServiceSid = NULL ;
PSID g_LocalServiceSid = NULL ;
ACCESS_ALLOWED_ACE *g_NetworkService_Ace = NULL ;
WORD g_NetworkService_AceSize = 0 ;
ACCESS_ALLOWED_ACE *g_LocalService_Ace = NULL ;
WORD g_LocalService_AceSize = 0 ;
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
HRESULT TraverseSetSecurity ( IWbemServices *a_Service )
{
IClientSecurity *t_Security = NULL ;
HRESULT t_Result = a_Service->QueryInterface ( IID_IClientSecurity , ( void ** ) & t_Security ) ;
if ( SUCCEEDED ( t_Result ) )
{
t_Result = t_Security->SetBlanket (
a_Service ,
RPC_C_AUTHN_WINNT,
RPC_C_AUTHZ_NONE,
NULL,
RPC_C_AUTHN_LEVEL_DEFAULT ,
RPC_C_IMP_LEVEL_IDENTIFY,
NULL,
EOAC_NONE
) ;
t_Security->Release () ;
}
return t_Result ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
HRESULT InsertServiceAccess (
SAFEARRAY *a_Array ,
SAFEARRAY *&a_NewArray
)
{
HRESULT t_Result = S_OK ;
if ( SafeArrayGetDim ( a_Array ) == 1 )
{
LONG t_Dimension = 1 ;
LONG t_Lower ;
SafeArrayGetLBound ( a_Array , t_Dimension , & t_Lower ) ;
LONG t_Upper ;
SafeArrayGetUBound ( a_Array , t_Dimension , & t_Upper ) ;
LONG t_Count = ( t_Upper - t_Lower ) + 1 ;
BYTE *t_SecurityDescriptor = new BYTE [ t_Count ] ;
if ( t_SecurityDescriptor )
{
if ( t_Count )
{
for ( LONG t_ElementIndex = t_Lower ; t_ElementIndex <= t_Upper ; t_ElementIndex ++ )
{
BYTE t_Element ;
if ( SUCCEEDED ( SafeArrayGetElement ( a_Array , & t_ElementIndex , & t_Element ) ) )
{
t_SecurityDescriptor [ t_ElementIndex - t_Lower ] = t_Element ;
}
else
{
t_Result = WBEM_E_CRITICAL_ERROR ;
break ;
}
}
}
}
else
{
t_Result = WBEM_E_OUT_OF_MEMORY ;
}
if ( SUCCEEDED ( t_Result ) )
{
if ( IsValidSecurityDescriptor ( t_SecurityDescriptor ) == FALSE )
{
t_Result = WBEM_E_CRITICAL_ERROR ;
}
}
bool t_NetworkServicePresent = false ;
bool t_LocalServicePresent = false ;
if ( SUCCEEDED ( t_Result ) )
{
BOOL t_AclPresent = FALSE ;
BOOL t_AclDefaulted = FALSE ;
ACL *t_Dacl = NULL ;
BOOL t_Status = GetSecurityDescriptorDacl (t_SecurityDescriptor ,& t_AclPresent ,& t_Dacl ,& t_AclDefaulted) ;
if ( t_Status )
{
DWORD SidNetworkSvcSize = GetLengthSid(g_NetworkServiceSid);
DWORD SidLocalSvcSize = GetLengthSid(g_LocalServiceSid);
ACCESS_ALLOWED_ACE * pACE = (ACCESS_ALLOWED_ACE *)(t_Dacl+1);
for (USHORT i=0;i<t_Dacl->AceCount;i++)
{
DWORD sidSize = GetLengthSid((PSID)&pACE->SidStart);
if ((sidSize == SidNetworkSvcSize) &&
(0 == memcmp(&pACE->SidStart,g_NetworkServiceSid,sidSize)))
{
t_NetworkServicePresent = true;
}
if ((sidSize == SidLocalSvcSize) &&
(0 == memcmp(&pACE->SidStart,g_LocalServiceSid,sidSize)))
{
t_LocalServicePresent = true;
}
pACE = (ACCESS_ALLOWED_ACE *)((BYTE *)pACE + pACE->Header.AceSize);
}
}
else
{
t_Result = HRESULT_FROM_WIN32(GetLastError());
}
}
if ( SUCCEEDED ( t_Result ) )
{
SECURITY_DESCRIPTOR *t_AbsoluteSecurityDescriptor = NULL ;
DWORD t_AbsoluteSecurityDescriptorSize = sizeof ( SECURITY_DESCRIPTOR ) ;
PACL t_Dacl = NULL ;
PACL t_Sacl = NULL ;
PSID t_Owner = NULL ;
PSID t_PrimaryGroup = NULL ;
DWORD t_DaclSize = 0 ;
DWORD t_SaclSize = 0 ;
DWORD t_OwnerSize = 0 ;
DWORD t_PrimaryGroupSize = 0 ;
BOOL t_Status = MakeAbsoluteSD (t_SecurityDescriptor ,t_AbsoluteSecurityDescriptor ,& t_AbsoluteSecurityDescriptorSize ,
t_Dacl,& t_DaclSize,t_Sacl,& t_SaclSize,t_Owner,& t_OwnerSize,t_PrimaryGroup,& t_PrimaryGroupSize) ;
if ( ( t_Status == FALSE ) && GetLastError () == ERROR_INSUFFICIENT_BUFFER )
{
WORD t_Extra = 0 ;
if ( t_NetworkServicePresent == false )
{
t_Extra = t_Extra + g_NetworkService_AceSize ;
}
if ( t_LocalServicePresent == false )
{
t_Extra = t_Extra + g_LocalService_AceSize ;
}
t_DaclSize = t_DaclSize + t_Extra ;
t_Dacl = ( PACL ) new BYTE [ t_DaclSize ] ;
t_Sacl = ( PACL ) new BYTE [ t_SaclSize ] ;
t_Owner = ( PSID ) new BYTE [ t_OwnerSize ] ;
t_PrimaryGroup = ( PSID ) new BYTE [ t_PrimaryGroupSize ] ;
t_AbsoluteSecurityDescriptor = ( SECURITY_DESCRIPTOR * ) new BYTE [ t_AbsoluteSecurityDescriptorSize ] ;
if ( t_AbsoluteSecurityDescriptor && t_Dacl && t_Sacl && t_Owner && t_PrimaryGroup )
{
BOOL t_Status = InitializeSecurityDescriptor ( t_AbsoluteSecurityDescriptor , SECURITY_DESCRIPTOR_REVISION ) ;
if ( t_Status )
{
t_Status = MakeAbsoluteSD (t_SecurityDescriptor ,t_AbsoluteSecurityDescriptor ,& t_AbsoluteSecurityDescriptorSize ,
t_Dacl ,& t_DaclSize ,t_Sacl,& t_SaclSize,t_Owner,& t_OwnerSize,t_PrimaryGroup,& t_PrimaryGroupSize
) ;
WORD t_AceCount = t_Dacl->AceCount ;
if ( t_Status )
{
t_Dacl->AclSize = ( WORD ) t_DaclSize ;
if ( t_NetworkServicePresent == false )
{
t_Status = AddAce ( t_Dacl , ACL_REVISION, t_AceCount ++ , g_NetworkService_Ace , g_NetworkService_AceSize) ;
}
}
if ( t_Status )
{
if ( t_LocalServicePresent == false )
{
t_Status = AddAce ( t_Dacl , ACL_REVISION, t_AceCount ++ , g_LocalService_Ace , g_LocalService_AceSize) ;
}
}
if ( t_Status == FALSE )
{
t_Result = WBEM_E_CRITICAL_ERROR ;
}
}
}
}
if ( SUCCEEDED ( t_Result ) )
{
SECURITY_DESCRIPTOR *t_SecurityDescriptorRelative = NULL ;
DWORD t_FinalLength = 0 ;
t_Status = MakeSelfRelativeSD (t_AbsoluteSecurityDescriptor ,t_SecurityDescriptorRelative ,& t_FinalLength ) ;
if ( t_Status == FALSE && GetLastError () == ERROR_INSUFFICIENT_BUFFER )
{
t_SecurityDescriptorRelative = ( SECURITY_DESCRIPTOR * ) new BYTE [ t_FinalLength ] ;
if ( t_SecurityDescriptorRelative )
{
t_Status = InitializeSecurityDescriptor ( t_SecurityDescriptorRelative , SECURITY_DESCRIPTOR_REVISION ) ;
if ( t_Status )
{
t_Status = MakeSelfRelativeSD (t_AbsoluteSecurityDescriptor ,t_SecurityDescriptorRelative ,& t_FinalLength ) ;
if ( t_Status == FALSE )
{
t_Result = WBEM_E_CRITICAL_ERROR ;
}
}
else
{
t_Result = WBEM_E_CRITICAL_ERROR ;
}
}
else
{
t_Result = WBEM_E_OUT_OF_MEMORY ;
}
}
else
{
t_Result = WBEM_E_CRITICAL_ERROR ;
}
if ( SUCCEEDED ( t_Result ) )
{
SAFEARRAYBOUND t_Bounds ;
t_Bounds.lLbound = 0;
t_Bounds.cElements = t_FinalLength ;
a_NewArray = SafeArrayCreate ( VT_UI1 , 1 , & t_Bounds ) ;
if ( a_NewArray )
{
for ( LONG t_Index = 0 ; ( ( ULONG ) t_Index ) < t_FinalLength ; t_Index ++ )
{
BYTE t_Byte = * ( ( ( BYTE * ) t_SecurityDescriptorRelative ) + t_Index ) ;
t_Result = SafeArrayPutElement ( a_NewArray , & t_Index , & t_Byte ) ;
if ( FAILED ( t_Result ) )
{
break ;
}
}
}
else
{
t_Result = WBEM_E_OUT_OF_MEMORY ;
}
}
delete [] ( BYTE * ) t_SecurityDescriptorRelative ;
}
delete [] ( BYTE * ) t_Dacl ;
delete [] ( BYTE * ) t_Sacl ;
delete [] ( BYTE * ) t_Owner ;
delete [] ( BYTE * ) t_PrimaryGroup ;
}
delete [] t_SecurityDescriptor ;
}
else
{
t_Result = WBEM_E_CRITICAL_ERROR ;
}
return t_Result ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
HRESULT ConfigureSecurity (
IWbemServices *a_Service
)
{
HRESULT t_Result = S_OK ;
BSTR t_ObjectPath = SysAllocString ( L"__SystemSecurity" ) ;
BSTR t_MethodName = SysAllocString ( L"GetSD" ) ;
if ( t_ObjectPath && t_MethodName )
{
IWbemClassObject *t_Object = NULL ;
t_Result = a_Service->ExecMethod (t_ObjectPath ,t_MethodName ,0 ,NULL ,NULL ,& t_Object ,NULL);
if ( SUCCEEDED ( t_Result ) )
{
VARIANT t_Variant ;
VariantInit ( & t_Variant ) ;
LONG t_VarType = 0 ;
LONG t_Flavour = 0 ;
HRESULT t_Result = t_Object->Get ( L"SD" , 0 , & t_Variant , & t_VarType , & t_Flavour ) ;
if ( SUCCEEDED ( t_Result ) )
{
if ( t_Variant.vt == ( VT_UI1 | VT_ARRAY ) )
{
SAFEARRAY *t_Array = t_Variant.parray ;
SAFEARRAY *t_NewArray = NULL ;
t_Result = InsertServiceAccess (t_Array ,t_NewArray ) ;
if ( SUCCEEDED ( t_Result ) )
{
BSTR t_Class = SysAllocString ( L"__SystemSecurity" ) ;
if ( t_Class )
{
IWbemClassObject *t_InObject = NULL ;
t_Result = a_Service->GetObject (t_Class ,0 , NULL , & t_InObject ,NULL ) ;
if ( SUCCEEDED ( t_Result ) )
{
BSTR t_SetMethodName = SysAllocString ( L"SetSD" ) ;
if ( t_SetMethodName )
{
IWbemClassObject *t_InArgsClass = NULL ;
t_Result = t_InObject->GetMethod (t_SetMethodName ,0 ,& t_InArgsClass ,NULL ) ;
if ( SUCCEEDED ( t_Result ) )
{
IWbemClassObject *t_InArgs = NULL ;
t_Result = t_InArgsClass->SpawnInstance ( 0 , & t_InArgs ) ;
if ( SUCCEEDED ( t_Result ) )
{
VARIANT t_Variant ;
VariantInit ( & t_Variant ) ;
t_Variant.vt = VT_UI1 | VT_ARRAY ;
t_Variant.parray = t_NewArray ;
t_Result = t_InArgs->Put ( L"SD" ,0 ,& t_Variant ,CIM_UINT8 | CIM_FLAG_ARRAY) ;
if ( SUCCEEDED ( t_Result ) )
{
IWbemClassObject *t_OutArgs = NULL ;
a_Service->ExecMethod (t_ObjectPath ,t_SetMethodName ,0 ,NULL ,t_InArgs ,& t_OutArgs ,NULL ) ;
if ( SUCCEEDED ( t_Result ) )
{
if ( t_OutArgs )
{
t_OutArgs->Release () ;
}
}
}
t_InArgs->Release () ;
}
t_InArgsClass->Release () ;
}
SysFreeString ( t_SetMethodName ) ;
}
t_InObject->Release () ;
}
}
else
{
t_Result = WBEM_E_OUT_OF_MEMORY ;
}
SafeArrayDestroy ( t_NewArray ) ;
}
}
else
{
t_Result = WBEM_E_CRITICAL_ERROR ;
}
VariantClear ( & t_Variant ) ;
}
t_Object->Release () ;
}
}
else
{
t_Result = WBEM_E_OUT_OF_MEMORY ;
}
SysFreeString ( t_ObjectPath ) ;
SysFreeString ( t_MethodName ) ;
return t_Result ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
HRESULT Traverse (
IWbemServices *a_Service ,
BSTR a_Namespace
)
{
if ( wcslen ( a_Namespace ) < ( MAX_MSG_TEXT_LENGTH >> 1 ) )
{
char t_Buffer [ MAX_MSG_TEXT_LENGTH ] ;
StringCchPrintfA ( t_Buffer , MAX_MSG_TEXT_LENGTH, "\nTraversing [%S]" , a_Namespace ) ;
LogMessage(MSG_INFO, t_Buffer);
}
HRESULT t_Result = ConfigureSecurity (a_Service ) ;
if ( FAILED ( t_Result ) )
{
char t_Buffer [ MAX_MSG_TEXT_LENGTH ] ;
StringCchPrintfA ( t_Buffer, MAX_MSG_TEXT_LENGTH , "\nConfiguration of Security failed [%lx]" , t_Result ) ;
LogMessage(MSG_INFO, t_Buffer);
}
return t_Result ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
HRESULT ConfigureServiceSecurity ()
{
IWbemLocator *t_Locator = NULL ;
HRESULT t_Result = CoCreateInstance (CLSID_WbemLocator ,NULL ,CLSCTX_INPROC_SERVER | CLSCTX_LOCAL_SERVER ,
IID_IUnknown ,( void ** ) & t_Locator);
if ( SUCCEEDED ( t_Result ) )
{
BSTR t_Root = SysAllocString ( L"root" ) ;
if ( t_Root )
{
IWbemServices *t_Service = NULL ;
HRESULT t_Result = t_Locator->ConnectServer (t_Root ,NULL ,NULL,NULL ,0 ,NULL,NULL,&t_Service) ;
if ( SUCCEEDED ( t_Result ) )
{
t_Result = TraverseSetSecurity ( t_Service ) ;
if ( SUCCEEDED ( t_Result ) )
{
t_Result = Traverse (t_Service ,t_Root ) ;
}
t_Service->Release () ;
}
else
{
char t_Buffer [ MAX_MSG_TEXT_LENGTH ] ;
StringCchPrintfA ( t_Buffer , MAX_MSG_TEXT_LENGTH, "\nFailing Connecting to Namespace [%s] with result [%lx]" , t_Root , t_Result ) ;
LogMessage(MSG_INFO, t_Buffer);
}
SysFreeString ( t_Root ) ;
}
else
{
t_Result = WBEM_E_OUT_OF_MEMORY ;
}
t_Locator->Release () ;
}
return t_Result ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
HRESULT InitializeConstants ()
{
HRESULT t_Result = S_OK ;
SID_IDENTIFIER_AUTHORITY t_NtAuthoritySid = SECURITY_NT_AUTHORITY ;
BOOL t_Status = AllocateAndInitializeSid (& t_NtAuthoritySid ,1 ,SECURITY_NETWORK_SERVICE_RID,0,0,0,0,0,0,0,& g_NetworkServiceSid) ;
if ( t_Status )
{
DWORD t_SidLength = :: GetLengthSid ( g_NetworkServiceSid );
g_NetworkService_AceSize = sizeof(ACCESS_ALLOWED_ACE) + (WORD) ( t_SidLength - sizeof(DWORD) ) ;
g_NetworkService_Ace = (ACCESS_ALLOWED_ACE*) new BYTE [ g_NetworkService_AceSize ] ;
if ( g_NetworkService_Ace )
{
CopySid ( t_SidLength, (PSID) & g_NetworkService_Ace->SidStart, g_NetworkServiceSid ) ;
g_NetworkService_Ace->Mask = WBEM_ENABLE | WBEM_METHOD_EXECUTE | WBEM_WRITE_PROVIDER ;
g_NetworkService_Ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE ;
g_NetworkService_Ace->Header.AceFlags = CONTAINER_INHERIT_ACE ;
g_NetworkService_Ace->Header.AceSize = g_NetworkService_AceSize ;
}
else
{
t_Result = WBEM_E_OUT_OF_MEMORY ;
}
}
else
{
t_Result = WBEM_E_OUT_OF_MEMORY ;
}
if ( SUCCEEDED ( t_Result ) )
{
t_Status = AllocateAndInitializeSid (& t_NtAuthoritySid ,1 ,SECURITY_LOCAL_SERVICE_RID,0,0,0,0,0,0,0,& g_LocalServiceSid) ;
if ( t_Status )
{
DWORD t_SidLength = :: GetLengthSid ( g_LocalServiceSid );
g_LocalService_AceSize = sizeof(ACCESS_ALLOWED_ACE) + (WORD) ( t_SidLength - sizeof(DWORD) ) ;
g_LocalService_Ace = (ACCESS_ALLOWED_ACE*) new BYTE [ g_LocalService_AceSize ] ;
if ( g_LocalService_Ace )
{
CopySid ( t_SidLength, (PSID) & g_LocalService_Ace->SidStart, g_LocalServiceSid ) ;
g_LocalService_Ace->Mask = WBEM_ENABLE | WBEM_METHOD_EXECUTE | WBEM_WRITE_PROVIDER ;
g_LocalService_Ace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE ;
g_LocalService_Ace->Header.AceFlags = CONTAINER_INHERIT_ACE ;
g_LocalService_Ace->Header.AceSize = g_LocalService_AceSize ;
}
else
{
t_Result = WBEM_E_OUT_OF_MEMORY ;
}
}
else
{
t_Result = WBEM_E_OUT_OF_MEMORY ;
}
}
return t_Result ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
HRESULT UnInitializeConstants ()
{
FreeSid ( g_NetworkServiceSid ) ;
FreeSid ( g_LocalServiceSid ) ;
delete [] ( ( BYTE * ) g_NetworkService_Ace ) ;
delete [] ( ( BYTE * ) g_LocalService_Ace ) ;
return S_OK ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
HRESULT UpdateServiceSecurity ()
{
HRESULT t_Result = InitializeConstants () ;
if ( SUCCEEDED ( t_Result ) )
{
t_Result = ConfigureServiceSecurity () ;
UnInitializeConstants () ;
}
return t_Result ;
}
/******************************************************************************
*
* Name:
*
*
* Description:
*
*
*****************************************************************************/
HRESULT CheckForServiceSecurity ()
{
Registry r(WBEM_REG_WBEM);
if (r.GetStatus() != no_error)
{
LogMessage(MSG_ERROR, "Unable to access registry for UpdateServiceSecurity.");
return WBEM_E_CRITICAL_ERROR ;
}
char *t_BuildVersion = NULL ;
if ( r.GetStr ("Build", & t_BuildVersion ) )
{
LogMessage(MSG_ERROR, "Unable to get build version number for UpdateServiceSecurity.");
return WBEM_E_CRITICAL_ERROR ;
}
if ( strlen ( t_BuildVersion ) >= 4 )
{
t_BuildVersion [ 4 ] = 0 ;
}
else
{
LogMessage(MSG_ERROR, "Unexpected build version number for UpdateServiceSecurity.");
return WBEM_E_CRITICAL_ERROR ;
}
DWORD t_BuildVersionNumber = 0 ;
if ( sscanf ( t_BuildVersion , "%lu" , & t_BuildVersionNumber ) == NULL )
{
LogMessage(MSG_ERROR, "Unable to convert build version number for UpdateServiceSecurity.");
return WBEM_E_CRITICAL_ERROR ;
}
if ( t_BuildVersionNumber < 2600 )
{
LogMessage(MSG_INFO, "Operating System Version < WindowsXP (2600) UpdateServiceSecurity.");
return S_OK ;
}
else
{
return S_FALSE ;
}
}