Some changes to allow processing of ldap controls on modify requests.
authorNadezhda Ivanova <nadezhda.ivanova@postpath.com>
Fri, 20 Nov 2009 11:22:38 +0000 (13:22 +0200)
committerNadezhda Ivanova <nadezhda.ivanova@postpath.com>
Fri, 20 Nov 2009 11:22:38 +0000 (13:22 +0200)
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
source4/lib/ldb/common/ldb.c
source4/lib/ldb/include/ldb.h
source4/lib/ldb/pyldb.c
source4/scripting/python/pyglue.c
source4/scripting/python/samba/__init__.py

index 8c6b8f9fd6c3d4fddc708499a7f2036b04382542..5eabda972e8cfc40e5f0d529ab4c98a58b3817af 100644 (file)
@@ -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);
        }
 
index 20e32064ec8c22b58c741e13b32099050636d857..3a8023ac93b0a097e8a733735a57ead6be0a3c74 100644 (file)
@@ -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);
+}
 
 
 /*
index 1d0b533a332974b496f3c2fe3d6271d067238b49..62cd2b8c64215398c8e20bf345694c10c892bf38 100644 (file)
@@ -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
 
index 1f1dcf8e316bca3ddd1ba2f1fb8fd57850ad1fab..0d1d2fa9668e28c99f8e9fa8256b962e0d5420b4 100644 (file)
@@ -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;
index b138e3eeecea2a94513f21f9b59148d93af1f021..9f0110231646d2e5dea1ed3b8cc28dd832aafcdf 100644 (file)
@@ -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
index 06e276c2d0765afadb6913be81e8bfa3158eb807..f74304c01c5152d99011a0e00d997cfca6cae186 100644 (file)
@@ -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
+