#50443 Create a module in lib389 to Convert a byte sequence to a properly escaped for LDAP
Opened 5 months ago by aborah. Modified 2 days ago

Issue Description:

Create a module in lib389 to Convert a byte sequence to a properly escaped for LDAP


Metadata Update from @firstyear:
- Custom field origin adjusted to None
- Custom field reviewstatus adjusted to None

5 months ago

There are mainly two times you need this - dn escaping, and filter escaping. python-ldap provides both, and lib389 automatically handles this in _mapped_object in most cases.

The only other thing is url escaping, which should be around here but I don't see it (mainly for ldapi). https://www.python-ldap.org/en/python-ldap-3.2.0/reference/ldapurl.html?highlight=url

I think I want to know what your problem case is and what you are trying to achieve, because I think these apis already exist and work correctly ....

I have this binary value :

crt = b'0\x82\x05X0\x82\x03@\xa0\x03\x02\x01\x02\x02\x05\x00\xb1fg\xcd0\r\x06\t\x86H\x86\xf7\r\x01\x01\x0b\x05\x000e1\x0b0\t\x06\x03U\x04\x06\x13\x02AU1\x130\x11\x06\x03U\x04\x08\x13\nQueensland1\x0e0\x0c\x06\x03U\x04\x07\x13\x05389ds1\x100\x0e\x06\x03U\x04\n\x13\x07testing1\x1f0\x1d\x06\x03U\x04\x03\x13\x16ssca.389ds.example.com0\x1e\x17\r190613115811Z\x17\r210613115811Z0e1\x0b0\t\x06\x03U\x04\x06\x13\x02AU1\x130\x11\x06\x03U\x04\x08\x13\nQueensland1\x0e0\x0c\x06\x03U\x04\x07\x13\x05389ds1\x100\x0e\x06\x03U\x04\n\x13\x07testing1\x1f0\x1d\x06\x03U\x04\x03\x13\x16ssca.389ds.example.com0\x82\x02"0\r\x06\t\x86H\x86\xf7\r\x01\x01\x01\x05\x00\x03\x82\x02\x0f\x000\x82\x02\n\x02\x82\x02\x01\x00\xd6\xc6\x9e\xe7\x1cn\xd0\xe8l\xba\xb7\t/\x1b\xd9\xd6\xf7Du\x88\xd26\xcd.#\xa4@\xbde\xfcV\xb3XE\x10\x079\xdb\xd4\x18\xc3\x7f\xa4\x02K\x96#\x1c\xe1Jh\xaa\xdeh\xef\xfeO\xff3\xd1tl\xe0\xf9\x07\x8e7<\xa6]\x8bo\xe7\xc7iF\xd4\x951\xee\xe8\x97\x87\xc3\xb6\x9a\x9fo\xc81w\x9b\xe9lK\x8e\xd6u.\x98\xa9\xed\xd7T\xf6\x91\x05p\x14r\xb0\x93\x16(\xf0\x16:\xff,\xb8\xc5\x8e:\xe8\x13\xa8\x97\x17k\x93q\xf9]K\x1a\xfc2\x02\xcf!\xa8\x86-\xd0\xe3E\xbcIX\xb2\x86\x92Rz+\xd0\x1d\xeb{\xac\xc1t(k\xb3T\xf7t\xfd\xf4\x0bvY\x16c\xcc\xd3 -\xe58\xd8Xs\x99\xe4\x94gT\xae\xfa\t\x8axd\x98B\xf4v\xea\xe6\xfbfhG%\xc8R\xe2\x9a|(\xa2f\x1a\xaeT\xa1\x8d\xceN\xb9N\xbeE!]\xd0\x7f\xfc\xfcs5{\xe6z#\xea\xadrO\xfb\x0c[\xfc\xbf{\x0ck-\x9cN\xe6N\x8fAW\xb8\x08.H:\xb2C\x944\xd0\xfc{&i\xc4\x06\xb1\xd0\xf4\xbfy\xd6\xe2\xee\x9e\xb2\xc6\x0f-O0\xab\x0cF\xfc(\x9f\xa5;\x17xt|\xac\x8a b\xbf\xa7\xa3d\xf9VA\x05\xa2\x1d\xcd\xc7w\xcbI[muB\xa8br\xae\xdf\xe4\x1e\xc9\xe64\xd3\x1d^\x88\xb2\xc0\("\xa8z\x90\x1cEm\xfc[\'\x01\x08\'\x06,\x18\xc46\xcbF\x0b\xcc\x0b\x83\x17|l2,\x0c\x08\xda\x1e%a\x00\x19\x90\xd7_i\x03\xa5\xe4\xcc\xda\x8b\xces\xa0<;\x13\xc8\x04z\x8eK\xbb\xdb\x9a\xdf\x8e\xa3\x98u\xba\x18\x84\xf0\xfbO\x94\xa8\xefN]3-f\xcd\x11g<\xb6\xd5\x0c\xa6\x18\xb3+\xf99j\xff\xbe\xe2y\xf4\xac\x94=\x15\xb0\xea\x7fH\x03T\xe7\xb6\xa63\xde\x16H\x99\xa0\x1bL^\xfd\xaa]74\xe3\xa5[\xd6\x0f$.\xe3\x9d\xcb\xc69w\xe0\xa3\x8e\xcfE\xc2g\x0ff\x07\x11S\xf1\xfd5]Z\xf1\xd7\xeb\x1d\xd7#\xd3X^\x9dR{\xdb\x02\x03\x01\x00\x01\xa3\x0f0\r0\x0b\x06\x03U\x1d\x0f\x04\x04\x03\x02\x02\x040\r\x06\t*\x86H\x86\xf7\r\x01\x01\x0b\x05\x00\x03\x82\x02\x01\x00\xd2\x86\xc5\x020\xb4\x9a(\xec\xe9\xd0\xbc\xc0)u\xf8?\x9d\x95a\x1e\xe7=\xa6\x8e\xb7\x86Q\x8f\x8bM\xc4\x05\xe5\x07|\x04z;\x93^\xc1\xdf;\xa6\xfe0\xe4\x9e\x9ezE\x10k\x15v\xbf\xaa@4s\xa0\xaf\x16\xf9\xb0\xdbK\x14\xf5\xa9\x0e\xb6}\xfa\x86xv\x1f\xa1\x15\x8a\x83\x87\xbb\xeb\x89\xe9\xa8\x88t/Il\xcc\xee\xb4\x82!P\xa2\x95\t@\x1bE+\xfbbs9\xb3<Mkw<1\xca\x13\x1fZ\xd8|\x9eB\xf4\x03S!\t\x9f\xa7\xb3\xb85ID\xfbf\xd4#<\x86\xd3\xed<\x02LD\xcd\xc0\xa0\x16\x14\xcb\x17\x98r\x1e\\\x80\x99\xab\nC\x92m\x04\xfd\xa5a\xc5\x1f\x9e^C\xcci\xad\xc34\xfa{@\xb7\xc1_\x11\x0b\xe5\x0bT \xc25\xff\x15\x06\xd9\xdd\x06\x7f\x1f)\x84\x98\x91\xc73S[ATZ\xc3\x87^qR\xa9\xcf\x9a\xaf!d@{au\xa0\xac\xfc\x8e\xad&\xbf\x84\x10\xc7Z\xf1\x1e~?\xae\xf6\xd3i\x04e\xc7\x1e\x06\xf2~\x9c\xa8\r\xc6\xf1\xb1\xa4^\xec\x06\xa1\xa7PS\x1e\xe2O\xb4e\x98\x1au=4\x90\x81\xa3\xd3\xef\x19gY\xf5\x08\xe9\xc5\xba\xfc=\xac\xe1\xce\x95\x05\xdd\x8f\xe2\x7fH$\x8e\t\x94\x8bcz,\xe5\xbe3\xb0\xee\xfc\1\x11\xd7}u\xbe\xfd\xad\x83\xfdn\xa5}\xab#\xc8\xd8\x85\xebkhX\x9f\x81\xd2/2@\xcb\x10:K\xd5b\xc8\xf3\xce\xb43\x84\x07\xe8\xd7\xe3\xaf\x85etP%\xcb\xd9Y%\xbd\x84\xc7A\x0e\xae\x9e\x16\xeb\xde)]\xb3\xc2\xd6\xf1\x05w\x8b\xb9\xa6:9a\x1b?O\xb7\xbd/-ISS(\xbc/\x15\x0e\xd2\xfb\xd1\xc7!\xc2\x94\x03f\x81 \x11\xf2\x81E\xeb\xde\xb7/\x00\x1d\xa54\xe8\xab\xf2\xf7\x9b\x80<\x05\xdc\x0cEL\x8f\x1f\x16\x96t\xc3\xeb\xc9"\xc5\xf9\xf5\x9d\xf7(P(e\xef\xe9\xc8\xd8\x92u\x9c\xa8lBoQS\xc8\xac\xbd5Z\xf6$c-\xef\xb1_W\xdd#\xe5B\xbd8 \x1c\xf5\x93\xeek\xea\xae]7\xed\xc8'

