3 votes

Active Directory - vérifier si le mot de passe n'expire jamais ?

Existe-t-il un moyen en Visual Basic de vérifier si le mot de passe de l'utilisateur est configuré pour ne jamais expirer dans Active Directory ?

J'ai trouvé un moyen de trouver la dernière date de modification, mais je n'arrive pas à trouver les autres options disponibles.

Dim de As DirectoryServices.DirectoryEntry = GetUser(uDetails.username)
Dim objUser = GetObject(de.Path)
If objUser.PasswordLastChanged < DateTime.Now.AddMonths(-3) Then
...

Où puis-je trouver une liste de toutes les objUser des propriétés ?

6voto

marc_s Points 321990

Si vous utilisez .NET 3.5 et plus, vous devriez consulter le site Web de la Commission européenne. System.DirectoryServices.AccountManagement (S.DS.AM). Lisez tout à ce sujet ici :

En gros, vous pouvez définir un contexte de domaine et trouver facilement des utilisateurs et/ou des groupes dans AD :

// set up domain context
PrincipalContext ctx = new PrincipalContext(ContextType.Domain);

// find a user
UserPrincipal user = UserPrincipal.FindByIdentity(ctx, "SomeUserName");

if(user != null)
{
   // one of the properties exposed is "PasswordNeverExpires" (bool)
   if(user.PasswordNeverExpires)
   { 
      // do something here....      
      ...   
   }
}

Le nouveau S.DS.AM permet de jouer très facilement avec les utilisateurs et les groupes dans AD !

2voto

Chris Haas Points 23212

Pour .NET 2.0, vous pouvez utiliser des LDAP . La partie magique est userAccountControl:1.2.840.113556.1.4.803:=65536 . La première partie est la propriété que vous voulez rechercher, la deuxième signifie "ET par bit" et la troisième est le drapeau bit à vérifier, dans ce cas le 17ème bit. Pour en savoir plus sur le ET et le OU binaire dans Active Directory, consultez le document suivant Comment interroger Active Directory en utilisant un filtre de type bitwise .

Dans le code ci-dessous, mettez à jour le SearchRoot avec votre contrôleur de domaine (DC) et FQDN .

Imports System.DirectoryServices

Public Class Form1

    Private Sub Form1_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        ''//Bind to the root of our domain
        ''//    YOU_DOMAIN_CONTROLLER should be one of your DCs
        ''//    EXAMPLE and COM are the parts of your FQDN
        Dim SearchRoot As DirectoryEntry = New DirectoryEntry("LDAP://YOUR_DOMAIN_CONTROLLER/dc=EXAMPLE,dc=COM")

        ''//Create a searcher bound to the root
        Dim Searcher As DirectorySearcher = New DirectorySearcher(SearchRoot)

        ''//Set our filer. The last part is dumb but that is the way that LDAP was built.
        ''//It basically does a bitwise AND looking for the 17th bit to be set on that property "userAccountControl" which is the "password never expires" bit
        ''//See this if you care to learn more http://support.microsoft.com/kb/269181
        Searcher.Filter = "(&(objectCategory=person)(objectClass=user)(userAccountControl:1.2.840.113556.1.4.803:=65536))"
        ''//Find all of the results

        Dim Results = Searcher.FindAll()
        Dim DE As DirectoryEntry

        ''//Loop through each result
        For Each R As SearchResult In Results

            ''//Get the result as a DirectoryEntry object
            DE = R.GetDirectoryEntry()

            ''//Output the object name
            Console.WriteLine(DE.Name)
        Next
    End Sub

End Class

1voto

Tim Schmelter Points 163781

Vous pouvez utiliser le code suivant, tiré de ici que j'ai traduit du C# et modifié un peu en fonction de votre question (ajout d'un getter) :

Dim pwdNeverExpires = getPasswordNeverExpires("Tim")
setPasswordNeverExpires("Tim", True)

' See http://msdn.microsoft.com/en-us/library/aa772300(VS.85).aspx
<Flags()> _
Private Enum ADS_USER_FLAG_ENUM
    ADS_UF_SCRIPT = 1
    ' 0x1
    ADS_UF_ACCOUNTDISABLE = 2
    ' 0x2
    ADS_UF_HOMEDIR_REQUIRED = 8
    ' 0x8
    ADS_UF_LOCKOUT = 16
    ' 0x10
    ADS_UF_PASSWD_NOTREQD = 32
    ' 0x20
    ADS_UF_PASSWD_CANT_CHANGE = 64
    ' 0x40
    ADS_UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED = 128
    ' 0x80
    ADS_UF_TEMP_DUPLICATE_ACCOUNT = 256
    ' 0x100
    ADS_UF_NORMAL_ACCOUNT = 512
    ' 0x200
    ADS_UF_INTERDOMAIN_TRUST_ACCOUNT = 2048
    ' 0x800
    ADS_UF_WORKSTATION_TRUST_ACCOUNT = 4096
    ' 0x1000
    ADS_UF_SERVER_TRUST_ACCOUNT = 8192
    ' 0x2000
    ADS_UF_DONT_EXPIRE_PASSWD = 65536
    ' 0x10000
    ADS_UF_MNS_LOGON_ACCOUNT = 131072
    ' 0x20000
    ADS_UF_SMARTCARD_REQUIRED = 262144
    ' 0x40000
    ADS_UF_TRUSTED_FOR_DELEGATION = 524288
    ' 0x80000
    ADS_UF_NOT_DELEGATED = 1048576
    ' 0x100000
    ADS_UF_USE_DES_KEY_ONLY = 2097152
    ' 0x200000
    ADS_UF_DONT_REQUIRE_PREAUTH = 4194304
    ' 0x400000
    ADS_UF_PASSWORD_EXPIRED = 8388608
    ' 0x800000
    ADS_UF_TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = 16777216
    ' 0x1000000
