summaryrefslogtreecommitdiff
path: root/source4/dsdb/samdb
diff options
context:
space:
mode:
Diffstat (limited to 'source4/dsdb/samdb')
-rw-r--r--source4/dsdb/samdb/ldb_modules/linked_attributes.c107
1 files changed, 97 insertions, 10 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/linked_attributes.c b/source4/dsdb/samdb/ldb_modules/linked_attributes.c
index 3ad6f0ca8c..5ebf4efed4 100644
--- a/source4/dsdb/samdb/ldb_modules/linked_attributes.c
+++ b/source4/dsdb/samdb/ldb_modules/linked_attributes.c
@@ -64,8 +64,59 @@ struct la_context {
struct la_op_store *ops;
struct ldb_extended *op_response;
struct ldb_control **op_controls;
+ /*
+ * For futur use
+ * will tell which GC to use for resolving links
+ */
+ char *gc_dns_name;
};
+
+static int handle_verify_name_control(TALLOC_CTX *ctx, struct ldb_context *ldb,
+ struct ldb_control *control, struct la_context *ac)
+{
+ /*
+ * If we are a GC let's remove the control,
+ * if there is a specified GC check that is us.
+ */
+ struct ldb_verify_name_control *lvnc = (struct ldb_verify_name_control *)control->data;
+ if (samdb_is_gc(ldb)) {
+ /* Because we can't easily talloc a struct ldb_dn*/
+ struct ldb_dn **dn = talloc_array(ctx, struct ldb_dn *, 1);
+ int ret = samdb_server_reference_dn(ldb, ctx, dn);
+ const char *dns;
+
+ if (ret != LDB_SUCCESS) {
+ return ldb_operr(ldb);
+ }
+
+ dns = samdb_dn_to_dnshostname(ldb, ctx, *dn);
+ if (!dns) {
+ return ldb_operr(ldb);
+ }
+ if (!lvnc->gc || strcasecmp(dns, lvnc->gc) == 0) {
+ if (!ldb_save_controls(control, ctx, NULL)) {
+ return ldb_operr(ldb);
+ }
+ } else {
+ control->critical = true;
+ }
+ talloc_free(dn);
+ } else {
+ /* For the moment we don't remove the control is this case in order
+ * to fail the request. It's better than having the client thinking
+ * that we honnor its control.
+ * Hopefully only a very small set of usecase should hit this problem.
+ */
+ if (lvnc->gc) {
+ ac->gc_dns_name = talloc_strdup(ac, lvnc->gc);
+ }
+ control->critical = true;
+ }
+
+ return LDB_SUCCESS;
+}
+
static struct la_context *linked_attributes_init(struct ldb_module *module,
struct ldb_request *req)
{
@@ -189,6 +240,7 @@ static int linked_attributes_add(struct ldb_module *module, struct ldb_request *
const char *attr_name;
struct ldb_control *ctrl;
unsigned int i, j;
+ struct ldb_control *control;
int ret;
ldb = ldb_module_get_ctx(module);
@@ -198,23 +250,33 @@ static int linked_attributes_add(struct ldb_module *module, struct ldb_request *
return ldb_next_request(module, req);
}
+ ac = linked_attributes_init(module, req);
+ if (!ac) {
+ return ldb_operr(ldb);
+ }
+
+ control = ldb_request_get_control(req, LDB_CONTROL_VERIFY_NAME_OID);
+ if (control != NULL && control->data != NULL) {
+ ret = handle_verify_name_control(req, ldb, control, ac);
+ if (ret != LDB_SUCCESS) {
+ return ldb_operr(ldb);
+ }
+ }
+
if (!(ctrl = ldb_request_get_control(req, DSDB_CONTROL_APPLY_LINKS))) {
/* don't do anything special for linked attributes, repl_meta_data has done it */
+ talloc_free(ac);
return ldb_next_request(module, req);
}
ctrl->critical = false;
- ac = linked_attributes_init(module, req);
- if (!ac) {
- return ldb_operr(ldb);
- }
-
if (!ac->schema) {
/* without schema, this doesn't make any sense */
talloc_free(ac);
return ldb_next_request(module, req);
}
+
/* Need to ensure we only have forward links being specified */
for (i=0; i < req->op.add.message->num_elements; i++) {
const struct ldb_message_element *el = &req->op.add.message->elements[i];
@@ -409,6 +471,7 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques
/* Determine the effect of the modification */
/* Apply the modify to the linked entry */
+ struct ldb_control *control;
struct ldb_context *ldb;
unsigned int i, j;
struct la_context *ac;
@@ -424,17 +487,26 @@ static int linked_attributes_modify(struct ldb_module *module, struct ldb_reques
return ldb_next_request(module, req);
}
+ ac = linked_attributes_init(module, req);
+ if (!ac) {
+ return ldb_operr(ldb);
+ }
+
+ control = ldb_request_get_control(req, LDB_CONTROL_VERIFY_NAME_OID);
+ if (control != NULL && control->data != NULL) {
+ ret = handle_verify_name_control(req, ldb, control, ac);
+ if (ret != LDB_SUCCESS) {
+ return ldb_operr(ldb);
+ }
+ }
+
if (!(ctrl = ldb_request_get_control(req, DSDB_CONTROL_APPLY_LINKS))) {
/* don't do anything special for linked attributes, repl_meta_data has done it */
+ talloc_free(ac);
return ldb_next_request(module, req);
}
ctrl->critical = false;
- ac = linked_attributes_init(module, req);
- if (!ac) {
- return ldb_operr(ldb);
- }
-
if (!ac->schema) {
/* without schema, this doesn't make any sense */
return ldb_next_request(module, req);
@@ -1089,12 +1161,27 @@ static int linked_attributes_del_transaction(struct ldb_module *module)
return ldb_next_del_trans(module);
}
+static int linked_attributes_ldb_init(struct ldb_module *module)
+{
+ int ret;
+
+ ret = ldb_mod_register_control(module, LDB_CONTROL_VERIFY_NAME_OID);
+ if (ret != LDB_SUCCESS) {
+ ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_ERROR,
+ "verify_name: Unable to register control with rootdse!\n");
+ return ldb_operr(ldb_module_get_ctx(module));
+ }
+
+ return ldb_next_init(module);
+}
+
static const struct ldb_module_ops ldb_linked_attributes_module_ops = {
.name = "linked_attributes",
.add = linked_attributes_add,
.modify = linked_attributes_modify,
.rename = linked_attributes_rename,
+ .init_context = linked_attributes_ldb_init,
.start_transaction = linked_attributes_start_transaction,
.prepare_commit = linked_attributes_prepare_commit,
.del_transaction = linked_attributes_del_transaction,