Hi,

When LDAPError receives an errnum from ldap_get_option(l,
LDAP_OPT_ERROR_NUMBER, &errnum) that is out of bounds it causes a segfault.
I have attached a script that triggers it and patch that fixes it.

The test script requires an ldap URI and a BaseDN on the command line.  The
ldap server can be OpenLDAP 2.3 or 2.4 and the BaseDN should be configured
with a syncprov overlay and have syncprov-reloadhint TRUE.  eg:
/tmp/ldap-segfault.py ldap://ldap.example.com dc=example,dc=com

After patching _ldap.so we get a valid Exception:
Traceback (most recent call last):
  File "/tmp/ldap-segfault.py", line 39, in ?
    rtype, rdata, rmsgid, serverctrls = conn.result3(all=1, timeout=60)
  File "/usr/lib/python2.4/site-packages/ldap/ldapobject.py", line 438, in
result3
    rtype, rdata, rmsgid, serverctrls =
self._ldap_call(self._l.result3,msgid,all,timeout)
  File "/usr/lib/python2.4/site-packages/ldap/ldapobject.py", line 97, in
_ldap_call
    result = func(*args,**kwargs)
ldap.LDAPError: {'info': 'sync cookie is stale', 'desc': 'Content Sync
Refresh Required'}

-- 
Thanks,
Sean Burford
--- python-ldap-2.3.1/Modules/errors.c	2007-03-27 13:34:31.000000000 -0700
+++ python-ldap-2.3.1.patched/Modules/errors.c	2009-03-20 11:14:30.000000000 -0700
@@ -51,20 +51,25 @@ LDAPerror( LDAP*l, char*msg ) 
 		return NULL;
 	}
 	else {
-		int errnum;
+		int errnum, opt_errnum;
 		PyObject *errobj;
 		PyObject *info;
 		PyObject *str;
 
 		char *matched, *error;
-		if (ldap_get_option(l, LDAP_OPT_ERROR_NUMBER, &errnum) < 0)
-			errobj = LDAPexception_class;	/* unknown error XXX */
-		else
-			errobj = errobjects[errnum+LDAP_ERROR_OFFSET];
-		
+
+		opt_errnum = ldap_get_option(l, LDAP_OPT_ERROR_NUMBER, &errnum);
+		if (opt_errnum != LDAP_OPT_SUCCESS)
+			errnum = opt_errnum;
+
 		if (errnum == LDAP_NO_MEMORY)
 			return PyErr_NoMemory();
 
+		if (errnum >= LDAP_ERROR_MIN && errnum <= LDAP_ERROR_MAX)
+			errobj = errobjects[errnum+LDAP_ERROR_OFFSET];
+		else
+			errobj = LDAPexception_class;
+		
 		info = PyDict_New();
 		if (info == NULL)
 			return NULL;
#!/usr/bin/python2.4

import ldap
import ldap.controls
import struct
import sys

class SyncRequestControl(ldap.controls.LDAPControl):
  controlType='1.3.6.1.4.1.4203.1.9.1.1'

  def encodeControlValue(self, value):
    cookie = value

    len_cookie = len(cookie)
    result_content = struct.pack('BBBBBBB', 0x30, len_cookie + 5, 0x0A, 0x01, 0x01, 0x04, len_cookie)
    return result_content + cookie

try:
  host=sys.argv[1]
  base=sys.argv[2]
except IndexError:
  print 'Usage: %s ldap://HOSTNAME BASEDN'
  print 'HOSTNAME should have "syncprov-reloadhint TRUE" set for BASEDN'
  sys.exit(1)

cookie='rid=000,sid=000,csn=20010101010101.000000Z#000000#000#000000'

ldap.set_option(ldap.OPT_PROTOCOL_VERSION, ldap.VERSION3)
ldap.set_option(ldap.OPT_REFERRALS, 0)

conn = ldap.initialize(host)

sync_req_ctrl=SyncRequestControl(controlType=SyncRequestControl.controlType,
                                 criticality=True, controlValue=cookie)
conn.search_ext(base, ldap.SCOPE_SUBTREE, attrlist=('dn','entryCSN',),
                serverctrls=(sync_req_ctrl,))

rtype, rdata, rmsgid, serverctrls = conn.result3(all=1, timeout=60)
rtype, rdata, rmsgid, serverctrls = conn.result3(all=1, timeout=60)

------------------------------------------------------------------------------
Apps built with the Adobe(R) Flex(R) framework and Flex Builder(TM) are
powering Web 2.0 with engaging, cross-platform capabilities. Quickly and
easily build your RIAs with Flex Builder, the Eclipse(TM)based development
software that enables intelligent coding and step-through debugging.
Download the free 60 day trial. http://p.sf.net/sfu/www-adobe-com
_______________________________________________
Python-LDAP-dev mailing list
Python-LDAP-dev@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/python-ldap-dev

Reply via email to