[SCM] Samba Shared Repository - branch v4-0-test updated -
release-4-0-0alpha5-141-gbbe895d
Andrew Bartlett
abartlet at samba.org
Thu Jul 24 01:55:41 GMT 2008
The branch, v4-0-test has been updated
via bbe895db7144b192981fad9ab6bbd3ebacb8d299 (commit)
via 39f9184ddf215f2b512319211c0a05702218ef87 (commit)
from a7bfa1fb1bc6fb8e412990b7ff4c3ce9bc55099d (commit)
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=v4-0-test
- Log -----------------------------------------------------------------
commit bbe895db7144b192981fad9ab6bbd3ebacb8d299
Author: Anatoliy Atanasov <anatoliy.atanasov at postpath.com>
Date: Mon Jul 21 17:04:49 2008 +0300
dsdb_create_prefix_mapping() implementation checks for existing prefix maping in ldb.
if one not found it creates a mapping for it and updates the prefixMap schema attribute in ldb.
commit 39f9184ddf215f2b512319211c0a05702218ef87
Author: Anatoliy Atanasov <anatoliy.atanasov at postpath.com>
Date: Wed Jul 23 09:59:17 2008 +0300
Handle schema reloading request.
The ldif for that operation looks like this:
dn:
changetype: Modify
add: schemaUpdateNow
schemaUpdateNow: 1
It uses the rootdse's object functional attribute schemaUpdateNow.
In rootdse_modify() this command is being recognized and it is send as extended operation with DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID.
In the partition module its dispatched to the schema_fsmo module.
The request is processed in the schema_fsmo module by schema_fsmo_extended().
-----------------------------------------------------------------------
Summary of changes:
source/dsdb/samdb/ldb_modules/partition.c | 49 +++++
source/dsdb/samdb/ldb_modules/rootdse.c | 47 ++++-
source/dsdb/samdb/ldb_modules/schema_fsmo.c | 64 ++++++-
source/dsdb/samdb/samdb.h | 2 +
source/dsdb/schema/schema_init.c | 293 +++++++++++++++++++++++----
5 files changed, 415 insertions(+), 40 deletions(-)
Changeset truncated at 500 lines:
diff --git a/source/dsdb/samdb/ldb_modules/partition.c b/source/dsdb/samdb/ldb_modules/partition.c
index 22826e4..9285d6d 100644
--- a/source/dsdb/samdb/ldb_modules/partition.c
+++ b/source/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/source/dsdb/samdb/ldb_modules/rootdse.c b/source/dsdb/samdb/ldb_modules/rootdse.c
index 75f99a1..97491a2 100644
--- a/source/dsdb/samdb/ldb_modules/rootdse.c
+++ b/source/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/source/dsdb/samdb/ldb_modules/schema_fsmo.c b/source/dsdb/samdb/ldb_modules/schema_fsmo.c
index a397228..2acc5c0 100644
--- a/source/dsdb/samdb/ldb_modules/schema_fsmo.c
+++ b/source/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/source/dsdb/samdb/samdb.h b/source/dsdb/samdb/samdb.h
index 75aa819..b8a3e16 100644
--- a/source/dsdb/samdb/samdb.h
+++ b/source/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__ */
diff --git a/source/dsdb/schema/schema_init.c b/source/dsdb/schema/schema_init.c
index 71d952b..2ec5ad3 100644
--- a/source/dsdb/schema/schema_init.c
+++ b/source/dsdb/schema/schema_init.c
@@ -268,18 +268,145 @@ WERROR dsdb_verify_oid_mappings_drsuapi(const struct dsdb_schema *schema, const
WERROR dsdb_map_oid2int(const struct dsdb_schema *schema, const char *in, uint32_t *out)
{
+ return dsdb_find_prefix_for_oid(schema->num_prefixes, schema->prefixes, in, out);
+}
+
+
+WERROR dsdb_map_int2oid(const struct dsdb_schema *schema, uint32_t in, TALLOC_CTX *mem_ctx, const char **out)
+{
uint32_t i;
for (i=0; i < schema->num_prefixes; i++) {
+ const char *val;
+ if (schema->prefixes[i].id != (in & 0xFFFF0000)) {
+ continue;
+ }
+
+ val = talloc_asprintf(mem_ctx, "%s%u",
+ schema->prefixes[i].oid,
+ in & 0xFFFF);
+ W_ERROR_HAVE_NO_MEMORY(val);
+
+ *out = val;
+ return WERR_OK;
+ }
+
+ return WERR_DS_NO_MSDS_INTID;
+}
+
+/*
+ * this function is called from within a ldb transaction from the schema_fsmo module
+ */
+WERROR dsdb_create_prefix_mapping(struct ldb_context *ldb, struct dsdb_schema *schema, const char *full_oid)
+{
+ WERROR status;
+ uint32_t num_prefixes;
+ struct dsdb_schema_oid_prefix *prefixes;
+ struct ldb_val ndr_blob;
+ TALLOC_CTX *mem_ctx;
+ uint32_t out;
+
+ mem_ctx = talloc_new(ldb);
+ W_ERROR_HAVE_NO_MEMORY(mem_ctx);
+
+ /* Read prefixes from disk*/
+ status = dsdb_read_prefixes_from_ldb( mem_ctx, ldb, &num_prefixes, &prefixes );
+ if (!W_ERROR_IS_OK(status)) {
+ DEBUG(0,("dsdb_create_prefix_mapping: dsdb_read_prefixes_from_ldb failed\n"));
+ talloc_free(mem_ctx);
+ return status;
+ }
+
+ /* Check if there is a prefix for the oid in the prefixes array*/
+ status = dsdb_find_prefix_for_oid( num_prefixes, prefixes, full_oid, &out );
+ if (W_ERROR_IS_OK(status)) {
+ /* prefix found*/
+ talloc_free(mem_ctx);
+ return status;
+ }
+ /* Update prefix map in ldb*/
+ /* Update the prefixes */
+ status = dsdb_prefix_map_update(mem_ctx, &num_prefixes, &prefixes, full_oid);
+ if (!W_ERROR_IS_OK(status)) {
+ DEBUG(0,("dsdb_create_prefix_mapping: dsdb_prefix_map_update failed\n"));
+ talloc_free(mem_ctx);
+ return status;
+ }
+ /* Convert prefixes in ndr blob*/
+ status = dsdb_write_prefixes_to_ndr( mem_ctx, ldb, num_prefixes, prefixes, &ndr_blob );
+ if (!W_ERROR_IS_OK(status)) {
+ DEBUG(0,("dsdb_create_prefix_mapping: dsdb_write_prefixes_to_ndr failed\n"));
+ talloc_free(mem_ctx);
+ return status;
+ }
+
+ /* Update prefixMap in ldb*/
+ status = dsdb_write_prefixes_to_ldb( mem_ctx, ldb, &ndr_blob );
+ if (!W_ERROR_IS_OK(status)) {
+ DEBUG(0,("dsdb_create_prefix_mapping: dsdb_write_prefixes_to_ldb failed\n"));
+ talloc_free(mem_ctx);
+ return status;
+ }
+
+ talloc_free(mem_ctx);
+ return status;
+}
+
+WERROR dsdb_prefix_map_update(TALLOC_CTX *mem_ctx, uint32_t *num_prefixes, struct dsdb_schema_oid_prefix **prefixes, const char *oid)
+{
+ uint32_t new_num_prefixes, index_new_prefix, new_entry_id;
+ const char* lastDotOffset;
+ size_t size;
+
+ new_num_prefixes = *num_prefixes + 1;
+ index_new_prefix = *num_prefixes;
+ new_entry_id = (*num_prefixes)<<16;
+
+ /* Extract the prefix from the oid*/
+ lastDotOffset = strrchr(oid, '.');
+ if (lastDotOffset == NULL) {
+ DEBUG(0,("dsdb_prefix_map_update: failed to find the last dot\n"));
+ return WERR_NOT_FOUND;
+ }
+
+ /* Calculate the size of the remainig string that should be the prefix of it */
+ size = strlen(oid) - strlen(lastDotOffset);
+ if (size <= 0) {
+ DEBUG(0,("dsdb_prefix_map_update: size of the remaining string invalid\n"));
+ return WERR_FOOBAR;
+ }
+ /* Add one because we need to copy the dot */
+ size += 1;
+
+ /* Create a spot in the prefixMap for one more prefix*/
+ (*prefixes) = talloc_realloc(mem_ctx, *prefixes, struct dsdb_schema_oid_prefix, new_num_prefixes);
+ W_ERROR_HAVE_NO_MEMORY(*prefixes);
+
+ /* Add the new prefix entry*/
+ (*prefixes)[index_new_prefix].id = new_entry_id;
+ (*prefixes)[index_new_prefix].oid = talloc_strndup(mem_ctx, oid, size);
+ (*prefixes)[index_new_prefix].oid_len = strlen((*prefixes)[index_new_prefix].oid);
+
+ /* Increase num_prefixes because new prefix has been added */
+ ++(*num_prefixes);
+
+ return WERR_OK;
+}
+
+WERROR dsdb_find_prefix_for_oid(uint32_t num_prefixes, const struct dsdb_schema_oid_prefix *prefixes, const char *in, uint32_t *out)
+{
+ uint32_t i;
+
+ for (i=0; i < num_prefixes; i++) {
const char *val_str;
char *end_str;
unsigned val;
- if (strncmp(schema->prefixes[i].oid, in, schema->prefixes[i].oid_len) != 0) {
+ if (strncmp(prefixes[i].oid, in, prefixes[i].oid_len) != 0) {
continue;
}
- val_str = in + schema->prefixes[i].oid_len;
+ val_str = in + prefixes[i].oid_len;
end_str = NULL;
errno = 0;
@@ -305,58 +432,152 @@ WERROR dsdb_map_oid2int(const struct dsdb_schema *schema, const char *in, uint32
return WERR_INVALID_PARAM;
}
- *out = schema->prefixes[i].id | val;
+ *out = prefixes[i].id | val;
return WERR_OK;
}
return WERR_DS_NO_MSDS_INTID;
}
-WERROR dsdb_map_int2oid(const struct dsdb_schema *schema, uint32_t in, TALLOC_CTX *mem_ctx, const char **out)
+WERROR dsdb_write_prefixes_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, struct ldb_val *ndr_blob)
{
+ struct ldb_message msg;
+ struct ldb_dn *schema_dn;
+ struct ldb_message_element el;
+ int ret;
+
+ schema_dn = samdb_schema_dn(ldb);
+ if (!schema_dn) {
+ DEBUG(0,("dsdb_write_prefixes_to_ldb: no schema dn present\n"));
+ return WERR_FOOBAR;
+ }
+
+ el.num_values = 1;
+ el.values = ndr_blob;
+ el.flags = LDB_FLAG_MOD_REPLACE;
+ el.name = talloc_strdup(mem_ctx, "prefixMap");
+
+ msg.dn = ldb_dn_copy(mem_ctx, schema_dn);
+ msg.num_elements = 1;
+ msg.elements = ⪙
+
+ ret = ldb_modify( ldb, &msg );
+ if (ret != 0) {
+ DEBUG(0,("dsdb_write_prefixes_to_ldb: ldb_modify failed\n"));
+ return WERR_FOOBAR;
+ }
+
+ return WERR_OK;
+}
+
+WERROR dsdb_read_prefixes_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, uint32_t* num_prefixes, struct dsdb_schema_oid_prefix **prefixes)
+{
+ struct prefixMapBlob *blob;
+ enum ndr_err_code ndr_err;
uint32_t i;
+ const struct ldb_val *prefix_val;
+ struct ldb_dn *schema_dn;
+ struct ldb_result *schema_res;
+ int ret;
+ static const char *schema_attrs[] = {
+ "prefixMap",
+ NULL
+ };
- for (i=0; i < schema->num_prefixes; i++) {
- const char *val;
- if (schema->prefixes[i].id != (in & 0xFFFF0000)) {
- continue;
- }
+ schema_dn = samdb_schema_dn(ldb);
+ if (!schema_dn) {
+ DEBUG(0,("dsdb_read_prefixes_from_ldb: no schema dn present\n"));
+ return WERR_FOOBAR;
+ }
- val = talloc_asprintf(mem_ctx, "%s%u",
- schema->prefixes[i].oid,
- in & 0xFFFF);
- W_ERROR_HAVE_NO_MEMORY(val);
+ ret = ldb_search(ldb, schema_dn, LDB_SCOPE_BASE,NULL, schema_attrs,&schema_res);
+ if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+ DEBUG(0,("dsdb_read_prefixes_from_ldb: no prefix map present\n"));
+ return WERR_FOOBAR;
+ } else if (ret != LDB_SUCCESS) {
+ DEBUG(0,("dsdb_read_prefixes_from_ldb: failed to search the schema head\n"));
+ return WERR_FOOBAR;
+ }
- *out = val;
- return WERR_OK;
+ prefix_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "prefixMap");
+ if (!prefix_val) {
+ DEBUG(0,("dsdb_read_prefixes_from_ldb: no prefixMap attribute found\n"));
+ return WERR_FOOBAR;
}
- return WERR_DS_NO_MSDS_INTID;
+ blob = talloc(mem_ctx, struct prefixMapBlob);
+ W_ERROR_HAVE_NO_MEMORY(blob);
+
+ ndr_err = ndr_pull_struct_blob(prefix_val, blob,
+ lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
+ blob,
+ (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DEBUG(0,("dsdb_read_prefixes_from_ldb: ndr_pull_struct_blob failed\n"));
+ talloc_free(blob);
+ return WERR_FOOBAR;
+ }
+
+ if (blob->version != PREFIX_MAP_VERSION_DSDB) {
+ DEBUG(0,("dsdb_read_prefixes_from_ldb: blob->version incorect\n"));
+ talloc_free(blob);
+ return WERR_FOOBAR;
+ }
+
+ *num_prefixes = blob->ctr.dsdb.num_mappings;
+ *prefixes = talloc_array(mem_ctx, struct dsdb_schema_oid_prefix, *num_prefixes);
+ if(!(*prefixes)) {
+ talloc_free(blob);
+ return WERR_NOMEM;
+ }
+ for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
+ (*prefixes)[i].id = blob->ctr.dsdb.mappings[i].id_prefix<<16;
+ (*prefixes)[i].oid = talloc_strdup(mem_ctx, blob->ctr.dsdb.mappings[i].oid.oid);
+ (*prefixes)[i].oid = talloc_asprintf_append((*prefixes)[i].oid, ".");
+ (*prefixes)[i].oid_len = strlen(blob->ctr.dsdb.mappings[i].oid.oid);
+ }
+
+ talloc_free(blob);
+ return WERR_OK;
}
-/*
- * this function is called from within a ldb transaction from the schema_fsmo module
- */
-WERROR dsdb_create_prefix_mapping(struct ldb_context *ldb, struct dsdb_schema *schema, const char *full_oid)
+
+WERROR dsdb_write_prefixes_to_ndr(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, uint32_t num_prefixes, const struct dsdb_schema_oid_prefix *prefixes, struct ldb_val *out)
{
- /*
- * TODO:
--
Samba Shared Repository
More information about the samba-cvs
mailing list