int dsdb_find_nc_root(struct ldb_context *samdb, TALLOC_CTX *mem_ctx, struct ldb_dn *dn,
		      struct ldb_dn **nc_root)
{
	const char *root_attrs[] = { "namingContexts", NULL };
	TALLOC_CTX *tmp_ctx;
	int ret;
	struct ldb_message_element *el;
	struct ldb_result *root_res;
	unsigned int i;
	struct ldb_dn **nc_dns;

	tmp_ctx = talloc_new(samdb);
	if (tmp_ctx == NULL) {
		return ldb_oom(samdb);
	}

	ret = ldb_search(samdb, tmp_ctx, &root_res,
			 ldb_dn_new(tmp_ctx, samdb, ""), LDB_SCOPE_BASE, root_attrs, NULL);
	if (ret != LDB_SUCCESS || root_res->count == 0) {
		DEBUG(1,("Searching for namingContexts in rootDSE failed: %s\n", ldb_errstring(samdb)));
		talloc_free(tmp_ctx);
		return ret;
	}

	el = ldb_msg_find_element(root_res->msgs[0], "namingContexts");
	if ((el == NULL) || (el->num_values < 3)) {
		struct ldb_message *tmp_msg;

		DEBUG(5,("dsdb_find_nc_root: Finding a valid 'namingContexts' element in the RootDSE failed. Using a temporary list.\n"));

		/* This generates a temporary list of NCs in order to let the
		 * provisioning work. */
		tmp_msg = ldb_msg_new(tmp_ctx);
		if (tmp_msg == NULL) {
			talloc_free(tmp_ctx);
			return ldb_oom(samdb);
		}
		ret = ldb_msg_add_steal_string(tmp_msg, "namingContexts",
					       ldb_dn_alloc_linearized(tmp_msg, ldb_get_schema_basedn(samdb)));
		if (ret != LDB_SUCCESS) {
			talloc_free(tmp_ctx);
			return ret;
		}
		ret = ldb_msg_add_steal_string(tmp_msg, "namingContexts",
					       ldb_dn_alloc_linearized(tmp_msg, ldb_get_config_basedn(samdb)));
		if (ret != LDB_SUCCESS) {
			talloc_free(tmp_ctx);
			return ret;
		}
		ret = ldb_msg_add_steal_string(tmp_msg, "namingContexts",
					       ldb_dn_alloc_linearized(tmp_msg, ldb_get_default_basedn(samdb)));
		if (ret != LDB_SUCCESS) {
			talloc_free(tmp_ctx);
			return ret;
		}
		el = &tmp_msg->elements[0];
	}

       nc_dns = talloc_array(tmp_ctx, struct ldb_dn *, el->num_values);
       if (!nc_dns) {
	       talloc_free(tmp_ctx);
	       return ldb_oom(samdb);
       }

       for (i=0; i<el->num_values; i++) {
	       nc_dns[i] = ldb_dn_from_ldb_val(nc_dns, samdb, &el->values[i]);
	       if (nc_dns[i] == NULL) {
		       talloc_free(tmp_ctx);
		       return ldb_operr(samdb);
	       }
       }

       TYPESAFE_QSORT(nc_dns, el->num_values, dsdb_dn_compare_ptrs);

       for (i=0; i<el->num_values; i++) {
               if (ldb_dn_compare_base(nc_dns[i], dn) == 0) {
		       (*nc_root) = talloc_steal(mem_ctx, nc_dns[i]);
                       talloc_free(tmp_ctx);
                       return LDB_SUCCESS;
               }
       }

       talloc_free(tmp_ctx);
       return ldb_error(samdb, LDB_ERR_NO_SUCH_OBJECT, __func__);
}
int dsdb_find_nc_root(struct ldb_context *samdb, TALLOC_CTX *mem_ctx, struct ldb_dn *dn,
		      struct ldb_dn **nc_root)
{
	const char *root_attrs[] = { "namingContexts", NULL };
	TALLOC_CTX *tmp_ctx;
	int ret;
	struct ldb_message_element *el;
	struct ldb_result *root_res;
	unsigned int i;
	struct ldb_dn **nc_dns;

	tmp_ctx = talloc_new(samdb);
	if (tmp_ctx == NULL) {
		return ldb_oom(samdb);
	}

	ret = ldb_search(samdb, tmp_ctx, &root_res,
			 ldb_dn_new(tmp_ctx, samdb, ""), LDB_SCOPE_BASE, root_attrs, NULL);
	if (ret != LDB_SUCCESS || root_res->count == 0) {
		DEBUG(1,("Searching for namingContexts in rootDSE failed: %s\n", ldb_errstring(samdb)));
		talloc_free(tmp_ctx);
		return ret;
	}

	el = ldb_msg_find_element(root_res->msgs[0], "namingContexts");
	if ((el == NULL) || (el->num_values < 3)) {
		struct ldb_message *tmp_msg;

		DEBUG(5,("dsdb_find_nc_root: Finding a valid 'namingContexts' element in the RootDSE failed. Using a temporary list.\n"));

		 
		tmp_msg = ldb_msg_new(tmp_ctx);
		if (tmp_msg == NULL) {
			talloc_free(tmp_ctx);
			return ldb_oom(samdb);
		}
		ret = ldb_msg_add_steal_string(tmp_msg, "namingContexts",
					       ldb_dn_alloc_linearized(tmp_msg, ldb_get_schema_basedn(samdb)));
		if (ret != LDB_SUCCESS) {
			talloc_free(tmp_ctx);
			return ret;
		}
		ret = ldb_msg_add_steal_string(tmp_msg, "namingContexts",
					       ldb_dn_alloc_linearized(tmp_msg, ldb_get_config_basedn(samdb)));
		if (ret != LDB_SUCCESS) {
			talloc_free(tmp_ctx);
			return ret;
		}
		ret = ldb_msg_add_steal_string(tmp_msg, "namingContexts",
					       ldb_dn_alloc_linearized(tmp_msg, ldb_get_default_basedn(samdb)));
		if (ret != LDB_SUCCESS) {
			talloc_free(tmp_ctx);
			return ret;
		}
		el = &tmp_msg->elements[0];
	}

       nc_dns = talloc_array(tmp_ctx, struct ldb_dn *, el->num_values);
       if (!nc_dns) {
	       talloc_free(tmp_ctx);
	       return ldb_oom(samdb);
       }

       for (i=0; i<el->num_values; i++) {
	       nc_dns[i] = ldb_dn_from_ldb_val(nc_dns, samdb, &el->values[i]);
	       if (nc_dns[i] == NULL) {
		       talloc_free(tmp_ctx);
		       return ldb_operr(samdb);
	       }
       }

       TYPESAFE_QSORT(nc_dns, el->num_values, dsdb_dn_compare_ptrs);

       for (i=0; i<el->num_values; i++) {
               if (ldb_dn_compare_base(nc_dns[i], dn) == 0) {
		       (*nc_root) = talloc_steal(mem_ctx, nc_dns[i]);
                       talloc_free(tmp_ctx);
                       return LDB_SUCCESS;
               }
       }

       talloc_free(tmp_ctx);
       return ldb_error(samdb, LDB_ERR_NO_SUCH_OBJECT, __func__);
}