summaryrefslogtreecommitdiff
path: root/source4/lib/ldb
diff options
context:
space:
mode:
Diffstat (limited to 'source4/lib/ldb')
-rw-r--r--source4/lib/ldb/modules/paged_searches.c115
-rw-r--r--source4/lib/ldb/pyldb.c80
-rwxr-xr-xsource4/lib/ldb/tests/python/api.py13
3 files changed, 118 insertions, 90 deletions
diff --git a/source4/lib/ldb/modules/paged_searches.c b/source4/lib/ldb/modules/paged_searches.c
index 01e77cb22c..c5430eb9bf 100644
--- a/source4/lib/ldb/modules/paged_searches.c
+++ b/source4/lib/ldb/modules/paged_searches.c
@@ -2,6 +2,7 @@
ldb database library
Copyright (C) Simo Sorce 2005-2008
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
** NOTE! The following LGPL license applies to the ldb
** library. This does NOT imply that all of Samba is released
@@ -52,23 +53,40 @@ struct ps_context {
char **saved_referrals;
int num_referrals;
+
+ struct ldb_request *down_req;
};
-static int check_ps_continuation(struct ldb_request *req, struct ldb_reply *ares)
+static int check_ps_continuation(struct ps_context *ac, struct ldb_request *req, struct ldb_reply *ares)
{
- struct ps_context *ac;
- struct ldb_paged_control *rep_control, *req_control;
+ struct ldb_context *ldb;
+ struct ldb_control *rep_control, *req_control;
+ struct ldb_paged_control *paged_rep_control = NULL, *paged_req_control = NULL;
+ ldb = ldb_module_get_ctx(ac->module);
- ac = talloc_get_type(req->context, struct ps_context);
+ rep_control = ldb_reply_get_control(ares, LDB_CONTROL_PAGED_RESULTS_OID);
+ if (rep_control) {
+ paged_rep_control = talloc_get_type(rep_control->data, struct ldb_paged_control);
+ }
- /* look up our paged control */
- if (!ares->controls || strcmp(LDB_CONTROL_PAGED_RESULTS_OID, ares->controls[0]->oid) != 0) {
- /* something wrong here */
- return LDB_ERR_OPERATIONS_ERROR;
+ req_control = ldb_request_get_control(req, LDB_CONTROL_PAGED_RESULTS_OID);
+ paged_req_control = talloc_get_type(req_control->data, struct ldb_paged_control);
+
+ if (!rep_control || !paged_rep_control) {
+ if (paged_req_control->cookie) {
+ /* something wrong here - why give us a control back befre, but not one now? */
+ ldb_set_errstring(ldb, "paged_searches: ERROR: We got back a control from a previous page, but this time no control was returned!");
+ return LDB_ERR_OPERATIONS_ERROR;
+ } else {
+ /* No cookie recived yet, valid to just return the full data set */
+
+ /* we are done */
+ ac->pending = false;
+ return LDB_SUCCESS;
+ }
}
- rep_control = talloc_get_type(ares->controls[0]->data, struct ldb_paged_control);
- if (rep_control->cookie_len == 0) {
+ if (paged_rep_control->cookie_len == 0) {
/* we are done */
ac->pending = false;
return LDB_SUCCESS;
@@ -79,21 +97,14 @@ static int check_ps_continuation(struct ldb_request *req, struct ldb_reply *ares
/* if there's a reply control we must find a request
* control matching it */
- if (strcmp(LDB_CONTROL_PAGED_RESULTS_OID, req->controls[0]->oid) != 0) {
- /* something wrong here */
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- req_control = talloc_get_type(req->controls[0]->data, struct ldb_paged_control);
-
- if (req_control->cookie) {
- talloc_free(req_control->cookie);
+ if (paged_req_control->cookie) {
+ talloc_free(paged_req_control->cookie);
}
- req_control->cookie = talloc_memdup(req_control,
- rep_control->cookie,
- rep_control->cookie_len);
- req_control->cookie_len = rep_control->cookie_len;
+ paged_req_control->cookie = talloc_memdup(req_control,
+ paged_rep_control->cookie,
+ paged_rep_control->cookie_len);
+ paged_req_control->cookie_len = paged_rep_control->cookie_len;
ac->pending = true;
return LDB_SUCCESS;
@@ -141,8 +152,6 @@ static int send_referrals(struct ps_context *ac)
return LDB_SUCCESS;
}
-static int ps_next_request(struct ps_context *ac);
-
static int ps_callback(struct ldb_request *req, struct ldb_reply *ares)
{
struct ps_context *ac;
@@ -176,14 +185,15 @@ static int ps_callback(struct ldb_request *req, struct ldb_reply *ares)
case LDB_REPLY_DONE:
- ret = check_ps_continuation(req, ares);
+ ret = check_ps_continuation(ac, req, ares);
if (ret != LDB_SUCCESS) {
return ldb_module_done(ac->req, NULL, NULL, ret);
}
if (ac->pending) {
- ret = ps_next_request(ac);
+ ret = ldb_next_request(ac->module, ac->down_req);
+
if (ret != LDB_SUCCESS) {
return ldb_module_done(ac->req,
NULL, NULL, ret);
@@ -214,14 +224,16 @@ static int ps_search(struct ldb_module *module, struct ldb_request *req)
struct ldb_context *ldb;
struct private_data *private_data;
struct ps_context *ac;
+ struct ldb_paged_control *control;
+ int ret;
private_data = talloc_get_type(ldb_module_get_private(module), struct private_data);
ldb = ldb_module_get_ctx(module);
- /* check if paging is supported and if there is a any control */
- if (!private_data || !private_data->paged_supported || req->controls) {
+ /* check if paging is supported */
+ if (!private_data || !private_data->paged_supported) {
/* do not touch this request paged controls not
- * supported or explicit controls have been set or we
+ * supported or we
* are just not setup yet */
return ldb_next_request(module, req);
}
@@ -238,30 +250,9 @@ static int ps_search(struct ldb_module *module, struct ldb_request *req)
ac->saved_referrals = NULL;
ac->num_referrals = 0;
- return ps_next_request(ac);
-}
-
-static int ps_next_request(struct ps_context *ac) {
-
- struct ldb_context *ldb;
- struct ldb_paged_control *control;
- struct ldb_control **controls;
- struct ldb_request *new_req;
- int ret;
-
ldb = ldb_module_get_ctx(ac->module);
- controls = talloc_array(ac, struct ldb_control *, 2);
- if (!controls) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- controls[0] = talloc(controls, struct ldb_control);
- if (!controls[0]) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- control = talloc(controls[0], struct ldb_paged_control);
+ control = talloc(ac, struct ldb_paged_control);
if (!control) {
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -270,26 +261,28 @@ static int ps_next_request(struct ps_context *ac) {
control->cookie = NULL;
control->cookie_len = 0;
- controls[0]->oid = LDB_CONTROL_PAGED_RESULTS_OID;
- controls[0]->critical = 1;
- controls[0]->data = control;
- controls[1] = NULL;
-
- ret = ldb_build_search_req_ex(&new_req, ldb, ac,
+ ret = ldb_build_search_req_ex(&ac->down_req, ldb, ac,
ac->req->op.search.base,
ac->req->op.search.scope,
ac->req->op.search.tree,
ac->req->op.search.attrs,
- controls,
+ ac->req->controls,
ac,
ps_callback,
ac->req);
if (ret != LDB_SUCCESS) {
return ret;
}
- talloc_steal(new_req, controls);
- return ldb_next_request(ac->module, new_req);
+ ret = ldb_request_add_control(ac->down_req, LDB_CONTROL_PAGED_RESULTS_OID,
+ true, control);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ talloc_steal(ac->down_req, control);
+
+ return ldb_next_request(ac->module, ac->down_req);
}
static int check_supported_paged(struct ldb_request *req,
diff --git a/source4/lib/ldb/pyldb.c b/source4/lib/ldb/pyldb.c
index 81b960979f..bceda05e4f 100644
--- a/source4/lib/ldb/pyldb.c
+++ b/source4/lib/ldb/pyldb.c
@@ -5,7 +5,7 @@
Copyright (C) 2005,2006 Tim Potter <tpot@samba.org>
Copyright (C) 2006 Simo Sorce <idra@samba.org>
- Copyright (C) 2007-2008 Jelmer Vernooij <jelmer@samba.org>
+ Copyright (C) 2007-2009 Jelmer Vernooij <jelmer@samba.org>
** NOTE! The following LGPL license applies to the ldb
** library. This does NOT imply that all of Samba is released
@@ -65,18 +65,7 @@ static PyObject *PyObject_FromLdbValue(struct ldb_context *ldb_ctx,
PyObject *ret;
new_val = *val;
-
- if (ldb_ctx != NULL) {
- a = ldb_schema_attribute_by_name(ldb_ctx, el->name);
-
- if (a != NULL) {
- if (a->syntax->ldif_write_fn(ldb_ctx, mem_ctx, val, &new_val) != 0) {
- talloc_free(mem_ctx);
- return NULL;
- }
- }
- }
-
+
ret = PyString_FromStringAndSize((const char *)new_val.data, new_val.length);
talloc_free(mem_ctx);
@@ -84,6 +73,14 @@ static PyObject *PyObject_FromLdbValue(struct ldb_context *ldb_ctx,
return ret;
}
+/**
+ * Obtain a ldb DN from a Python object.
+ *
+ * @param mem_ctx Memory context
+ * @param object Python object
+ * @param ldb_ctx LDB context
+ * @return Whether or not the conversion succeeded
+ */
bool PyObject_AsDn(TALLOC_CTX *mem_ctx, PyObject *object,
struct ldb_context *ldb_ctx, struct ldb_dn **dn)
{
@@ -104,6 +101,12 @@ bool PyObject_AsDn(TALLOC_CTX *mem_ctx, PyObject *object,
return false;
}
+/**
+ * Create a Python object from a ldb_result.
+ *
+ * @param result LDB result to convert
+ * @return Python object with converted result (a list object)
+ */
static PyObject *PyLdbResult_FromResult(struct ldb_result *result)
{
PyObject *ret;
@@ -119,7 +122,16 @@ static PyObject *PyLdbResult_FromResult(struct ldb_result *result)
return ret;
}
-static struct ldb_result *PyLdbResult_AsResult(TALLOC_CTX *mem_ctx, PyObject *obj)
+/**
+ * Create a LDB Result from a Python object.
+ * If conversion fails, NULL will be returned and a Python exception set.
+ *
+ * @param mem_ctx Memory context in which to allocate the LDB Result
+ * @param obj Python object to convert
+ * @return a ldb_result, or NULL if the conversion failed
+ */
+static struct ldb_result *PyLdbResult_AsResult(TALLOC_CTX *mem_ctx,
+ PyObject *obj)
{
struct ldb_result *res;
int i;
@@ -451,7 +463,6 @@ static PyObject *py_ldb_get_schema_basedn(PyLdbObject *self)
return PyLdbDn_FromDn(dn);
}
-
static PyObject *py_ldb_get_config_basedn(PyLdbObject *self)
{
struct ldb_dn *dn = ldb_get_config_basedn(PyLdb_AsLdbContext(self));
@@ -460,7 +471,6 @@ static PyObject *py_ldb_get_config_basedn(PyLdbObject *self)
return PyLdbDn_FromDn(dn);
}
-
static PyObject *py_ldb_get_default_basedn(PyLdbObject *self)
{
struct ldb_dn *dn = ldb_get_default_basedn(PyLdb_AsLdbContext(self));
@@ -469,19 +479,20 @@ static PyObject *py_ldb_get_default_basedn(PyLdbObject *self)
return PyLdbDn_FromDn(dn);
}
-static const char **PyList_AsStringList(TALLOC_CTX *mem_ctx, PyObject *list)
+static const char **PyList_AsStringList(TALLOC_CTX *mem_ctx, PyObject *list,
+ const char *paramname)
{
const char **ret;
int i;
if (!PyList_Check(list)) {
- PyErr_SetString(PyExc_TypeError, "options is not a list");
+ PyErr_Format(PyExc_TypeError, "%s is not a list", paramname);
return NULL;
}
ret = talloc_array(NULL, const char *, PyList_Size(list)+1);
for (i = 0; i < PyList_Size(list); i++) {
PyObject *item = PyList_GetItem(list, i);
if (!PyString_Check(item)) {
- PyErr_SetString(PyExc_TypeError, "options should be strings");
+ PyErr_Format(PyExc_TypeError, "%s should be strings", paramname);
return NULL;
}
ret[i] = PyString_AsString(item);
@@ -510,7 +521,7 @@ static int py_ldb_init(PyLdbObject *self, PyObject *args, PyObject *kwargs)
if (py_options == Py_None) {
options = NULL;
} else {
- options = PyList_AsStringList(ldb, py_options);
+ options = PyList_AsStringList(ldb, py_options, "options");
if (options == NULL)
return -1;
}
@@ -563,7 +574,7 @@ static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwa
if (py_options == Py_None) {
options = NULL;
} else {
- options = PyList_AsStringList(NULL, py_options);
+ options = PyList_AsStringList(NULL, py_options, "options");
if (options == NULL)
return NULL;
}
@@ -651,8 +662,6 @@ static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args)
Py_RETURN_NONE;
}
-
-
static PyObject *py_ldb_delete(PyLdbObject *self, PyObject *args)
{
PyObject *py_dn;
@@ -813,7 +822,7 @@ static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwar
if (py_attrs == Py_None) {
attrs = NULL;
} else {
- attrs = PyList_AsStringList(ldb_ctx, py_attrs);
+ attrs = PyList_AsStringList(ldb_ctx, py_attrs, "attrs");
if (attrs == NULL)
return NULL;
}
@@ -828,7 +837,7 @@ static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwar
if (py_controls == Py_None) {
parsed_controls = NULL;
} else {
- const char **controls = PyList_AsStringList(ldb_ctx, py_controls);
+ const char **controls = PyList_AsStringList(ldb_ctx, py_controls, "controls");
parsed_controls = ldb_parse_control_strings(ldb_ctx, ldb_ctx, controls);
talloc_free(controls);
}
@@ -1129,7 +1138,7 @@ static PyObject *py_ldb_module_search(PyLdbModuleObject *self, PyObject *args, P
mod = self->mod;
ret = ldb_build_search_req(&req, mod->ldb, NULL, PyLdbDn_AsDn(py_base),
- scope, NULL /* expr */, py_attrs == Py_None?NULL:PyList_AsStringList(req, py_attrs),
+ scope, NULL /* expr */, py_attrs == Py_None?NULL:PyList_AsStringList(req, py_attrs, "attrs"),
NULL /* controls */, NULL, NULL, NULL);
PyErr_LDB_ERROR_IS_ERR_RAISE(ret, mod->ldb);
@@ -1256,6 +1265,21 @@ PyTypeObject PyLdbModule = {
.tp_flags = Py_TPFLAGS_DEFAULT,
};
+
+/**
+ * Create a ldb_message_element from a Python object.
+ *
+ * This will accept any sequence objects that contains strings, or
+ * a string object.
+ *
+ * A reference to set_obj will be borrowed.
+ *
+ * @param mem_ctx Memory context
+ * @param set_obj Python object to convert
+ * @param flags ldb_message_element flags to set
+ * @param attr_name Name of the attribute
+ * @return New ldb_message_element, allocated as child of mem_ctx
+ */
struct ldb_message_element *PyObject_AsMessageElement(TALLOC_CTX *mem_ctx,
PyObject *set_obj, int flags,
const char *attr_name)
@@ -1273,9 +1297,7 @@ struct ldb_message_element *PyObject_AsMessageElement(TALLOC_CTX *mem_ctx,
me->num_values = 1;
me->values = talloc_array(me, struct ldb_val, me->num_values);
me->values[0].length = PyString_Size(set_obj);
- me->values[0].data = (uint8_t *)talloc_strndup(me->values,
- PyString_AsString(set_obj),
- me->values[0].length);
+ me->values[0].data = (uint8_t *)PyString_AsString(set_obj);
} else if (PySequence_Check(set_obj)) {
int i;
me->num_values = PySequence_Size(set_obj);
diff --git a/source4/lib/ldb/tests/python/api.py b/source4/lib/ldb/tests/python/api.py
index c372b8fa71..07500e2372 100755
--- a/source4/lib/ldb/tests/python/api.py
+++ b/source4/lib/ldb/tests/python/api.py
@@ -258,6 +258,19 @@ class SimpleLdb(unittest.TestCase):
l = ldb.Ldb(filename())
l.set_debug(my_report_fn)
+ def test_zero_byte_string(self):
+ """Testing we do not get trapped in the \0 byte in a property string."""
+ l = ldb.Ldb(filename())
+ l.add({
+ "dn" : "dc=somedn",
+ "objectclass" : "user",
+ "cN" : "LDAPtestUSER",
+ "givenname" : "ldap",
+ "displayname" : "foo\0bar",
+ })
+ res = l.search(expression="(dn=dc=somedn)")
+ self.assertEquals("foo\0bar", res[0]["displayname"][0])
+
class DnTests(unittest.TestCase):
def setUp(self):