i also came across this that might help:
http://www.scriptinganswer
Main Topics
Browse All TopicsWe're running active directory on a Win2000 server. I am trying with a .net application to produce a list of all users that have the property "user cannot change password" enabled.
From what I've read I thought I would be able to obtain this by examing the userAccountControl property for the PASSWD_CANT_CHANGE value of 64. My actual results however are showing a value of 66048 which I interpret to mean DONT_EXPIRE_PASSWORD (65536) + NORMAL_ACCOUNT (512). I am getting the value of 66048 for users whether or not they have their user cannot change password flag enabled.
I am far from being an expert working with AD so any explanations or suggestions would be appreciated.
This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.
Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.
If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.
Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.
Access the answers to your technology questions today.
30-day free trial. Register in 60 seconds.
Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Try it out and discover for yourself.
30-day free trial. Register in 60 seconds.
Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.
i also came across this that might help:
http://www.scriptinganswer
I appreciate your response but unfortunately that doesn't help me. I can get the values out fine they just aren't the results I'm expecting.
For a simple test case and cleared all of the optional properties for a user and query the userAccountControl value and get a result of 512 (Normal Account). Now I edit the user and check "User Cannot Change Passoword" and run my query again and I still get a result of 512 - as I understand it I should get a result of 576 (512 + 64). [ I also tried a custom search within AD using: (&(objectclass=person) (userAccountControl=576)) and it didn't return any values so I don't think the problem is with retrieving the values. ]
I suspect there is something basic I'm missing or something with the way our AD is setup that is obscuring this value.
Any other thoughts?
i don't know but i found a freeware tool that you might be able to use with better results
http://joeware.net/freetoo
i found it in this thread
http://www.experts-exchang
That's actually a pretty tricky one. While you can set it using the Flags you can't enumerate or remove it in the same way.
You have to enumerate the Security Descriptor for the account to see if it's been set or not. That can get quite complex, however if you're interested in continuing there's an MSDN page on this:
http://msdn2.microsoft.com
Chris
Hi Chris,
I think I'm tantalizingly close. I have gotten the following code working but I *think* it is pulling back the admin user object from AD and returning admin properties. I need to run a report for all users and I obviously don't know their passwords - do you have any idea where I'm off?
dso = GetObject("LDAP:")
oUser = dso.OpenDSObject("LDAP://b
oSecDesc = oUser.Get("ntSecurityDescr
oACL = oSecDesc.DiscretionaryAcl
For Each oACE In oACL
If UCase(oACE.ObjectType) = UCase(CHANGE_PASSWORD_GUID
If oACE.Trustee = "Everyone" And
oACE.AceType = ADS_ACETYPE_ACCESS_DENIED_
fEveryone = True
End If
If oACE.Trustee = "NT AUTHORITY\SELF" And
oACE.AceType = ADS_ACETYPE_ACCESS_DENIED_
fSelf = True
End If
End If
Next
Return (fSelf AND fEveryone)
Hey again,
You don't need to use the username and password of the account you're binding to, only a username and password of an account with permission to read the directory (any account in the domain).
So, generally I don't use OpenDSObject method at all when running administrative queries, instead I use the GetObject for an ADSI connection using current credentials:
Set objUser = GetObject("LDAP://CN=Users
Are you looking to return all user objects from the directory as well? Or how is the current user you're getting the information for being defined?
Chris
Appreciate your patience... My ultimate goal is to produce a list of users that don't have permisson to change their password (this will go into a database as part of a larger project but for now I just want to see the list).
I began with this code (asterisks replace sensitive info):
Dim objGroupEntry As DirectoryEntry
Dim objSearchADAM As DirectorySearcher
Dim objSearchResults As SearchResultCollection
Dim objResult As SearchResult
objSearchADAM = New DirectorySearcher(New DirectoryEntry("LDAP://bi.
objSearchADAM.PropertiesTo
objSearchADAM.PropertiesTo
objSearchADAM.Sort.Propert
objSearchADAM.SearchScope = SearchScope.Subtree
objSearchADAM.Filter = "(&(objectClass=person))"
objSearchResults = objSearchADAM.FindAll()
For Each objResult In objSearchResults
objGroupEntry = objResult.GetDirectoryEntr
Response.Write("<br>Person
Response.Write("Control: " & objGroupEntry.Properties("
'*** IS USER PERMITTED TO CHANGE THEIR PASSWORD? ***
Next objResult
Where I want to determine if user can change their password I created a function with the code I posted previously. This executed but returned FALSE for every user (should be roughly 50% true).
I tried changing to the code you suggested:
objUser = GetObject("LDAP://CN=JoeUs
And this throws an error "Cannot Create ActiveX Object". I left out the "OU" piece of it because afaik we don't do anything with it.
Does this make any sense to you?
Hey,
I have no experience at all coding in Visual Basic, all my work is with VbScript. I'll try not to let that stop me ;)
You shouldn't need this bit at all:
objUser = GetObject("LDAP://CN=JoeUs
As you should have a connection to the user object by virtue of this:
objGroupEntry = objResult.GetDirectoryEntr
If it were VbScript I'd pass through "objGroupEntry" as a parameter into the function, then access the Security Descriptor from there. e.g.:
Function UserCannotChangePassword(o
UserCannotChangePassword = False
Dim oSecDesc As IADsSecurityDescriptor
Dim oACL As IADsAccessControlList
Dim oACE As IADsAccessControlEntry
Dim fEveryone As Boolean
Dim fSelf As Boolean
fEveryone = False
fSelf = False
Set oSecDesc = oUser.Get("ntSecurityDescr
Set oACL = oSecDesc.DiscretionaryAcl
For Each oACE In oACL
If UCase(oACE.ObjectType) = UCase(CHANGE_PASSWORD_GUID
If oACE.Trustee = "Everyone" And oACE.AceType = ADS_ACETYPE_ACCESS_DENIED_
fEveryone = True
End If
If oACE.Trustee = "NT AUTHORITY\SELF" And oACE.AceType = ADS_ACETYPE_ACCESS_DENIED_
fSelf = True
End If
End If
Next
If fSelf And fEveryone Then
UserCannotChangePassword = True
Else
UserCannotChangePassword = False
End If
End Function
I'm not sure that'll work with VB, but it'd be fun to try :) I'm not entirely sure of the difference between an object of type IADS and a DirectoryEntry. Could you give it a try?
Chris
Chris - That did it. A few tweaks to make it .Net compatible and it is now working perfectly - thanks so much for the help! - frodoman
For any future readers the following .Net code produces the output desired:
==========================
Imports System.DirectoryServices
Imports ActiveDs
Protected Sub Page_Load(ByVal sender As Object, _
ByVal e As System.EventArgs) Handles Me.Load
Dim objGroupEntry As DirectoryEntry
Dim objSearchADAM As DirectorySearcher
Dim objSearchResults As SearchResultCollection
Dim objResult As SearchResult
Dim bLockedPWord As Boolean
objSearchADAM = New DirectorySearcher(New _
DirectoryEntry("LDAP://DOM
objSearchADAM.PropertiesTo
objSearchADAM.PropertiesTo
objSearchADAM.Sort.Propert
objSearchADAM.SearchScope = SearchScope.Subtree
objSearchADAM.Filter = "(&(objectClass=person))"
objSearchResults = objSearchADAM.FindAll()
For Each objResult In objSearchResults
objGroupEntry = objResult.GetDirectoryEntr
Response.Write("Account: " & objGroupEntry.Properties _
("samAccountName").Value & "...")
bUserCantChangePWord = IsPWordLocked(objGroupEntr
Response.Write("Password Flag: " & bLockedPWord & "<br>")
Next objResult
Response.Flush()
End Sub
Function IsPWordLocked(ByVal oUser As DirectoryEntry) As Boolean
Const ADS_ACETYPE_ACCESS_DENIED_
Const CHANGE_PASSWORD_GUID = _
"{AB721A53-1E2F-11D0-9819-
Dim oSecDesc As IADsSecurityDescriptor
Dim oACL As IADsAccessControlList
Dim oACE As IADsAccessControlEntry
Dim fEveryone As Boolean = False
Dim fSelf As Boolean = False
oSecDesc = oUser.InvokeGet("ntSecurit
oACL = oSecDesc.DiscretionaryAcl
For Each oACE In oACL
If UCase(oACE.ObjectType) = UCase(CHANGE_PASSWORD_GUID
If oACE.Trustee = "Everyone" And oACE.AceType = _
ADS_ACETYPE_ACCESS_DENIED_
fEveryone = True
End If
If oACE.Trustee = "NT AUTHORITY\SELF" And oACE.AceType = _
ADS_ACETYPE_ACCESS_DENIED_
fSelf = True
End If
End If
Next
Return (fSelf And fEveryone)
End Function
Business Accounts
Answer for Membership
by: opie6373Posted on 2007-08-29 at 06:19:37ID: 19790871
i found this script that you might try... it involves a command line tool dsquery
ips/Tip.as px?id=7687
http://www.jsifaq.com/SF/T