diff --git a/CHANGES b/CHANGES index beb007b..f9366df 100644 --- a/CHANGES +++ b/CHANGES @@ -1,3 +1,11 @@ +---------------------------------------------------------------- +Released 2.4.20 2015-05-xx + +Changes since 2.4.19: + +* New wrapping of OpenLDAP's function ldap_sasl_bind_s() allows + to intercept the SASL handshake (thanks to René Kijewski) + ---------------------------------------------------------------- Released 2.4.19 2015-01-10 @@ -1144,4 +1152,4 @@ Released 2.0.0pre02 2002-02-01 ---------------------------------------------------------------- Released 1.10alpha3 2000-09-19 -$Id: CHANGES,v 1.338 2015/01/10 17:08:52 stroeder Exp $ +$Id: CHANGES,v 1.339 2015/05/02 16:19:23 stroeder Exp $ diff --git a/Lib/ldap/ldapobject.py b/Lib/ldap/ldapobject.py index 97deccf..7e2878f 100644 --- a/Lib/ldap/ldapobject.py +++ b/Lib/ldap/ldapobject.py @@ -3,7 +3,7 @@ ldapobject.py - wraps class _ldap.LDAPObject See http://www.python-ldap.org/ for details. -\$Id: ldapobject.py,v 1.143 2014/11/23 18:51:53 stroeder Exp $ +\$Id: ldapobject.py,v 1.144 2015/05/02 16:19:23 stroeder Exp $ Compability: - Tested with Python 2.0+ but should work with Python 1.5.x @@ -136,6 +136,14 @@ class SimpleLDAPObject: self.__class__.__name__,repr(name) ) + def fileno(): + """ + Returns file description of LDAP connection. + + Just a convenience wrapper for LDAPObject.get_option(ldap.OPT_DESC) + """ + return self.get_option(ldap.OPT_DESC) + def abandon_ext(self,msgid,serverctrls=None,clientctrls=None): """ abandon_ext(msgid[,serverctrls=None[,clientctrls=None]]) -> None @@ -235,6 +243,12 @@ class SimpleLDAPObject: """ return self._ldap_call(self._l.sasl_interactive_bind_s,who,auth,RequestControlTuples(serverctrls),RequestControlTuples(clientctrls),sasl_flags) + def sasl_bind_s(self,dn,mechanism,cred,serverctrls=None,clientctrls=None): + """ + sasl_bind_s(dn, mechanism, cred [,serverctrls=None[,clientctrls=None]]) -> int|str + """ + return self._ldap_call(self._l.sasl_bind_s,dn,mechanism,cred,RequestControlTuples(serverctrls),RequestControlTuples(clientctrls)) + def compare_ext(self,dn,attr,value,serverctrls=None,clientctrls=None): """ compare_ext(dn, attr, value [,serverctrls=None[,clientctrls=None]]) -> int @@ -895,6 +909,11 @@ class ReconnectLDAPObject(SimpleLDAPObject): self._store_last_bind(SimpleLDAPObject.sasl_interactive_bind_s,*args,**kwargs) return res + def sasl_bind_s(self,dn,mechanism,cred,serverctrls=None,clientctrls=None): + res = self._apply_method_s(SimpleLDAPObject.sasl_bind_s,*args,**kwargs) + self._store_last_bind(SimpleLDAPObject.sasl_bind_s,*args,**kwargs) + return res + def add_ext_s(self,*args,**kwargs): return self._apply_method_s(SimpleLDAPObject.add_ext_s,*args,**kwargs) diff --git a/Modules/LDAPObject.c b/Modules/LDAPObject.c index 1b2326a..eddd7e1 100644 --- a/Modules/LDAPObject.c +++ b/Modules/LDAPObject.c @@ -1,5 +1,5 @@ /* See http://www.python-ldap.org/ for details. - * $Id: LDAPObject.c,v 1.90 2011/04/11 11:29:59 stroeder Exp $ */ + * $Id: LDAPObject.c,v 1.91 2015/05/02 16:19:23 stroeder Exp $ */ #include "common.h" #include "patchlevel.h" @@ -616,6 +616,59 @@ int py_ldap_sasl_interaction( LDAP *ld, return LDAP_SUCCESS; } +static PyObject* +l_ldap_sasl_bind_s( LDAPObject* self, PyObject* args ) +{ + const char *dn; + const char *mechanism; + struct berval cred; + Py_ssize_t cred_len; + + PyObject *serverctrls = Py_None; + PyObject *clientctrls = Py_None; + LDAPControl** server_ldcs = NULL; + LDAPControl** client_ldcs = NULL; + + struct berval *servercred; + int ldaperror; + + if (!PyArg_ParseTuple(args, "zzz#OO", &dn, &mechanism, &cred.bv_val, &cred_len, &serverctrls, &clientctrls )) + return NULL; + + if (not_valid(self)) return NULL; + + cred.bv_len = cred_len; + + if (!PyNone_Check(serverctrls)) { + if (!LDAPControls_from_object(serverctrls, &server_ldcs)) + return NULL; + } + if (!PyNone_Check(clientctrls)) { + if (!LDAPControls_from_object(clientctrls, &client_ldcs)) + return NULL; + } + + LDAP_BEGIN_ALLOW_THREADS( self ); + ldaperror = ldap_sasl_bind_s(self->ldap, + dn, + mechanism, + cred.bv_val ? &cred : NULL, + (LDAPControl**) server_ldcs, + (LDAPControl**) client_ldcs, + &servercred); + LDAP_END_ALLOW_THREADS( self ); + + LDAPControl_List_DEL( server_ldcs ); + LDAPControl_List_DEL( client_ldcs ); + + if (ldaperror == LDAP_SASL_BIND_IN_PROGRESS) { + if (servercred && servercred->bv_val && *servercred->bv_val) + return PyString_FromStringAndSize( servercred->bv_val, servercred->bv_len ); + } else if (ldaperror != LDAP_SUCCESS) + return LDAPerror( self->ldap, "l_ldap_sasl_bind_s" ); + return PyInt_FromLong( ldaperror ); +} + static PyObject* l_ldap_sasl_interactive_bind_s( LDAPObject* self, PyObject* args ) { @@ -1317,6 +1370,7 @@ static PyMethodDef methods[] = { {"simple_bind", (PyCFunction)l_ldap_simple_bind, METH_VARARGS }, #ifdef HAVE_SASL {"sasl_interactive_bind_s", (PyCFunction)l_ldap_sasl_interactive_bind_s, METH_VARARGS }, + {"sasl_bind_s", (PyCFunction)l_ldap_sasl_bind_s, METH_VARARGS }, #endif {"compare_ext", (PyCFunction)l_ldap_compare_ext, METH_VARARGS }, {"delete_ext", (PyCFunction)l_ldap_delete_ext, METH_VARARGS },