From a760f169f4936d7e2677db9229181e2c5ac23bcd Mon Sep 17 00:00:00 2001 From: Nadezhda Ivanova Date: Fri, 20 Nov 2009 13:22:38 +0200 Subject: [PATCH] Some changes to allow processing of ldap controls on modify requests. ldap_backend used to filter out ldap controls on modify. Also, modified python binding for ldap_modify to allow writing tests for such controls. --- source4/ldap_server/ldap_backend.c | 2 +- source4/lib/ldb/common/ldb.c | 17 ++++-- source4/lib/ldb/include/ldb.h | 18 +++++++ source4/lib/ldb/pyldb.c | 61 +++++++++++++++++++++- source4/scripting/python/pyglue.c | 6 +++ source4/scripting/python/samba/__init__.py | 12 +++-- 6 files changed, 106 insertions(+), 10 deletions(-) diff --git a/source4/ldap_server/ldap_backend.c b/source4/ldap_server/ldap_backend.c index 8c6b8f9fd6..5eabda972e 100644 --- a/source4/ldap_server/ldap_backend.c +++ b/source4/ldap_server/ldap_backend.c @@ -546,7 +546,7 @@ reply: NT_STATUS_HAVE_NO_MEMORY(modify_reply); if (result == LDAP_SUCCESS) { - ldb_ret = ldb_modify(samdb, msg); + ldb_ret = ldb_modify_ctrl(samdb, msg, call->request->controls); result = map_ldb_error(local_ctx, ldb_ret, &errstr); } diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index 20e32064ec..3a8023ac93 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -1378,10 +1378,11 @@ int ldb_add(struct ldb_context *ldb, } /* - modify the specified attributes of a record + same as ldb_modify, but accepts controls */ -int ldb_modify(struct ldb_context *ldb, - const struct ldb_message *message) +int ldb_modify_ctrl(struct ldb_context *ldb, + const struct ldb_message *message, + struct ldb_control **controls) { struct ldb_request *req; int ret; @@ -1393,7 +1394,7 @@ int ldb_modify(struct ldb_context *ldb, ret = ldb_build_mod_req(&req, ldb, ldb, message, - NULL, + controls, NULL, ldb_op_default_callback, NULL); @@ -1406,6 +1407,14 @@ int ldb_modify(struct ldb_context *ldb, talloc_free(req); return ret; } +/* + modify the specified attributes of a record +*/ +int ldb_modify(struct ldb_context *ldb, + const struct ldb_message *message) +{ + return ldb_modify_ctrl(ldb, message, NULL); +} /* diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index 1d0b533a33..62cd2b8c64 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -1208,6 +1208,24 @@ int ldb_search(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, int ldb_add(struct ldb_context *ldb, const struct ldb_message *message); +/** + Modify the specified attributes of a record + + This function modifies a record that is in the database. + + \param ldb the context associated with the database (from + ldb_init()) + \param message the message containing the changes required. + + \param controls ldap controls for the request + + \return result code (LDB_SUCCESS if the record was modified as + requested, otherwise a failure code) +*/ +int ldb_modify_ctrl(struct ldb_context *ldb, + const struct ldb_message *message, + struct ldb_control **controls); + /** Modify the specified attributes of a record diff --git a/source4/lib/ldb/pyldb.c b/source4/lib/ldb/pyldb.c index 1f1dcf8e31..0d1d2fa966 100644 --- a/source4/lib/ldb/pyldb.c +++ b/source4/lib/ldb/pyldb.c @@ -641,16 +641,73 @@ static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwa static PyObject *py_ldb_modify(PyLdbObject *self, PyObject *args) { PyObject *py_msg; + PyObject *py_controls = Py_None; + struct ldb_context *ldb_ctx; + struct ldb_request *req; + struct ldb_control **parsed_controls; + struct ldb_message *msg; int ret; - if (!PyArg_ParseTuple(args, "O", &py_msg)) + if (!PyArg_ParseTuple(args, "O|O", &py_msg, &py_controls)) return NULL; + ldb_ctx = PyLdb_AsLdbContext(self); + + if (py_controls == Py_None) { + parsed_controls = NULL; + } else { + const char **controls = PyList_AsStringList(ldb_ctx, py_controls, "controls"); + parsed_controls = ldb_parse_control_strings(ldb_ctx, ldb_ctx, controls); + talloc_free(controls); + } + if (!PyLdbMessage_Check(py_msg)) { PyErr_SetString(PyExc_TypeError, "Expected Ldb Message"); return NULL; } + msg = PyLdbMessage_AsMessage(py_msg); + + ret = ldb_msg_sanity_check(ldb_ctx, msg); + if (ret != LDB_SUCCESS) { + PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, PyLdb_AsLdbContext(self)); + return NULL; + } - ret = ldb_modify(PyLdb_AsLdbContext(self), PyLdbMessage_AsMessage(py_msg)); + ret = ldb_build_mod_req(&req, ldb_ctx, ldb_ctx, + msg, + parsed_controls, + NULL, + ldb_op_default_callback, + NULL); + + if (ret != LDB_SUCCESS) { + PyErr_SetString(PyExc_TypeError, "failed to build request"); + return NULL; + } + + /* do request and autostart a transaction */ + /* Then let's LDB handle the message error in case of pb as they are meaningful */ + + ret = ldb_transaction_start(ldb_ctx); + if (ret != LDB_SUCCESS) { + talloc_free(req); + PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, PyLdb_AsLdbContext(self)); + } + + ret = ldb_request(ldb_ctx, req); + if (ret == LDB_SUCCESS) { + ret = ldb_wait(req->handle, LDB_WAIT_ALL); + } + + if (ret == LDB_SUCCESS) { + ret = ldb_transaction_commit(ldb_ctx); + } else { + ldb_transaction_cancel(ldb_ctx); + if (ldb_ctx->err_string == NULL) { + /* no error string was setup by the backend */ + ldb_asprintf_errstring(ldb_ctx, "%s (%d)", ldb_strerror(ret), ret); + } + } + talloc_free(req); PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, PyLdb_AsLdbContext(self)); Py_RETURN_NONE; diff --git a/source4/scripting/python/pyglue.c b/source4/scripting/python/pyglue.c index b138e3eeec..9f01102316 100644 --- a/source4/scripting/python/pyglue.c +++ b/source4/scripting/python/pyglue.c @@ -566,6 +566,12 @@ void initglue(void) PyModule_AddObject(m, "DS_DC_FUNCTION_2008", PyInt_FromLong(DS_DC_FUNCTION_2008)); PyModule_AddObject(m, "DS_DC_FUNCTION_2008_R2", PyInt_FromLong(DS_DC_FUNCTION_2008_R2)); + /* "LDAP_SERVER_SD_FLAGS_OID" */ + PyModule_AddObject(m, "SECINFO_OWNER", PyInt_FromLong(SECINFO_OWNER)); + PyModule_AddObject(m, "SECINFO_GROUP", PyInt_FromLong(SECINFO_GROUP)); + PyModule_AddObject(m, "SECINFO_DACL", PyInt_FromLong(SECINFO_DACL)); + PyModule_AddObject(m, "SECINFO_SACL", PyInt_FromLong(SECINFO_SACL)); + /* one of the most annoying things about python scripts is that they don't die when you hit control-C. This fixes that sillyness. As we do all database operations using diff --git a/source4/scripting/python/samba/__init__.py b/source4/scripting/python/samba/__init__.py index 06e276c2d0..f74304c01c 100644 --- a/source4/scripting/python/samba/__init__.py +++ b/source4/scripting/python/samba/__init__.py @@ -241,7 +241,7 @@ class Ldb(ldb.Ldb): """ self.add_ldif(open(ldif_path, 'r').read()) - def add_ldif(self, ldif,controls=None): + def add_ldif(self, ldif, controls=None): """Add data based on a LDIF string. :param ldif: LDIF text. @@ -250,13 +250,13 @@ class Ldb(ldb.Ldb): assert changetype == ldb.CHANGETYPE_NONE self.add(msg,controls) - def modify_ldif(self, ldif): + def modify_ldif(self, ldif, controls=None): """Modify database based on a LDIF string. :param ldif: LDIF text. """ for changetype, msg in self.parse_ldif(ldif): - self.modify(msg) + self.modify(msg, controls) def set_domain_sid(self, sid): """Change the domain SID used by this LDB. @@ -423,3 +423,9 @@ DS_DC_FUNCTION_2003 = glue.DS_DC_FUNCTION_2003 DS_DC_FUNCTION_2008 = glue.DS_DC_FUNCTION_2008 DS_DC_FUNCTION_2008_R2 = glue.DS_DC_FUNCTION_2008_R2 +#LDAP_SERVER_SD_FLAGS_OID flags +SECINFO_OWNER = glue.SECINFO_OWNER +SECINFO_GROUP = glue.SECINFO_GROUP +SECINFO_DACL = glue.SECINFO_DACL +SECINFO_SACL = glue.SECINFO_SACL + -- 2.34.1