Now i want to put it on filter

Accounts(standalone, DEFAULT_SUFFIX).filter(f"(userCertificate={crt})")

Pretty sure that should "just work". You don't need to escape anything, as ldap is capable of searching this field and filtering on it. It could be good to check your lib389 log or access log to see if you are leaking in python byto flags or similar. IE you may need ensure_str first on your f string.

Saying this, This looks like userCert stuff which you were asking about on the mailing list - I asked you about the test cas you wanted to write and the steps you needed and you didn't respond ... so maybe we should respond to that mail first to discuss the approach you are taking here to be sure it is the right way. Sometimes looking at these problems is distracting from different issues which is the approach to the greater problem.

So please answer the mail on the list about the test case and the steps you need to perform, then let's talk about what we need to do. Thanks,

Metadata Update from @firstyear:
- Issue close_status updated to: invalid
- Issue status updated to: Closed (was: Open)

5 months ago

Metadata Update from @vashirov:
- Issue status updated to: Open (was: Closed)

5 months ago

@firstyear, escape_filter_chars() doesn't take care of non-ascii symbols:
https://github.com/python-ldap/python-ldap/blob/adf47613f2df5a9b080d00f9b2632da556a61ea8/Lib/ldap/filter.py#L17

ldap3 module does handle this:
https://github.com/cannatag/ldap3/blob/08810e435392a1f1a96d5e65bb444b9cb9e96ae3/ldap3/utils/conv.py#L91
by using escape_bytes().

The use case: I need to read der certificate file and escape it so it's suitable for an LDAP filter:

>>> from ldap.filter import escape_filter_chars
>>> from ldap3.utils.conv import escape_bytes
>>> cert_der = open('user-testuser1.der', 'rb').read()[:10]
>>> escape_bytes(cert_der)
'\\30\\82\\05\\73\\30\\82\\03\\5b\\a0\\03'
>>> escape_filter_chars(cert_der)
Traceback (most recent call last):
  File "<input>", line 1, in <module>
    escape_filter_chars(cert_der)
  File "/usr/lib64/python3.7/site-packages/ldap/filter.py", line 41, in escape_filter_chars
    s = assertion_value.replace('\\', r'\5c')
TypeError: a bytes-like object is required, not 'str'

Would it be safe to add the escape_bytes into the filter generation / escaping areas in _mapped_object.py by default? Or is it only safe to add this for byte-only expressions?

Metadata Update from @mreynolds:
- Issue set to the milestone: 1.4.2

3 months ago

@firstyear, I think it should be safe to add it to mapped_object.py, me and @aborah will test it.

Or is it only safe to add this for byte-only expressions?

You mean add it to ensure_bytes?

So we did a quick tests and adding it to mapped_object.py is not solving our problem. escape_bytes should be applied to only to one part of the filter (the one in bytes).
I think we should have just escape_bytes method and use it only when needed, like when we're constructing a filter.

Sure, sounds reasonable.

Login to comment on this ticket.

Metadata
Related Pull Requests
  • #50466 Last updated 5 hours ago