Partager via


Détection du masque de schéma

services de domaine Active Directory disposez d’un système de mise à jour multi-master ; chaque contrôleur de domaine détient une copie accessible en écriture du répertoire. Les mises à jour de schéma sont propagées à tous les domaines qui appartiennent à la même arborescence ou forêt. Étant donné qu’il est difficile de rapprocher les mises à jour en conflit avec le schéma, les mises à jour de schéma ne peuvent être effectuées que sur un seul serveur. Le serveur ayant le droit d’effectuer des mises à jour peut changer, mais un seul serveur aura ce droit à un moment donné. Ce serveur est appelé master de schéma. Le premier contrôleur de domaine installé dans une entreprise est, par défaut, le schéma master.

Les modifications de schéma ne peuvent être apportées qu’au niveau du schéma master. Pour détecter quel contrôleur de domaine est le schéma master, procédez comme suit.

Détection du contrôleur de schéma contrôleur de domaine

  1. Lisez l’attribut fsmoRoleOwner du conteneur de schémas sur n’importe quel contrôleur de domaine. L’attribut fsmoRoleOwner retourne le nom unique (DN) de l’objet nTDSDSA pour le schéma master.
  2. Liez à l’objet nTDSDSA dont vous venez de récupérer le nom de domaine. Le parent de cet objet est l’objet serveur du contrôleur de domaine contenant le schéma master.
  3. Obtenez l’ADsPath pour le parent de l’objet nTDSDSA . Le parent est un objet serveur.
  4. Lier à l’objet serveur.
  5. Obtenez l’attribut dNSHostName de l’objet serveur. Il s’agit du nom DNS du contrôleur de domaine qui contient le schéma master.
  6. Spécifiez le nom DNS du schéma master comme serveur et le nom de domaine comme nom de domaine du conteneur de schémas à lier au schéma master. Par exemple, si le serveur était « dc1.fabrikam.com » et que le nom de domaine du conteneur de schéma était « cn=schema,cn=configuration,dc=fabrikam,dc=com », ADsPath se présente comme suit.
    LDAP://dc1.fabrikam.com/cn=schema,cn=configuration,dc=fabrikam,dc=com
    

Il est recommandé de rechercher le schéma master et de lier à celui-ci pour apporter des modifications au schéma. Toutefois, vous pouvez déplacer le schéma master vers un autre serveur.

Pour faire d’un autre serveur le schéma master, un utilisateur disposant de privilèges convenables peut :

  • Utilisez le composant logiciel enfichable MMC du Gestionnaire de schémas.

    Notes

    Le composant logiciel enfichable MMC de schéma Active Directory doit être inscrit manuellement. Pour inscrire le composant logiciel enfichable Schéma, vous devez exécuter la commande suivante à partir de l’invite de commandes dans le répertoire Windows System32.

    regsvr32.exe schmmgmt.dll

     

  • Utilisez l’utilitaire de ligne de commande NTDSUTIL.

  • Utilisez une application tierce (une application qui émet l’écriture LDAP appropriée).

Pour devenir le schéma master par programmation, une application s’exécutant dans le contexte d’un utilisateur disposant de privilèges appropriés peut émettre une écriture LDAP de l’attribut opérationnel becomeSchemaMaster dans rootDSE sur ce contrôleur de domaine. Cela lance un transfert atomique du schéma master directement du titulaire actuel vers le contrôleur de domaine local.

L’exemple de code suivant recherche le schéma master. La fonction suivante est liée au conteneur de schémas sur l’ordinateur qui est le schéma master.

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;
}

L’exemple de code suivant affiche le nom DNS de l’ordinateur qui est le schéma 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