Thanks to visit codestin.com
Credit goes to github.com

Skip to content

"SystemError: error return without exception set" when server returns an unknown resultCode #240

Closed
@jmb202

Description

@jmb202

Issue description:

If a server returns a response to a search request containing a response code that is in the range [LDAP_ERROR_MIN,LDAP_ERROR_MAX], but is not one that is actually known, then python-ldap will attempt to use NULL as an exception object, which then causes the Python runtime to raise a SystemError.

Steps to reproduce:

Perform a search against an LDAP server that returns an unknown response code. For example, OKTA (https://www.okta.com/) will return resultCode 92 (notSupported) if you attempt to perform a search using a non-trivial filter (e.g. (&(objectClass=person)(uid=foo)). Sadly, this is a proprietary solution, and the LDAP functionality doesn't appear to be generally available. However, here's the raw BER-encoded response data they send:

30 0c 02 01 02 65 07 0a
01 5c 04 00 04 00

or, decoded:

30 0c -- LDAPMessage (payload size = 12 octets)
   02 01 02 -- Message ID (integer object, value = 2)
   65 07 -- SearchResultDone operation (payload size = 7 octets)
      0a 01 5c -- result code (enumerated value 0x5c == 92)
      04 00 -- matched DN (empty octet string)
      04 00 -- diagnostic message (empty octet string)

(resultCode 92 is in the range reserved for client-side errors, so probably shouldn't be appearing on the wire, but still).

Operating system:

Debian Stretch

Python version:

2.7.13

python-ldap version:

2.4.28

Here's a trivial patch against HEAD of master as of the time I'm writing this (363e417) that causes the base LDAPError exception to be raised in this scenario (which is more likely to be expected by client code):

--- a/Modules/constants.c
+++ b/Modules/constants.c
@@ -32,7 +32,8 @@ static PyObject *errobjects[LDAP_ERROR_MAX - LDAP_ERROR_MIN + 1];
 PyObject *
 LDAPerr(int errnum)
 {
-    if (errnum >= LDAP_ERROR_MIN && errnum <= LDAP_ERROR_MAX) {
+    if (errnum >= LDAP_ERROR_MIN && errnum <= LDAP_ERROR_MAX
+        && errobjects[errnum + LDAP_ERROR_OFFSET] != NULL) {
         PyErr_SetNone(errobjects[errnum + LDAP_ERROR_OFFSET]);
     }
     else {
@@ -72,7 +73,8 @@ LDAPerror(LDAP *l, char *msg)
         if (errnum == LDAP_NO_MEMORY)
             return PyErr_NoMemory();
 
-        if (errnum >= LDAP_ERROR_MIN && errnum <= LDAP_ERROR_MAX)
+        if (errnum >= LDAP_ERROR_MIN && errnum <= LDAP_ERROR_MAX
+            && errobjects[errnum + LDAP_ERROR_OFFSET] != NULL)
             errobj = errobjects[errnum + LDAP_ERROR_OFFSET];
         else
             errobj = LDAPexception_class;

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions