Erkennen des Schemamasters
Active Directory Domain Services über ein Updatesystem mit mehreren master verfügen; jeder Domänencontroller enthält eine beschreibbare Kopie des Verzeichnisses. Schemaupdates werden an alle Domänen weitergegeben, die zur gleichen Struktur oder Gesamtstruktur gehören. Da es schwierig ist, in Konflikt stehende Updates mit dem Schema zu vereinbaren, können Schemaupdates nur auf einem einzelnen Server ausgeführt werden. Der Server mit dem Recht, Updates durchzuführen, kann sich ändern, aber nur ein Server hat dieses Recht zu einem bestimmten Zeitpunkt. Dieser Server wird als Schema master bezeichnet. Der erste in einem Unternehmen installierte DC ist standardmäßig das Schema master.
Schemaänderungen können nur auf der Ebene des Schemas master vorgenommen werden. Führen Sie die folgenden Schritte aus, um zu ermitteln, welcher DC das schema master ist.
Erkennen des DC-Schemamasters
- Lesen Sie das fsmoRoleOwner-Attribut des Schemacontainers auf einem beliebigen DC. Das attribut fsmoRoleOwner gibt den distinguished name (DN) des nTDSDSA-Objekts für das schema master zurück.
- Binden Sie an das nTDSDSA-Objekt , dessen DN Sie gerade abgerufen haben. Das übergeordnete Objekt dieses Objekts ist das Serverobjekt für den DC, das das Schema master enthält.
- Rufen Sie den ADsPath für das übergeordnete Objekt des nTDSDSA-Objekts ab. Das übergeordnete Objekt ist ein Serverobjekt.
- Binden sie an das Serverobjekt.
- Rufen Sie das dNSHostName-Attribut des Serverobjekts ab. Dies ist der DNS-Name des Domänencontrollers, der das Schema master enthält.
- Geben Sie den DNS-Namen des Schemas master als Server und den DN als DN des Schemacontainers an, der an das Schema master gebunden werden soll. Wenn der Server beispielsweise "dc1.fabrikam.com" und der Schemacontainer-DN "cn=schema,cn=configuration,dc=fabrikam,dc=com" lautet, lautet der ADsPath wie folgt.
LDAP://dc1.fabrikam.com/cn=schema,cn=configuration,dc=fabrikam,dc=com
Es wird empfohlen, das Schema master zu finden und an dieses zu binden, um Schemaänderungen vorzunehmen. Sie können das Schema jedoch master auf einen anderen Server verschieben.
Um einen anderen Server als Schema master zu machen, hat ein entsprechend privilegierter Benutzer folgende Möglichkeiten:
Verwenden Sie das MMC-Snap-In schema-Manager.
Hinweis
Das Active Directory-Schema-MMC-Snap-In muss manuell registriert werden. Um das Schema-Snap-In zu registrieren, müssen Sie den folgenden Befehl an der Eingabeaufforderung im Windows System32-Verzeichnis ausführen.
regsvr32.exe schmmgmt.dll
Verwenden Sie das Befehlszeilenprogramm NTDSUTIL.
Verwenden Sie eine Drittanbieteranwendung (eine Anwendung, die den entsprechenden LDAP-Schreibvorgang ausgibt).
Um programmgesteuert zum Schema master zu werden, kann eine Anwendung, die im Kontext eines entsprechend privilegierten Benutzers ausgeführt wird, einen LDAP-Schreibvorgang des betriebsbezogenen Attributs "becomeSchemaMaster" in den rootDSE auf diesem DC ausgeben. Dadurch wird eine atomare Übertragung des Schemas master direkt vom aktuellen Halter auf den lokalen DC initiiert.
Im folgenden Codebeispiel wird das Schema master. Die folgende Funktion bindet an den Schemacontainer auf dem Computer, der das Schema master ist.
HRESULT BindToSchemaMaster(IADsContainer **ppSchemaMaster)
{
HRESULT hr = E_FAIL;
// Get rootDSE and the schema container DN.
IADs *pObject = NULL;
IADs *pTempSchema = NULL;
IADs *pNTDS = NULL;
IADs *pServer = NULL;
BSTR bstrParent;
LPOLESTR szPath = new OLECHAR[MAX_PATH];
VARIANT var, varRole,varComputer;
hr = ADsOpenObject(L"LDAP://rootDSE",
NULL,
NULL,
ADS_SECURE_AUTHENTICATION, // Use Secure Authentication.
IID_IADs,
(void**)&pObject);
if (hr == S_OK)
{
hr = pObject->Get(CComBSTR("schemaNamingContext"), &var);
if (hr == S_OK)
{
wcscpy_s(szPath,L"LDAP://");
wcscat_s(szPath,var.bstrVal);
hr = ADsOpenObject(szPath,
NULL,
NULL,
ADS_SECURE_AUTHENTICATION, // Use Secure Authentication.
IID_IADs,
(void**)&pTempSchema);
if (hr == S_OK)
{
/*
Read the fsmoRoleOwner attribute to identify which server is
the schema master.
*/
hr = pTempSchema->Get(CComBSTR("fsmoRoleOwner"), &varRole);
if (hr == S_OK)
{
// The fsmoRoleOwner attribute returns the nTDSDSA object.
// The parent is the server object.
// Bind to NTDSDSA object and get parent.
wcscpy_s(szPath,L"LDAP://");
wcscat_s(szPath,varRole.bstrVal);
hr = ADsOpenObject(szPath,
NULL,
NULL,
ADS_SECURE_AUTHENTICATION,
IID_IADs,
(void**)&pNTDS);
if (hr == S_OK)
{
hr = pNTDS->get_Parent(&bstrParent);
if (hr == S_OK)
{
/*
Bind to server object and get the DNS name of
the server.
*/
wcscpy_s(szPath,bstrParent);
hr = ADsOpenObject(szPath,
NULL,
NULL,
ADS_SECURE_AUTHENTICATION,
IID_IADs,
(void**)&pServer);
if (hr == S_OK)
{
// Get the dns name of the server.
hr = pServer->Get(CComBSTR("dNSHostName"),
&varComputer);
if (hr == S_OK)
{
wcscpy_s(szPath,L"LDAP://");
wcscat_s(szPath,varComputer.bstrVal);
wcscat_s(szPath,L"/");
wcscat_s(szPath,var.bstrVal);
hr = ADsOpenObject(szPath,
NULL,
NULL,
ADS_SECURE_AUTHENTICATION,
IID_IADs,
(void**)ppSchemaMaster);
if (FAILED(hr))
{
if (*ppSchemaMaster)
{
(*ppSchemaMaster)->Release();
(*ppSchemaMaster) = NULL;
}
}
}
VariantClear(&varComputer);
}
if (pServer)
pServer->Release();
}
SysFreeString(bstrParent);
}
if (pNTDS)
pNTDS->Release();
}
VariantClear(&varRole);
}
if (pTempSchema)
pTempSchema->Release();
}
VariantClear(&var);
}
if (pObject)
pObject->Release();
return hr;
}
Im folgenden Codebeispiel wird der DNS-Name für den Computer angezeigt, der das Schema master.
On Error Resume Next
'''''''''''''''''''
' Bind to the rootDSE
''''''''''''''''''''
sPrefix = "LDAP://"
Set root= GetObject(sPrefix & "rootDSE")
If (Err.Number <> 0) Then
BailOnFailure Err.Number, "on GetObject method"
End If
'''''''''''''''''''
' Get the DN for the schema
''''''''''''''''''''
sSchema = root.Get("schemaNamingContext")
If (Err.Number <> 0) Then
BailOnFailure Err.Number, "on Get method"
End If
'''''''''''''''''''
' Bind to the schema container
''''''''''''''''''''
Set Schema= GetObject(sPrefix & sSchema )
If (Err.Number <> 0) Then
BailOnFailure Err.Number, "on GetObject method to bind to schema"
End If
''''''''''''''''''''
' Read the fsmoRoleOwner attribute to see which server is the
' schema master.
''''''''''''''''''''
sMaster = Schema.Get("fsmoRoleOwner")
If (Err.Number <> 0) Then
BailOnFailure Err.Number, "on IADs::Get method for fsmoRoleOwner"
End If
''''''''''''''''''''
' The fsmoRoleOwner attribute returns the nTDSDSA object.
' The parent is the server object.
' Bind to NTDSDSA object and get the parent object.
''''''''''''''''''''
Set NTDS = GetObject(sPrefix & sMaster)
If (Err.Number <> 0) Then
BailOnFailure Err.Number, "on GetObject method for NTDS"
End If
sServer = NTDS.Parent
If (Err.Number <> 0) Then
BailOnFailure Err.Number, "on IADs::get_Parent method"
End If
''''''''''''''''''''
' Bind to server object
' and get the reference to the computer object.
''''''''''''''''''''
Set Server = GetObject(sServer)
If (Err.Number <> 0) Then
BailOnFailure Err.Number, "on GetObject method for " & sServer
End If
sComputer = Server.Get("dNSHostName")
''''''''''''''''''''
' Display the DNS name for the computer.
''''''''''''''''''''
strText = "Schema master has the following DNS name: "& sComputer
WScript.echo strText
''''''''''''''''''''
' Display subroutines
''''''''''''''''''''
Sub BailOnFailure(ErrNum, ErrText)
strText = "Error 0x" & Hex(ErrNum) & " " & ErrText
MsgBox strText, vbInformation, "ADSI Error"
WScript.Quit
End Sub