diff options
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/partition.c | 49 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/rootdse.c | 47 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/schema_fsmo.c | 64 | ||||
-rw-r--r-- | source4/dsdb/samdb/samdb.h | 2 |
4 files changed, 158 insertions, 4 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c index 22826e4f33..9285d6d0d8 100644 --- a/source4/dsdb/samdb/ldb_modules/partition.c +++ b/source4/dsdb/samdb/ldb_modules/partition.c @@ -699,6 +699,50 @@ static int partition_extended_replicated_objects(struct ldb_module *module, stru 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 partition_private_data *data; + struct ldb_dn *schema_dn; + struct partition_context *ac; + struct ldb_module *backend; + int ret; + + schema_dn = talloc_get_type(req->op.extended.data, struct ldb_dn); + if (!schema_dn) { + ldb_debug(module->ldb, LDB_DEBUG_FATAL, "partition_extended: invalid extended data\n"); + return LDB_ERR_PROTOCOL_ERROR; + } + + data = talloc_get_type(module->private_data, struct partition_private_data); + if (!data) { + return LDB_ERR_OPERATIONS_ERROR; + } + + partition = find_partition( data, schema_dn ); + if (!partition) { + return ldb_next_request(module, req); + } + + ac = partition_init_handle(req, module); + if (!ac) { + return LDB_ERR_OPERATIONS_ERROR; + } + + backend = make_module_for_next_request(req, module->ldb, partition->module); + if (!backend) { + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = ldb_request_add_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID, false, partition); + if (ret != LDB_SUCCESS) { + return ret; + } + + return ldb_next_request(backend, req); +} + + /* extended */ static int partition_extended(struct ldb_module *module, struct ldb_request *req) { @@ -708,6 +752,11 @@ static int partition_extended(struct ldb_module *module, struct ldb_request *req 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 ); + } + /* * as the extended operation has no dn * we need to send it to all partitions diff --git a/source4/dsdb/samdb/ldb_modules/rootdse.c b/source4/dsdb/samdb/ldb_modules/rootdse.c index 75f99a139d..97491a2ae3 100644 --- a/source4/dsdb/samdb/ldb_modules/rootdse.c +++ b/source4/dsdb/samdb/ldb_modules/rootdse.c @@ -391,9 +391,50 @@ static int rootdse_init(struct ldb_module *module) return ldb_next_init(module); } +static int rootdse_modify(struct ldb_module *module, struct ldb_request *req) +{ + struct ldb_result *ext_res; + int ret; + struct ldb_dn *schema_dn; + struct ldb_message_element *schemaUpdateNowAttr; + + /* + If dn is not "" we should let it pass through + */ + if (!ldb_dn_is_null(req->op.mod.message->dn)) { + return ldb_next_request(module, req); + } + + /* + dn is empty so check for schemaUpdateNow attribute + "The type of modification and values specified in the LDAP modify operation do not matter." MSDN + */ + schemaUpdateNowAttr = ldb_msg_find_element(req->op.mod.message, "schemaUpdateNow"); + if (!schemaUpdateNowAttr) { + return LDB_ERR_OPERATIONS_ERROR; + } + + schema_dn = samdb_schema_dn(module->ldb); + if (!schema_dn) { + ldb_reset_err_string(module->ldb); + ldb_debug(module->ldb, LDB_DEBUG_WARNING, + "rootdse_modify: no schema dn present: (skip ldb_extended call)\n"); + return ldb_next_request(module, req); + } + + ret = ldb_extended(module->ldb, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID, schema_dn, &ext_res); + if (ret != LDB_SUCCESS) { + return LDB_ERR_OPERATIONS_ERROR; + } + + talloc_free(ext_res); + return ret; +} + _PUBLIC_ const struct ldb_module_ops ldb_rootdse_module_ops = { .name = "rootdse", - .init_context = rootdse_init, - .search = rootdse_search, - .request = rootdse_request + .init_context = rootdse_init, + .search = rootdse_search, + .request = rootdse_request, + .modify = rootdse_modify }; diff --git a/source4/dsdb/samdb/ldb_modules/schema_fsmo.c b/source4/dsdb/samdb/ldb_modules/schema_fsmo.c index a397228723..2acc5c0af4 100644 --- a/source4/dsdb/samdb/ldb_modules/schema_fsmo.c +++ b/source4/dsdb/samdb/ldb_modules/schema_fsmo.c @@ -148,8 +148,70 @@ static int schema_fsmo_add(struct ldb_module *module, struct ldb_request *req) return ldb_next_request(module, req); } +static int schema_fsmo_extended(struct ldb_module *module, struct ldb_request *req) +{ + WERROR status; + struct ldb_dn *schema_dn; + struct dsdb_schema *schema; + char *error_string = NULL; + int ret; + TALLOC_CTX *mem_ctx; + + if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) != 0) { + return ldb_next_request(module, req); + } + + schema_dn = samdb_schema_dn(module->ldb); + if (!schema_dn) { + ldb_reset_err_string(module->ldb); + ldb_debug(module->ldb, LDB_DEBUG_WARNING, + "schema_fsmo_extended: no schema dn present: (skip schema loading)\n"); + return ldb_next_request(module, req); + } + + mem_ctx = talloc_new(module); + if (!mem_ctx) { + ldb_oom(module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + ret = dsdb_schema_from_schema_dn(mem_ctx, module->ldb, + lp_iconv_convenience(ldb_get_opaque(module->ldb, "loadparm")), + schema_dn, &schema, &error_string); + + if (ret == LDB_ERR_NO_SUCH_OBJECT) { + ldb_reset_err_string(module->ldb); + ldb_debug(module->ldb, LDB_DEBUG_WARNING, + "schema_fsmo_extended: no schema head present: (skip schema loading)\n"); + talloc_free(mem_ctx); + return ldb_next_request(module, req); + } + + if (ret != LDB_SUCCESS) { + ldb_asprintf_errstring(module->ldb, + "schema_fsmo_extended: dsdb_schema load failed: %s", + error_string); + talloc_free(mem_ctx); + return ldb_next_request(module, req); + } + + /* Replace the old schema*/ + ret = dsdb_set_schema(module->ldb, schema); + if (ret != LDB_SUCCESS) { + ldb_debug_set(module->ldb, LDB_DEBUG_FATAL, + "schema_fsmo_extended: dsdb_set_schema() failed: %d:%s", + ret, ldb_strerror(ret)); + talloc_free(mem_ctx); + return ret; + } + + talloc_free(mem_ctx); + return LDB_SUCCESS; +} + _PUBLIC_ const struct ldb_module_ops ldb_schema_fsmo_module_ops = { .name = "schema_fsmo", .init_context = schema_fsmo_init, - .add = schema_fsmo_add + .add = schema_fsmo_add, + .extended = schema_fsmo_extended }; diff --git a/source4/dsdb/samdb/samdb.h b/source4/dsdb/samdb/samdb.h index 75aa819ccd..b8a3e16d46 100644 --- a/source4/dsdb/samdb/samdb.h +++ b/source4/dsdb/samdb/samdb.h @@ -90,4 +90,6 @@ struct dsdb_pdc_fsmo { struct ldb_dn *master_dn; }; +#define DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID "1.3.6.1.4.1.7165.4.4.2" + #endif /* __SAMDB_H__ */ |