Printout Header
RSS Feed

AD Berechtigungen :
Einstellung "Benutzer kann Kennwort nicht ändern" (de)aktivieren


Beim Scripten in Active Directory Umgebungen benötigt man manchmal eine Änderung der Berechtigung von AD-Objekten, auch wenn es auf den ersten Blick nicht so aussieht. Ein Beispiel dafür ist das Setzen der Option "Benutzer kann Kennwort nicht ändern" in den Konto-Eigenschaften eines Active Directory Benutzerkontos:

AD Users and Computers: Benutzer kann Kennwort nicht ändern
Es handelt sich hier nämlich nicht um eine Eigenschaft, die auf TRUE oder FALSE gesetzt wird, sondern das hier gezeigte Häkchen wird ganz klassisch über AD-Berechtigungen verwaltet:


Option "Benutzer kann Kennwort nicht ändern" selbst setzen im Script

Auf der Kommandozeile könnte man hier mit dem System-Utility DSACLS.EXE einfach folgende Befehle am DC ausf?hren, je nachdem ob man die Option aktivieren will oder nicht

dsacls "LDAP-Pfad des User Accounts" /D "EVERYONE":CA;"Change Password"        <- verweigert das Recht zum Passwort-Setzen

dsacls "LDAP-Pfad des User Accounts" /G "SELF":CA;"Change Password"            <- gewährt das Recht zum Passwort-Setzen
dsacls "LDAP-Pfad des User Accounts" /G "EVERYONE":CA;"Change Password"

Übrigens müßte an auf einem deutschsprachigen System statt "SELF" und "EVERYONE" ein "SELBST" bzw. "JEDER" verwenden! Der LDAP-Pfad eines Benutzers sieht z.B. so aus: cn=Philipp,ou=Dev,dc=ldapexplorer,dc=com.


Vorsicht: Mit diesem Befehl kann man einmalig die Option "Benutzer kann Kennwort nicht ändern" setzen, jedoch wird durch einen DSACLS-Eintrag nicht das bestehende Standard-Grant-Recht gelöscht. Es existieren dann zwei gegenläufige Einträge in der ACL des Benutzers (von denen das "Deny" gewinnt):

DSACLS: Benutzer kann Kennwort nicht ändern


Man kann mit DSACLS eben nicht einzelne ACL-Einträge ersetzen, sondern nur die gesamte Rechte-Liste, was für unseren Fall jedoch nicht erwünscht ist. Um also tatsächlich die Option an- und abschalten zu können, brauchen wir ein eigenes Script, das wie folgt vorgeht:

  1. Liest die Rechteliste des betreffenden Userobjektes aus. Nimmt alle Einträge AUSSER denen, in denen "SELF" und "EVERYONE" das Recht zum Passwort setzen gewährt oder verweigert wird.
  2. Baut daraus eine neue ACL.
  3. Fügt dieser ACL je nach Wunsch den Eintrag hinzu, mit dem "SELF" bzw. "EVERYONE" das Recht zum Passwort setzen gewährt bzw. verweigert bekommt.
  4. Schreibt die neue ACL zurück ins Verzeichnis.

Wie eine ACL aufgebaut ist und wie man sie manipuliert, wird ausführlich in einem SelfADSI Turorial-Artikel über AD Security Descriptoren besprochen.

Hier also nur das reine Script, das für einen bestimmten Benutzer die Option "Benutzer kann Kennwort nicht ändern" setzt.

'Sie müssen hier ein Objekt und einen Trustee aus Ihrer eigene Umgebung angeben! Set user = GetObject("LDAP://CN=user01,OU=accounts,DC=ldapexplorer,DC=com") '__________________________________________________________________ notwendigen Konstanten Const ADS_REVISION_DS = 4 Const ADS_ACETYPE_ACCESS_DENIED_OBJECT = 6 Const ADS_RIGHT_DS_CONTROL_ACCESS = &H100 Const ADS_FLAG_OBJECT_TYPE_PRESENT = 1 Const GUID_RIGHT_CHANGEPASSWORD = "{AB721A53-1E2F-11D0-9819-00AA0040529B}" Const WKSID_SELF_SDDL = "S-1-5-10" Const WKSID_SELF = "NT AUTHORITY\SELF" Const WKSID_EVERYONE_SDDL = "S-1-1-0" Const WKSID_EVERYONE = "EVERYONE" '__________________________________________________________________ ACL lesen Set userACL = user.get("nTSecurityDescriptor") Set userDACL = userACL.DiscretionaryAcl WScript.Echo user.distinguishedname & vbCrLf '__________________________________________________________________ neue ACL bauen Set newDACL = CreateObject("AccessControlList") newDACL.AclRevision = ADS_REVISION_DS newDACL.AceCount = 0 Set userAce = CreateObject("AccessControlEntry") For Each userAce In userDACL 'alle bisherigen ACEs beibehalten, falls sie ' 1) nicht "User cannot set Passwort" - Rechte setzen/verweigern ' 2) nicht vererbt sind If Not ((UCase(CStr(userAce.ObjectType)) = GUID_RIGHT_CHANGEPASSWORD) And _ ((UCase(CStr(userAce.Trustee)) = WKSID_SELF) Or _ (UCase(CStr(userAce.Trustee)) = WKSID_EVERYONE))) Then If ((userAce.AceFlags And ADS_ACEFLAG_INHERITED_ACE) = 0) Then newDAcl.AddAce userAce End If End If Next '_______________________________ neuen ACE-Eintrag erzeugen : Deny Set Passwort für EveryOne Set newAce = CreateObject("AccessControlEntry") newAce.Trustee = WKSID_EVERYONE_SDDL newAce.AceType = ADS_ACETYPE_ACCESS_DENIED_OBJECT newAce.AceFlags = 0 newAce.AccessMask = ADS_RIGHT_DS_CONTROL_ACCESS newACE.Flags = ADS_FLAG_OBJECT_TYPE_PRESENT newACE.ObjectType = GUID_RIGHT_CHANGEPASSWORD newDACL.AddAce newAce '_______________________________ neue ACL ins Ve?rzeichnis zurückschreiben userACL.DiscretionaryAcl = newDACL user.Put "ntSecurityDescriptor", userACL user.SetInfo

