From cc5eb899c26949405c67e49de462903f01f1c243 Mon Sep 17 00:00:00 2001 From: CravateRouge Date: Sat, 1 Mar 2025 14:11:31 +0800 Subject: [PATCH] Option to send raw values --- msldap/client.py | 7 +++++-- msldap/connection.py | 7 +++++-- msldap/protocol/typeconversion.py | 19 +++++++++++++++++-- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/msldap/client.py b/msldap/client.py index dbc1c0e..fe75b25 100644 --- a/msldap/client.py +++ b/msldap/client.py @@ -1154,7 +1154,7 @@ async def get_object_by_dn(self, dn:str, expected_class = None): elif 'group' in temp: yield MSADGroup.from_ldap(entry), None - async def modify(self, dn:str, changes:Dict[str, object], controls:Dict[str, object] = None): + async def modify(self, dn:str, changes:Dict[str, object], controls:Dict[str, object] = None, encode=True): """ Performs the modify operation. @@ -1164,6 +1164,9 @@ async def modify(self, dn:str, changes:Dict[str, object], controls:Dict[str, obj :type changes: dict :param controls: additional controls to be passed in the query :type controls: dict + :param encode: encode the changes provided before sending them to the server + :type encode: bool + :return: A tuple of (True, None) on success or (False, Exception) on error. :rtype: (:class:`bool`, :class:`Exception`) """ @@ -1172,7 +1175,7 @@ async def modify(self, dn:str, changes:Dict[str, object], controls:Dict[str, obj controls_conv = [] for control in controls: controls_conv.append(Control(control)) - return await self._con.modify(dn, changes, controls=controls_conv) + return await self._con.modify(dn, changes, controls=controls_conv, encode=encode) async def add(self, dn:str, attributes:Dict[str, object]): diff --git a/msldap/connection.py b/msldap/connection.py index 4789467..2486e2d 100644 --- a/msldap/connection.py +++ b/msldap/connection.py @@ -591,7 +591,7 @@ async def add(self, entry:str, attributes:Dict[str, object]): except Exception as e: return False, e - async def modify(self, entry:str, changes:Dict[str, object], controls:List[Control] = None): + async def modify(self, entry:str, changes:Dict[str, object], controls:List[Control] = None, encode=True,): """ Performs the modify operation. @@ -601,13 +601,16 @@ async def modify(self, entry:str, changes:Dict[str, object], controls:List[Contr :type changes: dict :param controls: additional controls to be passed in the query :type controls: List[class:`Control`] + :param encode: encode the changes provided before sending them to the server + :type encode: bool + :return: A tuple of (True, None) on success or (False, Exception) on error. :rtype: (:class:`bool`, :class:`Exception`) """ try: req = { 'object' : entry.encode(), - 'changes' : encode_changes(changes) + 'changes' : encode_changes(changes, encode) } br = { 'modifyRequest' : ModifyRequest(req)} msg = { 'protocolOp' : protocolOp(br)} diff --git a/msldap/protocol/typeconversion.py b/msldap/protocol/typeconversion.py index 198b88d..2cd6df1 100644 --- a/msldap/protocol/typeconversion.py +++ b/msldap/protocol/typeconversion.py @@ -420,6 +420,8 @@ def encode_attributes(x): lookup_table = MSLDAP_BUILTIN_ATTRIBUTE_TYPES_ENC elif k in MSLDAP_BUILTIN_ATTRIBUTE_TYPES: lookup_table = MSLDAP_BUILTIN_ATTRIBUTE_TYPES + elif k in LDAP_WELL_KNOWN_ATTRS: + lookup_table = LDAP_WELL_KNOWN_ATTRS else: raise Exception('Unknown conversion type for key "%s"' % k) @@ -456,7 +458,7 @@ def convert_result(x): } -def encode_changes(x): +def encode_changes(x, encode=True): logger.debug('Encode changes: %s' % x) res = [] for k in x: @@ -465,15 +467,28 @@ def encode_changes(x): lookup_table = MSLDAP_BUILTIN_ATTRIBUTE_TYPES_ENC elif k in MSLDAP_BUILTIN_ATTRIBUTE_TYPES: lookup_table = MSLDAP_BUILTIN_ATTRIBUTE_TYPES + elif k in LDAP_WELL_KNOWN_ATTRS: + lookup_table = LDAP_WELL_KNOWN_ATTRS else: raise Exception('Unknown conversion type for key "%s"' % k) for mod, value in x[k]: + encoder = lookup_table[k] + splitted_name = encoder.__name__.split("_") + if isinstance(value, list) and "single" == splitted_name[0]: + if len(value) > 1: + raise TypeError(f"{k} takes only one value but multiple values have been given.") + value = value[0] + if not encode and splitted_name[1] != ["bytes"]: + if splitted_name[0] == "single": + encoder = single_bytes + else: + encoder = multi_bytes res.append(Change({ 'operation' : mod, 'modification' : PartialAttribute({ 'type' : k.encode(), - 'attributes' : lookup_table[k](value, True) + 'attributes' : encoder(value, True) }) })) #print(lookup_table[k](value, True))