diff options
-rw-r--r-- | source4/dsdb/common/util.c | 118 |
1 files changed, 90 insertions, 28 deletions
diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c index 408a959276..811d4745a7 100644 --- a/source4/dsdb/common/util.c +++ b/source4/dsdb/common/util.c @@ -837,52 +837,114 @@ int samdb_msg_add_delete(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struc } /* - add a add attribute value to a message + add an add attribute value to a message or enhance an existing attribute + which has the same name and the add flag set. */ -int samdb_msg_add_addval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, - const char *attr_name, const char *value) +int samdb_msg_add_addval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, + struct ldb_message *msg, const char *attr_name, + const char *value) { struct ldb_message_element *el; - char *a, *v; + struct ldb_val val, *vals; + char *v; + unsigned int i; + bool found = false; int ret; - a = talloc_strdup(mem_ctx, attr_name); - if (a == NULL) - return LDB_ERR_OPERATIONS_ERROR; + v = talloc_strdup(mem_ctx, value); - if (v == NULL) + if (v == NULL) { return LDB_ERR_OPERATIONS_ERROR; - ret = ldb_msg_add_string(msg, a, v); - if (ret != 0) - return ret; - el = ldb_msg_find_element(msg, a); - if (el == NULL) + } + + val.data = (uint8_t *) v; + val.length = strlen(v); + + if (val.length == 0) { + /* allow empty strings as non-existent attributes */ + return LDB_SUCCESS; + } + + for (i = 0; i < msg->num_elements; i++) { + el = &msg->elements[i]; + if ((ldb_attr_cmp(el->name, attr_name) == 0) && + (el->flags == LDB_FLAG_MOD_ADD)) { + found = true; + break; + } + } + if (!found) { + ret = ldb_msg_add_empty(msg, attr_name, LDB_FLAG_MOD_ADD, + &el); + if (ret != LDB_SUCCESS) { + return ret; + } + } + + vals = talloc_realloc(msg, el->values, struct ldb_val, + el->num_values + 1); + if (vals == NULL) { return LDB_ERR_OPERATIONS_ERROR; - el->flags = LDB_FLAG_MOD_ADD; + } + el->values = vals; + el->values[el->num_values] = val; + ++(el->num_values); + return LDB_SUCCESS; } /* - add a delete attribute value to a message + add a delete attribute value to a message or enhance an existing attribute + which has the same name and the delete flag set. */ -int samdb_msg_add_delval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg, - const char *attr_name, const char *value) +int samdb_msg_add_delval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, + struct ldb_message *msg, const char *attr_name, + const char *value) { struct ldb_message_element *el; - char *a, *v; + struct ldb_val val, *vals; + char *v; + unsigned int i; + bool found = false; int ret; - a = talloc_strdup(mem_ctx, attr_name); - if (a == NULL) - return LDB_ERR_OPERATIONS_ERROR; + v = talloc_strdup(mem_ctx, value); - if (v == NULL) + if (v == NULL) { return LDB_ERR_OPERATIONS_ERROR; - ret = ldb_msg_add_string(msg, a, v); - if (ret != 0) - return ret; - el = ldb_msg_find_element(msg, a); - if (el == NULL) + } + + val.data = (uint8_t *) v; + val.length = strlen(v); + + if (val.length == 0) { + /* allow empty strings as non-existent attributes */ + return LDB_SUCCESS; + } + + for (i = 0; i < msg->num_elements; i++) { + el = &msg->elements[i]; + if ((ldb_attr_cmp(el->name, attr_name) == 0) && + (el->flags == LDB_FLAG_MOD_DELETE)) { + found = true; + break; + } + } + if (!found) { + ret = ldb_msg_add_empty(msg, attr_name, LDB_FLAG_MOD_DELETE, + &el); + if (ret != LDB_SUCCESS) { + return ret; + } + } + + vals = talloc_realloc(msg, el->values, struct ldb_val, + el->num_values + 1); + if (vals == NULL) { return LDB_ERR_OPERATIONS_ERROR; - el->flags = LDB_FLAG_MOD_DELETE; + } + el->values = vals; + el->values[el->num_values] = val; + ++(el->num_values); + return LDB_SUCCESS; } |