summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/dsdb/common/util.c118
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;
}