2008-10-07 6 views
3

Je dois verrouiller les comptes d'utilisateur dans Active Directory par programmation en C#.Verrouiller les comptes Active Directory par programme

Malheureusement, cela ne fonctionne pas via l'attribut userAccountControl. Chaque fois que je mets userAccountControl à 528 (= compte normal w/lockout flag), Active Directory n'acceptera pas la valeur et la réinitialisera sans autre notification à 512 (= compte normal).

Maintenant, j'ai essayé de verrouiller le compte en fournissant des informations d'identification incorrectes (voir ci-dessous), mais cela ne fonctionne pas non plus.

int retries = 0; 
while (!adsUser.IsAccountLocked && retries < MAX_LOCK_RETRIES) 
{ 
    retries++; 

    try 
    { 
     new DirectoryEntry(userPath, logonName, incorrectPassword).RefreshCache(); 
    } 
    catch (Exception) 
    { 
     /* ... */ 
    } 
    adsUser.GetInfo(); 
} 

Des idées?

Répondre

4

Assurez-vous que le compte que vous utilisez pour désactiver le compte dispose de privilèges suffisants pour désactiver les comptes. Voir this example de Microsoft.

0

Ceci fonctionnera une fois que vous aurez l'objet d'entrée de répertoire.

DirectoryEntry de = result.GetDirectoryEntry(); 
int val = (int)de.Properties["userAccountControl"].Value; 
de.Properties["userAccountControl"].Value = val | 0x0002; 
+0

Cela désactive le compte, cela ne le verrouille pas. – KoenVosters

0

Ce code fonctionne pour verrouiller un utilisateur dans AD

/// <summary> 
/// Locks a user account 
/// </summary> 
/// <param name="userName">The name of the user whose account you want to unlock</param> 
/// <remarks> 
/// This actually trys to log the user in with a wrong password. 
/// This in turn will lock the user out 
/// </remarks> 
public void LockAccount(string userName) 
{ 
    DirectoryEntry user = GetUser(userName); 
    string path = user.Path; 
    string badPassword = "SomeBadPassword"; 
    int maxLoginAttempts = 10; 

    for (int i = 0; i &lt maxLoginAttempts; i++) 
    { 
     try 
     { 
      new DirectoryEntry(path, userName, badPassword).RefreshCache(); 
     } 
     catch (Exception e) 
     { 

     } 
    } 
    user.Close(); 
} 
1

En fonction de vos politiques Active Directory, les tentatives de connexion interactives peuvent être nécessaires pour verrouiller un compte. Vous pouvez simuler ceux qui utilisent le LogonUser method of advapi32.dll. Dans mes tests, j'ai vu que l'exécution de cette boucle 100 fois ne garantit pas 100 mauvaises tentatives de mot de passe au contrôleur de domaine, donc vous devriez check the user is locked out et faire plus de tentatives si nécessaire. En fin de compte, vous devriez désactiver le compte au lieu d'essayer de le verrouiller. Il y a no functional difference between locked and disabled accounts. Le code ci-dessous est un hack.

using System; 
using System.Runtime.InteropServices; 

namespace Test 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      IntPtr token = IntPtr.Zero; 
      string userPrincipalName = "[email protected]"; 
      string authority = null; // Can be null when using UPN (user principal name) 
      string badPassword = "bad"; 

      int maxTries = 100; 
      bool res = false; 

      for (var i = 0; i < maxTries; i++) 
      { 
       res = LogonUser(userPrincipalName, authority, badPassword, LogonSessionType.Interactive, LogonProvider.Default, out token); 
       CloseHandle(token); 
      } 
     } 

     [DllImport("advapi32.dll", SetLastError = true)] 
     static extern bool LogonUser(
      string principal, 
      string authority, 
      string password, 
      LogonSessionType logonType, 
      LogonProvider logonProvider, 
      out IntPtr token); 

     [DllImport("kernel32.dll", SetLastError = true)] 
     static extern bool CloseHandle(IntPtr handle); 
     enum LogonSessionType : uint 
     { 
      Interactive = 2, 
      Network, 
      Batch, 
      Service, 
      NetworkCleartext = 8, 
      NewCredentials 
     } 

     enum LogonProvider : uint 
     { 
      Default = 0, // default for platform (use this!) 
      WinNT35,  // sends smoke signals to authority 
      WinNT40,  // uses NTLM 
      WinNT50  // negotiates Kerb or NTLM 
     } 
    } 
} 
Questions connexes