/* Compare lower-case representations of two Python objects. Returns 1 they are matched, -1 if it's failed, and 0 otherwise. */ int lowerCaseMatch(PyObject *o1, PyObject *o2) { int match = 0; char *str1 = lowercase(PyObject2char(o1)); char *str2 = lowercase(PyObject2char(o2)); if (str1 == NULL || str2 == NULL) return -1; if (strcmp(str1, str2) == 0) match = 1; free(str1); free(str2); return match; }
int _LDAP_initialization(LDAP **ld, PyObject *url) { int rc; int portnum; char *hoststr = NULL; const int version = LDAP_VERSION3; PyObject *scheme = PyObject_GetAttrString(url, "scheme"); PyObject *host = PyObject_GetAttrString(url, "host"); PyObject *port = PyObject_GetAttrString(url, "port"); if (scheme == NULL || host == NULL || port == NULL) return -1; hoststr = PyObject2char(host); portnum = PyLong_AsLong(port); Py_DECREF(host); Py_DECREF(port); if (hoststr == NULL) return -1; if (PyUnicode_CompareWithASCIIString(scheme, "ldaps") == 0) { *ld = ldap_sslinit(hoststr, portnum, 1); } else { *ld = ldap_init(hoststr, portnum); } Py_DECREF(scheme); if (ld == NULL) return -1; ldap_set_option(*ld, LDAP_OPT_PROTOCOL_VERSION, &version); rc = ldap_connect(*ld, NULL); return rc; }
LDAPMod * createLDAPModFromItem(int mod_op, PyObject *key, PyObject *value) { LDAPMod *mod; mod = (LDAPMod *)malloc(sizeof(LDAPMod)); if (mod == NULL) return NULL; mod->mod_op = mod_op; mod->mod_type = PyObject2char(key); mod->mod_vals.modv_bvals = PyList2BervalList(value); return mod; }
int _LDAP_initialization(LDAP **ld, PyObject *url) { int rc; char *addrstr; const int version = LDAP_VERSION3; PyObject *addr = PyObject_CallMethod(url, "get_address", NULL); if (addr == NULL) return -1; addrstr = PyObject2char(addr); Py_DECREF(addr); if (addrstr == NULL) return -1; rc = ldap_initialize(ld, addrstr); if (rc != LDAP_SUCCESS) return rc; ldap_set_option(*ld, LDAP_OPT_PROTOCOL_VERSION, &version); return rc; }
int _LDAP_initialization(LDAP **ld, PyObject *url, int tls_option) { int rc; int portnum; char *hoststr = NULL; const int version = LDAP_VERSION3; const int tls_settings = SCH_CRED_MANUAL_CRED_VALIDATION | SCH_CRED_NO_SERVERNAME_CHECK; PyObject *scheme = PyObject_GetAttrString(url, "scheme"); PyObject *host = PyObject_GetAttrString(url, "host"); PyObject *port = PyObject_GetAttrString(url, "port"); if (scheme == NULL || host == NULL || port == NULL) return -1; hoststr = PyObject2char(host); portnum = PyLong_AsLong(port); Py_DECREF(host); Py_DECREF(port); if (hoststr == NULL) return -1; if (PyUnicode_CompareWithASCIIString(scheme, "ldaps") == 0) { *ld = ldap_sslinit(hoststr, portnum, 1); } else { *ld = ldap_init(hoststr, portnum); } Py_DECREF(scheme); if (ld == NULL) return -1; ldap_set_option(*ld, LDAP_OPT_PROTOCOL_VERSION, &version); switch (tls_option) { case -1: /* Cert policy is not set, nothing to do.*/ break; case 2: case 4: /* Cert policy is demand or try, then standard procedure. */ break; case 0: case 3: /* Cert policy is never or allow, then set TLS settings. */ ldap_set_option(*ld, 0x43, &tls_settings); ldap_set_option(*ld, LDAP_OPT_SERVER_CERTIFICATE, &noverify); break; } rc = ldap_connect(*ld, NULL); return rc; }
static PyObject * LDAPEntry_delete(LDAPEntry *self, PyObject *args, PyObject *kwds) { char *dnstr; PyObject *keys = PyMapping_Keys((PyObject *)self); PyObject *iter, *key; PyObject *tmp; LDAPValueList *value; /* Client must be set. */ if (self->client == NULL) { PyErr_SetString(PyExc_AttributeError, "LDAPClient is not set."); return NULL; } /* Get DN string. */ tmp = PyObject_Str(self->dn); dnstr = PyObject2char(tmp); Py_DECREF(tmp); if (dnstr == NULL) return NULL; if (LDAPClient_DelEntryStringDN(self->client, dnstr) != 0) return NULL; if (keys == NULL) return NULL; iter = PyObject_GetIter(keys); Py_DECREF(keys); if (iter == NULL) return NULL; for (key = PyIter_Next(iter); key != NULL; key = PyIter_Next(iter)) { /* Return value: New reference. */ value = (LDAPValueList *)LDAPEntry_GetItem(self, key); if (value == NULL) { Py_DECREF(iter); Py_DECREF(key); return NULL; } value->status = 2; } return Py_None; }
/* Preform a LDAP add or modify operation depend on the `mod` parameter. */ PyObject * add_or_modify(LDAPEntry *self, int mod) { int rc = -1; char *dnstr = NULL; LDAPMod **mods = NULL; PyObject *tmp; /* Get DN string. */ tmp = PyObject_Str(self->dn); dnstr = PyObject2char(tmp); Py_DECREF(tmp); if (dnstr == NULL || strlen(dnstr) == 0) { PyErr_SetString(PyExc_AttributeError, "Missing distinguished name."); return NULL; } mods = LDAPEntry_CreateLDAPMods(self); if (mods == NULL) { PyErr_SetString(PyExc_MemoryError, "Create LDAPMods is failed."); return NULL; } if (mod == 0) { rc = ldap_add_ext_s(self->client->ld, dnstr, mods, NULL, NULL); } else { rc = ldap_modify_ext_s(self->client->ld, dnstr, mods, NULL, NULL); } if (rc != LDAP_SUCCESS) { //TODO Proper errors PyObject *ldaperror = get_error("LDAPError"); PyErr_SetString(ldaperror, ldap_err2string(rc)); Py_DECREF(ldaperror); LDAPEntry_DismissLDAPMods(self, mods); free(dnstr); return NULL; } free(dnstr); LDAPEntry_DismissLDAPMods(self, mods); return Py_None; }
int _LDAP_initialization(LDAP **ld, PyObject *url, int tls_option) { int rc; char *addrstr; const int version = LDAP_VERSION3; PyObject *addr = PyObject_CallMethod(url, "get_address", NULL); if (addr == NULL) return -1; addrstr = PyObject2char(addr); Py_DECREF(addr); if (addrstr == NULL) return -1; rc = ldap_initialize(ld, addrstr); if (rc != LDAP_SUCCESS) return rc; ldap_set_option(*ld, LDAP_OPT_PROTOCOL_VERSION, &version); if (tls_option != -1) { ldap_set_option(*ld, LDAP_OPT_X_TLS_REQUIRE_CERT, &tls_option); /* Set TLS option globally. */ ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &tls_option); } return rc; }
/* Convert `list` object to a tuple, which contains only lowercase Python string elements. */ static PyObject * get_lowercase_tuple(PyObject *list) { char *str; Py_ssize_t i, n; PyObject *tup = NULL; PyObject *seq, *item; if (list == NULL) return NULL; seq = PySequence_Fast(list, "Argument is not iterable."); n = PySequence_Fast_GET_SIZE(seq); tup = PyTuple_New(n); if (tup == NULL) { Py_XDECREF(seq); return PyErr_NoMemory(); } for (i = 0; i < n; i++) { item = PySequence_Fast_GET_ITEM(seq, i); if (PyDict_Check(item) || PyList_Check(item) || PyTuple_Check(item)) { PyErr_SetString(PyExc_ValueError, "This type of list can not contain instances of Python tuple, list or dict."); Py_DECREF(tup); Py_XDECREF(seq); return NULL; } str = lowercase(PyObject2char(item)); if (PyTuple_SetItem(tup, i, PyUnicode_FromString(str)) != 0) { PyErr_BadInternalCall(); Py_DECREF(tup); Py_XDECREF(seq); return NULL; } free(str); } Py_XDECREF(seq); return tup; }
/* Add new LDAPMod to the list. */ int LDAPModList_Add(LDAPModList *self, int mod_op, PyObject *key, PyObject *value) { LDAPMod *mod; /* Add to the next free slot, if there is one. */ if (self->last == self->size) { PyErr_Format(PyExc_OverflowError, "The LDAPModList is full."); return -1; } /* Malloc a new LDAPMod struct. */ mod = (LDAPMod *)malloc(sizeof(LDAPMod)); if (mod == NULL) return -1; /* Set the values with the parameters. */ mod->mod_op = mod_op; mod->mod_type = PyObject2char(key); mod->mod_vals.modv_bvals = PyList2BervalList(value); self->mod_list[self->last++] = mod; self->mod_list[self->last] = NULL; return 0; }
/* Set item to LDAPEntry with a case-insensitive key. */ int LDAPEntry_SetItem(LDAPEntry *self, PyObject *key, PyObject *value) { int found = 0; int rc = 0; int status = 1; char *newkey = lowercase(PyObject2char(key)); LDAPValueList *list; /* Search for a match. */ key = searchLowerCaseKeyMatch(self, key, &found); if (found == 1) { status = 2; } if (value != NULL) { /* If theres an item with a `dn` key, and with a string value set to the dn attribute. */ if (strcmp(newkey, "dn") == 0) { if (PyUnicode_Check(value)) { char *dnstr = PyObject2char(value); LDAPEntry_SetStringDN(self, dnstr); free(dnstr); } else { PyErr_SetString(PyExc_TypeError, "Distinguished name must be string type."); Py_DECREF(key); return -1; } } else { /* Set the new value to the item. */ if (LDAPValueList_Check(value) == 0) { /* Convert value to LDAPValueList object. */ list = LDAPValueList_New(); if (PyList_Check(value) || PyTuple_Check(value)) { LDAPValueList_Extend(list, value); } else { LDAPValueList_Append(list, value); } rc = PyDict_SetItem((PyObject *)self, key, (PyObject *)list); list->status = status; Py_DECREF(list); } else { rc = PyDict_SetItem((PyObject *)self, key, value); ((LDAPValueList *)value)->status = status; } /* Avoid inconsistency. (same key in the added and the deleted list) */ if (PySequence_Contains((PyObject *)self->deleted, key)) { if (UniqueList_Remove(self->deleted, key) != 0) return -1; } if (rc != 0) return rc; /* New key should be added to the attribute list. */ if (found == 0) { if (UniqueList_Append(self->attributes, key) != 0) { Py_DECREF(key); return -1; } } } } else { /* This means, it has to remove the item. */ if (PyDict_DelItem((PyObject *)self, key) != 0) return -1; if (UniqueList_Append(self->deleted, key) != 0) return -1; /* Remove from the attributes list. */ if (PySequence_DelItem((PyObject *)self->attributes, PySequence_Index((PyObject *)self->attributes, key)) != 0) { Py_DECREF(key); return -1; } } Py_DECREF(key); return 0; }
static PyObject * LDAPEntry_rename(LDAPEntry *self, PyObject *args, PyObject *kwds) { int rc; char *newparent_str, *newrdn_str, *olddn_str; PyObject *newdn, *newparent, *newrdn; PyObject *tmp; char *kwlist[] = {"newdn", NULL}; /* Client must be set. */ if (self->client == NULL) { PyErr_SetString(PyExc_AttributeError, "LDAPClient is not set."); return NULL; } /* Client must be connected. */ if (!self->client->connected) { PyObject *ldaperror = get_error("NotConnected"); PyErr_SetString(ldaperror, "Client has to connect to the server first."); Py_DECREF(ldaperror); return NULL; } if (!PyArg_ParseTupleAndKeywords(args, kwds, "O", kwlist, &newdn)) { PyErr_SetString(PyExc_AttributeError, "Wrong parameter."); return NULL; } /* Save old dn string. */ tmp = PyObject_Str(self->dn); olddn_str = PyObject2char(tmp); Py_DECREF(tmp); if (olddn_str == NULL) return NULL; /* Validate and set new LDAP DN. */ if (LDAPEntry_setDN(self, newdn, NULL) != 0) return NULL; /* Get rdn and parent strings. */ newrdn = PyObject_CallMethod(self->dn, "get_rdn", "(i)", 0); newparent = PyObject_CallMethod(self->dn, "get_ancestors", NULL); if (newrdn == NULL || newparent == NULL) return NULL; newrdn_str = PyObject2char(newrdn); newparent_str = PyObject2char(newparent); Py_DECREF(newrdn); Py_DECREF(newparent); rc = ldap_rename_s(self->client->ld, olddn_str, newrdn_str, newparent_str, 1, NULL, NULL); if (rc != LDAP_SUCCESS) { //TODO Proper errors PyObject *ldaperror = get_error("LDAPError"); PyErr_SetString(ldaperror, ldap_err2string(rc)); Py_DECREF(ldaperror); free(olddn_str); free(newrdn_str); free(newparent_str); return NULL; } free(olddn_str); free(newrdn_str); free(newparent_str); return Py_None; }
/* Converts Python simple objects (String, Long, Float, Boolean, Bytes, and None) to C string. If the `obj` is none of these types, then call PyObject_Str, and recall this function with the result. */ char * PyObject2char(PyObject *obj) { char *str = NULL; char *tmp = NULL; const wchar_t *wstr; Py_ssize_t length = 0; const unsigned int len = 24; /* The max length that a number's char* representation can be. */ if (obj == NULL) return NULL; /* If Python objects is a None return an empty("") char*. */ if (obj == Py_None) { str = (char *)malloc(sizeof(char)); str[0] = '\0'; return str; } if (PyUnicode_Check(obj)) { /* Python string converting. From Python 3.3 could be use PyUnicode_AsUTF8AndSize(). */ wstr = PyUnicode_AsWideCharString(obj, &length); str = (char *)malloc(sizeof(char) * (length + 1)); if (str == NULL) return (char *)PyErr_NoMemory(); wcstombs(str, wstr, length); /* Put the delimiter at the end. */ str[length] = '\0'; } else if (PyLong_Check(obj)) { /* Python integer converting. Could be longer, literally. */ long int inum = PyLong_AsLong(obj); tmp = malloc(sizeof(char) * len); if (tmp == NULL) return (char *)PyErr_NoMemory(); sprintf(tmp, "%ld", inum); } else if (PyFloat_Check(obj)) { /* Python floating point number converting. */ double dnum = PyFloat_AsDouble(obj); tmp = malloc(sizeof(char) * len); if (tmp == NULL) return (char *)PyErr_NoMemory(); sprintf(tmp, "%lf", dnum); } else if (PyBool_Check(obj)) { /* Python boolean converting to number representation (0 or 1). */ if (obj == Py_True) { str = "1"; } else { str = "0"; } } else if (PyBytes_Check(obj)) { /* Python bytes converting. */ tmp = PyBytes_AsString(obj); if (tmp == NULL) return NULL; str = (char *)malloc(sizeof(char) * (strlen(tmp) + 1)); strcpy(str, tmp); return str; } else { PyObject *tmpobj = PyObject_Str(obj); if (tmpobj == NULL) { PyErr_BadInternalCall(); return NULL; } str = PyObject2char(tmpobj); Py_DECREF(tmpobj); return str; } /* In case of converting numbers, optimizing the memory allocation. */ if (tmp != NULL) { str = strdup(tmp); free(tmp); } return str; }
/* This function is based on the OpenLDAP liblutil's sasl.c source file for creating a lutilSASLdefaults struct with default values based on the given parameters or client's options. */ void * create_conn_info(char *mech, SOCKET sock, PyObject *creds) { ldap_conndata_t *defaults = NULL; char *authcid = NULL; char *authzid = NULL; char *binddn = NULL; char *passwd = NULL; char *realm = NULL; char *ktname = NULL; DEBUG("create_conn_info (mech:%s, sock:%d, creds:%p)", mech, (int)sock, creds); /* Get credential information, if it's given. */ if (PyDict_Check(creds)) { if (strcmp(mech, "SIMPLE") == 0) { binddn = PyObject2char(PyDict_GetItemString(creds, "user")); } else { authcid = PyObject2char(PyDict_GetItemString(creds, "user")); realm = PyObject2char(PyDict_GetItemString(creds, "realm")); authzid = PyObject2char(PyDict_GetItemString(creds, "authz_id")); ktname = PyObject2char(PyDict_GetItemString(creds, "keytab")); } passwd = PyObject2char(PyDict_GetItemString(creds, "password")); } defaults = malloc(sizeof(ldap_conndata_t)); if (defaults == NULL) { free(passwd); free(binddn); free(realm); free(authcid); free(authzid); free(ktname); return (void *)PyErr_NoMemory(); } defaults->mech = mech ? strdup(mech) : NULL; defaults->realm = realm; defaults->authcid = authcid; defaults->passwd = passwd; defaults->authzid = authzid; defaults->binddn = binddn; #ifdef WIN32 defaults->thread = NULL; defaults->ld = NULL; defaults->sock = sock; #else defaults->resps = NULL; defaults->nresps = 0; defaults->rmech = NULL; #ifdef HAVE_KRB5 defaults->ctx = NULL; defaults->ccache = NULL; defaults->gsscred = GSS_C_NO_CREDENTIAL; defaults->errmsg = NULL; defaults->request_tgt = 0; defaults->ktname = ktname; #endif #endif return defaults; }
/* Opens a connection to the LDAP server. Initializes LDAP structure. If TLS is true, starts TLS session. */ static int connecting(LDAPConnection *self) { int rc = -1; int tls_option = -1; char *binddn = NULL; char *pswstr = NULL; char *mech = NULL; char *authzid = ""; char *realm = NULL; char *authcid = NULL; PyObject *url = NULL; PyObject *tls = NULL; PyObject *tmp = NULL; PyObject *creds = NULL; url = PyObject_GetAttrString(self->client, "_LDAPClient__url"); if (url == NULL) return -1; tmp = PyObject_GetAttrString(self->client, "_LDAPClient__cert_policy"); tls_option = (int)PyLong_AsLong(tmp); Py_DECREF(tmp); rc = _LDAP_initialization(&(self->ld), url, tls_option); Py_DECREF(url); if (rc != LDAP_SUCCESS) { PyObject *ldaperror = get_error_by_code(rc); PyErr_SetString(ldaperror, ldap_err2string(rc)); Py_DECREF(ldaperror); return -1; } tls = PyObject_GetAttrString(self->client, "_LDAPClient__tls"); if (tls == NULL) return -1; /* Start TLS, if it necessary. */ if (PyObject_IsTrue(tls)) { #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) rc = ldap_start_tls_sA(self->ld, NULL, NULL, NULL, NULL); #else rc = ldap_start_tls_s(self->ld, NULL, NULL); #endif if (rc != LDAP_SUCCESS) { //TODO Proper errors PyObject *ldaperror = get_error_by_code(rc); PyErr_SetString(ldaperror, ldap_err2string(rc)); Py_DECREF(ldaperror); Py_DECREF(tls); return -1; } } Py_DECREF(tls); creds = PyObject_GetAttrString(self->client, "_LDAPClient__credentials"); if (creds == NULL) return -1; tmp = PyObject_GetAttrString(self->client, "_LDAPClient__mechanism"); if (tmp == NULL) return -1; mech = PyObject2char(tmp); Py_XDECREF(tmp); /* Get credential information, if it's given. */ if (PyTuple_Check(creds) && PyTuple_Size(creds) > 1) { if (strcmp(mech, "SIMPLE") == 0) { tmp = PyTuple_GetItem(creds, 0); binddn = PyObject2char(tmp); } else { tmp = PyTuple_GetItem(creds, 0); authcid = PyObject2char(tmp); tmp = PyDict_GetItemString(creds, "realm"); realm = PyObject2char(tmp); } tmp = PyTuple_GetItem(creds, 1); pswstr = PyObject2char(tmp); } if (authzid == NULL) authzid = ""; rc = _LDAP_bind_s(self->ld, mech, binddn, pswstr, authcid, realm, authzid); free(mech); free(binddn); free(pswstr); free(authcid); free(realm); if (strcmp(authzid, "") != 0) free(authzid); if (rc != LDAP_SUCCESS) { PyObject *ldaperror = get_error_by_code(rc); PyErr_SetString(ldaperror, ldap_err2string(rc)); Py_DECREF(ldaperror); Py_DECREF(creds); return -1; } Py_DECREF(creds); return 0; }
/* Searches for LDAP entries. */ static PyObject * LDAPConnection_Search(LDAPConnection *self, PyObject *args, PyObject *kwds) { int scope = -1; int timeout = 0, sizelimit = 0, attrsonly = 0; char *basestr = NULL; char *filterstr = NULL; char **attrs = NULL; PyObject *ldapdn_type = NULL; PyObject *basedn = NULL; PyObject *attrlist = NULL; PyObject *attrsonlyo = NULL; PyObject *url = NULL; LDAPSearchIter *search_iter = NULL; static char *kwlist[] = {"base", "scope", "filter", "attrlist", "timeout", "sizelimit", "attrsonly", NULL}; if (!PyArg_ParseTupleAndKeywords(args, kwds, "|OizO!iiO!", kwlist, &basedn, &scope, &filterstr, &PyList_Type, &attrlist, &timeout, &sizelimit, &PyBool_Type, &attrsonlyo)) { PyErr_SetString(PyExc_AttributeError, "Wrong parameters (base<str|LDAPDN>, scope<int>, filter<str>, attrlist<List>, timeout<int>, attrsonly<bool>)."); return NULL; } /* Load LDAPDN to check basedn's type.*/ ldapdn_type = load_python_object("pyldap.ldapdn", "LDAPDN"); if (ldapdn_type == NULL) return NULL; /* Get additional informations from the LDAP URL. */ url = PyObject_GetAttrString(self->client, "_LDAPClient__url"); if (url == NULL) return NULL; if (basedn != NULL && (PyObject_IsInstance(basedn, ldapdn_type) || PyUnicode_Check(basedn))) { /* If basedn is an LDAPDN object convert to Python string. If basedn already a string increment reference. */ basedn = PyObject_Str(basedn); if (basedn == NULL) { Py_DECREF(url); Py_DECREF(ldapdn_type); return NULL; } /* Convert the basedn to char*. */ basestr = PyObject2char(basedn); Py_DECREF(basedn); basedn = NULL; } Py_DECREF(ldapdn_type); if (basedn != NULL) { PyErr_SetString(PyExc_AttributeError, "Wrong parameters, `base` must be string or LDAPDN"); return NULL; } search_iter = LDAPSearchIter_New(self); if (search_iter == NULL) { return PyErr_NoMemory(); } if (basestr == NULL) { basedn = PyObject_GetAttrString(url, "basedn"); if (basedn == NULL) { Py_DECREF(search_iter); Py_DECREF(url); return NULL; } if (basedn == Py_None) { Py_DECREF(basedn); PyErr_SetString(PyExc_AttributeError, "Search base DN cannot be None."); Py_DECREF(search_iter); Py_DECREF(url); return NULL; } else { basestr = PyObject2char(basedn); Py_DECREF(basedn); if (basestr == NULL) { Py_DECREF(url); Py_DECREF(search_iter); return NULL; } } } if (scope == -1) { PyObject *scopeobj = PyObject_GetAttrString(url, "scope_num"); if (scopeobj == NULL) { Py_DECREF(url); Py_DECREF(search_iter); return NULL; } if (scopeobj == Py_None) { Py_DECREF(scopeobj); Py_DECREF(url); PyErr_SetString(PyExc_AttributeError, "Search scope cannot be None."); return NULL; } else { scope = PyLong_AsLong(scopeobj); Py_DECREF(scopeobj); if (scope == -1) { Py_DECREF(url); Py_DECREF(search_iter); return NULL; } } } if (filterstr == NULL) { PyObject *filter = PyObject_GetAttrString(url, "filter"); if (filter == NULL) { Py_DECREF(url); Py_DECREF(search_iter); return NULL; } if (filter == Py_None) { Py_DECREF(filter); } else { filterstr = PyObject2char(filter); Py_DECREF(filter); if (filterstr == NULL) { Py_DECREF(url); Py_DECREF(search_iter); return NULL; } } } if (attrsonlyo != NULL) { attrsonly = PyObject_IsTrue(attrsonlyo); } if (attrlist == NULL) { PyObject *attr_list = PyObject_GetAttrString(url, "attributes"); if (attr_list == NULL) { Py_DECREF(url); Py_DECREF(search_iter); return NULL; } attrs = PyList2StringList(attr_list); Py_DECREF(attr_list); } else { attrs = PyList2StringList(attrlist); } Py_DECREF(url); if (LDAPSearchIter_SetParams(search_iter, attrs, attrsonly, basestr, filterstr, scope, sizelimit, timeout) != 0) { Py_DECREF(url); Py_DECREF(search_iter); return NULL; } if (self->page_size > 0) { /* Create cookie for the page result. */ search_iter->cookie = (struct berval *)malloc(sizeof(struct berval)); if (search_iter->cookie == NULL) return PyErr_NoMemory(); search_iter->cookie->bv_len = 0; search_iter->cookie->bv_val = NULL; /* Get the first page, and create an iterator for the next. */ search_iter->buffer = LDAPConnection_Searching(self, (PyObject *)search_iter); if (search_iter->buffer == NULL) return NULL; return (PyObject *)search_iter; } return LDAPConnection_Searching(self, (PyObject *)search_iter); }