[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 = &el;
+ 
+	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