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;  }  | 
