| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303 |
- /* See http://www.python-ldap.org/ for details.
- * $Id: LDAPObject.c,v 1.88 2009/10/08 18:22:44 stroeder Exp $ */
- #include "common.h"
- #include "patchlevel.h"
- #include <math.h>
- #include <limits.h>
- #include "errors.h"
- #include "constants.h"
- #include "LDAPObject.h"
- #include "ldapcontrol.h"
- #include "message.h"
- #include "berval.h"
- #include "options.h"
- #ifdef HAVE_SASL
- #include <sasl.h>
- #endif
- static void free_attrs(char***);
- /* constructor */
- LDAPObject*
- newLDAPObject( LDAP* l )
- {
- LDAPObject* self = (LDAPObject*) PyObject_NEW(LDAPObject, &LDAP_Type);
- if (self == NULL)
- return NULL;
- self->ldap = l;
- self->_save = NULL;
- self->valid = 1;
- return self;
- }
- /* destructor */
- static void
- dealloc( LDAPObject* self )
- {
- if (self->ldap) {
- if (self->valid) {
- LDAP_BEGIN_ALLOW_THREADS( self );
- ldap_unbind_ext( self->ldap, NULL, NULL );
- LDAP_END_ALLOW_THREADS( self );
- self->valid = 0;
- }
- self->ldap = NULL;
- }
- PyObject_DEL(self);
- }
- /*------------------------------------------------------------
- * utility functions
- */
- /*
- * check to see if the LDAPObject is valid,
- * ie has been opened, and not closed. An exception is set if not valid.
- */
- static int
- not_valid( LDAPObject* l ) {
- if (l->valid) {
- return 0;
- } else {
- PyErr_SetString( LDAPexception_class, "LDAP connection invalid" );
- return 1;
- }
- }
- /* free a LDAPMod (complete or partially) allocated in Tuple_to_LDAPMod() */
- static void
- LDAPMod_DEL( LDAPMod* lm )
- {
- Py_ssize_t i;
- if (lm->mod_type)
- PyMem_DEL(lm->mod_type);
- if (lm->mod_bvalues) {
- for (i = 0; lm->mod_bvalues[i]; i++) {
- PyMem_DEL(lm->mod_bvalues[i]);
- }
- PyMem_DEL(lm->mod_bvalues);
- }
- PyMem_DEL(lm);
- }
- /*
- * convert a tuple of the form (int,str,[str,...])
- * or (str, [str,...]) if no_op is true, into an LDAPMod structure.
- * See ldap_modify(3) for details.
- *
- * NOTE: the resulting LDAPMod structure has pointers directly into
- * the Python string storage, so LDAPMod structures MUST have a
- * shorter lifetime than the tuple passed in.
- */
- /* XXX - there is no way to pass complex-structured BER objects in here! */
- static LDAPMod*
- Tuple_to_LDAPMod( PyObject* tup, int no_op )
- {
- int op;
- char *type;
- PyObject *list, *item;
- LDAPMod *lm = NULL;
- Py_ssize_t i, len, nstrs;
- if (!PyTuple_Check(tup)) {
- PyErr_SetObject(PyExc_TypeError, Py_BuildValue("sO",
- "expected a tuple", tup));
- return NULL;
- }
- if (no_op) {
- if (!PyArg_ParseTuple( tup, "sO", &type, &list ))
- return NULL;
- op = 0;
- } else {
- if (!PyArg_ParseTuple( tup, "isO", &op, &type, &list ))
- return NULL;
- }
- lm = PyMem_NEW(LDAPMod, 1);
- if (lm == NULL)
- goto nomem;
- lm->mod_op = op | LDAP_MOD_BVALUES;
- lm->mod_bvalues = NULL;
- len = strlen(type);
- lm->mod_type = PyMem_NEW(char, len + 1);
- if (lm->mod_type == NULL)
- goto nomem;
- memcpy(lm->mod_type, type, len + 1);
- if (list == Py_None) {
- /* None indicates a NULL mod_bvals */
- } else if (PyString_Check(list)) {
- /* Single string is a singleton list */
- lm->mod_bvalues = PyMem_NEW(struct berval *, 2);
- if (lm->mod_bvalues == NULL)
- goto nomem;
- lm->mod_bvalues[0] = PyMem_NEW(struct berval, 1);
- if (lm->mod_bvalues[0] == NULL)
- goto nomem;
- lm->mod_bvalues[1] = NULL;
- lm->mod_bvalues[0]->bv_len = PyString_Size(list);
- lm->mod_bvalues[0]->bv_val = PyString_AsString(list);
- } else if (PySequence_Check(list)) {
- nstrs = PySequence_Length(list);
- lm->mod_bvalues = PyMem_NEW(struct berval *, nstrs + 1);
- if (lm->mod_bvalues == NULL)
- goto nomem;
- for (i = 0; i < nstrs; i++) {
- lm->mod_bvalues[i] = PyMem_NEW(struct berval, 1);
- if (lm->mod_bvalues[i] == NULL)
- goto nomem;
- lm->mod_bvalues[i+1] = NULL;
- item = PySequence_GetItem(list, i);
- if (item == NULL)
- goto error;
- if (!PyString_Check(item)) {
- PyErr_SetObject( PyExc_TypeError, Py_BuildValue( "sO",
- "expected a string in the list", item));
- Py_DECREF(item);
- goto error;
- }
- lm->mod_bvalues[i]->bv_len = PyString_Size(item);
- lm->mod_bvalues[i]->bv_val = PyString_AsString(item);
- Py_DECREF(item);
- }
- if (nstrs == 0)
- lm->mod_bvalues[0] = NULL;
- }
- return lm;
- nomem:
- PyErr_NoMemory();
- error:
- if (lm)
- LDAPMod_DEL(lm);
- return NULL;
- }
- /* free the structure allocated in List_to_LDAPMods() */
- static void
- LDAPMods_DEL( LDAPMod** lms ) {
- LDAPMod** lmp;
- for ( lmp = lms; *lmp; lmp++ )
- LDAPMod_DEL( *lmp );
- PyMem_DEL(lms);
- }
- /*
- * convert a list of tuples into a LDAPMod*[] array structure
- * NOTE: list of tuples must live longer than the LDAPMods
- */
- static LDAPMod**
- List_to_LDAPMods( PyObject *list, int no_op ) {
- Py_ssize_t i, len;
- LDAPMod** lms;
- PyObject *item;
- if (!PySequence_Check(list)) {
- PyErr_SetObject( PyExc_TypeError, Py_BuildValue("sO",
- "expected list of tuples", list ));
- return NULL;
- }
- len = PySequence_Length(list);
- if (len < 0) {
- PyErr_SetObject( PyExc_TypeError, Py_BuildValue("sO",
- "expected list of tuples", list ));
- return NULL;
- }
- lms = PyMem_NEW(LDAPMod *, len + 1);
- if (lms == NULL)
- goto nomem;
- for (i = 0; i < len; i++) {
- lms[i] = NULL;
- item = PySequence_GetItem(list, i);
- if (item == NULL)
- goto error;
- lms[i] = Tuple_to_LDAPMod(item, no_op);
- Py_DECREF(item);
- if (lms[i] == NULL)
- goto error;
- }
- lms[len] = NULL;
- return lms;
- nomem:
- PyErr_NoMemory();
- error:
- if (lms)
- LDAPMods_DEL(lms);
- return NULL;
- }
- /*
- * convert a python list of strings into an attr list (char*[]).
- * returns 1 if successful, 0 if not (with exception set)
- * XXX the strings should live longer than the resulting attrs pointer.
- */
- int
- attrs_from_List( PyObject *attrlist, char***attrsp ) {
- char **attrs = NULL;
- Py_ssize_t i, len;
- PyObject *item;
- if (attrlist == Py_None) {
- /* None means a NULL attrlist */
- } else if (PyString_Check(attrlist)) {
- /* caught by John Benninghoff <johnb@netscape.com> */
- PyErr_SetObject( PyExc_TypeError, Py_BuildValue("sO",
- "expected *list* of strings, not a string", attrlist ));
- goto error;
- } else if (PySequence_Check(attrlist)) {
- len = PySequence_Length(attrlist);
- attrs = PyMem_NEW(char *, len + 1);
- if (attrs == NULL)
- goto nomem;
- for (i = 0; i < len; i++) {
- attrs[i] = NULL;
- item = PySequence_GetItem(attrlist, i);
- if (item == NULL)
- goto error;
- if (!PyString_Check(item)) {
- PyErr_SetObject(PyExc_TypeError, Py_BuildValue("sO",
- "expected string in list", item));
- Py_DECREF(item);
- goto error;
- }
- attrs[i] = PyString_AsString(item);
- Py_DECREF(item);
- }
- attrs[len] = NULL;
- } else {
- PyErr_SetObject( PyExc_TypeError, Py_BuildValue("sO",
- "expected list of strings or None", attrlist ));
- goto error;
- }
- *attrsp = attrs;
- return 1;
- nomem:
- PyErr_NoMemory();
- error:
- free_attrs(&attrs);
- return 0;
- }
- /* free memory allocated from above routine */
- static void
- free_attrs( char*** attrsp ) {
- char **attrs = *attrsp;
- if (attrs != NULL) {
- PyMem_DEL(attrs);
- *attrsp = NULL;
- }
- }
- /*------------------------------------------------------------
- * methods
- */
- /* ldap_unbind_ext */
- static PyObject*
- l_ldap_unbind_ext( LDAPObject* self, PyObject* args )
- {
- PyObject *serverctrls = Py_None;
- PyObject *clientctrls = Py_None;
- LDAPControl** server_ldcs = NULL;
- LDAPControl** client_ldcs = NULL;
- int ldaperror;
- if (!PyArg_ParseTuple( args, "|OO", &serverctrls, &clientctrls)) return NULL;
- if (not_valid(self)) return NULL;
- 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_unbind_ext( self->ldap, server_ldcs, client_ldcs );
- LDAP_END_ALLOW_THREADS( self );
- LDAPControl_List_DEL( server_ldcs );
- LDAPControl_List_DEL( client_ldcs );
- if ( ldaperror!=LDAP_SUCCESS )
- return LDAPerror( self->ldap, "ldap_unbind_ext" );
- self->valid = 0;
- Py_INCREF(Py_None);
- return Py_None;
- }
- /* ldap_abandon_ext */
- static PyObject*
- l_ldap_abandon_ext( LDAPObject* self, PyObject* args )
- {
- int msgid;
- PyObject *serverctrls = Py_None;
- PyObject *clientctrls = Py_None;
- LDAPControl** server_ldcs = NULL;
- LDAPControl** client_ldcs = NULL;
- int ldaperror;
- if (!PyArg_ParseTuple( args, "i|OO", &msgid, &serverctrls, &clientctrls)) return NULL;
- if (not_valid(self)) return NULL;
- 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_abandon_ext( self->ldap, msgid, server_ldcs, client_ldcs );
- LDAP_END_ALLOW_THREADS( self );
- LDAPControl_List_DEL( server_ldcs );
- LDAPControl_List_DEL( client_ldcs );
- if ( ldaperror!=LDAP_SUCCESS )
- return LDAPerror( self->ldap, "ldap_abandon_ext" );
- Py_INCREF(Py_None);
- return Py_None;
- }
- /* ldap_add_ext */
- static PyObject *
- l_ldap_add_ext( LDAPObject* self, PyObject *args )
- {
- char *dn;
- PyObject *modlist;
- PyObject *serverctrls = Py_None;
- PyObject *clientctrls = Py_None;
- LDAPControl** server_ldcs = NULL;
- LDAPControl** client_ldcs = NULL;
- int msgid;
- int ldaperror;
- LDAPMod **mods;
- if (!PyArg_ParseTuple( args, "sO|OO", &dn, &modlist, &serverctrls, &clientctrls )) return NULL;
- if (not_valid(self)) return NULL;
- mods = List_to_LDAPMods( modlist, 1 );
- if (mods == NULL)
- return NULL;
- 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_add_ext( self->ldap, dn, mods, server_ldcs, client_ldcs, &msgid);
- LDAP_END_ALLOW_THREADS( self );
- LDAPMods_DEL( mods );
- LDAPControl_List_DEL( server_ldcs );
- LDAPControl_List_DEL( client_ldcs );
- if ( ldaperror!=LDAP_SUCCESS )
- return LDAPerror( self->ldap, "ldap_add_ext" );
- return PyInt_FromLong(msgid);
- }
- /* ldap_simple_bind */
- static PyObject*
- l_ldap_simple_bind( LDAPObject* self, PyObject* args )
- {
- char *who;
- int msgid;
- int ldaperror;
- Py_ssize_t cred_len;
- PyObject *serverctrls = Py_None;
- PyObject *clientctrls = Py_None;
- LDAPControl** server_ldcs = NULL;
- LDAPControl** client_ldcs = NULL;
- struct berval cred;
- if (!PyArg_ParseTuple( args, "ss#|OO", &who, &cred.bv_val, &cred_len, &serverctrls, &clientctrls )) return NULL;
- cred.bv_len = (ber_len_t) cred_len;
- if (not_valid(self)) return NULL;
- 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( self->ldap, who, LDAP_SASL_SIMPLE, &cred, server_ldcs, client_ldcs, &msgid);
- LDAP_END_ALLOW_THREADS( self );
- LDAPControl_List_DEL( server_ldcs );
- LDAPControl_List_DEL( client_ldcs );
- if ( ldaperror!=LDAP_SUCCESS )
- return LDAPerror( self->ldap, "ldap_simple_bind" );
- return PyInt_FromLong( msgid );
- }
- #ifdef HAVE_SASL
- /* The following functions implement SASL binds. A new method
- sasl_interactive_bind_s(bind_dn, sasl_mechanism) has been introduced.
- * The bind_dn argument will be passed to the c library; however,
- normally it is not needed and should be an empty string.
- * The sasl_mechanism argument is an instance of a class that
- implements a callback interface. For convenience, it should be
- derived from the sasl class (which lives in the ldap.sasl module).
- See the module documentation for more information.
- Check your /usr/lib/sasl/ directory for locally installed SASL
- auth modules ("mechanisms"), or try
- ldapsearch -b "" -s base -LLL -x supportedSASLMechanisms
-
- (perhaps with an additional -h and -p argument for ldap host and
- port). The latter will show you which SASL mechanisms are known
- to the LDAP server. If you do not want to set up Kerberos, you
- can still use SASL binds. Your authentication data should then be
- stored in /etc/sasldb (see saslpasswd(8)). If the LDAP server
- does not find the sasldb, it wont allow for DIGEST-MD5 and
- CRAM-MD5. One important thing to get started with sasldb: you
- should first add a dummy user (saslpasswd -c dummy), and this
- will give you some strange error messages. Then delete the dummy
- user (saslpasswd -d dummy), and now you can start adding users to
- your sasldb (again, use the -c switch). Strange, eh?
- * The sasl_mechanism object must implement a method, which will be
- called by the sasl lib several times. The prototype of the
- callback looks like this: callback(id, challenge, prompt,
- defresult) has to return a string (or maybe None). The id
- argument specifies, which information should be passed back to
- the SASL lib (see SASL_CB_xxx in sasl.h)
- A nice "Howto get LDAPv3 up and running with Kerberos and SSL" can
- be found at http://www.bayour.com/LDAPv3-HOWTO.html. Instead of
- MIT Kerberos, I used Heimdal for my tests (since it is included
- with SuSE Linux).
- Todo:
-
- * Find a better interface than the python callback. This is
- really ugly. Perhaps one could make use of a sasl class, like
- in the perl ldap module.
- * Thread safety?
- * Memory Management?
-
- * Write more docs
- * ...
- */
- static int interaction ( unsigned flags,
- sasl_interact_t *interact,
- PyObject* SASLObject )
- {
- /* const char *dflt = interact->defresult; */
- PyObject *result;
- char *c_result;
- result = PyObject_CallMethod(SASLObject,
- "callback",
- "isss",
- interact->id, /* see sasl.h */
- interact->challenge,
- interact->prompt,
- interact->defresult);
- if (result == NULL)
- /*searching for a better error code */
- return LDAP_OPERATIONS_ERROR;
- c_result = PyString_AsString(result); /*xxx Error checking?? */
-
- /* according to the sasl docs, we should malloc() the returned
- string only for calls where interact->id == SASL_CB_PASS, so we
- probably leak a few bytes per ldap bind. However, if I restrict
- the strdup() to this case, I get segfaults. Should probably be
- fixed sometimes.
- */
- interact->result = strdup( c_result );
- if (interact->result == NULL)
- return LDAP_OPERATIONS_ERROR;
- interact->len = strlen(c_result);
- /* We _should_ overwrite the python string buffer for security
- reasons, however we may not (api/stringObjects.html). Any ideas?
- */
-
- Py_DECREF(result); /*not needed any longer */
- result = NULL;
-
- return LDAP_SUCCESS;
- }
- /*
- This function will be called by ldap_sasl_interactive_bind(). The
- "*in" is an array of sasl_interact_t's (see sasl.h for a
- reference). The last interact in the array has an interact->id of
- SASL_CB_LIST_END.
- */
- int py_ldap_sasl_interaction( LDAP *ld,
- unsigned flags,
- void *defaults,
- void *in )
- {
- /* These are just typecasts */
- sasl_interact_t *interact = (sasl_interact_t *) in;
- PyObject *SASLObject = (PyObject *) defaults;
- /* Loop over the array of sasl_interact_t structs */
- while( interact->id != SASL_CB_LIST_END ) {
- int rc = 0;
- rc = interaction( flags, interact, SASLObject );
- if( rc ) return rc;
- interact++;
- }
- return LDAP_SUCCESS;
- }
- static PyObject*
- l_ldap_sasl_interactive_bind_s( LDAPObject* self, PyObject* args )
- {
- char *c_mechanism;
- char *who;
- PyObject *serverctrls = Py_None;
- PyObject *clientctrls = Py_None;
- LDAPControl** server_ldcs = NULL;
- LDAPControl** client_ldcs = NULL;
- PyObject *SASLObject = NULL;
- PyObject *mechanism = NULL;
- int msgid;
- static unsigned sasl_flags = LDAP_SASL_QUIET;
- /*
- * In Python 2.3+, a "I" format argument indicates that we're either converting
- * the Python object into a long or an unsigned int. In versions prior to that,
- * it will always convert to a long. Since the sasl_flags variable is an
- * unsigned int, we need to use the "I" flag if we're running Python 2.3+ and a
- * "i" otherwise.
- */
- #if (PY_MAJOR_VERSION == 2) && (PY_MINOR_VERSION < 3)
- if (!PyArg_ParseTuple(args, "sOOOi", &who, &SASLObject, &serverctrls, &clientctrls, &sasl_flags ))
- #else
- if (!PyArg_ParseTuple(args, "sOOOI", &who, &SASLObject, &serverctrls, &clientctrls, &sasl_flags ))
- #endif
- return NULL;
- if (not_valid(self)) return NULL;
- 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;
- }
- /* now we extract the sasl mechanism from the SASL Object */
- mechanism = PyObject_GetAttrString(SASLObject, "mech");
- if (mechanism == NULL) return NULL;
- c_mechanism = PyString_AsString(mechanism);
- Py_DECREF(mechanism);
- mechanism = NULL;
- /* Don't know if it is the "intended use" of the defaults
- parameter of ldap_sasl_interactive_bind_s when we pass the
- Python object SASLObject, but passing it through some
- static variable would destroy thread safety, IMHO.
- */
- msgid = ldap_sasl_interactive_bind_s(self->ldap,
- who,
- c_mechanism,
- (LDAPControl**) server_ldcs,
- (LDAPControl**) client_ldcs,
- sasl_flags,
- py_ldap_sasl_interaction,
- SASLObject);
- LDAPControl_List_DEL( server_ldcs );
- LDAPControl_List_DEL( client_ldcs );
- if (msgid != LDAP_SUCCESS)
- return LDAPerror( self->ldap, "ldap_sasl_interactive_bind_s" );
- return PyInt_FromLong( msgid );
- }
- #endif
- #ifdef LDAP_API_FEATURE_CANCEL
- /* ldap_cancel */
- static PyObject*
- l_ldap_cancel( LDAPObject* self, PyObject* args )
- {
- int msgid;
- int cancelid;
- PyObject *serverctrls = Py_None;
- PyObject *clientctrls = Py_None;
- LDAPControl** server_ldcs = NULL;
- LDAPControl** client_ldcs = NULL;
- int ldaperror;
- if (!PyArg_ParseTuple( args, "i|OO", &cancelid, &serverctrls, &clientctrls)) return NULL;
- if (not_valid(self)) return NULL;
- 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_cancel( self->ldap, cancelid, server_ldcs, client_ldcs, &msgid );
- LDAP_END_ALLOW_THREADS( self );
- LDAPControl_List_DEL( server_ldcs );
- LDAPControl_List_DEL( client_ldcs );
- if ( ldaperror!=LDAP_SUCCESS )
- return LDAPerror( self->ldap, "ldap_cancel" );
- return PyInt_FromLong( msgid );
- }
- #endif
- /* ldap_compare_ext */
- static PyObject *
- l_ldap_compare_ext( LDAPObject* self, PyObject *args )
- {
- char *dn, *attr;
- PyObject *serverctrls = Py_None;
- PyObject *clientctrls = Py_None;
- LDAPControl** server_ldcs = NULL;
- LDAPControl** client_ldcs = NULL;
- int msgid;
- int ldaperror;
- Py_ssize_t value_len;
- struct berval value;
- if (!PyArg_ParseTuple( args, "sss#|OO", &dn, &attr, &value.bv_val, &value_len, &serverctrls, &clientctrls )) return NULL;
- value.bv_len = (ber_len_t) value_len;
- if (not_valid(self)) return NULL;
- 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_compare_ext( self->ldap, dn, attr, &value, server_ldcs, client_ldcs, &msgid );
- LDAP_END_ALLOW_THREADS( self );
- LDAPControl_List_DEL( server_ldcs );
- LDAPControl_List_DEL( client_ldcs );
- if ( ldaperror!=LDAP_SUCCESS )
- return LDAPerror( self->ldap, "ldap_compare_ext" );
- return PyInt_FromLong( msgid );
- }
- /* ldap_delete_ext */
- static PyObject *
- l_ldap_delete_ext( LDAPObject* self, PyObject *args )
- {
- char *dn;
- PyObject *serverctrls = Py_None;
- PyObject *clientctrls = Py_None;
- LDAPControl** server_ldcs = NULL;
- LDAPControl** client_ldcs = NULL;
- int msgid;
- int ldaperror;
- if (!PyArg_ParseTuple( args, "s|OO", &dn, &serverctrls, &clientctrls )) return NULL;
- if (not_valid(self)) return NULL;
- 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_delete_ext( self->ldap, dn, server_ldcs, client_ldcs, &msgid );
- LDAP_END_ALLOW_THREADS( self );
- LDAPControl_List_DEL( server_ldcs );
- LDAPControl_List_DEL( client_ldcs );
- if ( ldaperror!=LDAP_SUCCESS )
- return LDAPerror( self->ldap, "ldap_delete_ext" );
- return PyInt_FromLong(msgid);
- }
- /* ldap_modify_ext */
- static PyObject *
- l_ldap_modify_ext( LDAPObject* self, PyObject *args )
- {
- char *dn;
- PyObject *modlist;
- PyObject *serverctrls = Py_None;
- PyObject *clientctrls = Py_None;
- LDAPControl** server_ldcs = NULL;
- LDAPControl** client_ldcs = NULL;
- int msgid;
- int ldaperror;
- LDAPMod **mods;
- if (!PyArg_ParseTuple( args, "sO|OO", &dn, &modlist, &serverctrls, &clientctrls )) return NULL;
- if (not_valid(self)) return NULL;
- mods = List_to_LDAPMods( modlist, 0 );
- if (mods == NULL)
- return NULL;
- 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_modify_ext( self->ldap, dn, mods, server_ldcs, client_ldcs, &msgid );
- LDAP_END_ALLOW_THREADS( self );
- LDAPMods_DEL( mods );
- LDAPControl_List_DEL( server_ldcs );
- LDAPControl_List_DEL( client_ldcs );
- if ( ldaperror!=LDAP_SUCCESS )
- return LDAPerror( self->ldap, "ldap_modify_ext" );
- return PyInt_FromLong( msgid );
- }
- /* ldap_rename */
- static PyObject *
- l_ldap_rename( LDAPObject* self, PyObject *args )
- {
- char *dn, *newrdn;
- char *newSuperior = NULL;
- int delold = 1;
- PyObject *serverctrls = Py_None;
- PyObject *clientctrls = Py_None;
- LDAPControl** server_ldcs = NULL;
- LDAPControl** client_ldcs = NULL;
- int msgid;
- int ldaperror;
- if (!PyArg_ParseTuple( args, "ss|ziOO", &dn, &newrdn, &newSuperior, &delold, &serverctrls, &clientctrls ))
- return NULL;
- if (not_valid(self)) return NULL;
- 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_rename( self->ldap, dn, newrdn, newSuperior, delold, server_ldcs, client_ldcs, &msgid );
- LDAP_END_ALLOW_THREADS( self );
- LDAPControl_List_DEL( server_ldcs );
- LDAPControl_List_DEL( client_ldcs );
- if ( ldaperror!=LDAP_SUCCESS )
- return LDAPerror( self->ldap, "ldap_rename" );
- return PyInt_FromLong( msgid );
- }
- /* ldap_result3 */
- static PyObject *
- l_ldap_result3( LDAPObject* self, PyObject *args )
- {
- int msgid = LDAP_RES_ANY;
- int all = 1;
- double timeout = -1.0;
- struct timeval tv;
- struct timeval* tvp;
- int res_type;
- LDAPMessage *msg = NULL;
- PyObject *result_str, *retval, *pmsg, *pyctrls = 0;
- int res_msgid = 0;
- if (!PyArg_ParseTuple( args, "|iid", &msgid, &all, &timeout ))
- return NULL;
- if (not_valid(self)) return NULL;
-
- if (timeout >= 0) {
- tvp = &tv;
- set_timeval_from_double( tvp, timeout );
- } else {
- tvp = NULL;
- }
- LDAP_BEGIN_ALLOW_THREADS( self );
- res_type = ldap_result( self->ldap, msgid, all, tvp, &msg );
- LDAP_END_ALLOW_THREADS( self );
- if (res_type < 0) /* LDAP or system error */
- return LDAPerror( self->ldap, "ldap_result3" );
- if (res_type == 0) {
- /* Polls return (None, None, None, None); timeouts raise an exception */
- if (timeout == 0)
- return Py_BuildValue("(OOOO)", Py_None, Py_None, Py_None, Py_None);
- else
- return LDAPerr(LDAP_TIMEOUT);
- }
- if (msg)
- res_msgid = ldap_msgid(msg);
- int result;
- char **refs = NULL;
- LDAPControl **serverctrls = 0;
- LDAP_BEGIN_ALLOW_THREADS( self );
- ldap_parse_result( self->ldap, msg, &result, NULL, NULL, &refs,
- &serverctrls, 0 );
- LDAP_END_ALLOW_THREADS( self );
- if (result != LDAP_SUCCESS) { /* result error */
- char *e, err[1024];
- if (result == LDAP_REFERRAL && refs && refs[0]) {
- snprintf(err, sizeof(err), "Referral:\n%s", refs[0]);
- e = err;
- } else
- e = "ldap_parse_result";
- ldap_msgfree(msg);
- return LDAPerror( self->ldap, e );
- }
- if (!(pyctrls = LDAPControls_to_List(serverctrls))) {
- int err = LDAP_NO_MEMORY;
- ldap_set_option(self->ldap, LDAP_OPT_ERROR_NUMBER, &err);
- ldap_msgfree(msg);
- return LDAPerror(self->ldap, "LDAPControls_to_List");
- }
- ldap_controls_free(serverctrls);
- pmsg = LDAPmessage_to_python( self->ldap, msg );
- result_str = LDAPconstant( res_type );
- if (pmsg == NULL) {
- retval = NULL;
- } else {
- if (pyctrls != NULL) {
- retval = Py_BuildValue("(OOiO)", result_str, pmsg, res_msgid,
- pyctrls);
- } else {
- PyObject *pNewList = PyList_New(0);
- retval = Py_BuildValue("(OOiO)", result_str, pmsg, res_msgid,
- pNewList);
- Py_DECREF(pNewList);
- }
- if (pmsg != Py_None) {
- Py_DECREF(pmsg);
- }
- }
- Py_XDECREF(pyctrls);
- Py_DECREF(result_str);
- return retval;
- }
- /* ldap_search_ext */
- static PyObject*
- l_ldap_search_ext( LDAPObject* self, PyObject* args )
- {
- char *base;
- int scope;
- char *filter;
- PyObject *attrlist = Py_None;
- char **attrs;
- int attrsonly = 0;
- PyObject *serverctrls = Py_None;
- PyObject *clientctrls = Py_None;
- LDAPControl** server_ldcs = NULL;
- LDAPControl** client_ldcs = NULL;
- double timeout = -1.0;
- struct timeval tv;
- struct timeval* tvp;
- int sizelimit = 0;
- int msgid;
- int ldaperror;
- if (!PyArg_ParseTuple( args, "sis|OiOOdi",
- &base, &scope, &filter, &attrlist, &attrsonly,
- &serverctrls, &clientctrls, &timeout, &sizelimit )) return NULL;
- if (not_valid(self)) return NULL;
- if (!attrs_from_List( attrlist, &attrs ))
- return NULL;
- if (timeout >= 0) {
- tvp = &tv;
- set_timeval_from_double( tvp, timeout );
- } else {
- tvp = NULL;
- }
- 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_search_ext( self->ldap, base, scope, filter, attrs, attrsonly,
- server_ldcs, client_ldcs, tvp, sizelimit, &msgid );
- LDAP_END_ALLOW_THREADS( self );
- free_attrs( &attrs );
- LDAPControl_List_DEL( server_ldcs );
- LDAPControl_List_DEL( client_ldcs );
- if ( ldaperror!=LDAP_SUCCESS )
- return LDAPerror( self->ldap, "ldap_search_ext" );
- return PyInt_FromLong( msgid );
- }
- /* ldap_whoami_s (available since OpenLDAP 2.1.13) */
- static PyObject*
- l_ldap_whoami_s( LDAPObject* self, PyObject* args )
- {
- PyObject *serverctrls = Py_None;
- PyObject *clientctrls = Py_None;
- LDAPControl** server_ldcs = NULL;
- LDAPControl** client_ldcs = NULL;
- struct berval *bvalue = NULL;
- PyObject *result;
- int ldaperror;
- if (!PyArg_ParseTuple( args, "|OO", &serverctrls, &clientctrls)) return NULL;
- 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_whoami_s( self->ldap, &bvalue, server_ldcs, client_ldcs );
- LDAP_END_ALLOW_THREADS( self );
- LDAPControl_List_DEL( server_ldcs );
- LDAPControl_List_DEL( client_ldcs );
- if ( ldaperror!=LDAP_SUCCESS )
- return LDAPerror( self->ldap, "ldap_whoami_s" );
- result = LDAPberval_to_object(bvalue);
- return result;
- }
- #ifdef HAVE_TLS
- /* ldap_start_tls_s */
- static PyObject*
- l_ldap_start_tls_s( LDAPObject* self, PyObject* args )
- {
- int result;
- if (!PyArg_ParseTuple( args, "" )) return NULL;
- if (not_valid(self)) return NULL;
- result = ldap_start_tls_s( self->ldap, NULL, NULL );
- if ( result != LDAP_SUCCESS ){
- ldap_set_option(self->ldap, LDAP_OPT_ERROR_NUMBER, &result);
- return LDAPerror( self->ldap, "ldap_start_tls_s" );
- }
- Py_INCREF(Py_None);
- return Py_None;
- }
- #endif
- /* ldap_set_option */
- static PyObject*
- l_ldap_set_option(PyObject* self, PyObject *args)
- {
- PyObject *value;
- int option;
- if (!PyArg_ParseTuple(args, "iO:set_option", &option, &value))
- return NULL;
- if (LDAP_set_option((LDAPObject *)self, option, value) == -1)
- return NULL;
- Py_INCREF(Py_None);
- return Py_None;
- }
- /* ldap_get_option */
- static PyObject*
- l_ldap_get_option(PyObject* self, PyObject *args)
- {
- int option;
- if (!PyArg_ParseTuple(args, "i:get_option", &option))
- return NULL;
- return LDAP_get_option((LDAPObject *)self, option);
- }
- /* ldap_passwd */
- static PyObject *
- l_ldap_passwd( LDAPObject* self, PyObject *args )
- {
- struct berval user;
- Py_ssize_t user_len;
- struct berval oldpw;
- Py_ssize_t oldpw_len;
- struct berval newpw;
- Py_ssize_t newpw_len;
- PyObject *serverctrls = Py_None;
- PyObject *clientctrls = Py_None;
- LDAPControl** server_ldcs = NULL;
- LDAPControl** client_ldcs = NULL;
- int msgid;
- int ldaperror;
- if (!PyArg_ParseTuple( args, "z#z#z#|OO", &user.bv_val, &user_len, &oldpw.bv_val, &oldpw_len, &newpw.bv_val, &newpw_len, &serverctrls, &clientctrls ))
- return NULL;
- user.bv_len = (ber_len_t) user_len;
- oldpw.bv_len = (ber_len_t) oldpw_len;
- newpw.bv_len = (ber_len_t) newpw_len;
-
- if (not_valid(self)) return NULL;
- 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_passwd( self->ldap,
- user.bv_val != NULL ? &user : NULL,
- oldpw.bv_val != NULL ? &oldpw : NULL,
- newpw.bv_val != NULL ? &newpw : NULL,
- server_ldcs,
- client_ldcs,
- &msgid );
- LDAP_END_ALLOW_THREADS( self );
-
- LDAPControl_List_DEL( server_ldcs );
- LDAPControl_List_DEL( client_ldcs );
- if ( ldaperror!=LDAP_SUCCESS )
- return LDAPerror( self->ldap, "ldap_passwd" );
- return PyInt_FromLong( msgid );
- }
- /* methods */
- static PyMethodDef methods[] = {
- {"unbind_ext", (PyCFunction)l_ldap_unbind_ext, METH_VARARGS },
- {"abandon_ext", (PyCFunction)l_ldap_abandon_ext, METH_VARARGS },
- {"add_ext", (PyCFunction)l_ldap_add_ext, METH_VARARGS },
- {"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 },
- #endif
- {"compare_ext", (PyCFunction)l_ldap_compare_ext, METH_VARARGS },
- {"delete_ext", (PyCFunction)l_ldap_delete_ext, METH_VARARGS },
- {"modify_ext", (PyCFunction)l_ldap_modify_ext, METH_VARARGS },
- {"rename", (PyCFunction)l_ldap_rename, METH_VARARGS },
- {"result3", (PyCFunction)l_ldap_result3, METH_VARARGS },
- {"search_ext", (PyCFunction)l_ldap_search_ext, METH_VARARGS },
- #ifdef HAVE_TLS
- {"start_tls_s", (PyCFunction)l_ldap_start_tls_s, METH_VARARGS },
- #endif
- {"whoami_s", (PyCFunction)l_ldap_whoami_s, METH_VARARGS },
- {"passwd", (PyCFunction)l_ldap_passwd, METH_VARARGS },
- {"set_option", (PyCFunction)l_ldap_set_option, METH_VARARGS },
- {"get_option", (PyCFunction)l_ldap_get_option, METH_VARARGS },
- #ifdef LDAP_API_FEATURE_CANCEL
- {"cancel", (PyCFunction)l_ldap_cancel, METH_VARARGS },
- #endif
- { NULL, NULL }
- };
- /* get attribute */
- static PyObject*
- getattr(LDAPObject* self, char* name)
- {
- return Py_FindMethod(methods, (PyObject*)self, name);
- }
- /* set attribute */
- static int
- setattr(LDAPObject* self, char* name, PyObject* value)
- {
- PyErr_SetString(PyExc_AttributeError, name);
- return -1;
- }
- /* type entry */
- PyTypeObject LDAP_Type = {
- #if defined(MS_WINDOWS) || defined(__CYGWIN__)
- /* see http://www.python.org/doc/FAQ.html#3.24 */
- PyObject_HEAD_INIT(NULL)
- #else /* ! MS_WINDOWS */
- PyObject_HEAD_INIT(&PyType_Type)
- #endif /* MS_WINDOWS */
- 0, /*ob_size*/
- "LDAP", /*tp_name*/
- sizeof(LDAPObject), /*tp_basicsize*/
- 0, /*tp_itemsize*/
- /* methods */
- (destructor)dealloc, /*tp_dealloc*/
- 0, /*tp_print*/
- (getattrfunc)getattr, /*tp_getattr*/
- (setattrfunc)setattr, /*tp_setattr*/
- 0, /*tp_compare*/
- 0, /*tp_repr*/
- 0, /*tp_as_number*/
- 0, /*tp_as_sequence*/
- 0, /*tp_as_mapping*/
- 0, /*tp_hash*/
- };
|