コード例 #1
0
ファイル: utils.c プロジェクト: KarapulYa/pyLDAP
/*	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;
}
コード例 #2
0
ファイル: utils.c プロジェクト: KarapulYa/pyLDAP
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;
}
コード例 #3
0
ファイル: utils.c プロジェクト: KarapulYa/pyLDAP
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;
}
コード例 #4
0
ファイル: utils.c プロジェクト: KarapulYa/pyLDAP
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;
}
コード例 #5
0
ファイル: utils.c プロジェクト: ihrwein/PyLDAP
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;
}
コード例 #6
0
ファイル: ldapentry.c プロジェクト: KarapulYa/pyLDAP
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;
}
コード例 #7
0
ファイル: ldapentry.c プロジェクト: KarapulYa/pyLDAP
/* 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;
}
コード例 #8
0
ファイル: utils.c プロジェクト: ihrwein/PyLDAP
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;
}
コード例 #9
0
ファイル: uniquelist.c プロジェクト: matepeter90/PyLDAP
/*	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;
}
コード例 #10
0
/* 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;
}
コード例 #11
0
ファイル: ldapentry.c プロジェクト: KarapulYa/pyLDAP
/*	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;
}
コード例 #12
0
ファイル: ldapentry.c プロジェクト: KarapulYa/pyLDAP
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;
}
コード例 #13
0
ファイル: utils.c プロジェクト: ihrwein/PyLDAP
/*	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;
}
コード例 #14
0
ファイル: ldap-xplat.c プロジェクト: Noirello/bonsai
/*  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;
}
コード例 #15
0
ファイル: ldapconnection.c プロジェクト: ihrwein/PyLDAP
/*	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;
}
コード例 #16
0
ファイル: ldapconnection.c プロジェクト: ihrwein/PyLDAP
/* 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);
}