Inhaltsverzeichnis > Erweiterter Umgang mit AD Objekten > AD Berechtigungen : "Benutzer kann Kennwort nicht ändern"
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:
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:
- Benutzer kann Kennwort nicht ändern aktiviert => Berechtigung "Selbst : Kennwort ändern" wird verweigert.
BILD
- Benutzer kann Kennwort nicht ändern deaktiviert => Berechtigung "Selbst : Kennwort ändern" wird gewährt.
BILD
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):
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:
- 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.
- Baut daraus eine neue ACL.
- 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.
- 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!