diff options
Diffstat (limited to 'source4/dsdb/samdb/ldb_modules')
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/partition.c | 162 |
1 files changed, 86 insertions, 76 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c index 563abf672a..515d437861 100644 --- a/source4/dsdb/samdb/ldb_modules/partition.c +++ b/source4/dsdb/samdb/ldb_modules/partition.c @@ -40,8 +40,13 @@ #include "lib/ldb/include/ldb_private.h" #include "dsdb/samdb/samdb.h" +struct dsdb_partition { + struct ldb_module *module; + struct dsdb_control_current_partition *ctrl; +}; + struct partition_private_data { - struct dsdb_control_current_partition **partitions; + struct dsdb_partition **partitions; struct ldb_dn **replicate; }; @@ -139,16 +144,32 @@ static int partition_request(struct ldb_module *module, struct ldb_request *requ return ret; } -static struct dsdb_control_current_partition *find_partition(struct partition_private_data *data, - struct ldb_dn *dn) +static struct dsdb_partition *find_partition(struct partition_private_data *data, + struct ldb_dn *dn, + struct ldb_request *req) { int i; + struct ldb_control *partition_ctrl; + + /* see if the request has the partition DN specified in a + * control. The repl_meta_data module can specify this to + * ensure that replication happens to the right partition + */ + partition_ctrl = ldb_request_get_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID); + if (partition_ctrl) { + const struct dsdb_control_current_partition *partition; + partition = talloc_get_type(partition_ctrl->data, + struct dsdb_control_current_partition); + if (partition != NULL) { + dn = partition->dn; + } + } /* Look at base DN */ /* Figure out which partition it is under */ /* Skip the lot if 'data' isn't here yet (initialisation) */ for (i=0; data && data->partitions && data->partitions[i]; i++) { - if (ldb_dn_compare_base(data->partitions[i]->dn, dn) == 0) { + if (ldb_dn_compare_base(data->partitions[i]->ctrl->dn, dn) == 0) { return data->partitions[i]; } } @@ -239,7 +260,7 @@ static int partition_req_callback(struct ldb_request *req, } static int partition_prep_request(struct partition_context *ac, - struct dsdb_control_current_partition *partition) + struct dsdb_partition *partition) { int ret; struct ldb_request *req; @@ -326,20 +347,22 @@ static int partition_prep_request(struct partition_context *ac, if (partition) { ac->part_req[ac->num_requests].module = partition->module; - ret = ldb_request_add_control(req, - DSDB_CONTROL_CURRENT_PARTITION_OID, - false, partition); - if (ret != LDB_SUCCESS) { - return ret; + if (!ldb_request_get_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID)) { + ret = ldb_request_add_control(req, + DSDB_CONTROL_CURRENT_PARTITION_OID, + false, partition->ctrl); + if (ret != LDB_SUCCESS) { + return ret; + } } if (req->operation == LDB_SEARCH) { /* If the search is for 'more' than this partition, * then change the basedn, so a remote LDAP server * doesn't object */ - if (ldb_dn_compare_base(partition->dn, + if (ldb_dn_compare_base(partition->ctrl->dn, req->op.search.base) != 0) { - req->op.search.base = partition->dn; + req->op.search.base = partition->ctrl->dn; } } @@ -393,7 +416,7 @@ static int partition_replicate(struct ldb_module *module, struct ldb_request *re struct partition_context *ac; unsigned i; int ret; - struct dsdb_control_current_partition *partition; + struct dsdb_partition *partition; struct partition_private_data *data = talloc_get_type(module->private_data, struct partition_private_data); if (!data || !data->partitions) { @@ -419,7 +442,7 @@ static int partition_replicate(struct ldb_module *module, struct ldb_request *re /* Otherwise, we need to find the partition to fire it to */ /* Find partition */ - partition = find_partition(data, dn); + partition = find_partition(data, dn, req); if (!partition) { /* * if we haven't found a matching partition @@ -520,19 +543,19 @@ static int partition_search(struct ldb_module *module, struct ldb_request *req) or 3) the DN we are looking for is a child of the partition */ - if (ldb_dn_compare(data->partitions[i]->dn, req->op.search.base) == 0) { + if (ldb_dn_compare(data->partitions[i]->ctrl->dn, req->op.search.base) == 0) { match = true; if (req->op.search.scope == LDB_SCOPE_BASE) { stop = true; } } if (!match && - (ldb_dn_compare_base(req->op.search.base, data->partitions[i]->dn) == 0 && + (ldb_dn_compare_base(req->op.search.base, data->partitions[i]->ctrl->dn) == 0 && req->op.search.scope != LDB_SCOPE_BASE)) { match = true; } if (!match && - ldb_dn_compare_base(data->partitions[i]->dn, req->op.search.base) == 0) { + ldb_dn_compare_base(data->partitions[i]->ctrl->dn, req->op.search.base) == 0) { match = true; stop = true; /* note that this relies on partition ordering */ } @@ -592,7 +615,7 @@ static int partition_delete(struct ldb_module *module, struct ldb_request *req) static int partition_rename(struct ldb_module *module, struct ldb_request *req) { /* Find backend */ - struct dsdb_control_current_partition *backend, *backend2; + struct dsdb_partition *backend, *backend2; struct partition_private_data *data = talloc_get_type(module->private_data, struct partition_private_data); @@ -602,8 +625,8 @@ static int partition_rename(struct ldb_module *module, struct ldb_request *req) return LDB_ERR_OPERATIONS_ERROR; } - backend = find_partition(data, req->op.rename.olddn); - backend2 = find_partition(data, req->op.rename.newdn); + backend = find_partition(data, req->op.rename.olddn, req); + backend2 = find_partition(data, req->op.rename.newdn, req); if ((backend && !backend2) || (!backend && backend2)) { return LDB_ERR_AFFECTS_MULTIPLE_DSAS; @@ -613,9 +636,9 @@ static int partition_rename(struct ldb_module *module, struct ldb_request *req) ldb_asprintf_errstring(ldb_module_get_ctx(module), "Cannot rename from %s in %s to %s in %s: %s", ldb_dn_get_linearized(req->op.rename.olddn), - ldb_dn_get_linearized(backend->dn), + ldb_dn_get_linearized(backend->ctrl->dn), ldb_dn_get_linearized(req->op.rename.newdn), - ldb_dn_get_linearized(backend2->dn), + ldb_dn_get_linearized(backend2->ctrl->dn), ldb_strerror(LDB_ERR_AFFECTS_MULTIPLE_DSAS)); return LDB_ERR_AFFECTS_MULTIPLE_DSAS; } @@ -834,12 +857,14 @@ static int partition_sequence_number(struct ldb_module *module, struct ldb_reque return ret; } - ret = ldb_request_add_control(treq, - DSDB_CONTROL_CURRENT_PARTITION_OID, - false, data->partitions[i]); - if (ret != LDB_SUCCESS) { - talloc_free(res); - return ret; + if (!ldb_request_get_control(treq, DSDB_CONTROL_CURRENT_PARTITION_OID)) { + ret = ldb_request_add_control(treq, + DSDB_CONTROL_CURRENT_PARTITION_OID, + false, data->partitions[i]->ctrl); + if (ret != LDB_SUCCESS) { + talloc_free(res); + return ret; + } } ret = partition_request(data->partitions[i]->module, treq); @@ -933,12 +958,14 @@ static int partition_sequence_number(struct ldb_module *module, struct ldb_reque return ret; } - ret = ldb_request_add_control(treq, - DSDB_CONTROL_CURRENT_PARTITION_OID, - false, data->partitions[i]); - if (ret != LDB_SUCCESS) { - talloc_free(res); - return ret; + if (!ldb_request_get_control(treq, DSDB_CONTROL_CURRENT_PARTITION_OID)) { + ret = ldb_request_add_control(treq, + DSDB_CONTROL_CURRENT_PARTITION_OID, + false, data->partitions[i]->ctrl); + if (ret != LDB_SUCCESS) { + talloc_free(res); + return ret; + } } ret = partition_request(data->partitions[i]->module, treq); @@ -1005,28 +1032,9 @@ static int partition_sequence_number(struct ldb_module *module, struct ldb_reque return ldb_module_done(req, NULL, ext, LDB_SUCCESS); } -static int partition_extended_replicated_objects(struct ldb_module *module, struct ldb_request *req) -{ - struct dsdb_extended_replicated_objects *ext; - - ext = talloc_get_type(req->op.extended.data, struct dsdb_extended_replicated_objects); - if (!ext) { - ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_FATAL, "partition_extended_replicated_objects: invalid extended data\n"); - return LDB_ERR_PROTOCOL_ERROR; - } - - if (ext->version != DSDB_EXTENDED_REPLICATED_OBJECTS_VERSION) { - ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_FATAL, "partition_extended_replicated_objects: extended data invalid version [%u != %u]\n", - ext->version, DSDB_EXTENDED_REPLICATED_OBJECTS_VERSION); - return LDB_ERR_PROTOCOL_ERROR; - } - - return partition_replicate(module, req, ext->partition_dn); -} - static int partition_extended_schema_update_now(struct ldb_module *module, struct ldb_request *req) { - struct dsdb_control_current_partition *partition; + struct dsdb_partition *partition; struct partition_private_data *data; struct ldb_dn *schema_dn; struct partition_context *ac; @@ -1043,7 +1051,7 @@ static int partition_extended_schema_update_now(struct ldb_module *module, struc return LDB_ERR_OPERATIONS_ERROR; } - partition = find_partition( data, schema_dn ); + partition = find_partition( data, schema_dn, req); if (!partition) { return ldb_next_request(module, req); } @@ -1085,10 +1093,6 @@ static int partition_extended(struct ldb_module *module, struct ldb_request *req return partition_sequence_number(module, req); } - if (strcmp(req->op.extended.oid, DSDB_EXTENDED_REPLICATED_OBJECTS_OID) == 0) { - return partition_extended_replicated_objects(module, req); - } - /* forward schemaUpdateNow operation to schema_fsmo module*/ if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) == 0) { return partition_extended_schema_update_now( module, req ); @@ -1109,13 +1113,13 @@ static int partition_extended(struct ldb_module *module, struct ldb_request *req static int partition_sort_compare(const void *v1, const void *v2) { - const struct dsdb_control_current_partition *p1; - const struct dsdb_control_current_partition *p2; + const struct dsdb_partition *p1; + const struct dsdb_partition *p2; - p1 = *((struct dsdb_control_current_partition * const*)v1); - p2 = *((struct dsdb_control_current_partition * const*)v2); + p1 = *((struct dsdb_partition * const*)v1); + p2 = *((struct dsdb_partition * const*)v2); - return ldb_dn_compare(p1->dn, p2->dn); + return ldb_dn_compare(p1->ctrl->dn, p2->ctrl->dn); } static int partition_init(struct ldb_module *module) @@ -1165,7 +1169,7 @@ static int partition_init(struct ldb_module *module) talloc_free(mem_ctx); return LDB_ERR_CONSTRAINT_VIOLATION; } - data->partitions = talloc_array(data, struct dsdb_control_current_partition *, partition_attributes->num_values + 1); + data->partitions = talloc_array(data, struct dsdb_partition *, partition_attributes->num_values + 1); if (!data->partitions) { talloc_free(mem_ctx); return LDB_ERR_OPERATIONS_ERROR; @@ -1173,6 +1177,8 @@ static int partition_init(struct ldb_module *module) for (i=0; i < partition_attributes->num_values; i++) { char *base = talloc_strdup(data->partitions, (char *)partition_attributes->values[i].data); char *p = strchr(base, ':'); + const char *backend; + if (!p) { ldb_asprintf_errstring(ldb_module_get_ctx(module), "partition_init: " @@ -1189,30 +1195,34 @@ static int partition_init(struct ldb_module *module) talloc_free(mem_ctx); return LDB_ERR_CONSTRAINT_VIOLATION; } - data->partitions[i] = talloc(data->partitions, struct dsdb_control_current_partition); + data->partitions[i] = talloc(data->partitions, struct dsdb_partition); if (!data->partitions[i]) { talloc_free(mem_ctx); return LDB_ERR_OPERATIONS_ERROR; } - data->partitions[i]->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION; - - data->partitions[i]->dn = ldb_dn_new(data->partitions[i], ldb_module_get_ctx(module), base); - if (!data->partitions[i]->dn) { + data->partitions[i]->ctrl = talloc(data->partitions[i], struct dsdb_control_current_partition); + if (!data->partitions[i]->ctrl) { + talloc_free(mem_ctx); + return LDB_ERR_OPERATIONS_ERROR; + } + data->partitions[i]->ctrl->version = DSDB_CONTROL_CURRENT_PARTITION_VERSION; + data->partitions[i]->ctrl->dn = ldb_dn_new(data->partitions[i], ldb_module_get_ctx(module), base); + if (!data->partitions[i]->ctrl->dn) { ldb_asprintf_errstring(ldb_module_get_ctx(module), "partition_init: invalid DN in partition record: %s", base); talloc_free(mem_ctx); return LDB_ERR_CONSTRAINT_VIOLATION; } - data->partitions[i]->backend = samdb_relative_path(ldb_module_get_ctx(module), + backend = samdb_relative_path(ldb_module_get_ctx(module), data->partitions[i], p); - if (!data->partitions[i]->backend) { + if (!backend) { ldb_asprintf_errstring(ldb_module_get_ctx(module), "partition_init: unable to determine an relative path for partition: %s", base); talloc_free(mem_ctx); } - ret = ldb_connect_backend(ldb_module_get_ctx(module), data->partitions[i]->backend, NULL, &data->partitions[i]->module); + ret = ldb_connect_backend(ldb_module_get_ctx(module), backend, NULL, &data->partitions[i]->module); if (ret != LDB_SUCCESS) { talloc_free(mem_ctx); return ret; @@ -1234,7 +1244,7 @@ static int partition_init(struct ldb_module *module) } req->operation = LDB_REQ_REGISTER_PARTITION; - req->op.reg_partition.dn = data->partitions[i]->dn; + req->op.reg_partition.dn = data->partitions[i]->ctrl->dn; req->callback = ldb_op_default_callback; ldb_set_timeout(ldb_module_get_ctx(module), req, 0); @@ -1289,7 +1299,7 @@ static int partition_init(struct ldb_module *module) for (i=0; i < modules_attributes->num_values; i++) { struct ldb_dn *base_dn; int partition_idx; - struct dsdb_control_current_partition *partition = NULL; + struct dsdb_partition *partition = NULL; const char **modules = NULL; char *base = talloc_strdup(data->partitions, (char *)modules_attributes->values[i].data); @@ -1321,7 +1331,7 @@ static int partition_init(struct ldb_module *module) } for (partition_idx = 0; data->partitions[partition_idx]; partition_idx++) { - if (ldb_dn_compare(data->partitions[partition_idx]->dn, base_dn) == 0) { + if (ldb_dn_compare(data->partitions[partition_idx]->ctrl->dn, base_dn) == 0) { partition = data->partitions[partition_idx]; break; } |