End Enum

Protected Overridable Function getPasswordNeverExpires(ByVal userName As String) As Boolean
    Const userNameString As String = "userName"
    Const userFlagsString As String = "userFlags"

    Dim machineName As String = Environment.MachineName

    Dim userInThisComputerDirectoryEntry As DirectoryEntry = getUserInThisComputerDirectoryEntry(machineName, userName)
    If userInThisComputerDirectoryEntry Is Nothing Then
        Throw New ArgumentException("not found in " & machineName, userNameString)
    End If

    Dim userFlagsProperties As PropertyValueCollection = userInThisComputerDirectoryEntry.Properties(userFlagsString)
    Dim userFlags As ADS_USER_FLAG_ENUM = CType(userFlagsProperties.Value, ADS_USER_FLAG_ENUM)

    Return userFlags = (userFlags Or ADS_USER_FLAG_ENUM.ADS_UF_DONT_EXPIRE_PASSWD)
End Function

Protected Overridable Sub setPasswordNeverExpires(ByVal userName As String, ByVal passwordNeverExpires As Boolean)
    Const userNameString As String = "userName"
    Const userFlagsString As String = "userFlags"

    Dim machineName As String = Environment.MachineName

    Dim userInThisComputerDirectoryEntry As DirectoryEntry = getUserInThisComputerDirectoryEntry(machineName, userName)
    If userInThisComputerDirectoryEntry Is Nothing Then
        Throw New ArgumentException("not found in " & machineName, userNameString)
    End If

    Dim userFlagsProperties As PropertyValueCollection = userInThisComputerDirectoryEntry.Properties(userFlagsString)

    Dim userFlags As ADS_USER_FLAG_ENUM = CType(userFlagsProperties.Value, ADS_USER_FLAG_ENUM)
    Dim newUserFlags As ADS_USER_FLAG_ENUM = userFlags

    If passwordNeverExpires Then
        newUserFlags = newUserFlags Or ADS_USER_FLAG_ENUM.ADS_UF_DONT_EXPIRE_PASSWD
    Else
        newUserFlags = newUserFlags And (Not ADS_USER_FLAG_ENUM.ADS_UF_DONT_EXPIRE_PASSWD)
    End If

    userFlagsProperties.Value = newUserFlags

    userInThisComputerDirectoryEntry.CommitChanges()
End Sub

Protected Overridable Function getUserInThisComputerDirectoryEntry(ByVal machineName As String, ByVal userName As String) As DirectoryEntry
    Dim computerDirectoryEntry As DirectoryEntry = getComputerDirectoryEntry(machineName)

    Const userSchemaClassName As String = "user"
    Return computerDirectoryEntry.Children.Find(userName, userSchemaClassName)
End Function

Protected Overridable Function getComputerDirectoryEntry(ByVal machineName As String) As DirectoryEntry
    'Initiate DirectoryEntry Class To Connect Through WINNT Protocol
    ' see: http://msdn.microsoft.com/en-us/library/system.directoryservices.directoryentry.path.aspx
    Const pathUsingWinNTComputerMask As String = "WinNT://{0},computer"
    Dim path As String = String.Format(pathUsingWinNTComputerMask, machineName)
    Dim thisComputerDirectoryEntry As New DirectoryEntry(path)
    Return thisComputerDirectoryEntry
End Function

Vous devez ajouter une référence à System.DirectoryServices . Je l'ai testé sur Windows Server 2008 avec .NET Framework 4 (il devrait également fonctionner sous 2.0) sans Active Directory . Mais testez-le vous-même et n'hésitez pas à l'étendre pour obtenir/définir d'autres propriétés ou vous connecter à d'autres machines ( SomeDomain/OtherComputerName au lieu de Environment.MachineName ).

1voto

KSM Points 252
public bool isPasswordExpired(String p_UserName, String p_DomainName)
{
    bool m_Check=false;

    int m_Val1 = (int)de1.Properties["userAccountControl"].Value;
    int m_Val2 = (int) 0x10000;

    if (Convert.ToBoolean(m_Val1 & m_Val2))
    {
        m_Check = true;
    } //end

    return m_Check
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X