|
|
///////////////////////////////////////////////////////////////////////////////
//
// Copyright (c) Microsoft Corporation
//
// SYNOPSIS
//
// Win2k and early Whistler DB to Whistler DB Migration
//
///////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "GlobalData.h"
#include "migratecontent.h"
#include "MigrateEapConfig.h"
#include "Objects.h"
#include "Properties.h"
#include "updatemschap.h"
//////////////////////////////////////////////////////////////////////////////
// CopyTree
//
// Param:
// - the Id in the Reference (Ref) database: place to read from (iasold.mdb)
// - the parent of that same node but in the Standard (Std) database:
// the place to write to (ias.mdb)
//
//////////////////////////////////////////////////////////////////////////////
HRESULT CMigrateContent::CopyTree(LONG RefId, LONG ParentParam) { /////////////////////////////////////////
// get the name and Parent in the Ref DB
/////////////////////////////////////////
_bstr_t Name; LONG Parent; HRESULT hr = m_GlobalData.m_pRefObjects->GetObjectIdentity( Name, Parent, RefId ); if ( FAILED(hr) ) { return hr; }
///////////////////////////////////////////////////////
// insert the object (gives an Identity) in the Std DB
///////////////////////////////////////////////////////
LONG NewIdentity;
BOOL InsertOk = m_GlobalData.m_pObjects->InsertObject( Name, ParentParam, NewIdentity ); if ( !InsertOk ) { ///////////////////////////////////////////////
// the object already exists don't do anything
///////////////////////////////////////////////
return S_OK; }
_bstr_t PropertyName; _bstr_t StrVal; LONG Type;
/////////////////////////////////////////////////////////////////
// Copy the properties of that object from the Ref to the Std DB
/////////////////////////////////////////////////////////////////
hr = m_GlobalData.m_pRefProperties->GetProperty( RefId, PropertyName, Type, StrVal ); LONG IndexProperty = 1; while ( hr == S_OK ) { m_GlobalData.m_pProperties->InsertProperty( NewIdentity, PropertyName, Type, StrVal ); hr = m_GlobalData.m_pRefProperties->GetNextProperty( RefId, PropertyName, Type, StrVal, IndexProperty ); ++IndexProperty;
} // here safely ignore hr
//////////////////////////////////////////////////////////
// get all the childs of the object in the Ref DB (RefId)
//////////////////////////////////////////////////////////
_bstr_t ObjectName; LONG ObjectIdentity; hr = m_GlobalData.m_pRefObjects->GetObject( ObjectName, ObjectIdentity, RefId ); LONG IndexObject = 1; while ( SUCCEEDED(hr) ) { ///////////////////////////////////////////////////////////
// and for each, call CopyTree(ChildIdentity, NewIdentity)
///////////////////////////////////////////////////////////
hr = CopyTree(ObjectIdentity, NewIdentity); if ( FAILED(hr) ){return hr;}
hr = m_GlobalData.m_pRefObjects->GetNextObject( ObjectName, ObjectIdentity, RefId, IndexObject ); ++IndexObject; }
///////////////////////////////////////////////
// if no child: return S_Ok. hr safely ignored
///////////////////////////////////////////////
return S_OK; }
//////////////////////////////////////////////////////////////////////////////
// MigrateXXX functions
// Description:
// These functions follow the same model:
// - Get the ID of a container in iasold.mdb
// - Get the ID of the same container in ias.mdb
// - Get the ID of that container's parent in ias.mdb
// - Recursively deletes the container in ias.mdb
// - Then copy the content of that container from iasold.mdb into ias.mdb
// using the parent's container as the place to attach the result.
//
// Some functions also update some specific properties without doing
// a full copy
//
//////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////
// MigrateClients
//////////////////////////////////////////////////////////////////////////////
void CMigrateContent::MigrateClients() { const WCHAR ClientPath[] = L"Root\0" L"Microsoft Internet Authentication Service\0" L"Protocols\0" L"Microsoft Radius Protocol\0" L"Clients\0";
LONG ClientIdentity; m_GlobalData.m_pRefObjects->WalkPath(ClientPath, ClientIdentity);
const WCHAR RadiusProtocolPath[] = L"Root\0" L"Microsoft Internet Authentication Service\0" L"Protocols\0" L"Microsoft Radius Protocol\0";
LONG RadiusProtocolIdentity; m_GlobalData.m_pObjects->WalkPath( RadiusProtocolPath, RadiusProtocolIdentity );
// delete the clients container and its content
LONG DestClientIdentity; m_GlobalData.m_pObjects->WalkPath(ClientPath, DestClientIdentity);
_com_util::CheckError(m_GlobalData.m_pObjects->DeleteObject( DestClientIdentity));
// for each client in src, copy it in dest with its properties.
_com_util::CheckError(CopyTree(ClientIdentity, RadiusProtocolIdentity)); }
//////////////////////////////////////////////////////////////////////////////
// MigrateProfilesPolicies
//////////////////////////////////////////////////////////////////////////////
void CMigrateContent::MigrateProfilesPolicies() { const WCHAR ProfilesPath[] = L"Root\0" L"Microsoft Internet Authentication Service\0" L"RadiusProfiles\0";
LONG DestProfilesIdentity; m_GlobalData.m_pObjects->WalkPath(ProfilesPath, DestProfilesIdentity);
const WCHAR PoliciesPath[] = L"Root\0" L"Microsoft Internet Authentication Service\0" L"NetworkPolicy\0";
LONG DestPoliciesIdentity; m_GlobalData.m_pObjects->WalkPath(PoliciesPath, DestPoliciesIdentity);
// Delete the profiles and policies containers from ias.mdb
_com_util::CheckError(m_GlobalData.m_pObjects->DeleteObject( DestProfilesIdentity));
_com_util::CheckError(m_GlobalData.m_pObjects->DeleteObject( DestPoliciesIdentity));
// default profiles and policies deleted from now on
LONG ProfilesIdentity; m_GlobalData.m_pRefObjects->WalkPath(ProfilesPath, ProfilesIdentity);
LONG PoliciesIdentity; m_GlobalData.m_pRefObjects->WalkPath(PoliciesPath, PoliciesIdentity);
const WCHAR IASPath[] = L"Root\0" L"Microsoft Internet Authentication Service\0";
LONG IASIdentity; m_GlobalData.m_pObjects->WalkPath(IASPath, IASIdentity);
// for each profiles and policies in iasold.mdb,
// copy it in dest with its properties.
_com_util::CheckError(CopyTree(ProfilesIdentity, IASIdentity)); _com_util::CheckError(CopyTree(PoliciesIdentity, IASIdentity)); }
//////////////////////////////////////////////////////////////////////////////
// MigrateProxyProfilesPolicies
//////////////////////////////////////////////////////////////////////////////
void CMigrateContent::MigrateProxyProfilesPolicies() { const WCHAR ProfilesPath[] = L"Root\0" L"Microsoft Internet Authentication Service\0" L"Proxy Profiles\0";
LONG DestProfilesIdentity; m_GlobalData.m_pObjects->WalkPath(ProfilesPath, DestProfilesIdentity);
const WCHAR PoliciesPath[] = L"Root\0" L"Microsoft Internet Authentication Service\0" L"Proxy Policies\0";
LONG DestPoliciesIdentity; m_GlobalData.m_pObjects->WalkPath(PoliciesPath, DestPoliciesIdentity);
// Delete the profiles and policies containers from ias.mdb
_com_util::CheckError(m_GlobalData.m_pObjects->DeleteObject( DestProfilesIdentity));
_com_util::CheckError(m_GlobalData.m_pObjects->DeleteObject( DestPoliciesIdentity));
// default profiles and policies deleted from now on
LONG ProfilesIdentity; m_GlobalData.m_pRefObjects->WalkPath(ProfilesPath, ProfilesIdentity);
LONG PoliciesIdentity; m_GlobalData.m_pRefObjects->WalkPath(PoliciesPath, PoliciesIdentity);
const WCHAR IASPath[] = L"Root\0" L"Microsoft Internet Authentication Service\0";
LONG IASIdentity; m_GlobalData.m_pObjects->WalkPath(IASPath, IASIdentity);
// for each profiles and policies in iasold.mdb,
// copy it in dest with its properties.
_com_util::CheckError(CopyTree(ProfilesIdentity, IASIdentity)); _com_util::CheckError(CopyTree(PoliciesIdentity, IASIdentity)); }
//////////////////////////////////////////////////////////////////////////////
// MigrateAccounting
//////////////////////////////////////////////////////////////////////////////
void CMigrateContent::MigrateAccounting() { const WCHAR AccountingPath[] = L"Root\0" L"Microsoft Internet Authentication Service\0" L"RequestHandlers\0" L"Microsoft Accounting\0";
LONG AccountingIdentity; m_GlobalData.m_pRefObjects->WalkPath(AccountingPath, AccountingIdentity);
const WCHAR RequestHandlerPath[] = L"Root\0" L"Microsoft Internet Authentication Service\0" L"RequestHandlers\0";
LONG RequestHandlerIdentity; m_GlobalData.m_pObjects->WalkPath( RequestHandlerPath, RequestHandlerIdentity );
// delete the Accounting container and its content in ias.mdb
LONG DestAccountingIdentity; m_GlobalData.m_pObjects->WalkPath( AccountingPath, DestAccountingIdentity );
_com_util::CheckError(m_GlobalData.m_pObjects->DeleteObject( DestAccountingIdentity));
// for each accounting in src, copy it in dest with its properties.
_com_util::CheckError(CopyTree( AccountingIdentity, RequestHandlerIdentity )); }
//////////////////////////////////////////////////////////////////////////////
// MigrateEventLog
//////////////////////////////////////////////////////////////////////////////
void CMigrateContent::MigrateEventLog() { const WCHAR EventLogPath[] = L"Root\0" L"Microsoft Internet Authentication Service\0" L"Auditors\0" L"Microsoft NT Event Log Auditor\0";
LONG EventLogIdentity; m_GlobalData.m_pRefObjects->WalkPath(EventLogPath, EventLogIdentity);
const WCHAR AuditorsPath[] = L"Root\0" L"Microsoft Internet Authentication Service\0" L"Auditors\0";
LONG AuditorsIdentity; m_GlobalData.m_pObjects->WalkPath(AuditorsPath, AuditorsIdentity);
// delete the Auditors container and its content in ias.mdb
LONG DestEventLogIdentity; m_GlobalData.m_pObjects->WalkPath(EventLogPath, DestEventLogIdentity);
_com_util::CheckError(m_GlobalData.m_pObjects->DeleteObject( DestEventLogIdentity));
// for each EventLog in src, copy it in dest with its properties.
_com_util::CheckError(CopyTree(EventLogIdentity, AuditorsIdentity)); }
//////////////////////////////////////////////////////////////////////////////
// MigrateService
//////////////////////////////////////////////////////////////////////////////
void CMigrateContent::MigrateService() { const LONG PORT_SIZE_MAX = 34; const WCHAR ServicePath[] = L"Root\0" L"Microsoft Internet Authentication Service\0" L"Protocols\0" L"Microsoft Radius Protocol\0";
LONG RefServiceIdentity; m_GlobalData.m_pRefObjects->WalkPath(ServicePath, RefServiceIdentity);
LONG DestServiceIdentity; m_GlobalData.m_pObjects->WalkPath(ServicePath, DestServiceIdentity);
_bstr_t PropertyName = L"Authentication Port"; _bstr_t RadiusPort; LONG Type = 0; m_GlobalData.m_pRefProperties->GetPropertyByName( RefServiceIdentity, PropertyName, Type, RadiusPort ); if ( Type != VT_BSTR ) { _com_issue_error(E_UNEXPECTED); }
m_GlobalData.m_pProperties->UpdateProperty( DestServiceIdentity, PropertyName, VT_BSTR, RadiusPort );
_bstr_t AcctPort; PropertyName = L"Accounting Port"; Type = 0; m_GlobalData.m_pRefProperties->GetPropertyByName( RefServiceIdentity, PropertyName, Type, AcctPort );
if ( Type != VT_BSTR ) { _com_issue_error(E_UNEXPECTED); }
m_GlobalData.m_pProperties->UpdateProperty( DestServiceIdentity, PropertyName, VT_BSTR, AcctPort ); // Now update the service description (name)
const WCHAR IASPath[] = L"Root\0" L"Microsoft Internet Authentication Service\0";
LONG RefIASIdentity; m_GlobalData.m_pRefObjects->WalkPath(IASPath, RefIASIdentity);
LONG DestIASIdentity; m_GlobalData.m_pObjects->WalkPath(IASPath, DestIASIdentity);
PropertyName = L"Description"; _bstr_t Description; Type = 0; m_GlobalData.m_pRefProperties->GetPropertyByName( RefIASIdentity, PropertyName, Type, Description ); if ( Type != VT_BSTR ) { _com_issue_error(E_UNEXPECTED); }
m_GlobalData.m_pProperties->UpdateProperty( DestIASIdentity, PropertyName, VT_BSTR, Description ); }
//////////////////////////////////////////////////////////////////////////////
// MigrateWin2kRealms
//
// Not used: msUserIdentityAlgorithm
// msManipulationRule
// msManipulationTarget (enum: 1, 30 or 31)
//////////////////////////////////////////////////////////////////////////////
void CMigrateContent::MigrateWin2kRealms() { const WCHAR DEFAULT_REALM_TARGET[] = L"1"; const int MAX_LONG_SIZE = 32;
/////////////////////////////////////////////////
// Get the Microsoft Realms Evaluator's Identity
/////////////////////////////////////////////////
LPCWSTR RealmPath = L"Root\0" L"Microsoft Internet Authentication Service\0" L"RequestHandlers\0" L"Microsoft Realms Evaluator\0";
LONG RealmIdentity; m_GlobalData.m_pRefObjects->WalkPath(RealmPath, RealmIdentity);
///////////////////////////////////////////////
// Get the Proxy Profiles container's Identity
///////////////////////////////////////////////
LPCWSTR ProxyProfilePath = L"Root\0" L"Microsoft Internet Authentication Service\0" L"Proxy Profiles\0";
LONG ProxyContainerIdentity; m_GlobalData.m_pObjects->WalkPath( ProxyProfilePath, ProxyContainerIdentity );
//////////////////////////////////////////////////////////////////////
// Now get the first Object with the above container as parent.
// this is the default proxy profile (it's localized: I can't search
// for the name directly).
//////////////////////////////////////////////////////////////////////
_bstr_t ObjectName; LONG ProxyProfileIdentity; HRESULT hr = m_GlobalData.m_pObjects->GetObject( ObjectName, ProxyProfileIdentity, ProxyContainerIdentity );
_com_util::CheckError(hr); _bstr_t PropertyName; LONG Type; _bstr_t StrVal;
//////////////////////////
// get all the properties
//////////////////////////
_com_util::CheckError(m_GlobalData.m_pRefProperties->GetProperty( RealmIdentity, PropertyName, Type, StrVal )); LONG IndexProperty = 1; LONG NbPropertiesInserted = 0; _bstr_t NewName = L"msManipulationRule";
while ( hr == S_OK ) { /////////////////////////////////////////
// for each, if Name == L"Realms"
// then add to the default proxy profile
/////////////////////////////////////////
if (_wcsicmp(PropertyName, L"Realms") == 0) { m_GlobalData.m_pProperties->InsertProperty( ProxyProfileIdentity, NewName, Type, StrVal ); ++NbPropertiesInserted; }
hr = m_GlobalData.m_pRefProperties->GetNextProperty( RealmIdentity, PropertyName, Type, StrVal, IndexProperty ); ++IndexProperty; };
hr = S_OK;
////////////////////////////////////////////////////////////////
// Check that an even number of msManipulationRule was inserted
////////////////////////////////////////////////////////////////
if ( (NbPropertiesInserted % 2) ) { /////////////////////////
// Inconsistent database
/////////////////////////
_com_issue_error(E_FAIL); }
//////////////////////////////////////////
// No realm migrated: nothing else to set.
//////////////////////////////////////////
if ( !NbPropertiesInserted ) { return; }
/////////////////////////////////////
// Now process the reg keys settings
/////////////////////////////////////
BOOL OverRide = m_Utils.OverrideUserNameSet(); DWORD IdentityAtt = m_Utils.GetUserIdentityAttribute(); BOOL UserIdentSet = m_Utils.UserIdentityAttributeSet();
if ( (IdentityAtt != 1) && (!OverRide) ) { // log a warning / error for the user?
// the new behavior will not be exactly the same as before
}
//////////////////////////////////////////////////
// insert the UserIdentityAttribute if it was set.
//////////////////////////////////////////////////
_bstr_t TargetName = L"msManipulationTarget"; _bstr_t TargetStrVal; if ( UserIdentSet ) { WCHAR TempString[MAX_LONG_SIZE]; _ltow(IdentityAtt, TempString, 10); // base 10 will never change
// Add the msManipulationTarget Property based on the reg key
// "SYSTEM\\CurrentControlSet\\Services\\RemoteAccess\\Policy";
// "User Identity Attribute"; // Attribute used to identify the user.
// If not set then default to RADIUS_ATTRIBUTE_USER_NAME
// (1: "User-Name")
TargetStrVal = TempString; } else { // Not set in the registry: write the default
TargetStrVal = DEFAULT_REALM_TARGET; } m_GlobalData.m_pProperties->InsertProperty( ProxyProfileIdentity, TargetName, VT_I4, TargetStrVal ); }
//////////////////////////////////////////////////////////////////////////////
// MigrateServerGroups
//////////////////////////////////////////////////////////////////////////////
void CMigrateContent::MigrateServerGroups() { const WCHAR SvrGroupPath[] = L"Root\0" L"Microsoft Internet Authentication Service\0" L"RADIUS Server Groups\0";
LONG SvrGroupIdentity; m_GlobalData.m_pRefObjects->WalkPath(SvrGroupPath, SvrGroupIdentity);
const WCHAR IASPath[] = L"Root\0" L"Microsoft Internet Authentication Service\0";
LONG IASIdentity; m_GlobalData.m_pObjects->WalkPath(IASPath, IASIdentity);
// delete the SvrGroups container and its content
LONG DestSvrGroupIdentity; m_GlobalData.m_pObjects->WalkPath(SvrGroupPath, DestSvrGroupIdentity);
_com_util::CheckError(m_GlobalData.m_pObjects->DeleteObject( DestSvrGroupIdentity));
// for each SvrGroup in src, copy it in dest with its properties.
_com_util::CheckError(CopyTree(SvrGroupIdentity, IASIdentity)); }
//////////////////////////////////////////////////////////////////////////////
// Migrate
// migrate the content of a Win2k or Whistler DB before the proxy feature
// into a whistler DB.
//////////////////////////////////////////////////////////////////////////////
void CMigrateContent::Migrate() { MigrateClients(); MigrateProfilesPolicies(); MigrateAccounting(); MigrateEventLog(); MigrateService(); MigrateWin2kRealms();
//////////////////////////////////////////////////////
// Update the MSChap Authentication types (password)
//////////////////////////////////////////////////////
CUpdateMSCHAP UpdateMSCHAP(m_GlobalData); UpdateMSCHAP.Execute();
MigrateEapConfig(m_GlobalData).Execute(); }
//////////////////////////////////////////////////////////////////////////////
// UpdateWhistler
// migrate the content from a Whistler DB to a whistler DB.
// This is used by the netshell aaaa context
//////////////////////////////////////////////////////////////////////////////
void CMigrateContent::UpdateWhistler(DWORD flags) { // the configType parameter was introducet after .Net Server Beta3
// therefore, it cannot be set to anything meaningful for any script
// created before that.
switch(m_ConfigType) { case CLIENTS: { MigrateClients(); break; } case REMOTE_ACCESS_POLICIES: { MigrateProfilesPolicies(); ApplyProfileFlags(flags); break; } case LOGGING: { MigrateAccounting(); break; } case SERVER_SETTINGS: { MigrateEventLog(); MigrateService(); break; } case CONNECTION_REQUEST_POLICIES: { MigrateProxyProfilesPolicies(); MigrateServerGroups(); break; } case CONFIG: { MigrateClients(); MigrateProfilesPolicies(); MigrateAccounting(); MigrateEventLog(); MigrateService(); MigrateProxyProfilesPolicies(); MigrateServerGroups(); ApplyProfileFlags(flags); break; } default: { _ASSERT(FALSE); } } }
void CMigrateContent::ApplyProfileFlags(DWORD flags) { if ((flags & updateChangePassword) != 0) { CUpdateMSCHAP(m_GlobalData).Execute(); } if ((flags & migrateEapConfig) != 0) { MigrateEapConfig(m_GlobalData).Execute(); } }
|