windows-nt/Source/XPSP1/NT/ds/security/gina/rsoputil/create.cpp
2020-09-26 16:20:57 +08:00

1478 lines
43 KiB
C++

//*************************************************************
//
// Create namespace classes
//
// Microsoft Confidential
// Copyright (c) Microsoft Corporation 1995
// All rights reserved
//
// History: 9-Sep-99 SitaramR Created
//
//*************************************************************
#include <windows.h>
#include <wchar.h>
#include <ole2.h>
#include <initguid.h>
#include <wbemcli.h>
#define SECURITY_WIN32
#include <security.h>
#include <aclapi.h>
#include <seopaque.h>
#include <ntdsapi.h>
#include <winldap.h>
#include <ntldap.h>
#include <dsgetdc.h>
#include <lm.h>
#include "smartptr.h"
#include "RsopInc.h"
#include "rsopsec.h"
#include "rsoputil.h"
#include "rsopdbg.h"
#include "stdio.h"
#include "wbemtime.h"
#define ARRAYSIZE(a) (sizeof(a)/sizeof(a[0]))
BOOL PrintToString( XPtrST<WCHAR>& xwszValue, WCHAR *pwszString,
WCHAR *pwszParam1, WCHAR *pwszParam2,
DWORD dwParam3 );
//
// b7b1b3dd-ab09-4242-9e30-9980e5d322f7
//
const GUID guidProperty = {0xb7b1b3dd, 0xab09, 0x4242, 0x9e, 0x30, 0x99, 0x80, 0xe5, 0xd3, 0x22, 0xf7};
DWORD
RSoPBuildPrivileges( PSECURITY_DESCRIPTOR pSD, PSECURITY_DESCRIPTOR pAbsoluteSD, LPWSTR*, DWORD );
LPWSTR
GetDomainName();
DWORD
MakeUserName( LPWSTR szDomain, LPWSTR szUser, LPWSTR* pszUserName );
//*************************************************************
//
// CreateNameSpace
//
// Purpose: Creates a new namespace
//
// Parameters: pwszNameSpace - Namespace to create
// pwszParentNS - Parent namespace in which to create pwszNameSpace
//
// pWbemLocator - Wbem locator
//
// Returns: True if successful, false otherwise
//
//*************************************************************
HRESULT
CreateNameSpace( WCHAR *pwszNameSpace, WCHAR *pwszParentNS, IWbemLocator *pWbemLocator )
{
IWbemClassObject *pNSClass = NULL;
IWbemClassObject *pNSInstance = NULL;
IWbemServices *pWbemServices = NULL;
XBStr xParentNameSpace( pwszParentNS );
if ( !xParentNameSpace )
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("LogRegistryRsopData: Unable to allocate memory" ));
return E_OUTOFMEMORY;
}
HRESULT hr = pWbemLocator->ConnectServer( xParentNameSpace,
NULL,
NULL,
0L,
0L,
NULL,
NULL,
&pWbemServices );
if ( FAILED(hr) )
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("CreateNameSpace::ConnectServer failed with 0x%x" ), hr );
return hr;
}
XInterface<IWbemServices> xWbemServices( pWbemServices );
XBStr xbstrNS( L"__Namespace" );
if ( !xbstrNS )
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("CreateNameSpace::Failed to allocated memory" ));
return E_OUTOFMEMORY;
}
hr = pWbemServices->GetObject( xbstrNS,
0, NULL, &pNSClass, NULL );
if ( FAILED(hr) )
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("CreateNameSpace::GetObject failed with 0x%x" ), hr );
return hr;
}
XInterface<IWbemClassObject> xNSClass( pNSClass );
hr = pNSClass->SpawnInstance( 0, &pNSInstance );
if ( FAILED(hr) )
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("CreateNameSpace: SpawnInstance failed with 0x%x" ), hr );
return hr;
}
XInterface<IWbemClassObject> xNSInstance( pNSInstance );
XBStr xbstrName( L"Name" );
if ( !xbstrName )
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("CreateNameSpace::Failed to allocated memory" ));
return E_OUTOFMEMORY;
}
XBStr xbstrNameSpace( pwszNameSpace );
if ( !xbstrNameSpace )
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("CreateNameSpace::Failed to allocated memory" ));
return E_OUTOFMEMORY;
}
VARIANT var;
var.vt = VT_BSTR;
var.bstrVal = xbstrNameSpace;
hr = pNSInstance->Put( xbstrName, 0, &var, 0 );
if ( FAILED(hr) )
{
dbg.Msg(DEBUG_MESSAGE_WARNING, TEXT("CreateNameSpace: Put failed with 0x%x" ), hr );
return hr;
}
hr = pWbemServices->PutInstance( pNSInstance, WBEM_FLAG_CREATE_ONLY, NULL, NULL );
if ( FAILED(hr) )
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("CreateNameSpace: PutInstance failed with 0x%x" ), hr );
return hr;
}
return hr;
}
//*************************************************************
//
// Function: SetupCreationTimeAndCommit
//
// Purpose: Connects to a namespace where it expects to
// find class RSOP_Session as defined in rsop.mof.
// It then instantiates the class and sets the
// data member 'creationTime' to the current
// date and time.
//
// Parameters: pWbemLocator - Pointer to IWbemLocator used to
// connect to the namespace.
// wszNamespace - Name of the Namespace to connect.
//
// Returns: On success, it returns S_OK.
// On failure, it returns an HRESULT error code.
//
// History: 12/07/99 - LeonardM - Created.
//
//*************************************************************
HRESULT SetupCreationTimeAndCommit(IWbemLocator* pWbemLocator, LPWSTR wszNamespace)
{
//
// Check arguments
//
if(!pWbemLocator || !wszNamespace || (wcscmp(wszNamespace, L"") == 0))
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupCreationTimeAndCommit: Function called with invalid argument(s)."));
return WBEM_E_INVALID_PARAMETER;
}
//
// Connect to the namespace
//
XBStr xbstrNamespace = wszNamespace;
if(!xbstrNamespace)
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupCreationTimeAndCommit: Function failed to allocate memory."));
return E_OUTOFMEMORY;
}
XInterface<IWbemServices>xpNamespace;
HRESULT hr = pWbemLocator->ConnectServer( xbstrNamespace,
NULL,
NULL,
NULL,
0,
NULL,
NULL,
&xpNamespace);
if(FAILED(hr))
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupCreationTimeAndCommit: ConnectServer failed. hr=0x%08X"), hr);
return hr;
}
VARIANT var;
VariantInit(&var);
//
// Get class RSOP_Session
//
XBStr xbstrClassName = L"RSOP_Session";
if (!xbstrClassName)
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupCreationTimeAndCommit: Function failed to allocate memory."));
return E_OUTOFMEMORY;
}
XInterface<IWbemClassObject>xpClass;
hr = xpNamespace->GetObject(xbstrClassName, 0, NULL, &xpClass, NULL);
if(FAILED(hr))
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupCreationTimeAndCommit: GetObject failed. hr=0x%08X"), hr);
return hr;
}
//
// Spawn an instance of class RSOP_Session
//
XBStr xbstrInstancePath = L"RSOP_Session.id=\"Session1\"";
if(!xbstrInstancePath)
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("CSessionLogger::Log: Failed to allocate memory."));
return FALSE;
}
XInterface<IWbemClassObject>xpInstance;
hr = xpNamespace->GetObject(xbstrInstancePath, 0, NULL, &xpInstance, NULL);
if(FAILED(hr))
{
dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("SetupCreationTimeAndCommit: GetObject failed. trying to spawn instance. hr=0x%08X"), hr);
hr = xpClass->SpawnInstance(0, &xpInstance);
}
if(FAILED(hr))
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupCreationTimeAndCommit: SpawnInstance failed. hr=0x%08X"), hr);
return hr;
}
//
// Set the 'id' data member of class RSOP_Session
//
XBStr xbstrPropertyName;
XBStr xbstrPropertyValue;
xbstrPropertyName = L"id";
if(!xbstrPropertyName)
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupCreationTimeAndCommit: Function failed to allocate memory."));
return E_OUTOFMEMORY;
}
xbstrPropertyValue = L"Session1";
if(!xbstrPropertyValue)
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupCreationTimeAndCommit: Function failed to allocate memory."));
return E_OUTOFMEMORY;
}
var.vt = VT_BSTR;
var.bstrVal = xbstrPropertyValue;
hr = xpInstance->Put(xbstrPropertyName, 0, &var, 0);
if(FAILED(hr))
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupCreationTimeAndCommit: Put failed. hr=0x%08X"), hr);
return hr;
}
//
// Set the 'creationTime' data member of class RSOP_Session
//
xbstrPropertyName = L"creationTime";
if(!xbstrPropertyName)
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupCreationTimeAndCommit: Function failed to allocate memory."));
return E_OUTOFMEMORY;
}
hr = GetCurrentWbemTime(xbstrPropertyValue);
if(FAILED(hr))
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupCreationTimeAndCommit: GetCurrentWbemTime. hr=0x%08X"), hr);
return hr;
}
var.vt = VT_BSTR;
var.bstrVal = xbstrPropertyValue;
hr = xpInstance->Put(xbstrPropertyName, 0, &var, 0);
if(FAILED(hr))
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupCreationTimeAndCommit: Put failed. hr=0x%08X"), hr);
return hr;
}
//
// Set the 'ttlMinutes' data member of class RSOP_Session
//
xbstrPropertyName = L"ttlMinutes";
if(!xbstrPropertyName)
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupCreationTimeAndCommit: Function failed to allocate memory."));
return E_OUTOFMEMORY;
}
var.vt = VT_I4;
var.lVal = DEFAULT_NAMESPACE_TTL_MINUTES;
hr = xpInstance->Put(xbstrPropertyName, 0, &var, 0);
if(FAILED(hr))
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupCreationTimeAndCommit: Put failed. hr=0x%08X"), hr);
return hr;
}
// if any more data integrity checks needs to be done
// it can be done at this point
//
// Put instance of class RSOP_Session
//
hr = xpNamespace->PutInstance(xpInstance, WBEM_FLAG_CREATE_OR_UPDATE, NULL, NULL);
if(FAILED(hr))
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupCreationTimeAndCommit: PutInstance failed. hr=0x%08X"), hr);
return hr;
}
return S_OK;
}
//*************************************************************
//
// SetupNameSpaceSecurity
//
// Purpose: Sets namespace security.
//
// Parameters: szNamespace - New namespace returned here
// pSD - source security descriptor
// pWbemLocator - Wbem locator
//
// Returns: True if successful, false otherwise
//
//*************************************************************
HRESULT
SetNameSpaceSecurity( LPCWSTR szNamespace,
PSECURITY_DESCRIPTOR pSD,
IWbemLocator* pWbemLocator)
{
XBStr xNameSpace( (LPWSTR) szNamespace );
if ( !xNameSpace )
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupNameSpaceSecurity: Unable to allocate memory" ));
return E_FAIL;
}
XInterface<IWbemServices> xptrServices;
HRESULT hr = pWbemLocator->ConnectServer( xNameSpace,
0,
0,
0L,
0L,
0,
0,
&xptrServices );
if ( FAILED(hr) )
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupNameSpaceSecurity::ConnectServer failed with 0x%x" ), hr );
return hr;
}
return SetNamespaceSD( (SECURITY_DESCRIPTOR*)pSD, xptrServices);
}
//*************************************************************
//
// GetNameSpaceSecurity
//
// Purpose: Sets namespace security.
//
// Parameters: szNamespace - New namespace returned here
// pSD - source security descriptor
// pWbemLocator - Wbem locator
//
// Returns: True if successful, false otherwise
//
//*************************************************************
HRESULT
GetNameSpaceSecurity( LPCWSTR szNamespace,
PSECURITY_DESCRIPTOR *ppSD,
IWbemLocator* pWbemLocator)
{
XBStr xNameSpace( (LPWSTR) szNamespace );
if ( !xNameSpace )
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("GetNameSpaceSecurity: Unable to allocate memory" ));
return E_FAIL;
}
XInterface<IWbemServices> xptrServices;
HRESULT hr = pWbemLocator->ConnectServer( xNameSpace,
0,
0,
0L,
0L,
0,
0,
&xptrServices );
if ( FAILED(hr) )
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("GetNameSpaceSecurity::ConnectServer failed with 0x%x" ), hr );
return hr;
}
return GetNamespaceSD(xptrServices, (SECURITY_DESCRIPTOR **)ppSD);
}
//*************************************************************
//
// CopyNameSpaceSecurity
//
// Purpose: Copies namespace security.
//
// Parameters: pwszSrcNameSpace - Source namespace
// pwszDstNameSpace - Dest namespace
// pWbemLocator - Wbem locator
//
// Returns: HRESULT
//
//*************************************************************
HRESULT CopyNameSpaceSecurity(LPWSTR pwszSrcNameSpace, LPWSTR pwszDstNameSpace, IWbemLocator *pWbemLocator )
{
XHandle xhThreadToken;
//
// There is a bug in WMI which destroys the current thread token
// if connectserver is called to the local machine with impersonation.
// The following SetThreadToken needs to be removed once WMI bug 454721 is fixed.
//
if (!OpenThreadToken (GetCurrentThread(), TOKEN_IMPERSONATE | TOKEN_READ,
TRUE, &xhThreadToken)) {
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("CopyNameSpaceSecurity: Openthreadtoken failed with error %d."), GetLastError());
}
// internal function. arg checks not needed
dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("CopyNameSpaceSecurity: Copying Sec Desc from <%s> -> <%s>."),
pwszSrcNameSpace, pwszDstNameSpace );
//
// Copy to a BStr
//
XBStr xSrcNameSpace(pwszSrcNameSpace);
if (!xSrcNameSpace) {
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("CopyNameSpaceSecurity: Function failed to allocate memory."));
return E_OUTOFMEMORY;
}
XBStr xDstNameSpace(pwszDstNameSpace);
if (!xDstNameSpace) {
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("CopyNameSpaceSecurity: Function failed to allocate memory."));
return E_OUTOFMEMORY;
}
//
// Get the Source WBem Service
//
XInterface<IWbemServices> xpSrcSvc;
HRESULT hr = pWbemLocator->ConnectServer( xSrcNameSpace,
NULL,
NULL,
NULL,
0,
NULL,
NULL,
&xpSrcSvc);
SetThreadToken(NULL, xhThreadToken);
if(FAILED(hr))
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("CopyNameSpaceSecurity: ConnectServer failed for src. hr=0x%08X"), hr);
return hr;
}
//
// Self relative SD on the Source Name Space
//
XPtrLF<SECURITY_DESCRIPTOR> xpSelfRelativeSD;
hr = GetNamespaceSD(xpSrcSvc, &xpSelfRelativeSD);
SetThreadToken(NULL, xhThreadToken);
if(FAILED(hr))
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("CopyNameSpaceSecurity: GetNameSpaceSD failed for src. hr=0x%08X"), hr);
return hr;
}
//
// Get the Dest WBem Service
//
XInterface<IWbemServices> xpDstSvc;
hr = pWbemLocator->ConnectServer( xDstNameSpace,
NULL,
NULL,
NULL,
0,
NULL,
NULL,
&xpDstSvc);
SetThreadToken(NULL, xhThreadToken);
if(FAILED(hr))
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("CopyNameSpaceSecurity: ConnectServer failed for Dst. hr=0x%08X"), hr);
return hr;
}
//
// Set the SD already got on the Destination
//
hr = SetNamespaceSD( xpSelfRelativeSD, xpDstSvc);
SetThreadToken(NULL, xhThreadToken);
if(FAILED(hr))
{
dbg.Msg( DEBUG_MESSAGE_VERBOSE, L"CopyNameSpaceSecurity: SetNamespaceSD failed on Dst, 0x%08X", hr );
return hr;
}
// All Done
return S_OK;
}
//*************************************************************
//
// ProviderDeleteRsopNameSpace
//
// Purpose: WMI doesn't provide a mechanism to allow a user to delete a namespace
// unless it has write permissions on the parent
//
// Parameters: pwszNameSpace - Namespace to be deleted
// hToken - Token of the calling user.
// szSidString - String form of the calling user's sid.
// dwFlags - Flag to indicate planning mode or diagnostic mode
//
// Returns: S_OK if successful, HRESULT o/w
//
//*************************************************************
HRESULT ProviderDeleteRsopNameSpace( IWbemLocator *pWbemLocator, LPWSTR szNameSpace, HANDLE hToken, LPWSTR szSidString, DWORD dwFlags)
{
BOOL bDelete = FALSE;
BOOL bFound = FALSE;
HRESULT hr = S_OK;
LPWSTR pStr = szNameSpace;
//
// Make sure that the namespace is under root\rsop
//
for ( ;*pStr; pStr++) {
if (_wcsnicmp(pStr, RSOP_NS_ROOT_CHK, wcslen(RSOP_NS_ROOT_CHK)) == 0) {
bFound = TRUE;
break;
}
}
if (!bFound) {
dbg.Msg( DEBUG_MESSAGE_WARNING, L"ProviderDeleteRsopNameSpace: namespace is not under root\\rsop" );
return E_INVALIDARG;
}
if ( dwFlags & SETUP_NS_SM && IsInteractiveNameSpace(szNameSpace, szSidString)) {
dbg.Msg( DEBUG_MESSAGE_VERBOSE, L"ProviderDeleteRsopNameSpace: interactive namespace for the user." );
bDelete = TRUE;
}
else {
//
// if it is not interactive namespace check access
//
XPtrLF<SECURITY_DESCRIPTOR> xsd;
hr = GetNameSpaceSecurity(szNameSpace, (PSECURITY_DESCRIPTOR *)&xsd, pWbemLocator);
if (FAILED(hr)) {
dbg.Msg( DEBUG_MESSAGE_WARNING, L"ProviderDeleteRsopNameSpace: GetNameSpaceSecurity failed with error 0x%x", hr );
return hr;
}
GENERIC_MAPPING map;
PRIVILEGE_SET ps[3];
DWORD dwSize = 3 * sizeof(PRIVILEGE_SET);
BOOL bResult;
DWORD dwGranted = 0;
map.GenericRead = WMI_GENERIC_READ;
map.GenericWrite = WMI_GENERIC_WRITE;
map.GenericExecute = WMI_GENERIC_EXECUTE;
map.GenericAll = WMI_GENERIC_ALL;
if (!AccessCheck(xsd, hToken, RSOP_ALL_PERMS, &map, ps, &dwSize, &dwGranted, &bResult)) {
hr = HRESULT_FROM_WIN32(GetLastError());
dbg.Msg( DEBUG_MESSAGE_WARNING, L"ProviderDeleteRsopNameSpace: AccessCheck failed with error 0x%x", hr );
return hr;
}
if(bResult && dwGranted) {
dbg.Msg( DEBUG_MESSAGE_VERBOSE, L"ProviderDeleteRsopNameSpace: User has full rights on the child namespace");
bDelete = TRUE;
}
else {
dbg.Msg( DEBUG_MESSAGE_VERBOSE, L"ProviderDeleteRsopNameSpace: This user is not granted access on the namespace", hr );
}
}
if (bDelete) {
hr = DeleteRsopNameSpace(szNameSpace, pWbemLocator);
}
else {
hr = WBEM_E_ACCESS_DENIED;
}
return hr;
}
//*************************************************************
//
// SetupNewNameSpace
//
// Purpose: Creates a new temp namespace and two child namespaces, User and Computer.
// It also copies all the class definitions
// Additionally, it calls SetupCreationTimeAndCommit
// which in turn instantiates RSOP_Session and updates the
// data member 'creationTime' with the current time.
//
// Parameters: pwszNameSpace - New namespace returned here (This is allocated here)
// szRemoteComputer - Remote Computer under which this name space has to be
// created.
// szUserSid - UserSid. Only relevant in Diagnostic mode
// pSid - Sid of the calling User
// pWbemLocator - Wbem locator
// dwFlags - Flag to indicate planning mode or diagnostic mode
// dwExtendedInfo - The extended info to modify appropriately
//
// Returns: True if successful, false otherwise
//
//
// Usage:
// In Diagnostic mode, we copy instances. In planning mode we just copy Classes
//*************************************************************
HRESULT SetupNewNameSpace(
LPWSTR *pwszOutNameSpace,
LPWSTR szRemoteComputer,
LPWSTR szUserSid,
PSID pSid,
IWbemLocator *pWbemLocator,
DWORD dwFlags,
DWORD *pdwExtendedInfo)
{
GUID guid;
XPtrLF<WCHAR> xwszRelNameSpace;
XPtrLF<WCHAR> xwszRootNameSpace;
XPtrLF<WCHAR> xwszSrcNameSpace;
DWORD dwSrcNSLen;
XPtrLF<WCHAR> xwszNameSpace;
LPWSTR szComputerLocal;
HRESULT hr = S_OK, hrUser = S_OK, hrMachine = S_OK;
if ((dwFlags & SETUP_NS_SM_INTERACTIVE) ||
(dwFlags & SETUP_NS_SM_NO_USER) ||
(dwFlags & SETUP_NS_SM_NO_COMPUTER)) {
if (!(dwFlags & SETUP_NS_SM)) {
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupNewNameSpace::invalid flag parameters"));
return E_INVALIDARG;
}
}
XPtrLF<SECURITY_DESCRIPTOR> xsd;
SECURITY_ATTRIBUTES sa;
CSecDesc Csd;
*pwszOutNameSpace = NULL;
Csd.AddLocalSystem(RSOP_ALL_PERMS, CONTAINER_INHERIT_ACE);
Csd.AddAdministrators(RSOP_ALL_PERMS, CONTAINER_INHERIT_ACE);
if (dwFlags & SETUP_NS_SM_INTERACTIVE) {
Csd.AddSid(pSid, RSOP_READ_PERMS, CONTAINER_INHERIT_ACE);
}
else {
Csd.AddSid(pSid, RSOP_ALL_PERMS, CONTAINER_INHERIT_ACE);
}
Csd.AddAdministratorsAsOwner();
Csd.AddAdministratorsAsGroup();
xsd = Csd.MakeSelfRelativeSD();
if (!xsd) {
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupNewNameSpace::Makeselfrelativesd failed with %d"), GetLastError());
return HRESULT_FROM_WIN32(GetLastError());
}
//
// ignore inheritted perms..
//
if (!SetSecurityDescriptorControl( (SECURITY_DESCRIPTOR *)xsd, SE_DACL_PROTECTED, SE_DACL_PROTECTED )) {
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupNewNameSpace::SetSecurityDescriptorControl failed with %d"), GetLastError());
return HRESULT_FROM_WIN32(GetLastError());
}
//
// Initialise the out params
//
if ((dwFlags & SETUP_NS_SM) && (!szUserSid))
return E_INVALIDARG;
//
// Calculate the length required for the name spaces
//
DWORD dwLenNS=RSOP_NS_TEMP_LEN;
if ((szRemoteComputer) && (*szRemoteComputer)) {
dwLenNS += lstrlen(szRemoteComputer);
szComputerLocal = szRemoteComputer;
}
else {
szComputerLocal = L".";
}
xwszRelNameSpace = (LPWSTR)LocalAlloc(LPTR, (1+MAX(RSOP_NS_TEMP_LEN, lstrlen(szUserSid)))*sizeof(WCHAR));
if (!xwszRelNameSpace) {
hr = HRESULT_FROM_WIN32(GetLastError());
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupNewNameSpace::AllocMem failed with 0x%x"), hr );
return hr;
}
//
// guid for the Name Space
//
hr = CoCreateGuid( &guid );
if ( FAILED(hr) ) {
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupNewNameSpace::CoCreateGuid failed with 0x%x"), hr );
return hr;
}
//
// Allocate the memory and initialise
//
xwszRootNameSpace = (LPTSTR)LocalAlloc(LPTR, sizeof(WCHAR)*(lstrlen(szComputerLocal)+RSOP_NS_ROOT_LEN));
if (!xwszRootNameSpace) {
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupNewNameSpace::Not enough Space. Error - 0x%x"), GetLastError() );
return HRESULT_FROM_WIN32(GetLastError());
}
// allocating max needed
dwSrcNSLen = (RSOP_NS_ROOT_LEN+lstrlen(szUserSid)+RSOP_NS_MAX_OFFSET_LEN+10);
if (dwFlags & SETUP_NS_SM)
dwSrcNSLen += lstrlen(szUserSid);
xwszSrcNameSpace = (LPTSTR)LocalAlloc(LPTR, sizeof(WCHAR)*dwSrcNSLen);
if (!xwszSrcNameSpace) {
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupNewNameSpace::Not enough Space. Error - 0x%x"), GetLastError() );
return HRESULT_FROM_WIN32(GetLastError());
}
swprintf(xwszRootNameSpace, RSOP_NS_REMOTE_ROOT_FMT, szComputerLocal);
wcscpy(xwszSrcNameSpace, RSOP_NS_DIAG_ROOT);
LPTSTR lpEnd = xwszSrcNameSpace+lstrlen(xwszSrcNameSpace);
//
// Create a new Name Space under the root
//
dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("SetupNewNameSpace: Creating new NameSpace <%s>"), xwszRootNameSpace);
if (dwFlags & SETUP_NS_SM_INTERACTIVE) {
XPtrLF<WCHAR> xszWmiName = (LPTSTR)LocalAlloc(LPTR, sizeof(TCHAR)*(lstrlen(szUserSid)+1));
if (!xszWmiName) {
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupNewNameSpace::CreateNameSpace couldn't allocate memory with error %d"), GetLastError() );
return FALSE;
}
ConvertSidToWMIName(szUserSid, xszWmiName);
swprintf( xwszRelNameSpace,
L"%s%s",
RSOP_NS_TEMP_PREFIX,
xszWmiName);
}
else {
swprintf( xwszRelNameSpace,
L"%s%08lX_%04X_%04X_%02X%02X_%02X%02X%02X%02X%02X%02X",
RSOP_NS_TEMP_PREFIX,
guid.Data1,
guid.Data2,
guid.Data3,
guid.Data4[0], guid.Data4[1],
guid.Data4[2], guid.Data4[3],
guid.Data4[4], guid.Data4[5],
guid.Data4[6], guid.Data4[7] );
}
hr = CreateAndCopyNameSpace(pWbemLocator, xwszSrcNameSpace, xwszRootNameSpace,
xwszRelNameSpace, 0, xsd, &xwszNameSpace);
if ( FAILED(hr) ) {
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupNewNameSpace::CreateNameSpace failed with 0x%x"), hr );
return hr;
}
//
// if it has come till here, the assumption is that we
// could create the namespace in the context that we are running in
//
// In diagnostic interactive mode we have already made sure that the sid is the
// same as the user.
//
if (pdwExtendedInfo) {
*pdwExtendedInfo &= ~RSOP_USER_ACCESS_DENIED;
*pdwExtendedInfo &= ~RSOP_COMPUTER_ACCESS_DENIED;
}
wcscat(lpEnd, L"\\"); lpEnd++;
DWORD dwCopyFlags = 0;
if (dwFlags & SETUP_NS_PM) {
//
// if it is planning mode, copy classes from RSOP_NS_USER
//
wcscpy(lpEnd, RSOP_NS_USER_OFFSET);
dwCopyFlags = NEW_NS_FLAGS_COPY_CLASSES;
}
else {
if (dwFlags & SETUP_NS_SM_NO_USER) {
//
// If no user copy classes from root\rsop\user itself
//
wcscpy(lpEnd, RSOP_NS_SM_USER_OFFSET);
dwCopyFlags = NEW_NS_FLAGS_COPY_CLASSES;
}
else {
//
// if it is diagnostic mode, copy classes and instances from RSOP_NS_USER_SId
//
XPtrLF<WCHAR> xszWmiName = (LPTSTR)LocalAlloc(LPTR, sizeof(TCHAR)*(lstrlen(szUserSid)+1));
if (!xszWmiName) {
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupNewNameSpace::CreateNameSpace couldn't allocate memory with error %d"), GetLastError() );
return FALSE;
}
ConvertSidToWMIName(szUserSid, xszWmiName);
swprintf(lpEnd, RSOP_NS_DIAG_USER_OFFSET_FMT, xszWmiName);
dwCopyFlags = NEW_NS_FLAGS_COPY_CLASSES | NEW_NS_FLAGS_COPY_INSTS;
}
}
hrUser = CreateAndCopyNameSpace(pWbemLocator, xwszSrcNameSpace, xwszNameSpace,
RSOP_NS_SM_USER_OFFSET, dwCopyFlags,
xsd, NULL);
if ( FAILED(hrUser) ) {
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupNewNameSpace::CreateNameSpace failed with 0x%x"), hrUser );
}
//
// for machine only the flags are different. source namespaces are the same
//
if (dwFlags & SETUP_NS_PM) {
dwCopyFlags = NEW_NS_FLAGS_COPY_CLASSES;
}
else {
if (dwFlags & SETUP_NS_SM_NO_COMPUTER)
dwCopyFlags = NEW_NS_FLAGS_COPY_CLASSES;
else
dwCopyFlags = NEW_NS_FLAGS_COPY_CLASSES | NEW_NS_FLAGS_COPY_INSTS;
}
wcscpy(lpEnd, RSOP_NS_MACHINE_OFFSET);
hrMachine = CreateAndCopyNameSpace(pWbemLocator, xwszSrcNameSpace, xwszNameSpace,
RSOP_NS_DIAG_MACHINE_OFFSET, dwCopyFlags,
xsd, NULL);
if ( FAILED(hrMachine) ) {
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupNewNameSpace::CreateNameSpace failed with 0x%x"), hrMachine );
}
if (FAILED(hrUser)) {
if (pdwExtendedInfo) {
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupNewNameSpace::User part of rsop failed with 0x%x"), hrUser );
*pdwExtendedInfo |= RSOP_USER_ACCESS_DENIED;
}
}
if (FAILED(hrMachine)) {
if (pdwExtendedInfo) {
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupNewNameSpace::computer part of rsop failed with 0x%x"), hrMachine );
*pdwExtendedInfo |= RSOP_COMPUTER_ACCESS_DENIED;
}
}
if (FAILED(hrUser)) {
return hrUser;
}
if (FAILED(hrMachine)) {
return hrMachine;
}
dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("SetupNewNameSpace: Returning Successfully"));
//
// Now handover the ownership to the caller.
//
*pwszOutNameSpace = xwszNameSpace.Acquire();
return S_OK;
}
//*************************************************************
// ConvertSidToWMIName
//
// WMI doesn't like '-' in names. Connverting - to '_' blindly
//*************************************************************
void ConvertSidToWMIName(LPTSTR lpSid, LPTSTR lpWmiName)
{
for (;(*lpSid); lpSid++, lpWmiName++) {
if (*lpSid == L'-')
*lpWmiName = L'_';
else
*lpWmiName = *lpSid;
}
*lpWmiName = L'\0';
}
//*************************************************************
// ConvertWMINameToSid
//
// WMI doesn't like '-' in names.
//*************************************************************
void ConvertWMINameToSid(LPTSTR lpWmiName, LPTSTR lpSid )
{
for (;(*lpWmiName); lpSid++, lpWmiName++) {
if (*lpWmiName == L'_')
*lpSid = L'-';
else
*lpSid = *lpWmiName;
}
*lpSid = L'\0';
}
//*************************************************************
//
// DeleteNameSpace
//
// Purpose: Deletes namespace
//
// Parameters: pwszNameSpace - Namespace to delete
// pWbemLocator - Wbem locator pointer
//
// Returns: True if successful, false otherwise
//
//*************************************************************
HRESULT
DeleteNameSpace( WCHAR *pwszNameSpace, WCHAR *pwszParentNameSpace, IWbemLocator *pWbemLocator )
{
XBStr xParentNameSpace( pwszParentNameSpace );
if ( !xParentNameSpace )
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("DeleteNameSpace: Unable to allocate memory" ));
return E_OUTOFMEMORY;
}
IWbemServices *pWbemServices = NULL;
HRESULT hr = pWbemLocator->ConnectServer( xParentNameSpace,
NULL,
NULL,
0L,
0L,
NULL,
NULL,
&pWbemServices );
if ( FAILED(hr) )
{
dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("DeleteNameSpace::ConnectServer failed with 0x%x" ), hr );
return hr;
}
XInterface<IWbemServices> xWbemServices( pWbemServices );
WCHAR wszNSRef[] = L"__Namespace.name=\"%ws\"";
XPtrST<WCHAR> xwszNSValue;
if ( !PrintToString( xwszNSValue, wszNSRef, pwszNameSpace, 0, 0 ) )
{
return E_OUTOFMEMORY;
}
XBStr xbstrNSValue( xwszNSValue );
if ( !xbstrNSValue )
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("DeleteNameSpace: Failed to allocate memory" ));
return E_OUTOFMEMORY;
}
VARIANT var;
var.vt = VT_BSTR;
var.bstrVal = xbstrNSValue;
hr = pWbemServices->DeleteInstance( var.bstrVal,
0L,
NULL,
NULL );
if ( FAILED(hr) )
{
dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("DeleteNameSpace: Failed to DeleteInstance with 0x%x"), hr );
return hr;
}
dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("DeleteNameSpace: Deleted namespace %s under %s" ), pwszNameSpace, pwszParentNameSpace);
return hr;
}
//*************************************************************
//
// DeleteRsopNameSpace
//
// Purpose: Deletes namespace
//
// Parameters: pwszNameSpace - Namespace to delete (the full path)
// pWbemLocator - Wbem locator pointer
//
// Returns: True if successful, false otherwise
//
//*************************************************************
HRESULT DeleteRsopNameSpace( WCHAR *pwszNameSpace, IWbemLocator *pWbemLocator )
{
LPWSTR pwszChildName = NULL;
HRESULT hr = S_OK;
//
// Generating the parent child name by traversing the name
//
pwszChildName = wcsrchr(pwszNameSpace, L'\\');
if (!pwszChildName) {
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("DeleteRsopNameSpace: Invalid format - %s" ), pwszNameSpace);
return E_INVALIDARG;
}
WCHAR wTmp = *pwszChildName;
*pwszChildName = L'\0';
pwszChildName++;
hr = DeleteNameSpace(pwszChildName, pwszNameSpace, pWbemLocator);
*(pwszChildName-1) = wTmp;
return hr;
}
//*************************************************************
//
// IsInteractiveNameSpace
//
// Purpose: returns whether a namespace is a special namespace
// specifically created to allow interactive users to get rsop
// data
//
// Parameters: pwszNameSpace - Namespace
// szSid - Sid of the user
//
// Returns: True if successful, false otherwise
//
//*************************************************************
BOOL IsInteractiveNameSpace(WCHAR *pwszNameSpace, WCHAR *szSid)
{
LPWSTR pwszChildName = NULL;
HRESULT hr = S_OK;
XPtrLF<WCHAR> xwszInteractiveNameSpace;
BOOL bInteractive = FALSE;
xwszInteractiveNameSpace = (LPWSTR)LocalAlloc(LPTR, (5+wcslen(RSOP_NS_TEMP_PREFIX) + wcslen(szSid))*sizeof(WCHAR));
if (!xwszInteractiveNameSpace) {
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("IsInteractiveNameSpace: Couldn't Allocate memory. Error - %d" ), GetLastError());
return bInteractive;
}
//
// Generating the parent child name by traversing the name
//
pwszChildName = wcsrchr(pwszNameSpace, L'\\');
if (!pwszChildName) {
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("IsInteractiveNameSpace: Invalid format - %s" ), pwszNameSpace);
return bInteractive;
}
pwszChildName++;
XPtrLF<WCHAR> xszWmiName = (LPTSTR)LocalAlloc(LPTR, sizeof(TCHAR)*(lstrlen(szSid)+1));
if (!xszWmiName) {
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("IsInteractiveNameSpace::CreateNameSpace couldn't allocate memory with error %d"), GetLastError() );
return bInteractive;
}
ConvertSidToWMIName(szSid, xszWmiName);
swprintf( xwszInteractiveNameSpace,
L"%s%s",
RSOP_NS_TEMP_PREFIX,
xszWmiName);
if (_wcsicmp(pwszChildName, xwszInteractiveNameSpace) == 0) {
dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("IsInteractiveNameSpace:: Interactive namespace"));
bInteractive = TRUE;
}
return bInteractive;
}
//*************************************************************
//
// GetInteractiveNameSpace
//
// Purpose: returns whether a namespace is a special namespace
// specifically created to allow interactive users to get rsop
// data
//
// Parameters: pwszNameSpace - Namespace
// szSid - Sid of the user
//
// Returns: True if successful, false otherwise
//
//*************************************************************
HRESULT GetInteractiveNameSpace(WCHAR *szSid, LPWSTR *szNameSpace)
{
XPtrLF<WCHAR> xwszInteractiveNameSpace;
*szNameSpace = NULL;
xwszInteractiveNameSpace = (LPWSTR)LocalAlloc(LPTR, (5+wcslen(RSOP_NS_TEMP_FMT) + wcslen(szSid))*sizeof(WCHAR));
if (!xwszInteractiveNameSpace) {
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("GetInteractiveNameSpace: Couldn't Allocate memory. Error - %d" ), GetLastError());
return HRESULT_FROM_WIN32(GetLastError());
}
XPtrLF<WCHAR> xszWmiName = (LPTSTR)LocalAlloc(LPTR, sizeof(TCHAR)*(lstrlen(szSid)+1));
if (!xszWmiName) {
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("GetInteractiveNameSpace::Couldn't allocate memory with error %d"), GetLastError() );
return HRESULT_FROM_WIN32(GetLastError());
}
ConvertSidToWMIName(szSid, xszWmiName);
swprintf( xwszInteractiveNameSpace,
RSOP_NS_TEMP_FMT,
xszWmiName);
*szNameSpace = xwszInteractiveNameSpace.Acquire();
return S_OK;
}
//*************************************************************
//
// PrintToString
//
// Purpose: Safe swprintf routine
//
// Parameters: xwszValue - String returned here
// wszString - Format string
// pwszParam1 - Param 1
// pwszParam2 - Param 2
// dwParam3 - Param 3
//
//*************************************************************
BOOL PrintToString( XPtrST<WCHAR>& xwszValue, WCHAR *pwszString,
WCHAR *pwszParam1, WCHAR *pwszParam2,
DWORD dwParam3 )
{
DWORD dwSize = wcslen(pwszString)+32;
if ( pwszParam1 )
{
dwSize += wcslen( pwszParam1 );
}
if ( pwszParam2 )
{
dwSize += wcslen( pwszParam2 );
}
xwszValue = new WCHAR[dwSize];
if ( !xwszValue ) {
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("PrintToString: Failed to allocate memory" ));
return FALSE;
}
while ( _snwprintf( xwszValue, dwSize, pwszString,
pwszParam1, pwszParam2, dwParam3 ) <= 0 ) {
dwSize *= 2;
xwszValue = new WCHAR[dwSize];
if ( !xwszValue ) {
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("PrintToString: Failed to allocate memory" ));
return FALSE;
}
}
return TRUE;
}
//*************************************************************
//
// CreateAndCopyNameSpace
//
// Purpose: Creates and Copies the name space
// This does an exact replica of the Src Name Space including
// copying the security Descriptors from the Source
//
// Parameters:
//
// Returns: domain name if successful, 0 otherwise
//
//*************************************************************
HRESULT
CreateAndCopyNameSpace(IWbemLocator *pWbemLocator, LPWSTR szSrcNameSpace, LPWSTR szDstRootNameSpace,
LPWSTR szDstRelNameSpace, DWORD dwFlags, PSECURITY_DESCRIPTOR pSecDesc, LPWSTR *szDstNameSpaceOut)
{
BOOL bOk = TRUE, bAbort = FALSE;
BOOL bCopyClasses = (dwFlags & NEW_NS_FLAGS_COPY_CLASSES) ? TRUE : FALSE;
BOOL bCopyInstances = (dwFlags & NEW_NS_FLAGS_COPY_INSTS) ? TRUE : FALSE;
XPtrLF<WCHAR> xszDstNameSpace;
HRESULT hr = S_OK;
dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("CreateAndCopyNameSpace: New Name space from %s -> %s,%s, flags 0x%x "),
szSrcNameSpace, szDstRootNameSpace, szDstRelNameSpace, dwFlags);
if (szDstNameSpaceOut)
{
*szDstNameSpaceOut = 0;
}
xszDstNameSpace = (LPWSTR)LocalAlloc(LPTR, sizeof(WCHAR)*(lstrlen(szDstRootNameSpace)+lstrlen(szDstRelNameSpace)+5));
if (!xszDstNameSpace)
{
return E_OUTOFMEMORY;
}
lstrcpy(xszDstNameSpace, szDstRootNameSpace);
lstrcat(xszDstNameSpace, L"\\");
lstrcat(xszDstNameSpace, szDstRelNameSpace);
hr = CreateNameSpace( szDstRelNameSpace, szDstRootNameSpace, pWbemLocator );
if ( FAILED( hr ) )
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("CreateAndCopyNameSpace::CreateNameSpace failed with 0x%x"), hr );
return hr;
}
if (!pSecDesc)
{
hr = CopyNameSpaceSecurity(szSrcNameSpace, xszDstNameSpace, pWbemLocator );
if ( FAILED(hr) )
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("CreateAndCopyNameSpace::CopyNameSpaceSecurity failed with 0x%x"), hr );
goto Exit;
}
}
else
{
hr = SetNameSpaceSecurity( xszDstNameSpace, pSecDesc, pWbemLocator);
if ( FAILED(hr) ) {
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("SetupNewNameSpace::SetNameSpaceSecurity failed with 0x%x"), hr );
goto Exit;
}
}
if (bCopyClasses) {
hr = CopyNameSpace( szSrcNameSpace, xszDstNameSpace, bCopyInstances, &bAbort, pWbemLocator );
if ( FAILED(hr) )
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("CreateAndCopyNameSpace::CopyNameSpace failed with 0x%x"), hr );
goto Exit;
}
//
// Instantiate class RSOP_Session and set data member
// 'creationTime' with current date and time.
//
dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("CreateAndCopyNameSpace: Setting up creation time"));
hr = SetupCreationTimeAndCommit(pWbemLocator, xszDstNameSpace);
if(FAILED(hr))
{
dbg.Msg( DEBUG_MESSAGE_WARNING, TEXT("CreateAndCopyNameSpace: SetupCreationTimeAndCommit failed with 0x%x"), hr );
goto Exit;
}
}
dbg.Msg( DEBUG_MESSAGE_VERBOSE, TEXT("CreateAndCopyNameSpace: Returning with Success NameSpace %s "),
xszDstNameSpace);
if (szDstNameSpaceOut)
{
*szDstNameSpaceOut = xszDstNameSpace.Acquire();
}
return hr;
Exit:
DeleteNameSpace(szDstRelNameSpace, szDstRootNameSpace, pWbemLocator);
return hr;
}