Active Directory - check if password expires?

Is there a way in Visual Basic to check if a user password is set in Active Directory?

I found a way to find the last date when it was changed, but I cannot find other options available.

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

Where can I find a list of all available objUser properties?

+3
source share
4 answers
 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 } 
+1
source

If you are using .NET 3.5 and above, you should check the System.DirectoryServices.AccountManagement (S.DS.AM) namespace. Read more here:

Basically, you can define the context of a domain and easily find users and / or groups in 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.... ... } } 

The new S.DS.AM makes it very easy to play with users and groups in AD!

+5
source

For .NET 2.0, you can use LDAP . The magic part of userAccountControl:1.2.840.113556.1.4.803:=65536 . The first part is the property you want to look for, the second means bitwise AND, and the third is the bitwise flag to check, in this case, the 17th bit. You can see more by bitwise AND and OR in Active Directory in How to query Active Directory using a bitwise filter .

In the code below, update the SearchRoot variable with a domain controller (DC) and 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 
+2
source

You can use the following code from here , which I translated from C # and changed a little according to your question (getter added):

 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 

You must add a link to System.DirectoryServices . I tested it on Windows Server 2008 with the .NET Framework 4 (it should also work under 2.0) without Active Directory . But check it out yourself and feel free to extend it to get / set other properties or connect to other machines ( SomeDomain/OtherComputerName instead of Environment.MachineName ).

+1
source

All Articles