c# - Find users who cannot change their password -
i trying prepare report of users cannot change password in ad. ad installed on window server 2012.
here method, thought work isn't working -
/// <summary> /// check whether password of user cannot changed. /// </summary> /// <param name="user">the directoryentry object of user.</param> /// <returns>return true if password cannot changed else false.</returns> public static bool ispasswordcannotbechanged(directoryentry user) { if (user.properties.contains("useraccountcontrol") && user.properties["useraccountcontrol"].value != null) { var userflags = (userflags)user.properties["useraccountcontrol"].value; return userflags.contains(userflags.passwordcannotchange); } return false; }
and here enum userflags -
[flags] public enum userflags { // reference - chapter 10 (from .net developer's guide directory services programming) script = 1, // 0x1 accountdisabled = 2, // 0x2 homedirectoryrequired = 8, // 0x8 accountlockedout = 16, // 0x10 passwordnotrequired = 32, // 0x20 passwordcannotchange = 64, // 0x40 encryptedtextpasswordallowed = 128, // 0x80 tempduplicateaccount = 256, // 0x100 normalaccount = 512, // 0x200 interdomaintrustaccount = 2048, // 0x800 workstationtrustaccount = 4096, // 0x1000 servertrustaccount = 8192, // 0x2000 passworddoesnotexpire = 65536, // 0x10000 (also 66048 ) mnslogonaccount = 131072, // 0x20000 smartcardrequired = 262144, // 0x40000 trustedfordelegation = 524288, // 0x80000 accountnotdelegated = 1048576, // 0x100000 usedeskeyonly = 2097152, // 0x200000 dontrequirepreauth = 4194304, // 0x400000 passwordexpired = 8388608, // 0x800000 (applicable in window 2000 , window server 2003) trustedtoauthenticatefordelegation = 16777216, // 0x1000000 noauthdatarequired = 33554432 // 0x2000000 }
can share why 64 (for password cannot change), not returned user password cannot changed?
or have better approach make work out?
edit-
userflagextension code making things bit fast -
public static class userflagextensions { /// <summary> /// check if flags contains specific user flag. /// </summary> /// <param name="haystack">the bunch of flags</param> /// <param name="needle">the flag for.</param> /// <returns>return true if flag found in flags.</returns> public static bool contains(this userflags haystack, userflags needle) { return (haystack & needle) == needle; } }
after searching lot , struggling hours, able formulate working solution.
.net 2.0 way
please proceed link ad .net - user's can't change password attribute (get/set)
you need add reference activeds making work. although hadn't time test it. lot of places supposed working. so...
code snippet above article- (in case article removed)
public bool getcantchangepassword(string userid) { bool cantchange = false; try { directoryentry entry = new directoryentry(string.format("ldap://{0},{1}", "ou=standard users,ou=domain", "dc=domain,dc=org")); entry.authenticationtype = authenticationtypes.secure | authenticationtypes.serverbind; directorysearcher search = new directorysearcher(entry); search.filter = string.format("(&(objectclass=user)(objectcategory=person)(samaccountname={0}))", userid); search.searchscope = searchscope.subtree; searchresult results = search.findone(); if (results != null) { try { directoryentry user = results.getdirectoryentry(); activedirectorysecurity usersecurity = user.objectsecurity; securitydescriptor sd = (securitydescriptor)user.properties["ntsecuritydescriptor"].value; accesscontrollist oacl = (accesscontrollist)sd.discretionaryacl; bool everyonecantchange = false; bool selfcantchange = false; foreach (activeds.accesscontrolentry ace in oacl) { try { if (ace.objecttype.toupper().equals("{ab721a53-1e2f-11d0-9819-00aa0040529b}".toupper())) { if (ace.trustee.equals("everyone") && (ace.acetype == (int)ads_acetype_enum.ads_acetype_access_denied_object)) { everyonecantchange = true; } if (ace.trustee.equals(@"nt authority\self") && (ace.acetype == (int)ads_acetype_enum.ads_acetype_access_denied_object)) { selfcantchange = true; } } } catch (nullreferenceexception ex) { //logger.append(ex.message); } catch (exception ex) { logger.append(ex); } } if (everyonecantchange || selfcantchange) { cantchange = true; } else { cantchange = false; } user.close(); } catch (exception ex) { // log errors! } } entry.close(); } catch (exception ex) { // log errors! } return cantchange; }
.net 4.0 way
this how able nail down. , easy fix. however, need use authenticableprincipal.usercannotchangepassword property.
code snippet used-
/// <summary> /// check whether password of user cannot changed. /// </summary> /// <param name="user">the directoryentry object of user.</param> /// <returns>return true if password cannot changed else false.</returns> public static bool ispasswordcannotbechanged(directoryentry user) { var isusercantchangepass = false; try { // 1. samaccountname var samaccountname = convert.tostring(user.properties["samaccountname"].value); if (!string.isnullorempty(samaccountname)) { // 2. prepare domain context using (var domaincontext = new principalcontext(contexttype.domain, _domain, _domainuser, _domainpass)) { // 3. find user var userprincipal = userprincipal.findbyidentity(domaincontext, identitytype.samaccountname, samaccountname); // 4. check if user cannot change password using (userprincipal) if (userprincipal != null) isusercantchangepass = userprincipal.usercannotchangepassword; } } } catch (exception exc) { logger.write(exc); } return isusercantchangepass; }