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.
 
 
 
 
 
 

742 lines
28 KiB

///////////////////////////////////////////////////////////////////////////////
//
// 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();
}
}