Line data Source code
1 : /* See https://www.python-ldap.org/ for details. */
2 :
3 : #include "common.h"
4 : #include "patchlevel.h"
5 :
6 : #include <math.h>
7 : #include <limits.h>
8 : #include "constants.h"
9 : #include "LDAPObject.h"
10 : #include "ldapcontrol.h"
11 : #include "message.h"
12 : #include "berval.h"
13 : #include "options.h"
14 :
15 : #ifdef HAVE_SASL
16 : #include <sasl/sasl.h>
17 : #endif
18 :
19 : static void free_attrs(char***, PyObject*);
20 :
21 : /* constructor */
22 :
23 : LDAPObject*
24 108 : newLDAPObject( LDAP* l )
25 : {
26 108 : LDAPObject* self = (LDAPObject*) PyObject_NEW(LDAPObject, &LDAP_Type);
27 108 : if (self == NULL)
28 0 : return NULL;
29 108 : self->ldap = l;
30 108 : self->_save = NULL;
31 108 : self->valid = 1;
32 108 : return self;
33 : }
34 :
35 : /* destructor */
36 :
37 : static void
38 108 : dealloc( LDAPObject* self )
39 : {
40 108 : if (self->ldap) {
41 108 : if (self->valid) {
42 86 : LDAP_BEGIN_ALLOW_THREADS( self );
43 86 : ldap_unbind_ext( self->ldap, NULL, NULL );
44 86 : LDAP_END_ALLOW_THREADS( self );
45 86 : self->valid = 0;
46 : }
47 108 : self->ldap = NULL;
48 : }
49 108 : PyObject_DEL(self);
50 108 : }
51 :
52 : /*------------------------------------------------------------
53 : * utility functions
54 : */
55 :
56 : /*
57 : * check to see if the LDAPObject is valid,
58 : * ie has been opened, and not closed. An exception is set if not valid.
59 : */
60 :
61 : static int
62 425 : not_valid( LDAPObject* l ) {
63 425 : if (l->valid) {
64 423 : return 0;
65 : } else {
66 2 : PyErr_SetString( LDAPexception_class, "LDAP connection invalid" );
67 2 : return 1;
68 : }
69 : }
70 :
71 : /* free a LDAPMod (complete or partially) allocated in Tuple_to_LDAPMod() */
72 :
73 : static void
74 30 : LDAPMod_DEL( LDAPMod* lm )
75 : {
76 : Py_ssize_t i;
77 :
78 30 : if (lm->mod_type)
79 30 : PyMem_DEL(lm->mod_type);
80 30 : if (lm->mod_bvalues) {
81 61 : for (i = 0; lm->mod_bvalues[i]; i++) {
82 31 : PyMem_DEL(lm->mod_bvalues[i]);
83 : }
84 30 : PyMem_DEL(lm->mod_bvalues);
85 : }
86 30 : PyMem_DEL(lm);
87 30 : }
88 :
89 : /*
90 : * convert a tuple of the form (int,str,[str,...])
91 : * or (str, [str,...]) if no_op is true, into an LDAPMod structure.
92 : * See ldap_modify(3) for details.
93 : *
94 : * NOTE: the resulting LDAPMod structure has pointers directly into
95 : * the Python string storage, so LDAPMod structures MUST have a
96 : * shorter lifetime than the tuple passed in.
97 : */
98 :
99 : /* XXX - there is no way to pass complex-structured BER objects in here! */
100 :
101 : static LDAPMod*
102 30 : Tuple_to_LDAPMod( PyObject* tup, int no_op )
103 : {
104 : int op;
105 : char *type;
106 : PyObject *list, *item;
107 30 : LDAPMod *lm = NULL;
108 : Py_ssize_t i, len, nstrs;
109 :
110 30 : if (!PyTuple_Check(tup)) {
111 0 : LDAPerror_TypeError("expected a tuple", tup);
112 30 : return NULL;
113 : }
114 :
115 30 : if (no_op) {
116 25 : if (!PyArg_ParseTuple( tup, "sO", &type, &list ))
117 0 : return NULL;
118 25 : op = 0;
119 : } else {
120 5 : if (!PyArg_ParseTuple( tup, "isO", &op, &type, &list ))
121 0 : return NULL;
122 : }
123 :
124 30 : lm = PyMem_NEW(LDAPMod, 1);
125 30 : if (lm == NULL)
126 0 : goto nomem;
127 :
128 30 : lm->mod_op = op | LDAP_MOD_BVALUES;
129 30 : lm->mod_bvalues = NULL;
130 :
131 30 : len = strlen(type);
132 30 : lm->mod_type = PyMem_NEW(char, len + 1);
133 30 : if (lm->mod_type == NULL)
134 0 : goto nomem;
135 30 : memcpy(lm->mod_type, type, len + 1);
136 :
137 30 : if (list == Py_None) {
138 : /* None indicates a NULL mod_bvals */
139 30 : } else if (PyBytes_Check(list)) {
140 : /* Single string is a singleton list */
141 23 : lm->mod_bvalues = PyMem_NEW(struct berval *, 2);
142 23 : if (lm->mod_bvalues == NULL)
143 0 : goto nomem;
144 23 : lm->mod_bvalues[0] = PyMem_NEW(struct berval, 1);
145 23 : if (lm->mod_bvalues[0] == NULL)
146 0 : goto nomem;
147 23 : lm->mod_bvalues[1] = NULL;
148 23 : lm->mod_bvalues[0]->bv_len = PyBytes_Size(list);
149 23 : lm->mod_bvalues[0]->bv_val = PyBytes_AsString(list);
150 7 : } else if (PySequence_Check(list)) {
151 7 : nstrs = PySequence_Length(list);
152 7 : lm->mod_bvalues = PyMem_NEW(struct berval *, nstrs + 1);
153 7 : if (lm->mod_bvalues == NULL)
154 0 : goto nomem;
155 15 : for (i = 0; i < nstrs; i++) {
156 8 : lm->mod_bvalues[i] = PyMem_NEW(struct berval, 1);
157 8 : if (lm->mod_bvalues[i] == NULL)
158 0 : goto nomem;
159 8 : lm->mod_bvalues[i+1] = NULL;
160 8 : item = PySequence_GetItem(list, i);
161 8 : if (item == NULL)
162 0 : goto error;
163 8 : if (!PyBytes_Check(item)) {
164 0 : LDAPerror_TypeError("expected a byte string in the list", item);
165 0 : goto error;
166 : }
167 8 : lm->mod_bvalues[i]->bv_len = PyBytes_Size(item);
168 8 : lm->mod_bvalues[i]->bv_val = PyBytes_AsString(item);
169 8 : Py_DECREF(item);
170 : }
171 7 : if (nstrs == 0)
172 0 : lm->mod_bvalues[0] = NULL;
173 : }
174 :
175 30 : return lm;
176 :
177 0 : nomem:
178 0 : PyErr_NoMemory();
179 0 : error:
180 0 : if (lm)
181 0 : LDAPMod_DEL(lm);
182 :
183 0 : return NULL;
184 : }
185 :
186 : /* free the structure allocated in List_to_LDAPMods() */
187 :
188 : static void
189 15 : LDAPMods_DEL( LDAPMod** lms ) {
190 : LDAPMod** lmp;
191 45 : for ( lmp = lms; *lmp; lmp++ )
192 30 : LDAPMod_DEL( *lmp );
193 15 : PyMem_DEL(lms);
194 15 : }
195 :
196 : /*
197 : * convert a list of tuples into a LDAPMod*[] array structure
198 : * NOTE: list of tuples must live longer than the LDAPMods
199 : */
200 :
201 : static LDAPMod**
202 15 : List_to_LDAPMods( PyObject *list, int no_op ) {
203 :
204 : Py_ssize_t i, len;
205 : LDAPMod** lms;
206 : PyObject *item;
207 :
208 15 : if (!PySequence_Check(list)) {
209 0 : LDAPerror_TypeError("expected list of tuples", list);
210 0 : return NULL;
211 : }
212 :
213 15 : len = PySequence_Length(list);
214 :
215 15 : if (len < 0) {
216 0 : LDAPerror_TypeError("expected list of tuples", list);
217 0 : return NULL;
218 : }
219 :
220 15 : lms = PyMem_NEW(LDAPMod *, len + 1);
221 15 : if (lms == NULL)
222 0 : goto nomem;
223 :
224 45 : for (i = 0; i < len; i++) {
225 30 : lms[i] = NULL;
226 30 : item = PySequence_GetItem(list, i);
227 30 : if (item == NULL)
228 0 : goto error;
229 30 : lms[i] = Tuple_to_LDAPMod(item, no_op);
230 30 : Py_DECREF(item);
231 30 : if (lms[i] == NULL)
232 0 : goto error;
233 : }
234 15 : lms[len] = NULL;
235 15 : return lms;
236 :
237 0 : nomem:
238 0 : PyErr_NoMemory();
239 0 : error:
240 0 : if (lms)
241 0 : LDAPMods_DEL(lms);
242 0 : return NULL;
243 : }
244 :
245 : /*
246 : * convert a python list of strings into an attr list (char*[]).
247 : * returns 1 if successful, 0 if not (with exception set)
248 : */
249 :
250 : int
251 48 : attrs_from_List( PyObject *attrlist, char***attrsp, PyObject** seq) {
252 :
253 48 : char **attrs = NULL;
254 : Py_ssize_t i, len;
255 : PyObject *item;
256 :
257 48 : *seq = NULL;
258 :
259 48 : if (attrlist == Py_None) {
260 : /* None means a NULL attrlist */
261 : #if PY_MAJOR_VERSION == 2
262 : } else if (PyBytes_Check(attrlist)) {
263 : #else
264 23 : } else if (PyUnicode_Check(attrlist)) {
265 : #endif
266 : /* caught by John Benninghoff <johnb@netscape.com> */
267 0 : LDAPerror_TypeError(
268 : "expected *list* of strings, not a string", attrlist);
269 0 : goto error;
270 : } else {
271 23 : *seq = PySequence_Fast(attrlist, "expected list of strings or None");
272 23 : if (*seq == NULL)
273 0 : goto error;
274 :
275 23 : len = PySequence_Length(attrlist);
276 :
277 23 : attrs = PyMem_NEW(char *, len + 1);
278 23 : if (attrs == NULL)
279 0 : goto nomem;
280 :
281 61 : for (i = 0; i < len; i++) {
282 40 : attrs[i] = NULL;
283 40 : item = PySequence_Fast_GET_ITEM(*seq, i);
284 40 : if (item == NULL)
285 0 : goto error;
286 : #if PY_MAJOR_VERSION == 2
287 : /* Encoded by Python to UTF-8 */
288 : if (!PyBytes_Check(item)) {
289 : LDAPerror_TypeError("expected bytes in list", item);
290 : goto error;
291 : }
292 : attrs[i] = PyBytes_AsString(item);
293 : #else
294 40 : if (!PyUnicode_Check(item)) {
295 2 : LDAPerror_TypeError("expected string in list", item);
296 2 : goto error;
297 : }
298 38 : attrs[i] = PyUnicode_AsUTF8(item);
299 : #endif
300 : }
301 21 : attrs[len] = NULL;
302 : }
303 :
304 46 : *attrsp = attrs;
305 94 : return 1;
306 :
307 0 : nomem:
308 0 : PyErr_NoMemory();
309 2 : error:
310 2 : free_attrs(&attrs, *seq);
311 2 : return 0;
312 : }
313 :
314 : /* free memory allocated from above routine */
315 :
316 : static void
317 48 : free_attrs( char*** attrsp, PyObject* seq ) {
318 48 : char **attrs = *attrsp;
319 :
320 48 : if (attrs != NULL) {
321 23 : PyMem_DEL(attrs);
322 23 : *attrsp = NULL;
323 : }
324 :
325 48 : Py_XDECREF(seq);
326 48 : }
327 :
328 : /*------------------------------------------------------------
329 : * methods
330 : */
331 :
332 : /* ldap_unbind_ext */
333 :
334 : static PyObject*
335 25 : l_ldap_unbind_ext( LDAPObject* self, PyObject* args )
336 : {
337 25 : PyObject *serverctrls = Py_None;
338 25 : PyObject *clientctrls = Py_None;
339 25 : LDAPControl** server_ldcs = NULL;
340 25 : LDAPControl** client_ldcs = NULL;
341 :
342 : int ldaperror;
343 :
344 50 : if (!PyArg_ParseTuple( args, "|OO", &serverctrls, &clientctrls)) return NULL;
345 25 : if (not_valid(self)) return NULL;
346 :
347 24 : if (!PyNone_Check(serverctrls)) {
348 1 : if (!LDAPControls_from_object(serverctrls, &server_ldcs))
349 1 : return NULL;
350 : }
351 :
352 23 : if (!PyNone_Check(clientctrls)) {
353 1 : if (!LDAPControls_from_object(clientctrls, &client_ldcs)) {
354 1 : LDAPControl_List_DEL( server_ldcs );
355 1 : return NULL;
356 : }
357 : }
358 :
359 22 : LDAP_BEGIN_ALLOW_THREADS( self );
360 22 : ldaperror = ldap_unbind_ext( self->ldap, server_ldcs, client_ldcs );
361 22 : LDAP_END_ALLOW_THREADS( self );
362 :
363 22 : LDAPControl_List_DEL( server_ldcs );
364 22 : LDAPControl_List_DEL( client_ldcs );
365 :
366 22 : if ( ldaperror!=LDAP_SUCCESS )
367 0 : return LDAPerror( self->ldap, "ldap_unbind_ext" );
368 :
369 22 : self->valid = 0;
370 22 : Py_INCREF(Py_None);
371 22 : return Py_None;
372 : }
373 :
374 : /* ldap_abandon_ext */
375 :
376 : static PyObject*
377 5 : l_ldap_abandon_ext( LDAPObject* self, PyObject* args )
378 : {
379 : int msgid;
380 5 : PyObject *serverctrls = Py_None;
381 5 : PyObject *clientctrls = Py_None;
382 5 : LDAPControl** server_ldcs = NULL;
383 5 : LDAPControl** client_ldcs = NULL;
384 :
385 : int ldaperror;
386 :
387 10 : if (!PyArg_ParseTuple( args, "i|OO", &msgid, &serverctrls, &clientctrls)) return NULL;
388 5 : if (not_valid(self)) return NULL;
389 :
390 5 : if (!PyNone_Check(serverctrls)) {
391 1 : if (!LDAPControls_from_object(serverctrls, &server_ldcs))
392 1 : return NULL;
393 : }
394 :
395 4 : if (!PyNone_Check(clientctrls)) {
396 1 : if (!LDAPControls_from_object(clientctrls, &client_ldcs)) {
397 1 : LDAPControl_List_DEL( server_ldcs );
398 1 : return NULL;
399 : }
400 : }
401 :
402 3 : LDAP_BEGIN_ALLOW_THREADS( self );
403 3 : ldaperror = ldap_abandon_ext( self->ldap, msgid, server_ldcs, client_ldcs );
404 3 : LDAP_END_ALLOW_THREADS( self );
405 :
406 3 : LDAPControl_List_DEL( server_ldcs );
407 3 : LDAPControl_List_DEL( client_ldcs );
408 :
409 3 : if ( ldaperror!=LDAP_SUCCESS )
410 0 : return LDAPerror( self->ldap, "ldap_abandon_ext" );
411 :
412 3 : Py_INCREF(Py_None);
413 3 : return Py_None;
414 : }
415 :
416 : /* ldap_add_ext */
417 :
418 : static PyObject *
419 10 : l_ldap_add_ext( LDAPObject* self, PyObject *args )
420 : {
421 : char *dn;
422 : PyObject *modlist;
423 10 : PyObject *serverctrls = Py_None;
424 10 : PyObject *clientctrls = Py_None;
425 10 : LDAPControl** server_ldcs = NULL;
426 10 : LDAPControl** client_ldcs = NULL;
427 :
428 : int msgid;
429 : int ldaperror;
430 : LDAPMod **mods;
431 :
432 20 : if (!PyArg_ParseTuple( args, "sO|OO", &dn, &modlist, &serverctrls, &clientctrls )) return NULL;
433 10 : if (not_valid(self)) return NULL;
434 :
435 10 : mods = List_to_LDAPMods( modlist, 1 );
436 10 : if (mods == NULL)
437 0 : return NULL;
438 :
439 10 : if (!PyNone_Check(serverctrls)) {
440 1 : if (!LDAPControls_from_object(serverctrls, &server_ldcs)) {
441 1 : LDAPMods_DEL( mods );
442 1 : return NULL;
443 : }
444 : }
445 :
446 9 : if (!PyNone_Check(clientctrls)) {
447 1 : if (!LDAPControls_from_object(clientctrls, &client_ldcs)) {
448 1 : LDAPMods_DEL( mods );
449 1 : LDAPControl_List_DEL( server_ldcs );
450 1 : return NULL;
451 : }
452 : }
453 :
454 8 : LDAP_BEGIN_ALLOW_THREADS( self );
455 8 : ldaperror = ldap_add_ext( self->ldap, dn, mods, server_ldcs, client_ldcs, &msgid);
456 8 : LDAP_END_ALLOW_THREADS( self );
457 8 : LDAPMods_DEL( mods );
458 8 : LDAPControl_List_DEL( server_ldcs );
459 8 : LDAPControl_List_DEL( client_ldcs );
460 :
461 8 : if ( ldaperror!=LDAP_SUCCESS )
462 0 : return LDAPerror( self->ldap, "ldap_add_ext" );
463 :
464 8 : return PyInt_FromLong(msgid);
465 : }
466 :
467 : /* ldap_simple_bind */
468 :
469 : static PyObject*
470 95 : l_ldap_simple_bind( LDAPObject* self, PyObject* args )
471 : {
472 : char *who;
473 : int msgid;
474 : int ldaperror;
475 : Py_ssize_t cred_len;
476 95 : PyObject *serverctrls = Py_None;
477 95 : PyObject *clientctrls = Py_None;
478 95 : LDAPControl** server_ldcs = NULL;
479 95 : LDAPControl** client_ldcs = NULL;
480 : struct berval cred;
481 :
482 190 : if (!PyArg_ParseTuple( args, "ss#|OO", &who, &cred.bv_val, &cred_len, &serverctrls, &clientctrls )) return NULL;
483 94 : cred.bv_len = (ber_len_t) cred_len;
484 :
485 94 : if (not_valid(self)) return NULL;
486 :
487 94 : if (!PyNone_Check(serverctrls)) {
488 1 : if (!LDAPControls_from_object(serverctrls, &server_ldcs))
489 1 : return NULL;
490 : }
491 :
492 93 : if (!PyNone_Check(clientctrls)) {
493 1 : if (!LDAPControls_from_object(clientctrls, &client_ldcs)) {
494 1 : LDAPControl_List_DEL( server_ldcs );
495 1 : return NULL;
496 : }
497 : }
498 :
499 92 : LDAP_BEGIN_ALLOW_THREADS( self );
500 92 : ldaperror = ldap_sasl_bind( self->ldap, who, LDAP_SASL_SIMPLE, &cred, server_ldcs, client_ldcs, &msgid);
501 92 : LDAP_END_ALLOW_THREADS( self );
502 :
503 92 : LDAPControl_List_DEL( server_ldcs );
504 92 : LDAPControl_List_DEL( client_ldcs );
505 :
506 92 : if ( ldaperror!=LDAP_SUCCESS )
507 4 : return LDAPerror( self->ldap, "ldap_simple_bind" );
508 :
509 88 : return PyInt_FromLong( msgid );
510 : }
511 :
512 :
513 : #ifdef HAVE_SASL
514 : /* The following functions implement SASL binds. A new method
515 : sasl_interactive_bind_s(bind_dn, sasl_mechanism) has been introduced.
516 :
517 : * The bind_dn argument will be passed to the c library; however,
518 : normally it is not needed and should be an empty string.
519 :
520 : * The sasl_mechanism argument is an instance of a class that
521 : implements a callback interface. For convenience, it should be
522 : derived from the sasl class (which lives in the ldap.sasl module).
523 : See the module documentation for more information.
524 :
525 : Check your /usr/lib/sasl/ directory for locally installed SASL
526 : auth modules ("mechanisms"), or try
527 :
528 : ldapsearch -b "" -s base -LLL -x supportedSASLMechanisms
529 :
530 : (perhaps with an additional -h and -p argument for ldap host and
531 : port). The latter will show you which SASL mechanisms are known
532 : to the LDAP server. If you do not want to set up Kerberos, you
533 : can still use SASL binds. Your authentication data should then be
534 : stored in /etc/sasldb (see saslpasswd(8)). If the LDAP server
535 : does not find the sasldb, it wont allow for DIGEST-MD5 and
536 : CRAM-MD5. One important thing to get started with sasldb: you
537 : should first add a dummy user (saslpasswd -c dummy), and this
538 : will give you some strange error messages. Then delete the dummy
539 : user (saslpasswd -d dummy), and now you can start adding users to
540 : your sasldb (again, use the -c switch). Strange, eh?
541 :
542 : * The sasl_mechanism object must implement a method, which will be
543 : called by the sasl lib several times. The prototype of the
544 : callback looks like this: callback(id, challenge, prompt,
545 : defresult) has to return a string (or maybe None). The id
546 : argument specifies, which information should be passed back to
547 : the SASL lib (see SASL_CB_xxx in sasl.h)
548 : */
549 9 : static int interaction ( unsigned flags,
550 : sasl_interact_t *interact,
551 : PyObject* SASLObject )
552 : {
553 : /* const char *dflt = interact->defresult; */
554 : PyObject *result;
555 : char *c_result;
556 9 : result = PyObject_CallMethod(SASLObject,
557 : "callback",
558 : "isss",
559 : interact->id, /* see sasl.h */
560 : interact->challenge,
561 : interact->prompt,
562 : interact->defresult);
563 :
564 9 : if (result == NULL)
565 : /*searching for a better error code */
566 0 : return LDAP_OPERATIONS_ERROR;
567 9 : c_result = PyBytes_AsString(result); /*xxx Error checking?? */
568 :
569 : /* according to the sasl docs, we should malloc() the returned
570 : string only for calls where interact->id == SASL_CB_PASS, so we
571 : probably leak a few bytes per ldap bind. However, if I restrict
572 : the strdup() to this case, I get segfaults. Should probably be
573 : fixed sometimes.
574 : */
575 9 : interact->result = strdup( c_result );
576 9 : if (interact->result == NULL)
577 0 : return LDAP_OPERATIONS_ERROR;
578 9 : interact->len = strlen(c_result);
579 : /* We _should_ overwrite the python string buffer for security
580 : reasons, however we may not (api/stringObjects.html). Any ideas?
581 : */
582 :
583 9 : Py_DECREF(result); /*not needed any longer */
584 9 : result = NULL;
585 :
586 9 : return LDAP_SUCCESS;
587 : }
588 :
589 :
590 : /*
591 : This function will be called by ldap_sasl_interactive_bind(). The
592 : "*in" is an array of sasl_interact_t's (see sasl.h for a
593 : reference). The last interact in the array has an interact->id of
594 : SASL_CB_LIST_END.
595 :
596 : */
597 :
598 9 : int py_ldap_sasl_interaction( LDAP *ld,
599 : unsigned flags,
600 : void *defaults,
601 : void *in )
602 : {
603 : /* These are just typecasts */
604 9 : sasl_interact_t *interact = (sasl_interact_t *) in;
605 9 : PyObject *SASLObject = (PyObject *) defaults;
606 : /* Loop over the array of sasl_interact_t structs */
607 27 : while( interact->id != SASL_CB_LIST_END ) {
608 9 : int rc = 0;
609 9 : rc = interaction( flags, interact, SASLObject );
610 9 : if( rc ) return rc;
611 9 : interact++;
612 : }
613 9 : return LDAP_SUCCESS;
614 : }
615 :
616 : static PyObject*
617 2 : l_ldap_sasl_bind_s( LDAPObject* self, PyObject* args )
618 : {
619 : const char *dn;
620 : const char *mechanism;
621 : struct berval cred;
622 : Py_ssize_t cred_len;
623 :
624 2 : PyObject *serverctrls = Py_None;
625 2 : PyObject *clientctrls = Py_None;
626 2 : LDAPControl** server_ldcs = NULL;
627 2 : LDAPControl** client_ldcs = NULL;
628 :
629 : struct berval *servercred;
630 : int ldaperror;
631 :
632 2 : if (!PyArg_ParseTuple(args, "zzz#OO", &dn, &mechanism, &cred.bv_val, &cred_len, &serverctrls, &clientctrls ))
633 2 : return NULL;
634 :
635 2 : if (not_valid(self)) return NULL;
636 :
637 2 : cred.bv_len = cred_len;
638 :
639 2 : if (!PyNone_Check(serverctrls)) {
640 1 : if (!LDAPControls_from_object(serverctrls, &server_ldcs))
641 1 : return NULL;
642 : }
643 1 : if (!PyNone_Check(clientctrls)) {
644 1 : if (!LDAPControls_from_object(clientctrls, &client_ldcs)) {
645 1 : LDAPControl_List_DEL( server_ldcs );
646 1 : return NULL;
647 : }
648 : }
649 :
650 0 : LDAP_BEGIN_ALLOW_THREADS( self );
651 0 : ldaperror = ldap_sasl_bind_s(self->ldap,
652 : dn,
653 : mechanism,
654 0 : cred.bv_val ? &cred : NULL,
655 : (LDAPControl**) server_ldcs,
656 : (LDAPControl**) client_ldcs,
657 : &servercred);
658 0 : LDAP_END_ALLOW_THREADS( self );
659 :
660 0 : LDAPControl_List_DEL( server_ldcs );
661 0 : LDAPControl_List_DEL( client_ldcs );
662 :
663 0 : if (ldaperror == LDAP_SASL_BIND_IN_PROGRESS) {
664 0 : if (servercred && servercred->bv_val && *servercred->bv_val)
665 0 : return PyBytes_FromStringAndSize( servercred->bv_val, servercred->bv_len );
666 0 : } else if (ldaperror != LDAP_SUCCESS)
667 0 : return LDAPerror( self->ldap, "l_ldap_sasl_bind_s" );
668 0 : return PyInt_FromLong( ldaperror );
669 : }
670 :
671 : static PyObject*
672 11 : l_ldap_sasl_interactive_bind_s( LDAPObject* self, PyObject* args )
673 : {
674 : char *c_mechanism;
675 : char *who;
676 :
677 11 : PyObject *serverctrls = Py_None;
678 11 : PyObject *clientctrls = Py_None;
679 11 : LDAPControl** server_ldcs = NULL;
680 11 : LDAPControl** client_ldcs = NULL;
681 :
682 11 : PyObject *SASLObject = NULL;
683 11 : PyObject *mechanism = NULL;
684 : int msgid;
685 :
686 : static unsigned sasl_flags = LDAP_SASL_QUIET;
687 :
688 : /*
689 : * In Python 2.3+, a "I" format argument indicates that we're either converting
690 : * the Python object into a long or an unsigned int. In versions prior to that,
691 : * it will always convert to a long. Since the sasl_flags variable is an
692 : * unsigned int, we need to use the "I" flag if we're running Python 2.3+ and a
693 : * "i" otherwise.
694 : */
695 : #if (PY_MAJOR_VERSION == 2) && (PY_MINOR_VERSION < 3)
696 : if (!PyArg_ParseTuple(args, "sOOOi", &who, &SASLObject, &serverctrls, &clientctrls, &sasl_flags ))
697 : #else
698 11 : if (!PyArg_ParseTuple(args, "sOOOI", &who, &SASLObject, &serverctrls, &clientctrls, &sasl_flags ))
699 : #endif
700 11 : return NULL;
701 :
702 11 : if (not_valid(self)) return NULL;
703 :
704 11 : if (!PyNone_Check(serverctrls)) {
705 1 : if (!LDAPControls_from_object(serverctrls, &server_ldcs))
706 1 : return NULL;
707 : }
708 :
709 10 : if (!PyNone_Check(clientctrls)) {
710 1 : if (!LDAPControls_from_object(clientctrls, &client_ldcs)) {
711 1 : LDAPControl_List_DEL( server_ldcs );
712 1 : return NULL;
713 : }
714 : }
715 :
716 : /* now we extract the sasl mechanism from the SASL Object */
717 9 : mechanism = PyObject_GetAttrString(SASLObject, "mech");
718 9 : if (mechanism == NULL) return NULL;
719 9 : c_mechanism = PyBytes_AsString(mechanism);
720 9 : Py_DECREF(mechanism);
721 9 : mechanism = NULL;
722 :
723 : /* Don't know if it is the "intended use" of the defaults
724 : parameter of ldap_sasl_interactive_bind_s when we pass the
725 : Python object SASLObject, but passing it through some
726 : static variable would destroy thread safety, IMHO.
727 : */
728 9 : msgid = ldap_sasl_interactive_bind_s(self->ldap,
729 : who,
730 : c_mechanism,
731 : (LDAPControl**) server_ldcs,
732 : (LDAPControl**) client_ldcs,
733 : sasl_flags,
734 : py_ldap_sasl_interaction,
735 : SASLObject);
736 :
737 9 : LDAPControl_List_DEL( server_ldcs );
738 9 : LDAPControl_List_DEL( client_ldcs );
739 :
740 9 : if (msgid != LDAP_SUCCESS)
741 1 : return LDAPerror( self->ldap, "ldap_sasl_interactive_bind_s" );
742 8 : return PyInt_FromLong( msgid );
743 : }
744 : #endif
745 :
746 :
747 : #ifdef LDAP_API_FEATURE_CANCEL
748 :
749 : /* ldap_cancel */
750 :
751 : static PyObject*
752 3 : l_ldap_cancel( LDAPObject* self, PyObject* args )
753 : {
754 : int msgid;
755 : int cancelid;
756 3 : PyObject *serverctrls = Py_None;
757 3 : PyObject *clientctrls = Py_None;
758 3 : LDAPControl** server_ldcs = NULL;
759 3 : LDAPControl** client_ldcs = NULL;
760 :
761 : int ldaperror;
762 :
763 6 : if (!PyArg_ParseTuple( args, "i|OO", &cancelid, &serverctrls, &clientctrls)) return NULL;
764 3 : if (not_valid(self)) return NULL;
765 :
766 3 : if (!PyNone_Check(serverctrls)) {
767 1 : if (!LDAPControls_from_object(serverctrls, &server_ldcs))
768 1 : return NULL;
769 : }
770 :
771 2 : if (!PyNone_Check(clientctrls)) {
772 1 : if (!LDAPControls_from_object(clientctrls, &client_ldcs)) {
773 1 : LDAPControl_List_DEL( server_ldcs );
774 1 : return NULL;
775 : }
776 : }
777 :
778 1 : LDAP_BEGIN_ALLOW_THREADS( self );
779 1 : ldaperror = ldap_cancel( self->ldap, cancelid, server_ldcs, client_ldcs, &msgid );
780 1 : LDAP_END_ALLOW_THREADS( self );
781 :
782 1 : LDAPControl_List_DEL( server_ldcs );
783 1 : LDAPControl_List_DEL( client_ldcs );
784 :
785 1 : if ( ldaperror!=LDAP_SUCCESS )
786 0 : return LDAPerror( self->ldap, "ldap_cancel" );
787 :
788 1 : return PyInt_FromLong( msgid );
789 : }
790 :
791 : #endif
792 :
793 : /* ldap_compare_ext */
794 :
795 : static PyObject *
796 5 : l_ldap_compare_ext( LDAPObject* self, PyObject *args )
797 : {
798 : char *dn, *attr;
799 5 : PyObject *serverctrls = Py_None;
800 5 : PyObject *clientctrls = Py_None;
801 5 : LDAPControl** server_ldcs = NULL;
802 5 : LDAPControl** client_ldcs = NULL;
803 :
804 : int msgid;
805 : int ldaperror;
806 : Py_ssize_t value_len;
807 : struct berval value;
808 :
809 10 : if (!PyArg_ParseTuple( args, "sss#|OO", &dn, &attr, &value.bv_val, &value_len, &serverctrls, &clientctrls )) return NULL;
810 5 : value.bv_len = (ber_len_t) value_len;
811 :
812 5 : if (not_valid(self)) return NULL;
813 :
814 5 : if (!PyNone_Check(serverctrls)) {
815 1 : if (!LDAPControls_from_object(serverctrls, &server_ldcs))
816 1 : return NULL;
817 : }
818 :
819 4 : if (!PyNone_Check(clientctrls)) {
820 1 : if (!LDAPControls_from_object(clientctrls, &client_ldcs)) {
821 1 : LDAPControl_List_DEL( server_ldcs );
822 1 : return NULL;
823 : }
824 : }
825 :
826 3 : LDAP_BEGIN_ALLOW_THREADS( self );
827 3 : ldaperror = ldap_compare_ext( self->ldap, dn, attr, &value, server_ldcs, client_ldcs, &msgid );
828 3 : LDAP_END_ALLOW_THREADS( self );
829 :
830 3 : LDAPControl_List_DEL( server_ldcs );
831 3 : LDAPControl_List_DEL( client_ldcs );
832 :
833 3 : if ( ldaperror!=LDAP_SUCCESS )
834 0 : return LDAPerror( self->ldap, "ldap_compare_ext" );
835 :
836 3 : return PyInt_FromLong( msgid );
837 : }
838 :
839 :
840 : /* ldap_delete_ext */
841 :
842 : static PyObject *
843 5 : l_ldap_delete_ext( LDAPObject* self, PyObject *args )
844 : {
845 : char *dn;
846 5 : PyObject *serverctrls = Py_None;
847 5 : PyObject *clientctrls = Py_None;
848 5 : LDAPControl** server_ldcs = NULL;
849 5 : LDAPControl** client_ldcs = NULL;
850 :
851 : int msgid;
852 : int ldaperror;
853 :
854 10 : if (!PyArg_ParseTuple( args, "s|OO", &dn, &serverctrls, &clientctrls )) return NULL;
855 5 : if (not_valid(self)) return NULL;
856 :
857 5 : if (!PyNone_Check(serverctrls)) {
858 1 : if (!LDAPControls_from_object(serverctrls, &server_ldcs))
859 1 : return NULL;
860 : }
861 :
862 4 : if (!PyNone_Check(clientctrls)) {
863 1 : if (!LDAPControls_from_object(clientctrls, &client_ldcs)) {
864 1 : LDAPControl_List_DEL( server_ldcs );
865 1 : return NULL;
866 : }
867 : }
868 :
869 3 : LDAP_BEGIN_ALLOW_THREADS( self );
870 3 : ldaperror = ldap_delete_ext( self->ldap, dn, server_ldcs, client_ldcs, &msgid );
871 3 : LDAP_END_ALLOW_THREADS( self );
872 :
873 3 : LDAPControl_List_DEL( server_ldcs );
874 3 : LDAPControl_List_DEL( client_ldcs );
875 :
876 3 : if ( ldaperror!=LDAP_SUCCESS )
877 0 : return LDAPerror( self->ldap, "ldap_delete_ext" );
878 :
879 3 : return PyInt_FromLong(msgid);
880 : }
881 :
882 :
883 : /* ldap_modify_ext */
884 :
885 : static PyObject *
886 5 : l_ldap_modify_ext( LDAPObject* self, PyObject *args )
887 : {
888 : char *dn;
889 : PyObject *modlist;
890 5 : PyObject *serverctrls = Py_None;
891 5 : PyObject *clientctrls = Py_None;
892 5 : LDAPControl** server_ldcs = NULL;
893 5 : LDAPControl** client_ldcs = NULL;
894 :
895 : int msgid;
896 : int ldaperror;
897 : LDAPMod **mods;
898 :
899 10 : if (!PyArg_ParseTuple( args, "sO|OO", &dn, &modlist, &serverctrls, &clientctrls )) return NULL;
900 5 : if (not_valid(self)) return NULL;
901 :
902 5 : mods = List_to_LDAPMods( modlist, 0 );
903 5 : if (mods == NULL)
904 0 : return NULL;
905 :
906 5 : if (!PyNone_Check(serverctrls)) {
907 1 : if (!LDAPControls_from_object(serverctrls, &server_ldcs)) {
908 1 : LDAPMods_DEL( mods );
909 1 : return NULL;
910 : }
911 : }
912 :
913 4 : if (!PyNone_Check(clientctrls)) {
914 1 : if (!LDAPControls_from_object(clientctrls, &client_ldcs)) {
915 1 : LDAPMods_DEL( mods );
916 1 : LDAPControl_List_DEL( server_ldcs );
917 1 : return NULL;
918 : }
919 : }
920 :
921 3 : LDAP_BEGIN_ALLOW_THREADS( self );
922 3 : ldaperror = ldap_modify_ext( self->ldap, dn, mods, server_ldcs, client_ldcs, &msgid );
923 3 : LDAP_END_ALLOW_THREADS( self );
924 :
925 3 : LDAPMods_DEL( mods );
926 3 : LDAPControl_List_DEL( server_ldcs );
927 3 : LDAPControl_List_DEL( client_ldcs );
928 :
929 3 : if ( ldaperror!=LDAP_SUCCESS )
930 0 : return LDAPerror( self->ldap, "ldap_modify_ext" );
931 :
932 3 : return PyInt_FromLong( msgid );
933 : }
934 :
935 :
936 : /* ldap_rename */
937 :
938 : static PyObject *
939 4 : l_ldap_rename( LDAPObject* self, PyObject *args )
940 : {
941 : char *dn, *newrdn;
942 4 : char *newSuperior = NULL;
943 4 : int delold = 1;
944 4 : PyObject *serverctrls = Py_None;
945 4 : PyObject *clientctrls = Py_None;
946 4 : LDAPControl** server_ldcs = NULL;
947 4 : LDAPControl** client_ldcs = NULL;
948 :
949 : int msgid;
950 : int ldaperror;
951 :
952 4 : if (!PyArg_ParseTuple( args, "ss|ziOO", &dn, &newrdn, &newSuperior, &delold, &serverctrls, &clientctrls ))
953 4 : return NULL;
954 4 : if (not_valid(self)) return NULL;
955 :
956 4 : if (!PyNone_Check(serverctrls)) {
957 1 : if (!LDAPControls_from_object(serverctrls, &server_ldcs))
958 1 : return NULL;
959 : }
960 :
961 3 : if (!PyNone_Check(clientctrls)) {
962 1 : if (!LDAPControls_from_object(clientctrls, &client_ldcs)) {
963 1 : LDAPControl_List_DEL( server_ldcs );
964 1 : return NULL;
965 : }
966 : }
967 :
968 2 : LDAP_BEGIN_ALLOW_THREADS( self );
969 2 : ldaperror = ldap_rename( self->ldap, dn, newrdn, newSuperior, delold, server_ldcs, client_ldcs, &msgid );
970 2 : LDAP_END_ALLOW_THREADS( self );
971 :
972 2 : LDAPControl_List_DEL( server_ldcs );
973 2 : LDAPControl_List_DEL( client_ldcs );
974 :
975 2 : if ( ldaperror!=LDAP_SUCCESS )
976 0 : return LDAPerror( self->ldap, "ldap_rename" );
977 :
978 2 : return PyInt_FromLong( msgid );
979 : }
980 :
981 :
982 : /* ldap_result4 */
983 :
984 : static PyObject *
985 177 : l_ldap_result4( LDAPObject* self, PyObject *args )
986 : {
987 177 : int msgid = LDAP_RES_ANY;
988 177 : int all = 1;
989 177 : double timeout = -1.0;
990 177 : int add_ctrls = 0;
991 177 : int add_intermediates = 0;
992 177 : int add_extop = 0;
993 : struct timeval tv;
994 : struct timeval* tvp;
995 : int res_type;
996 177 : LDAPMessage *msg = NULL;
997 177 : PyObject *result_str, *retval, *pmsg, *pyctrls = 0;
998 177 : int res_msgid = 0;
999 177 : char *retoid = 0;
1000 177 : PyObject *valuestr = NULL;
1001 177 : int result = LDAP_SUCCESS;
1002 177 : char **refs = NULL;
1003 177 : LDAPControl **serverctrls = 0;
1004 :
1005 177 : if (!PyArg_ParseTuple( args, "|iidiii", &msgid, &all, &timeout, &add_ctrls, &add_intermediates, &add_extop ))
1006 177 : return NULL;
1007 177 : if (not_valid(self)) return NULL;
1008 :
1009 177 : if (timeout >= 0) {
1010 58 : tvp = &tv;
1011 58 : set_timeval_from_double( tvp, timeout );
1012 : } else {
1013 119 : tvp = NULL;
1014 : }
1015 :
1016 177 : LDAP_BEGIN_ALLOW_THREADS( self );
1017 177 : res_type = ldap_result( self->ldap, msgid, all, tvp, &msg );
1018 177 : LDAP_END_ALLOW_THREADS( self );
1019 :
1020 177 : if (res_type < 0) /* LDAP or system error */
1021 0 : return LDAPerror( self->ldap, "ldap_result4" );
1022 :
1023 177 : if (res_type == 0) {
1024 : /* Polls return (None, None, None, None); timeouts raise an exception */
1025 4 : if (timeout == 0) {
1026 0 : if (add_extop) {
1027 0 : return Py_BuildValue("(OOOOOO)", Py_None, Py_None, Py_None, Py_None, Py_None, Py_None);
1028 : } else {
1029 0 : return Py_BuildValue("(OOOO)", Py_None, Py_None, Py_None, Py_None);
1030 : }
1031 : }
1032 : else
1033 4 : return LDAPerr(LDAP_TIMEOUT);
1034 : }
1035 :
1036 173 : if (msg)
1037 173 : res_msgid = ldap_msgid(msg);
1038 :
1039 173 : if (res_type == LDAP_RES_SEARCH_ENTRY) {
1040 : /* LDAPmessage_to_python will parse entries and read the controls for each entry */
1041 144 : } else if (res_type == LDAP_RES_SEARCH_REFERENCE) {
1042 : /* LDAPmessage_to_python will parse refs and read the controls for each res */
1043 144 : } else if (res_type == LDAP_RES_INTERMEDIATE) {
1044 : /* LDAPmessage_to_python will parse intermediates and controls */
1045 : } else {
1046 : int rc;
1047 141 : if (res_type == LDAP_RES_EXTENDED) {
1048 2 : struct berval *retdata = 0;
1049 2 : LDAP_BEGIN_ALLOW_THREADS( self );
1050 2 : rc = ldap_parse_extended_result( self->ldap, msg, &retoid, &retdata, 0 );
1051 2 : LDAP_END_ALLOW_THREADS( self );
1052 : /* handle error rc!=0 here? */
1053 2 : if (rc == LDAP_SUCCESS) {
1054 2 : valuestr = LDAPberval_to_object(retdata);
1055 : }
1056 2 : ber_bvfree( retdata );
1057 : }
1058 :
1059 141 : LDAP_BEGIN_ALLOW_THREADS( self );
1060 141 : rc = ldap_parse_result( self->ldap, msg, &result, NULL, NULL, &refs,
1061 : &serverctrls, 0 );
1062 141 : LDAP_END_ALLOW_THREADS( self );
1063 : }
1064 :
1065 173 : if (result != LDAP_SUCCESS) { /* result error */
1066 : char *e, err[1024];
1067 15 : if (result == LDAP_REFERRAL && refs && refs[0]) {
1068 0 : snprintf(err, sizeof(err), "Referral:\n%s", refs[0]);
1069 0 : e = err;
1070 : } else
1071 15 : e = "ldap_parse_result";
1072 15 : ldap_msgfree(msg);
1073 15 : Py_XDECREF(valuestr);
1074 15 : return LDAPerror( self->ldap, e );
1075 : }
1076 :
1077 158 : if (!(pyctrls = LDAPControls_to_List(serverctrls))) {
1078 0 : int err = LDAP_NO_MEMORY;
1079 0 : LDAP_BEGIN_ALLOW_THREADS( self );
1080 0 : ldap_set_option(self->ldap, LDAP_OPT_ERROR_NUMBER, &err);
1081 0 : LDAP_END_ALLOW_THREADS( self );
1082 0 : ldap_msgfree(msg);
1083 0 : Py_XDECREF(valuestr);
1084 0 : return LDAPerror(self->ldap, "LDAPControls_to_List");
1085 : }
1086 158 : ldap_controls_free(serverctrls);
1087 :
1088 158 : pmsg = LDAPmessage_to_python( self->ldap, msg, add_ctrls, add_intermediates );
1089 :
1090 158 : if (res_type == 0) {
1091 0 : result_str = Py_None;
1092 0 : Py_INCREF(Py_None);
1093 : } else {
1094 158 : result_str = PyInt_FromLong( res_type );
1095 : }
1096 :
1097 158 : if (pmsg == NULL) {
1098 0 : retval = NULL;
1099 : } else {
1100 : /* s handles NULL, but O does not */
1101 158 : if (add_extop) {
1102 0 : retval = Py_BuildValue("(OOiOsO)", result_str, pmsg, res_msgid,
1103 : pyctrls, retoid, valuestr ? valuestr : Py_None);
1104 : } else {
1105 158 : retval = Py_BuildValue("(OOiO)", result_str, pmsg, res_msgid, pyctrls);
1106 : }
1107 :
1108 158 : if (pmsg != Py_None) {
1109 158 : Py_DECREF(pmsg);
1110 : }
1111 : }
1112 158 : Py_XDECREF(valuestr);
1113 158 : Py_XDECREF(pyctrls);
1114 158 : Py_DECREF(result_str);
1115 158 : return retval;
1116 : }
1117 :
1118 :
1119 : /* ldap_search_ext */
1120 :
1121 : static PyObject*
1122 52 : l_ldap_search_ext( LDAPObject* self, PyObject* args )
1123 : {
1124 : char *base;
1125 : int scope;
1126 : char *filter;
1127 52 : PyObject *attrlist = Py_None;
1128 : char **attrs;
1129 52 : int attrsonly = 0;
1130 :
1131 52 : PyObject *serverctrls = Py_None;
1132 52 : PyObject *clientctrls = Py_None;
1133 52 : PyObject *attrs_seq = NULL;
1134 52 : LDAPControl** server_ldcs = NULL;
1135 52 : LDAPControl** client_ldcs = NULL;
1136 :
1137 52 : double timeout = -1.0;
1138 : struct timeval tv;
1139 : struct timeval* tvp;
1140 :
1141 52 : int sizelimit = 0;
1142 :
1143 : int msgid;
1144 : int ldaperror;
1145 :
1146 52 : if (!PyArg_ParseTuple( args, "sis|OiOOdi",
1147 : &base, &scope, &filter, &attrlist, &attrsonly,
1148 56 : &serverctrls, &clientctrls, &timeout, &sizelimit )) return NULL;
1149 48 : if (not_valid(self)) return NULL;
1150 :
1151 48 : if (!attrs_from_List( attrlist, &attrs, &attrs_seq ))
1152 2 : return NULL;
1153 :
1154 46 : if (timeout >= 0) {
1155 0 : tvp = &tv;
1156 0 : set_timeval_from_double( tvp, timeout );
1157 : } else {
1158 46 : tvp = NULL;
1159 : }
1160 :
1161 46 : if (!PyNone_Check(serverctrls)) {
1162 7 : if (!LDAPControls_from_object(serverctrls, &server_ldcs)) {
1163 1 : free_attrs( &attrs, attrs_seq);
1164 1 : return NULL;
1165 : }
1166 : }
1167 :
1168 45 : if (!PyNone_Check(clientctrls)) {
1169 1 : if (!LDAPControls_from_object(clientctrls, &client_ldcs)) {
1170 1 : free_attrs( &attrs, attrs_seq);
1171 1 : LDAPControl_List_DEL( server_ldcs );
1172 1 : return NULL;
1173 : }
1174 : }
1175 :
1176 44 : LDAP_BEGIN_ALLOW_THREADS( self );
1177 44 : ldaperror = ldap_search_ext( self->ldap, base, scope, filter, attrs, attrsonly,
1178 : server_ldcs, client_ldcs, tvp, sizelimit, &msgid );
1179 44 : LDAP_END_ALLOW_THREADS( self );
1180 :
1181 44 : free_attrs( &attrs, attrs_seq);
1182 44 : LDAPControl_List_DEL( server_ldcs );
1183 44 : LDAPControl_List_DEL( client_ldcs );
1184 :
1185 44 : if ( ldaperror!=LDAP_SUCCESS )
1186 2 : return LDAPerror( self->ldap, "ldap_search_ext" );
1187 :
1188 42 : return PyInt_FromLong( msgid );
1189 : }
1190 :
1191 :
1192 : /* ldap_whoami_s (available since OpenLDAP 2.1.13) */
1193 :
1194 : static PyObject*
1195 21 : l_ldap_whoami_s( LDAPObject* self, PyObject* args )
1196 : {
1197 21 : PyObject *serverctrls = Py_None;
1198 21 : PyObject *clientctrls = Py_None;
1199 21 : LDAPControl** server_ldcs = NULL;
1200 21 : LDAPControl** client_ldcs = NULL;
1201 :
1202 21 : struct berval *bvalue = NULL;
1203 :
1204 : PyObject *result;
1205 :
1206 : int ldaperror;
1207 :
1208 42 : if (!PyArg_ParseTuple( args, "|OO", &serverctrls, &clientctrls)) return NULL;
1209 21 : if (not_valid(self)) return NULL;
1210 :
1211 20 : if (!PyNone_Check(serverctrls)) {
1212 1 : if (!LDAPControls_from_object(serverctrls, &server_ldcs))
1213 1 : return NULL;
1214 : }
1215 :
1216 19 : if (!PyNone_Check(clientctrls)) {
1217 1 : if (!LDAPControls_from_object(clientctrls, &client_ldcs)) {
1218 1 : LDAPControl_List_DEL( server_ldcs );
1219 1 : return NULL;
1220 : }
1221 : }
1222 :
1223 18 : LDAP_BEGIN_ALLOW_THREADS( self );
1224 18 : ldaperror = ldap_whoami_s( self->ldap, &bvalue, server_ldcs, client_ldcs );
1225 18 : LDAP_END_ALLOW_THREADS( self );
1226 :
1227 18 : LDAPControl_List_DEL( server_ldcs );
1228 18 : LDAPControl_List_DEL( client_ldcs );
1229 :
1230 18 : if ( ldaperror!=LDAP_SUCCESS ) {
1231 2 : ber_bvfree(bvalue);
1232 2 : return LDAPerror( self->ldap, "ldap_whoami_s" );
1233 : }
1234 :
1235 16 : result = LDAPberval_to_unicode_object(bvalue);
1236 : #ifdef DEMO_LEAK
1237 : /* ldap_whoami_s() allocates memory in bvalue but we are not freeing it */
1238 : #else
1239 : ber_bvfree(bvalue);
1240 : #endif
1241 :
1242 16 : return result;
1243 : }
1244 :
1245 : #ifdef HAVE_TLS
1246 : /* ldap_start_tls_s */
1247 :
1248 : static PyObject*
1249 4 : l_ldap_start_tls_s( LDAPObject* self, PyObject* args )
1250 : {
1251 : int ldaperror;
1252 :
1253 8 : if (!PyArg_ParseTuple( args, "" )) return NULL;
1254 4 : if (not_valid(self)) return NULL;
1255 :
1256 4 : LDAP_BEGIN_ALLOW_THREADS( self );
1257 4 : ldaperror = ldap_start_tls_s( self->ldap, NULL, NULL );
1258 4 : LDAP_END_ALLOW_THREADS( self );
1259 4 : if ( ldaperror != LDAP_SUCCESS ){
1260 1 : ldap_set_option(self->ldap, LDAP_OPT_ERROR_NUMBER, &ldaperror);
1261 1 : return LDAPerror( self->ldap, "ldap_start_tls_s" );
1262 : }
1263 :
1264 3 : Py_INCREF(Py_None);
1265 3 : return Py_None;
1266 : }
1267 :
1268 : #endif
1269 :
1270 : /* ldap_set_option */
1271 :
1272 : static PyObject*
1273 198 : l_ldap_set_option(PyObject* self, PyObject *args)
1274 : {
1275 : PyObject *value;
1276 : int option;
1277 :
1278 198 : if (!PyArg_ParseTuple(args, "iO:set_option", &option, &value))
1279 198 : return NULL;
1280 198 : if (!LDAP_set_option((LDAPObject *)self, option, value))
1281 7 : return NULL;
1282 191 : Py_INCREF(Py_None);
1283 191 : return Py_None;
1284 : }
1285 :
1286 :
1287 : /* ldap_get_option */
1288 :
1289 : static PyObject*
1290 34 : l_ldap_get_option(PyObject* self, PyObject *args)
1291 : {
1292 : int option;
1293 :
1294 34 : if (!PyArg_ParseTuple(args, "i:get_option", &option))
1295 34 : return NULL;
1296 34 : return LDAP_get_option((LDAPObject *)self, option);
1297 : }
1298 :
1299 :
1300 : /* ldap_passwd */
1301 :
1302 : static PyObject *
1303 4 : l_ldap_passwd( LDAPObject* self, PyObject *args )
1304 : {
1305 : struct berval user;
1306 : Py_ssize_t user_len;
1307 : struct berval oldpw;
1308 : Py_ssize_t oldpw_len;
1309 : struct berval newpw;
1310 : Py_ssize_t newpw_len;
1311 4 : PyObject *serverctrls = Py_None;
1312 4 : PyObject *clientctrls = Py_None;
1313 4 : LDAPControl** server_ldcs = NULL;
1314 4 : LDAPControl** client_ldcs = NULL;
1315 :
1316 : int msgid;
1317 : int ldaperror;
1318 :
1319 4 : 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 ))
1320 4 : return NULL;
1321 :
1322 4 : user.bv_len = (ber_len_t) user_len;
1323 4 : oldpw.bv_len = (ber_len_t) oldpw_len;
1324 4 : newpw.bv_len = (ber_len_t) newpw_len;
1325 :
1326 4 : if (not_valid(self)) return NULL;
1327 :
1328 4 : if (!PyNone_Check(serverctrls)) {
1329 1 : if (!LDAPControls_from_object(serverctrls, &server_ldcs))
1330 1 : return NULL;
1331 : }
1332 :
1333 3 : if (!PyNone_Check(clientctrls)) {
1334 1 : if (!LDAPControls_from_object(clientctrls, &client_ldcs)) {
1335 1 : LDAPControl_List_DEL( server_ldcs );
1336 1 : return NULL;
1337 : }
1338 : }
1339 :
1340 2 : LDAP_BEGIN_ALLOW_THREADS( self );
1341 8 : ldaperror = ldap_passwd( self->ldap,
1342 2 : user.bv_val != NULL ? &user : NULL,
1343 2 : oldpw.bv_val != NULL ? &oldpw : NULL,
1344 2 : newpw.bv_val != NULL ? &newpw : NULL,
1345 : server_ldcs,
1346 : client_ldcs,
1347 : &msgid );
1348 2 : LDAP_END_ALLOW_THREADS( self );
1349 :
1350 2 : LDAPControl_List_DEL( server_ldcs );
1351 2 : LDAPControl_List_DEL( client_ldcs );
1352 :
1353 2 : if ( ldaperror!=LDAP_SUCCESS )
1354 0 : return LDAPerror( self->ldap, "ldap_passwd" );
1355 :
1356 2 : return PyInt_FromLong( msgid );
1357 : }
1358 :
1359 :
1360 : /* ldap_extended_operation */
1361 :
1362 : static PyObject *
1363 2 : l_ldap_extended_operation( LDAPObject* self, PyObject *args )
1364 : {
1365 2 : char *reqoid = NULL;
1366 2 : struct berval reqvalue = {0, NULL};
1367 2 : PyObject *serverctrls = Py_None;
1368 2 : PyObject *clientctrls = Py_None;
1369 2 : LDAPControl** server_ldcs = NULL;
1370 2 : LDAPControl** client_ldcs = NULL;
1371 :
1372 : int msgid;
1373 : int ldaperror;
1374 :
1375 2 : if (!PyArg_ParseTuple( args, "sz#|OO", &reqoid, &reqvalue.bv_val, &reqvalue.bv_len, &serverctrls, &clientctrls ))
1376 2 : return NULL;
1377 :
1378 2 : if (not_valid(self)) return NULL;
1379 :
1380 2 : if (!PyNone_Check(serverctrls)) {
1381 1 : if (!LDAPControls_from_object(serverctrls, &server_ldcs))
1382 1 : return NULL;
1383 : }
1384 :
1385 1 : if (!PyNone_Check(clientctrls)) {
1386 1 : if (!LDAPControls_from_object(clientctrls, &client_ldcs)) {
1387 1 : LDAPControl_List_DEL( server_ldcs );
1388 1 : return NULL;
1389 : }
1390 : }
1391 :
1392 0 : LDAP_BEGIN_ALLOW_THREADS( self );
1393 0 : ldaperror = ldap_extended_operation( self->ldap, reqoid,
1394 0 : reqvalue.bv_val != NULL ? &reqvalue : NULL,
1395 : server_ldcs,
1396 : client_ldcs,
1397 : &msgid );
1398 0 : LDAP_END_ALLOW_THREADS( self );
1399 :
1400 0 : LDAPControl_List_DEL( server_ldcs );
1401 0 : LDAPControl_List_DEL( client_ldcs );
1402 :
1403 0 : if ( ldaperror!=LDAP_SUCCESS )
1404 0 : return LDAPerror( self->ldap, "ldap_extended_operation" );
1405 :
1406 0 : return PyInt_FromLong( msgid );
1407 : }
1408 :
1409 : /* methods */
1410 :
1411 : static PyMethodDef methods[] = {
1412 : {"unbind_ext", (PyCFunction)l_ldap_unbind_ext, METH_VARARGS },
1413 : {"abandon_ext", (PyCFunction)l_ldap_abandon_ext, METH_VARARGS },
1414 : {"add_ext", (PyCFunction)l_ldap_add_ext, METH_VARARGS },
1415 : {"simple_bind", (PyCFunction)l_ldap_simple_bind, METH_VARARGS },
1416 : #ifdef HAVE_SASL
1417 : {"sasl_interactive_bind_s", (PyCFunction)l_ldap_sasl_interactive_bind_s, METH_VARARGS },
1418 : {"sasl_bind_s", (PyCFunction)l_ldap_sasl_bind_s, METH_VARARGS },
1419 : #endif
1420 : {"compare_ext", (PyCFunction)l_ldap_compare_ext, METH_VARARGS },
1421 : {"delete_ext", (PyCFunction)l_ldap_delete_ext, METH_VARARGS },
1422 : {"modify_ext", (PyCFunction)l_ldap_modify_ext, METH_VARARGS },
1423 : {"rename", (PyCFunction)l_ldap_rename, METH_VARARGS },
1424 : {"result4", (PyCFunction)l_ldap_result4, METH_VARARGS },
1425 : {"search_ext", (PyCFunction)l_ldap_search_ext, METH_VARARGS },
1426 : #ifdef HAVE_TLS
1427 : {"start_tls_s", (PyCFunction)l_ldap_start_tls_s, METH_VARARGS },
1428 : #endif
1429 : {"whoami_s", (PyCFunction)l_ldap_whoami_s, METH_VARARGS },
1430 : {"passwd", (PyCFunction)l_ldap_passwd, METH_VARARGS },
1431 : {"set_option", (PyCFunction)l_ldap_set_option, METH_VARARGS },
1432 : {"get_option", (PyCFunction)l_ldap_get_option, METH_VARARGS },
1433 : #ifdef LDAP_API_FEATURE_CANCEL
1434 : {"cancel", (PyCFunction)l_ldap_cancel, METH_VARARGS },
1435 : #endif
1436 : {"extop", (PyCFunction)l_ldap_extended_operation, METH_VARARGS },
1437 : { NULL, NULL }
1438 : };
1439 :
1440 : /* type entry */
1441 :
1442 : PyTypeObject LDAP_Type = {
1443 : PyVarObject_HEAD_INIT(NULL, 0)
1444 : "LDAP", /*tp_name*/
1445 : sizeof(LDAPObject), /*tp_basicsize*/
1446 : 0, /*tp_itemsize*/
1447 : /* methods */
1448 : (destructor)dealloc, /*tp_dealloc*/
1449 : 0, /*tp_print*/
1450 : 0, /*tp_getattr*/
1451 : 0, /*tp_setattr*/
1452 : 0, /*tp_compare*/
1453 : 0, /*tp_repr*/
1454 : 0, /*tp_as_number*/
1455 : 0, /*tp_as_sequence*/
1456 : 0, /*tp_as_mapping*/
1457 : 0, /*tp_hash*/
1458 : 0, /*tp_call*/
1459 : 0, /*tp_str*/
1460 : 0, /*tp_getattro*/
1461 : 0, /*tp_setattro*/
1462 : 0, /*tp_as_buffer*/
1463 : 0, /*tp_flags*/
1464 : 0, /*tp_doc*/
1465 : 0, /*tp_traverse*/
1466 : 0, /*tp_clear*/
1467 : 0, /*tp_richcompare*/
1468 : 0, /*tp_weaklistoffset*/
1469 : 0, /*tp_iter*/
1470 : 0, /*tp_iternext*/
1471 : methods, /*tp_methods*/
1472 : 0, /*tp_members*/
1473 : 0, /*tp_getset*/
1474 : };
|