samba-cvs.cvs
[Top] [All Lists]

[SCM] Samba Shared Repository - branch master updated

Subject: [SCM] Samba Shared Repository - branch master updated
From: Simo Sorce
Date: Sat, 30 Jan 2010 00:04:36 -0600 CST
The branch, master has been updated
       via  df7be03... s4:ldb add support for permissive modify control
      from  1876b5a... Fix a really interesting problem found by Volker's 
conversion of sessionsetup SPNEGO to asynchronous code.

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit df7be036d7b4e08b18bd03399847dad41b78be50
Author: Simo Sorce <idra@xxxxxxxxx>
Date:   Sat Jan 30 00:33:22 2010 -0500

    s4:ldb add support for permissive modify control

-----------------------------------------------------------------------

Summary of changes:
 source4/lib/ldb/ldb_tdb/ldb_tdb.c |  120 +++++++++++++++++++++++++++++-------
 1 files changed, 96 insertions(+), 24 deletions(-)


Changeset truncated at 500 lines:

diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c 
b/source4/lib/ldb/ldb_tdb/ldb_tdb.c
index b8b4d39..568fc2a 100644
--- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c
+++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c
@@ -512,7 +512,7 @@ static int msg_delete_attribute(struct ldb_module *module,
 
        el = ldb_msg_find_element(msg, name);
        if (el == NULL) {
-               return -1;
+               return LDB_ERR_NO_SUCH_ATTRIBUTE;
        }
        i = el - msg->elements;
 
@@ -529,13 +529,13 @@ static int msg_delete_attribute(struct ldb_module *module,
        msg->elements = talloc_realloc(msg, msg->elements,
                                       struct ldb_message_element,
                                       msg->num_elements);
-       return 0;
+       return LDB_SUCCESS;
 }
 
 /*
   delete all elements matching an attribute name/value
 
-  return 0 on success, -1 on failure
+  return LDB Error on failure
 */
 static int msg_delete_element(struct ldb_module *module,
                              struct ldb_message *msg,
@@ -550,7 +550,7 @@ static int msg_delete_element(struct ldb_module *module,
 
        found = find_element(msg, name);
        if (found == -1) {
-               return -1;
+               return LDB_ERR_NO_SUCH_ATTRIBUTE;
        }
 
        el = &msg->elements[found];
@@ -566,7 +566,7 @@ static int msg_delete_element(struct ldb_module *module,
 
                        ret = ltdb_index_del_value(module, msg->dn, el, i);
                        if (ret != LDB_SUCCESS) {
-                               return -1;
+                               return ret;
                        }
 
                        if (i<el->num_values-1) {
@@ -578,12 +578,12 @@ static int msg_delete_element(struct ldb_module *module,
 
                        /* per definition we find in a canonicalised message an
                           attribute value only once. So we are finished here */
-                       return 0;
+                       return LDB_SUCCESS;
                }
        }
 
        /* Not found */
-       return -1;
+       return LDB_ERR_NO_SUCH_ATTRIBUTE;
 }
 
 
@@ -605,8 +605,14 @@ int ltdb_modify_internal(struct ldb_module *module,
        struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
        TDB_DATA tdb_key, tdb_data;
        struct ldb_message *msg2;
-       unsigned i, j;
+       unsigned i, j, k;
        int ret = LDB_SUCCESS, idx;
+       struct ldb_control *control_permissive = NULL;
+
+       if (req) {
+               control_permissive = ldb_request_get_control(req,
+                                       LDB_CONTROL_PERMISSIVE_MODIFY_OID);
+       }
 
        tdb_key = ltdb_key(module, msg->dn);
        if (!tdb_key.dptr) {
@@ -652,11 +658,31 @@ int ltdb_modify_internal(struct ldb_module *module,
 
                switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
                case LDB_FLAG_MOD_ADD:
-                       if (el->num_values == 0) {
-                               ldb_asprintf_errstring(ldb, "attribute %s on %s 
specified, but with 0 values (illigal)",
-                                                      el->name, 
ldb_dn_get_linearized(msg2->dn));
-                               ret = LDB_ERR_CONSTRAINT_VIOLATION;
-                               goto done;
+
+                       /* make a copy of the array so that a permissive
+                        * control can remove duplicates without changing the
+                        * original values, but do not copy data as we do not
+                        * need to keep it around once the operation is
+                        * finished */
+                       if (control_permissive) {
+                               el = talloc(msg2, struct ldb_message_element);
+                               if (!el) {
+                                       ret = LDB_ERR_OTHER;
+                                       goto done;
+                               }
+                               el->name = msg->elements[i].name;
+                               el->num_values = msg->elements[i].num_values;
+                               el->values = talloc_array(el, struct ldb_val, 
el->num_values);
+                               for (j = 0; j < el->num_values; j++) {
+                                       el->values[j] = 
msg->elements[i].values[j];
+                               }
+
+                               if (el->num_values == 0) {
+                                       ldb_asprintf_errstring(ldb, "attribute 
%s on %s specified, but with 0 values (illigal)",
+                                                              el->name, 
ldb_dn_get_linearized(msg2->dn));
+                                       ret = LDB_ERR_CONSTRAINT_VIOLATION;
+                                       goto done;
+                               }
                        }
 
                        if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) {
@@ -693,8 +719,19 @@ int ltdb_modify_internal(struct ldb_module *module,
 
                                /* Check that values don't exist yet on multi-
                                   valued attributes or aren't provided twice */
-                               for (j=0; j<el->num_values; j++) {
+                               for (j = 0; j < el->num_values; j++) {
                                        if (ldb_msg_find_val(el2, 
&el->values[j]) != NULL) {
+                                               if (control_permissive) {
+                                                       /* remove this one as 
if it was never added */
+                                                       el->num_values--;
+                                                       for (k = j; k < 
el->num_values; k++) {
+                                                               el->values[k] = 
el->values[k + 1];
+                                                       }
+                                                       j--; /* rewind */
+
+                                                       continue;
+                                               }
+
                                                ldb_asprintf_errstring(ldb, 
"%s: value #%d already exists", el->name, j);
                                                ret = 
LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
                                                goto done;
@@ -734,6 +771,7 @@ int ltdb_modify_internal(struct ldb_module *module,
                        break;
 
                case LDB_FLAG_MOD_REPLACE:
+
                        if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) {
                                /* the RELAX control overrides this
                                   check for replace. This is needed as
@@ -797,23 +835,33 @@ int ltdb_modify_internal(struct ldb_module *module,
 
                        if (msg->elements[i].num_values == 0) {
                                /* Delete the whole attribute */
-                               if (msg_delete_attribute(module, ldb, msg2,
-                                                        msg->elements[i].name) 
!= 0) {
+                               ret = msg_delete_attribute(module, ldb, msg2,
+                                                          
msg->elements[i].name);
+                               if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE &&
+                                   control_permissive) {
+                                       ret = LDB_SUCCESS;
+                               } else {
                                        ldb_asprintf_errstring(ldb, "No such 
attribute: %s for delete on %s",
                                                               
msg->elements[i].name, dn);
-                                       ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
+                               }
+                               if (ret != LDB_SUCCESS) {
                                        goto done;
                                }
                        } else {
                                /* Delete specified values from an attribute */
                                for (j=0; j < msg->elements[i].num_values; j++) 
{
-                                       if (msg_delete_element(module,
-                                                              msg2,
-                                                              
msg->elements[i].name,
-                                                              
&msg->elements[i].values[j]) != 0) {
+                                       ret = msg_delete_element(module,
+                                                                msg2,
+                                                                
msg->elements[i].name,
+                                                                
&msg->elements[i].values[j]);
+                                       if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE &&
+                                           control_permissive) {
+                                               ret = LDB_SUCCESS;
+                                       } else {
                                                ldb_asprintf_errstring(ldb, "No 
matching attribute value when deleting attribute: %s on %s",
                                                                       
msg->elements[i].name, dn);
-                                               ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
+                                       }
+                                       if (ret != LDB_SUCCESS) {
                                                goto done;
                                        }
                                }
@@ -1244,6 +1292,7 @@ static int ltdb_request_destructor(void *ptr)
 static int ltdb_handle_request(struct ldb_module *module,
                               struct ldb_request *req)
 {
+       struct ldb_control *control_permissive;
        struct ldb_context *ldb;
        struct tevent_context *ev;
        struct ltdb_context *ac;
@@ -1253,8 +1302,12 @@ static int ltdb_handle_request(struct ldb_module *module,
 
        ldb = ldb_module_get_ctx(module);
 
+       control_permissive = ldb_request_get_control(req,
+                                       LDB_CONTROL_PERMISSIVE_MODIFY_OID);
+
        for (i = 0; req->controls && req->controls[i]; i++) {
-               if (req->controls[i]->critical) {
+               if (req->controls[i]->critical &&
+                   req->controls[i] != control_permissive) {
                        ldb_asprintf_errstring(ldb, "Unsupported critical 
extension %s",
                                               req->controls[i]->oid);
                        return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
@@ -1306,8 +1359,27 @@ static int ltdb_handle_request(struct ldb_module *module,
        return LDB_SUCCESS;
 }
 
+static int ltdb_init_rootdse(struct ldb_module *module)
+{
+       struct ldb_context *ldb;
+       int ret;
+
+       ldb = ldb_module_get_ctx(module);
+
+       ret = ldb_mod_register_control(module,
+                                      LDB_CONTROL_PERMISSIVE_MODIFY_OID);
+       if (ret != LDB_SUCCESS) {
+               ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_tdb: "
+                         "Unable to register control with rootdse!");
+       }
+
+       /* there can be no module beyond the backend, just return */
+       return LDB_SUCCESS;
+}
+
 static const struct ldb_module_ops ltdb_ops = {
        .name              = "tdb",
+       .init_context      = ltdb_init_rootdse,
        .search            = ltdb_handle_request,
        .add               = ltdb_handle_request,
        .modify            = ltdb_handle_request,
@@ -1401,5 +1473,5 @@ static int ltdb_connect(struct ldb_context *ldb, const 
char *url,
 
 const struct ldb_backend_ops ldb_tdb_backend_ops = {
        .name = "tdb",
-       .connect_fn = ltdb_connect
+       .connect_fn = ltdb_connect,
 };


-- 
Samba Shared Repository

<Prev in Thread] Current Thread [Next in Thread>