예제 #1
0
int dsdb_set_schema(struct ldb_context *ldb, struct dsdb_schema *schema)
{
	int ret;

	ret = dsdb_setup_sorted_accessors(ldb, schema);
	if (ret != LDB_SUCCESS) {
		return ret;
	}

	ret = schema_fill_constructed(schema);
	if (ret != LDB_SUCCESS) {
		return ret;
	}

	ret = ldb_set_opaque(ldb, "dsdb_schema", schema);
	if (ret != LDB_SUCCESS) {
		return ret;
	}

	/* Set the new attributes based on the new schema */
	ret = dsdb_schema_set_attributes(ldb, schema, true);
	if (ret != LDB_SUCCESS) {
		return ret;
	}

	talloc_steal(ldb, schema);

	return LDB_SUCCESS;
}
예제 #2
0
파일: schema_set.c 프로젝트: sprymak/samba
/**
 * Attach the schema to an opaque pointer on the ldb,
 * so ldb modules can find it
 */
int dsdb_set_schema(struct ldb_context *ldb, struct dsdb_schema *schema)
{
	struct dsdb_schema *old_schema;
	int ret;

	ret = dsdb_setup_sorted_accessors(ldb, schema);
	if (ret != LDB_SUCCESS) {
		return ret;
	}

	old_schema = ldb_get_opaque(ldb, "dsdb_schema");

	ret = ldb_set_opaque(ldb, "dsdb_schema", schema);
	if (ret != LDB_SUCCESS) {
		return ret;
	}

	/* Remove the reference to the schema we just overwrote - if there was
	 * none, NULL is harmless here */
	if (old_schema != schema) {
		talloc_unlink(ldb, old_schema);
		talloc_steal(ldb, schema);
	}

	ret = ldb_set_opaque(ldb, "dsdb_use_global_schema", NULL);
	if (ret != LDB_SUCCESS) {
		return ret;
	}

	/* Set the new attributes based on the new schema */
	ret = dsdb_schema_set_attributes(ldb, schema, true);
	if (ret != LDB_SUCCESS) {
		return ret;
	}

	return LDB_SUCCESS;
}
예제 #3
0
struct dsdb_schema *dsdb_schema_copy_shallow(TALLOC_CTX *mem_ctx,
					     struct ldb_context *ldb,
					     const struct dsdb_schema *schema)
{
	int ret;
	struct dsdb_class *cls;
	struct dsdb_attribute *attr;
	struct dsdb_schema *schema_copy;

	schema_copy = dsdb_new_schema(mem_ctx);
	if (!schema_copy) {
		return NULL;
	}

	/* schema base_dn */
	schema_copy->base_dn = ldb_dn_copy(schema_copy, schema->base_dn);
	if (!schema_copy->base_dn) {
		goto failed;
	}

	/* copy prexiMap & schemaInfo */
	schema_copy->prefixmap = dsdb_schema_pfm_copy_shallow(schema_copy,
							      schema->prefixmap);
	if (!schema_copy->prefixmap) {
		goto failed;
	}

	schema_copy->schema_info = talloc_strdup(schema_copy, schema->schema_info);

	/* copy classes and attributes*/
	for (cls = schema->classes; cls; cls = cls->next) {
		struct dsdb_class *class_copy = talloc_memdup(schema_copy,
							      cls, sizeof(*cls));
		if (!class_copy) {
			goto failed;
		}
		DLIST_ADD(schema_copy->classes, class_copy);
	}
	schema_copy->num_classes = schema->num_classes;

	for (attr = schema->attributes; attr; attr = attr->next) {
		struct dsdb_attribute *a_copy = talloc_memdup(schema_copy,
							      attr, sizeof(*attr));
		if (!a_copy) {
			goto failed;
		}
		DLIST_ADD(schema_copy->attributes, a_copy);
	}
	schema_copy->num_attributes = schema->num_attributes;

	/* rebuild indexes */
	ret = dsdb_setup_sorted_accessors(ldb, schema_copy);
	if (ret != LDB_SUCCESS) {
		goto failed;
	}

	/* leave reload_seq_number = 0 so it will be refresh ASAP */
	schema_copy->refresh_fn = schema->refresh_fn;
	schema_copy->loaded_from_module = schema->loaded_from_module;

	return schema_copy;

failed:
	talloc_free(schema_copy);
	return NULL;
}
예제 #4
0
static WERROR dsdb_repl_merge_working_schema(struct ldb_context *ldb,
					     struct dsdb_schema *dest_schema,
					     const struct dsdb_schema *ref_schema)
{
	const struct dsdb_class *cur_class = NULL;
	const struct dsdb_attribute *cur_attr = NULL;
	int ret;

	for (cur_class = ref_schema->classes;
	     cur_class;
	     cur_class = cur_class->next)
	{
		const struct dsdb_class *tmp1;
		struct dsdb_class *tmp2;

		tmp1 = dsdb_class_by_governsID_id(dest_schema,
						  cur_class->governsID_id);
		if (tmp1 != NULL) {
			continue;
		}

		/*
		 * Do a shallow copy so that original next and prev are
		 * not modified, we don't need to do a deep copy
		 * as the rest won't be modified and this is for
		 * a short lived object.
		 */
		tmp2 = talloc(dest_schema, struct dsdb_class);
		if (tmp2 == NULL) {
			return WERR_NOMEM;
		}
		*tmp2 = *cur_class;
		DLIST_ADD(dest_schema->classes, tmp2);
	}

	for (cur_attr = ref_schema->attributes;
	     cur_attr;
	     cur_attr = cur_attr->next)
	{
		const struct dsdb_attribute *tmp1;
		struct dsdb_attribute *tmp2;

		tmp1 = dsdb_attribute_by_attributeID_id(dest_schema,
						cur_attr->attributeID_id);
		if (tmp1 != NULL) {
			continue;
		}

		/*
		 * Do a shallow copy so that original next and prev are
		 * not modified, we don't need to do a deep copy
		 * as the rest won't be modified and this is for
		 * a short lived object.
		 */
		tmp2 = talloc(dest_schema, struct dsdb_attribute);
		if (tmp2 == NULL) {
			return WERR_NOMEM;
		}
		*tmp2 = *cur_attr;
		DLIST_ADD(dest_schema->attributes, tmp2);
	}

	ret = dsdb_setup_sorted_accessors(ldb, dest_schema);
	if (LDB_SUCCESS != ret) {
		DEBUG(0,("Failed to add new attribute to reference schema!\n"));
		return WERR_INTERNAL_ERROR;
	}

	return WERR_OK;
}
예제 #5
0
WERROR dsdb_repl_resolve_working_schema(struct ldb_context *ldb,
					TALLOC_CTX *mem_ctx,
					struct dsdb_schema_prefixmap *pfm_remote,
					uint32_t cycle_before_switching,
					struct dsdb_schema *initial_schema,
					struct dsdb_schema *resulting_schema,
					uint32_t object_count,
					const struct drsuapi_DsReplicaObjectListItemEx *first_object)
{
	struct schema_list {
		struct schema_list *next, *prev;
		const struct drsuapi_DsReplicaObjectListItemEx *obj;
	};
	struct schema_list *schema_list = NULL, *schema_list_item, *schema_list_next_item;
	WERROR werr;
	struct dsdb_schema *working_schema;
	const struct drsuapi_DsReplicaObjectListItemEx *cur;
	DATA_BLOB empty_key = data_blob_null;
	int ret, pass_no;
	uint32_t ignore_attids[] = {
			DRSUAPI_ATTID_auxiliaryClass,
			DRSUAPI_ATTID_mayContain,
			DRSUAPI_ATTID_mustContain,
			DRSUAPI_ATTID_possSuperiors,
			DRSUAPI_ATTID_systemPossSuperiors,
			DRSUAPI_ATTID_INVALID
	};

	/* create a list of objects yet to be converted */
	for (cur = first_object; cur; cur = cur->next_object) {
		schema_list_item = talloc(mem_ctx, struct schema_list);
		if (schema_list_item == NULL) {
			return WERR_NOMEM;
		}

		schema_list_item->obj = cur;
		DLIST_ADD_END(schema_list, schema_list_item, struct schema_list);
	}

	/* resolve objects until all are resolved and in local schema */
	pass_no = 1;
	working_schema = initial_schema;

	while (schema_list) {
		uint32_t converted_obj_count = 0;
		uint32_t failed_obj_count = 0;

		if (resulting_schema != working_schema) {
			/*
			 * If the selfmade schema is not the schema used to
			 * translate and validate replicated object,
			 * Which means that we are using the bootstrap schema
			 * Then we add attributes and classes that were already
			 * translated to the working schema, the idea is that
			 * we might need to add new attributes and classes
			 * to be able to translate critical replicated objects
			 * and without that we wouldn't be able to translate them
			 */
			werr = dsdb_repl_merge_working_schema(ldb,
							working_schema,
							resulting_schema);
			if (!W_ERROR_IS_OK(werr)) {
				return werr;
			}
		}

		for (schema_list_item = schema_list;
		     schema_list_item;
		     schema_list_item=schema_list_next_item) {
			struct dsdb_extended_replicated_object object;

			cur = schema_list_item->obj;

			/*
			 * Save the next item, now we have saved out
			 * the current one, so we can DLIST_REMOVE it
			 * safely
			 */
			schema_list_next_item = schema_list_item->next;

			/*
			 * Convert the objects into LDB messages using the
			 * schema we have so far. It's ok if we fail to convert
			 * an object. We should convert more objects on next pass.
			 */
			werr = dsdb_convert_object_ex(ldb, working_schema,
						      pfm_remote,
						      cur, &empty_key,
						      ignore_attids,
						      0,
						      schema_list_item, &object);
			if (!W_ERROR_IS_OK(werr)) {
				DEBUG(4,("debug: Failed to convert schema "
					 "object %s into ldb msg, "
					 "will try during next loop\n",
					 cur->object.identifier->dn));

				failed_obj_count++;
			} else {
				/*
				 * Convert the schema from ldb_message format
				 * (OIDs as OID strings) into schema, using
				 * the remote prefixMap
				 *
				 * It's not likely, but possible to get the
				 * same object twice and we should keep
				 * the last instance.
				 */
				werr = dsdb_schema_set_el_from_ldb_msg_dups(ldb,
								resulting_schema,
								object.msg,
								true);
				if (!W_ERROR_IS_OK(werr)) {
					DEBUG(4,("debug: failed to convert "
						 "object %s into a schema element, "
						 "will try during next loop: %s\n",
						 ldb_dn_get_linearized(object.msg->dn),
						 win_errstr(werr)));
					failed_obj_count++;
				} else {
					DEBUG(8,("Converted object %s into a schema element\n",
						 ldb_dn_get_linearized(object.msg->dn)));
					DLIST_REMOVE(schema_list, schema_list_item);
					TALLOC_FREE(schema_list_item);
					converted_obj_count++;
				}
			}
		}

		DEBUG(4,("Schema load pass %d: converted %d, %d of %d objects left to be converted.\n",
			 pass_no, converted_obj_count, failed_obj_count, object_count));

		/* check if we converted any objects in this pass */
		if (converted_obj_count == 0) {
			DEBUG(0,("Can't continue Schema load: "
				 "didn't manage to convert any objects: "
				 "all %d remaining of %d objects "
				 "failed to convert\n",
				 failed_obj_count, object_count));
			return WERR_INTERNAL_ERROR;
		}

		/*
		 * Don't try to load the schema if there is missing object
		 * _and_ we are on the first pass as some critical objects
		 * might be missing.
		 */
		if (failed_obj_count == 0 || pass_no > cycle_before_switching) {
			/* prepare for another cycle */
			working_schema = resulting_schema;

			ret = dsdb_setup_sorted_accessors(ldb, working_schema);
			if (LDB_SUCCESS != ret) {
				DEBUG(0,("Failed to create schema-cache indexes!\n"));
				return WERR_INTERNAL_ERROR;
			}
		}
		pass_no++;
	}

	return WERR_OK;
}