Vorsicht: In Umgebungen mit nicht-englischen Sprachversionen müssen die Variablen WKSID_SELF und WKSID_EVERYONE entsprechend angepasst werden - auf deutsch installierten DCs muss es dann entsprechend "NT-AUTORITÄT\SELBST" und "JEDER" heißen!

Und hier die Version des Scripts, die umgekehrt zu vorher die Option "Benutzer kann Kennwort nicht ändern" wieder löscht:

'Sie müssen hier ein Objekt und einen Trustee aus Ihrer eigene Umgebung angeben! Set user = GetObject("LDAP://CN=user01,OU=accounts,DC=ldapexplorer,DC=com") '__________________________________________________________________ notwendigen Konstanten Const ADS_REVISION_DS = 4 Const ADS_ACETYPE_ACCESS_ALLOWED_OBJECT = 5 Const ADS_RIGHT_DS_CONTROL_ACCESS = &H100 Const ADS_FLAG_OBJECT_TYPE_PRESENT = 1 Const GUID_RIGHT_CHANGEPASSWORD = "{AB721A53-1E2F-11D0-9819-00AA0040529B}" Const WKSID_SELF_SDDL = "S-1-5-10" Const WKSID_SELF = "NT AUTHORITY\SELF" Const WKSID_EVERYONE_SDDL = "S-1-1-0" Const WKSID_EVERYONE = "EVERYONE" '__________________________________________________________________ ACL lesen Set userACL = user.get("nTSecurityDescriptor") Set userDACL = userACL.DiscretionaryAcl WScript.Echo user.distinguishedname & vbCrLf '__________________________________________________________________ neue ACL bauen Set newDACL = CreateObject("AccessControlList") newDACL.AclRevision = ADS_REVISION_DS newDACL.AceCount = 0 Set userAce = CreateObject("AccessControlEntry") For Each userAce In userDACL 'alle bisherigen ACEs beibehalten, falls sie ' 1) nicht "User cannot set Passwort" - Rechte setzen/verweigern ' 2) nicht vererbt sind If Not ((UCase(CStr(userAce.ObjectType)) = GUID_RIGHT_CHANGEPASSWORD) And _ ((UCase(CStr(userAce.Trustee)) = WKSID_SELF) Or _ (UCase(CStr(userAce.Trustee)) = WKSID_EVERYONE))) Then If ((userAce.AceFlags And ADS_ACEFLAG_INHERITED_ACE) = 0) Then newDAcl.AddAce userAce End If End If Next '_______________________________ neuen ACE-Eintrag erzeugen : Grant Set Passwort für EveryOne Set newAce = CreateObject("AccessControlEntry") newAce.Trustee = WKSID_EVERYONE_SDDL newAce.AceType = ADS_ACETYPE_ACCESS_ALLOWED_OBJECT newAce.AceFlags = 0 newAce.AccessMask = ADS_RIGHT_DS_CONTROL_ACCESS newACE.Flags = ADS_FLAG_OBJECT_TYPE_PRESENT newACE.ObjectType = GUID_RIGHT_CHANGEPASSWORD newDACL.AddAce newAce '_______________________________ neuen ACE-Eintrag erzeugen : Grant Set Passwort für Self Set newAce = CreateObject("AccessControlEntry") newAce.Trustee = WKSID_SELF_SDDL newAce.AceType = ADS_ACETYPE_ACCESS_ALLOWED_OBJECT newAce.AceFlags = 0 newAce.AccessMask = ADS_RIGHT_DS_CONTROL_ACCESS newACE.Flags = ADS_FLAG_OBJECT_TYPE_PRESENT newACE.ObjectType = GUID_RIGHT_CHANGEPASSWORD newDACL.AddAce newAce '_______________________________ neue ACL ins Verzeichnis zurückschreiben userACL.DiscretionaryAcl = newDACL user.Put "ntSecurityDescriptor", userACL user.SetInfo

Vorsicht: In Umgebungen mit nicht-englischen Sprachversionen müssen die Variablen WKSID_SELF und WKSID_EVERYONE entsprechend angepasst werden - auf deutsch installierten DCs muss es dann entsprechend "NT-AUTORITÄT\SELBST" und "JEDER" heißen!