cannatag / ldap3

a strictly RFC 4510 conforming LDAP V3 pure Python client. The same codebase works with Python 2. Python 3, PyPy and PyPy3
Other
873 stars 267 forks source link

How to modify pwdAccountLockedTime using Abstraction Layer ? #914

Open roldir opened 3 years ago

roldir commented 3 years ago

Hi,

I can't figure out how to modify the pwdAccountLockedTime operational attribute. This is what I've tried so far:

server = Server(url, get_info=ALL)
conn = Connection(server, user_dn, user_password, auto_bind=True, raise_exceptions=True)
objdefs = ['inetOrgPerson']
base = "ou=users,dc=eduroam,dc=cnrs,dc=fr"
filter = '(uid=myuid)'
reader = Reader(conn, objdefs, base, filter)
reader.get_operational_attributes = True
reader.search()

entry = reader.entries[0]
wentry = entry.entry_writable()
wentry.cn = "New Name"    # works as expected

# pprint(wentry.OA_pwdAccountLockedTime) displays:
# OA_pwdAccountLockedTime [OPERATIONAL]: 2020-02-27 04:45:10+00:00
wentry.OA_pwdAccountLockedTime = "2021027000000Z"  # raises an exception

The exception's message is "ldap3.core.exceptions.LDAPCursorAttributeError: attribute 'OA_pwdAccountLockedTime' not defined".

I tried with wentry["OA_pwdAccountLockedTime"].set("20210201000000Z"). It fails with message "AttributeError: 'OperationalAttribute' object has no attribute 'set'"

What am I doing wrong ?

Thanks a lot in advance R.

zorn96 commented 3 years ago

hi @roldir ! not all attributes can be modified. the mechanisms around attribute modification are defined in 2 ways:

  1. the schema for the attribute
  2. ACLs enforced within the LDAP server which are not natively visible via the LDAP protocol unless the server has an attribute to expose them

a lot of attributes, operational and structural, cannot be modified freely by users. if the pwdAccountLockedTime attribute you're using is this one - https://ldapwiki.com/wiki/PwdAccountLockedTime - then it seems like the schema defines it as not modifiable by users

if this is an oracle virtual directory system (the other place I've seen this attribute) then you're not supposed to modify it directly, as it's an attribute maintained by the system. if you're trying to change it then you should set a different attribute in a modify operation https://docs.oracle.com/middleware/11119/ovd/ovd-admin/basic_entries_schema.htm#sthref549

either way it seems related to whatever schema is backing the attribute in the ldap server

nox-4O4 commented 2 years ago

Hi @zorn96,

thanks for your answer. Unfortunately, I'm hitting the same error.

it seems like the schema defines it as not modifiable by users

The attribute pwdAccountLockedTime is not marked as non-modifiable. I'm using OpenLDAP 2.4.44. You can look up the schema definition here: https://git.openldap.org/openldap/openldap/-/blob/OPENLDAP_REL_ENG_2_4_44/servers/slapd/overlays/ppolicy.c#L124-135

"( 1.3.6.1.4.1.42.2.27.8.1.17 "
        "NAME ( 'pwdAccountLockedTime' ) "
        "DESC 'The time an user account was locked' "
        "EQUALITY generalizedTimeMatch "
        "ORDERING generalizedTimeOrderingMatch "
        "SYNTAX 1.3.6.1.4.1.1466.115.121.1.24 "
        "SINGLE-VALUE "
#if 0
        /* Not until Relax control is released */
        "NO-USER-MODIFICATION "
#endif
        "USAGE directoryOperation )"

The NO-USER-MODIFICATION-part is explicitly disabled (#if 0). Using ApacheDirectoryStudio it's possible to modify this attribute without problems. It looks like ldap3 does not allow to modify any operational attributes, regardless of whether they are marked as user-modifiable in the schema.

Are there any workarounds possible or does this bug has to be resolved in ldap3 first?

nox-4O4 commented 2 years ago

I did some digging. It looks like ldap3 is unaware of operational attributes not applied to an entry at instantiation time. This makes creating an LDAP entry with operational attributes or adding new operational attributes to an existing entry difficult.

ldap3 could use the schema definitions from the server schema (with OpenLDAP e.g., cn=Subschema) to check for user-modifiable operational attributes. It already uses the server schema for validation anyway, e.g., prior to performing the add operation.

In the meantime, a possible workaround is to manually add the required attribute definition to the entry definition:

definition = writable_entry.entry_definition
definition += AttrDef('pwdAccountLockedTime')
writable_entry.pwdAccountLockedTime = '000001010000Z'