Exemple #1
0
/*
  get a new RID pool for ourselves
  also returns the first rid for the new pool
 */
static int ridalloc_new_own_pool(struct ldb_module *module, uint64_t *new_pool, struct ldb_request *parent)
{
	TALLOC_CTX *tmp_ctx = talloc_new(module);
	struct ldb_dn *rid_manager_dn, *fsmo_role_dn;
	int ret;
	struct ldb_context *ldb = ldb_module_get_ctx(module);

	/* work out who is the RID Manager */
	ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn, parent);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, "Failed to find RID Manager object - %s",
				       ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	/* find the DN of the RID Manager */
	ret = dsdb_module_reference_dn(module, tmp_ctx, rid_manager_dn, "fSMORoleOwner", &fsmo_role_dn, parent);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, "Failed to find fSMORoleOwner in RID Manager object - %s",
				       ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), fsmo_role_dn) != 0) {
		ridalloc_poke_rid_manager(module);
		ldb_asprintf_errstring(ldb, "Remote RID Set allocation needs refresh");
		talloc_free(tmp_ctx);
		return LDB_ERR_UNWILLING_TO_PERFORM;
	}

	/* grab a pool from the RID Manager object */
	ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, new_pool, parent);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}

	talloc_free(tmp_ctx);
	return ret;
}
Exemple #2
0
static int pdc_fsmo_init(struct ldb_module *module)
{
	struct ldb_context *ldb;
	TALLOC_CTX *mem_ctx;
	struct ldb_dn *pdc_dn;
	struct dsdb_pdc_fsmo *pdc_fsmo;
	struct ldb_result *pdc_res;
	int ret;
	static const char *pdc_attrs[] = {
		"fSMORoleOwner",
		NULL
	};

	ldb = ldb_module_get_ctx(module);

	mem_ctx = talloc_new(module);
	if (!mem_ctx) {
		return ldb_oom(ldb);
	}

	pdc_dn = ldb_get_default_basedn(ldb);
	if (!pdc_dn) {
		ldb_debug_set(ldb, LDB_DEBUG_FATAL,
			  "pdc_fsmo_init: could not determine default basedn");
		talloc_free(mem_ctx);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	pdc_fsmo = talloc_zero(mem_ctx, struct dsdb_pdc_fsmo);
	if (!pdc_fsmo) {
		return ldb_oom(ldb);
	}
	ldb_module_set_private(module, pdc_fsmo);

	ret = dsdb_module_search_dn(module, mem_ctx, &pdc_res,
				    pdc_dn, 
				    pdc_attrs,
				    DSDB_FLAG_NEXT_MODULE, NULL);
	if (ret == LDB_ERR_NO_SUCH_OBJECT) {
		ldb_debug(ldb, LDB_DEBUG_TRACE,
			  "pdc_fsmo_init: no domain object present: (skip loading of domain details)");
		talloc_free(mem_ctx);
		return ldb_next_init(module);
	} else if (ret != LDB_SUCCESS) {
		ldb_debug_set(ldb, LDB_DEBUG_FATAL,
			      "pdc_fsmo_init: failed to search the domain object: %d:%s: %s",
			      ret, ldb_strerror(ret), ldb_errstring(ldb));
		talloc_free(mem_ctx);
		return ret;
	}

	pdc_fsmo->master_dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, pdc_res->msgs[0], "fSMORoleOwner");
	if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), pdc_fsmo->master_dn) == 0) {
		pdc_fsmo->we_are_master = true;
	} else {
		pdc_fsmo->we_are_master = false;
	}

	if (ldb_set_opaque(ldb, "dsdb_pdc_fsmo", pdc_fsmo) != LDB_SUCCESS) {
		return ldb_oom(ldb);
	}

	talloc_steal(module, pdc_fsmo);

	ldb_debug(ldb, LDB_DEBUG_TRACE,
			  "pdc_fsmo_init: we are master: %s\n",
			  (pdc_fsmo->we_are_master?"yes":"no"));

	talloc_free(mem_ctx);
	return ldb_next_init(module);
}
Exemple #3
0
/* 
  drsuapi_DsBind 
*/
static WERROR dcesrv_drsuapi_DsBind(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
		       struct drsuapi_DsBind *r)
{
	struct drsuapi_bind_state *b_state;
	struct dcesrv_handle *handle;
	struct drsuapi_DsBindInfoCtr *bind_info;
	struct GUID site_guid;
	struct ldb_result *site_res;
	struct ldb_dn *server_site_dn;
	static const char *site_attrs[] = { "objectGUID", NULL };
	struct ldb_result *ntds_res;
	struct ldb_dn *ntds_dn;
	static const char *ntds_attrs[] = { "ms-DS-ReplicationEpoch", NULL };
	uint32_t pid;
	uint32_t repl_epoch;
	int ret;
	struct auth_session_info *auth_info;
	WERROR werr;

	r->out.bind_info = NULL;
	ZERO_STRUCTP(r->out.bind_handle);

	b_state = talloc_zero(mem_ctx, struct drsuapi_bind_state);
	W_ERROR_HAVE_NO_MEMORY(b_state);

	/* if this is a DC connecting, give them system level access */
	werr = drs_security_level_check(dce_call, NULL);
	if (W_ERROR_IS_OK(werr)) {
		DEBUG(3,(__location__ ": doing DsBind with system_session\n"));
		auth_info = system_session(dce_call->conn->dce_ctx->lp_ctx);
	} else {
		auth_info = dce_call->conn->auth_state.session_info;
	}

	/*
	 * connect to the samdb
	 */
	b_state->sam_ctx = samdb_connect(b_state, dce_call->event_ctx, 
					 dce_call->conn->dce_ctx->lp_ctx, auth_info); 
	if (!b_state->sam_ctx) {
		return WERR_FOOBAR;
	}

	/*
	 * find out the guid of our own site
	 */
	server_site_dn = samdb_server_site_dn(b_state->sam_ctx, mem_ctx);
	W_ERROR_HAVE_NO_MEMORY(server_site_dn);

	ret = ldb_search(b_state->sam_ctx, mem_ctx, &site_res,
				 server_site_dn, LDB_SCOPE_BASE, site_attrs,
				 "(objectClass=*)");
	if (ret != LDB_SUCCESS) {
		return WERR_DS_DRA_INTERNAL_ERROR;
	}
	if (site_res->count != 1) {
		return WERR_DS_DRA_INTERNAL_ERROR;
	}
	site_guid = samdb_result_guid(site_res->msgs[0], "objectGUID");

	/*
	 * lookup the local servers Replication Epoch
	 */
	ntds_dn = samdb_ntds_settings_dn(b_state->sam_ctx);
	W_ERROR_HAVE_NO_MEMORY(ntds_dn);

	ret = ldb_search(b_state->sam_ctx, mem_ctx, &ntds_res,
				 ntds_dn, LDB_SCOPE_BASE, ntds_attrs,
				 "(objectClass=*)");
	if (ret != LDB_SUCCESS) {
		return WERR_DS_DRA_INTERNAL_ERROR;
	}
	if (ntds_res->count != 1) {
		return WERR_DS_DRA_INTERNAL_ERROR;
	}
	repl_epoch = samdb_result_uint(ntds_res->msgs[0], "ms-DS-ReplicationEpoch", 0);

	/*
	 * The "process identifier" of the client.
	 * According to the WSPP docs, sectin 5.35, this is
	 * for informational and debugging purposes only.
	 * The assignment is implementation specific.
	 */
	pid = 0;

	/*
	 * store the clients bind_guid
	 */
	if (r->in.bind_guid) {
		b_state->remote_bind_guid = *r->in.bind_guid;
	}

	/*
	 * store the clients bind_info
	 */
	if (r->in.bind_info) {
		switch (r->in.bind_info->length) {
		case 24: {
			struct drsuapi_DsBindInfo24 *info24;
			info24 = &r->in.bind_info->info.info24;
			b_state->remote_info28.supported_extensions	= info24->supported_extensions;
			b_state->remote_info28.site_guid		= info24->site_guid;
			b_state->remote_info28.pid			= info24->pid;
			b_state->remote_info28.repl_epoch		= 0;
			break;
		}
		case 28:
			b_state->remote_info28 = r->in.bind_info->info.info28;
			break;
		}
	}

	/*
	 * fill in our local bind info 28
	 */
	b_state->local_info28.supported_extensions	= 0;
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_BASE;
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_ASYNC_REPLICATION;
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_REMOVEAPI;
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_MOVEREQ_V2;
#if 0 /* we don't support MSZIP compression (only decompression) */
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_GETCHG_COMPRESS;
#endif
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V1;
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_RESTORE_USN_OPTIMIZATION;
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_KCC_EXECUTE;
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRY_V2;
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_LINKED_VALUE_REPLICATION;
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V2;
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_INSTANCE_TYPE_NOT_REQ_ON_MOD;
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_CRYPTO_BIND;
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_GET_REPL_INFO;
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_STRONG_ENCRYPTION;
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_DCINFO_V01;
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_TRANSITIVE_MEMBERSHIP;
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_ADD_SID_HISTORY;
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_POST_BETA3;
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_00100000;
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_GET_MEMBERSHIPS2;
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V6;
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_NONDOMAIN_NCS;
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8;
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V5;
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V6;
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3;
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_GETCHGREPLY_V7;
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_VERIFY_OBJECT;
#if 0 /* we don't support XPRESS compression yet */
	b_state->local_info28.supported_extensions	|= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS;
#endif
	b_state->local_info28.site_guid			= site_guid;
	b_state->local_info28.pid			= pid;
	b_state->local_info28.repl_epoch		= repl_epoch;

	/*
	 * allocate the return bind_info
	 */
	bind_info = talloc(mem_ctx, struct drsuapi_DsBindInfoCtr);
	W_ERROR_HAVE_NO_MEMORY(bind_info);

	bind_info->length	= 28;
	bind_info->info.info28	= b_state->local_info28;

	/*
	 * allocate a bind handle
	 */
	handle = dcesrv_handle_new(dce_call->context, DRSUAPI_BIND_HANDLE);
	W_ERROR_HAVE_NO_MEMORY(handle);
	handle->data = talloc_steal(handle, b_state);

	/*
	 * prepare reply
	 */
	r->out.bind_info = bind_info;
	*r->out.bind_handle = handle->wire_handle;

	return WERR_OK;
}
Exemple #4
0
/*
  see if we are on the last pool we have
 */
static int drepl_ridalloc_pool_exhausted(struct ldb_context *ldb,
					 bool *exhausted,
					 uint64_t *_alloc_pool)
{
	struct ldb_dn *server_dn, *machine_dn, *rid_set_dn;
	TALLOC_CTX *tmp_ctx = talloc_new(ldb);
	uint64_t alloc_pool;
	uint64_t prev_pool;
	uint32_t prev_pool_lo, prev_pool_hi;
	uint32_t next_rid;
	static const char * const attrs[] = {
		"rIDAllocationPool",
		"rIDPreviousAllocationPool",
		"rIDNextRid",
		NULL
	};
	int ret;
	struct ldb_result *res;

	*exhausted = false;
	*_alloc_pool = UINT64_MAX;

	server_dn = ldb_dn_get_parent(tmp_ctx, samdb_ntds_settings_dn(ldb));
	if (!server_dn) {
		talloc_free(tmp_ctx);
		return ldb_operr(ldb);
	}

	ret = samdb_reference_dn(ldb, tmp_ctx, server_dn, "serverReference", &machine_dn);
	if (ret != LDB_SUCCESS) {
		DEBUG(0,(__location__ ": Failed to find serverReference in %s - %s\n",
			 ldb_dn_get_linearized(server_dn), ldb_errstring(ldb)));
		talloc_free(tmp_ctx);
		return ret;
	}

	ret = samdb_reference_dn(ldb, tmp_ctx, machine_dn, "rIDSetReferences", &rid_set_dn);
	if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
		*exhausted = true;
		*_alloc_pool = 0;
		talloc_free(tmp_ctx);
		return LDB_SUCCESS;
	}
	if (ret != LDB_SUCCESS) {
		DEBUG(0,(__location__ ": Failed to find rIDSetReferences in %s - %s\n",
			 ldb_dn_get_linearized(machine_dn), ldb_errstring(ldb)));
		talloc_free(tmp_ctx);
		return ret;
	}

	ret = ldb_search(ldb, tmp_ctx, &res, rid_set_dn, LDB_SCOPE_BASE, attrs, NULL);
	if (ret != LDB_SUCCESS) {
		DEBUG(0,(__location__ ": Failed to load RID Set attrs from %s - %s\n",
			 ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb)));
		talloc_free(tmp_ctx);
		return ret;
	}

	alloc_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAllocationPool", 0);
	prev_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDPreviousAllocationPool", 0);
	prev_pool_lo = prev_pool & 0xFFFFFFFF;
	prev_pool_hi = prev_pool >> 32;
	next_rid = ldb_msg_find_attr_as_uint(res->msgs[0], "rIDNextRid", 0);

	if (alloc_pool != prev_pool) {
		talloc_free(tmp_ctx);
		return LDB_SUCCESS;
	}

	if (next_rid < (prev_pool_hi + prev_pool_lo)/2) {
		talloc_free(tmp_ctx);
		return LDB_SUCCESS;
	}

	*exhausted = true;
	*_alloc_pool = alloc_pool;
	talloc_free(tmp_ctx);
	return LDB_SUCCESS;
}
Exemple #5
0
/*
  see if we are low on RIDs in the RID Set rIDAllocationPool. If we
  are, then schedule a replication call with DRSUAPI_EXOP_FSMO_RID_ALLOC
  to the RID Manager
 */
WERROR dreplsrv_ridalloc_check_rid_pool(struct dreplsrv_service *service)
{
	struct ldb_dn *rid_manager_dn, *fsmo_role_dn;
	TALLOC_CTX *tmp_ctx = talloc_new(service);
	struct ldb_context *ldb = service->samdb;
	bool exhausted;
	WERROR werr;
	int ret;
	uint64_t alloc_pool;

	if (service->am_rodc) {
		talloc_free(tmp_ctx);
		return WERR_OK;
	}

	if (service->rid_alloc_in_progress) {
		talloc_free(tmp_ctx);
		return WERR_OK;
	}

	/*
	  steps:
	    - find who the RID Manager is
	    - if we are the RID Manager then nothing to do
	    - find our RID Set object
	    - load rIDAllocationPool and rIDPreviousAllocationPool
	    - if rIDAllocationPool != rIDPreviousAllocationPool then
	      nothing to do
	    - schedule a getncchanges with DRSUAPI_EXOP_FSMO_RID_ALLOC
	      to the RID Manager
	 */

	/* work out who is the RID Manager */
	ret = samdb_rid_manager_dn(ldb, tmp_ctx, &rid_manager_dn);
	if (ret != LDB_SUCCESS) {
		DEBUG(0, (__location__ ": Failed to find RID Manager object - %s\n", ldb_errstring(ldb)));
		talloc_free(tmp_ctx);
		return WERR_DS_DRA_INTERNAL_ERROR;
	}

	/* find the DN of the RID Manager */
	ret = samdb_reference_dn(ldb, tmp_ctx, rid_manager_dn, "fSMORoleOwner", &fsmo_role_dn);
	if (ret != LDB_SUCCESS) {
		DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in RID Manager object - %s\n",
			 ldb_errstring(ldb)));
		talloc_free(tmp_ctx);
		return WERR_DS_DRA_INTERNAL_ERROR;
	}

	if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), fsmo_role_dn) == 0) {
		/* we are the RID Manager - no need to do a
		   DRSUAPI_EXOP_FSMO_RID_ALLOC */
		talloc_free(tmp_ctx);
		return WERR_OK;
	}

	ret = drepl_ridalloc_pool_exhausted(ldb, &exhausted, &alloc_pool);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return WERR_DS_DRA_INTERNAL_ERROR;
	}

	if (!exhausted) {
		/* don't need a new pool */
		talloc_free(tmp_ctx);
		return WERR_OK;
	}

	DEBUG(2,(__location__ ": Requesting more RIDs from RID Manager\n"));

	werr = drepl_request_new_rid_pool(service, rid_manager_dn, fsmo_role_dn, alloc_pool);
	talloc_free(tmp_ctx);
	return werr;
}
Exemple #6
0
/*
  load the partitions list based on replicated NC attributes in our
  NTDSDSA object
 */
WERROR dreplsrv_load_partitions(struct dreplsrv_service *s)
{
	WERROR status;
	static const char *attrs[] = { "hasMasterNCs", "msDs-hasMasterNCs", "hasPartialReplicaNCs", "msDS-HasFullReplicaNCs", NULL };
	unsigned int a;
	int ret;
	TALLOC_CTX *tmp_ctx;
	struct ldb_result *res;
	struct ldb_message_element *el;
	struct ldb_dn *ntds_dn;

	tmp_ctx = talloc_new(s);
	W_ERROR_HAVE_NO_MEMORY(tmp_ctx);

	ntds_dn = samdb_ntds_settings_dn(s->samdb);
	if (!ntds_dn) {
		DEBUG(1,(__location__ ": Unable to find ntds_dn: %s\n", ldb_errstring(s->samdb)));
		talloc_free(tmp_ctx);
		return WERR_DS_DRA_INTERNAL_ERROR;
	}

	ret = dsdb_search_dn(s->samdb, tmp_ctx, &res, ntds_dn, attrs, DSDB_SEARCH_SHOW_EXTENDED_DN);
	if (ret != LDB_SUCCESS) {
		DEBUG(1,("Searching for hasMasterNCs in NTDS DN failed: %s\n", ldb_errstring(s->samdb)));
		talloc_free(tmp_ctx);
		return WERR_DS_DRA_INTERNAL_ERROR;
	}

	for (a=0; attrs[a]; a++) {
		int i;

		el = ldb_msg_find_element(res->msgs[0], attrs[a]);
		if (el == NULL) {
			continue;
		}
		for (i=0; i<el->num_values; i++) {
			struct ldb_dn *pdn;
			struct dreplsrv_partition *p, *tp;
			bool found;

			pdn = ldb_dn_from_ldb_val(tmp_ctx, s->samdb, &el->values[i]);
			if (pdn == NULL) {
				talloc_free(tmp_ctx);
				return WERR_DS_DRA_INTERNAL_ERROR;
			}
			if (!ldb_dn_validate(pdn)) {
				return WERR_DS_DRA_INTERNAL_ERROR;
			}

			p = talloc_zero(s, struct dreplsrv_partition);
			W_ERROR_HAVE_NO_MEMORY(p);

			p->dn = talloc_steal(p, pdn);
			p->service = s;

			if (strcasecmp(attrs[a], "hasPartialReplicaNCs") == 0) {
				p->partial_replica = true;
			} else if (strcasecmp(attrs[a], "msDS-HasFullReplicaNCs") == 0) {
				p->rodc_replica = true;
			}

			/* Do not add partitions more than once */
			found = false;
			for (tp = s->partitions; tp; tp = tp->next) {
				if (ldb_dn_compare(tp->dn, p->dn) == 0) {
					found = true;
					break;
				}
			}
			if (found) {
				talloc_free(p);
				continue;
			}

			DLIST_ADD(s->partitions, p);
			DEBUG(2, ("dreplsrv_partition[%s] loaded\n", ldb_dn_get_linearized(p->dn)));
		}
	}

	talloc_free(tmp_ctx);

	status = dreplsrv_refresh_partitions(s);
	W_ERROR_NOT_OK_RETURN(status);

	return WERR_OK;
}
Exemple #7
0
int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
				 struct ldb_result *schema_res,
				 struct ldb_result *attrs_class_res,
				 struct dsdb_schema **schema_out,
				 char **error_string)
{
	WERROR status;
	const struct ldb_val *prefix_val;
	const struct ldb_val *info_val;
	struct ldb_val info_val_default;
	struct dsdb_schema *schema;
	struct loadparm_context *lp_ctx = NULL;
	int ret;

	schema = dsdb_new_schema(mem_ctx);
	if (!schema) {
		dsdb_oom(error_string, mem_ctx);
		return ldb_operr(ldb);
	}

	schema->base_dn = talloc_steal(schema, schema_res->msgs[0]->dn);

	prefix_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "prefixMap");
	if (!prefix_val) {
		*error_string = talloc_asprintf(mem_ctx, 
						"schema_fsmo_init: no prefixMap attribute found");
		DEBUG(0,(__location__ ": %s\n", *error_string));
		return LDB_ERR_CONSTRAINT_VIOLATION;
	}
	info_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "schemaInfo");
	if (!info_val) {
		status = dsdb_schema_info_blob_new(mem_ctx, &info_val_default);
		if (!W_ERROR_IS_OK(status)) {
			*error_string = talloc_asprintf(mem_ctx,
			                                "schema_fsmo_init: dsdb_schema_info_blob_new() failed - %s",
			                                win_errstr(status));
			DEBUG(0,(__location__ ": %s\n", *error_string));
			return ldb_operr(ldb);
		}
		info_val = &info_val_default;
	}

	status = dsdb_load_oid_mappings_ldb(schema, prefix_val, info_val);
	if (!W_ERROR_IS_OK(status)) {
		*error_string = talloc_asprintf(mem_ctx, 
			      "schema_fsmo_init: failed to load oid mappings: %s",
			      win_errstr(status));
		DEBUG(0,(__location__ ": %s\n", *error_string));
		return LDB_ERR_CONSTRAINT_VIOLATION;
	}

	ret = dsdb_load_ldb_results_into_schema(mem_ctx, ldb, schema, attrs_class_res, error_string);
	if (ret != LDB_SUCCESS) {
		return ret;
	}

	schema->fsmo.master_dn = ldb_msg_find_attr_as_dn(ldb, schema, schema_res->msgs[0], "fSMORoleOwner");
	if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), schema->fsmo.master_dn) == 0) {
		schema->fsmo.we_are_master = true;
	} else {
		schema->fsmo.we_are_master = false;
	}

	lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
						struct loadparm_context);
	if (lp_ctx) {
		bool allowed = lpcfg_parm_bool(lp_ctx, NULL,
						"dsdb", "schema update allowed",
						false);
		schema->fsmo.update_allowed = allowed;
	} else {
		schema->fsmo.update_allowed = false;
	}

	DEBUG(5, ("schema_fsmo_init: we are master[%s] updates allowed[%s]\n",
		  (schema->fsmo.we_are_master?"yes":"no"),
		  (schema->fsmo.update_allowed?"yes":"no")));

	*schema_out = schema;
	return LDB_SUCCESS;
}
Exemple #8
0
int dsdb_schema_from_ldb_results(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
				 struct ldb_result *schema_res,
				 struct ldb_result *attrs_res, struct ldb_result *objectclass_res, 
				 struct dsdb_schema **schema_out,
				 char **error_string)
{
	WERROR status;
	unsigned int i;
	const struct ldb_val *prefix_val;
	const struct ldb_val *info_val;
	struct ldb_val info_val_default;
	struct dsdb_schema *schema;

	schema = dsdb_new_schema(mem_ctx);
	if (!schema) {
		dsdb_oom(error_string, mem_ctx);
		return ldb_operr(ldb);
	}

	schema->base_dn = talloc_steal(schema, schema_res->msgs[0]->dn);

	prefix_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "prefixMap");
	if (!prefix_val) {
		*error_string = talloc_asprintf(mem_ctx, 
						"schema_fsmo_init: no prefixMap attribute found");
		DEBUG(0,(__location__ ": %s\n", *error_string));
		return LDB_ERR_CONSTRAINT_VIOLATION;
	}
	info_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "schemaInfo");
	if (!info_val) {
		status = dsdb_schema_info_blob_new(mem_ctx, &info_val_default);
		if (!W_ERROR_IS_OK(status)) {
			*error_string = talloc_asprintf(mem_ctx,
			                                "schema_fsmo_init: dsdb_schema_info_blob_new() failed - %s",
			                                win_errstr(status));
			DEBUG(0,(__location__ ": %s\n", *error_string));
			return ldb_operr(ldb);
		}
		info_val = &info_val_default;
	}

	status = dsdb_load_oid_mappings_ldb(schema, prefix_val, info_val);
	if (!W_ERROR_IS_OK(status)) {
		*error_string = talloc_asprintf(mem_ctx, 
			      "schema_fsmo_init: failed to load oid mappings: %s",
			      win_errstr(status));
		DEBUG(0,(__location__ ": %s\n", *error_string));
		return LDB_ERR_CONSTRAINT_VIOLATION;
	}

	for (i=0; i < attrs_res->count; i++) {
		status = dsdb_attribute_from_ldb(ldb, schema, attrs_res->msgs[i]);
		if (!W_ERROR_IS_OK(status)) {
			*error_string = talloc_asprintf(mem_ctx, 
				      "schema_fsmo_init: failed to load attribute definition: %s:%s",
				      ldb_dn_get_linearized(attrs_res->msgs[i]->dn),
				      win_errstr(status));
			DEBUG(0,(__location__ ": %s\n", *error_string));
			return LDB_ERR_CONSTRAINT_VIOLATION;
		}
	}

	for (i=0; i < objectclass_res->count; i++) {
		status = dsdb_class_from_ldb(schema, objectclass_res->msgs[i]);
		if (!W_ERROR_IS_OK(status)) {
			*error_string = talloc_asprintf(mem_ctx, 
				      "schema_fsmo_init: failed to load class definition: %s:%s",
				      ldb_dn_get_linearized(objectclass_res->msgs[i]->dn),
				      win_errstr(status));
			DEBUG(0,(__location__ ": %s\n", *error_string));
			return LDB_ERR_CONSTRAINT_VIOLATION;
		}
	}

	schema->fsmo.master_dn = ldb_msg_find_attr_as_dn(ldb, schema, schema_res->msgs[0], "fSMORoleOwner");
	if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), schema->fsmo.master_dn) == 0) {
		schema->fsmo.we_are_master = true;
	} else {
		schema->fsmo.we_are_master = false;
	}

	DEBUG(5, ("schema_fsmo_init: we are master: %s\n",
		  (schema->fsmo.we_are_master?"yes":"no")));

	*schema_out = schema;
	return LDB_SUCCESS;
}
Exemple #9
0
WERROR dreplsrv_load_partitions(struct dreplsrv_service *s)
{
	WERROR status;
	static const char *attrs[] = { "hasMasterNCs", "hasPartialReplicaNCs", NULL };
	unsigned int i;
	int ret;
	TALLOC_CTX *tmp_ctx;
	struct ldb_result *res;
	struct ldb_message_element *el;
	struct ldb_dn *ntds_dn;

	tmp_ctx = talloc_new(s);
	W_ERROR_HAVE_NO_MEMORY(tmp_ctx);

	ntds_dn = samdb_ntds_settings_dn(s->samdb);
	if (!ntds_dn) {
		DEBUG(1,(__location__ ": Unable to find ntds_dn: %s\n", ldb_errstring(s->samdb)));
		talloc_free(tmp_ctx);
		return WERR_DS_DRA_INTERNAL_ERROR;
	}

	ret = dsdb_search_dn(s->samdb, tmp_ctx, &res, ntds_dn, attrs, DSDB_SEARCH_SHOW_EXTENDED_DN);
	if (ret != LDB_SUCCESS) {
		DEBUG(1,("Searching for hasMasterNCs in NTDS DN failed: %s\n", ldb_errstring(s->samdb)));
		talloc_free(tmp_ctx);
		return WERR_DS_DRA_INTERNAL_ERROR;
	}

	el = ldb_msg_find_element(res->msgs[0], "hasMasterNCs");
	if (!el) {
		DEBUG(1,("Finding hasMasterNCs element in root_res failed: %s\n",
			 ldb_errstring(s->samdb)));
		talloc_free(tmp_ctx);
		return WERR_DS_DRA_INTERNAL_ERROR;
	}

	for (i=0; i<el->num_values; i++) {
		struct ldb_dn *pdn;
		struct dreplsrv_partition *p;

		pdn = ldb_dn_from_ldb_val(tmp_ctx, s->samdb, &el->values[i]);
		if (pdn == NULL) {
			talloc_free(tmp_ctx);
			return WERR_DS_DRA_INTERNAL_ERROR;
		}
		if (!ldb_dn_validate(pdn)) {
			return WERR_DS_DRA_INTERNAL_ERROR;
		}

		p = talloc_zero(s, struct dreplsrv_partition);
		W_ERROR_HAVE_NO_MEMORY(p);

		p->dn = talloc_steal(p, pdn);
		p->service = s;

		DLIST_ADD(s->partitions, p);

		DEBUG(2, ("dreplsrv_partition[%s] loaded\n", ldb_dn_get_linearized(p->dn)));
	}

	el = ldb_msg_find_element(res->msgs[0], "hasPartialReplicaNCs");

	for (i=0; el && i<el->num_values; i++) {
		struct ldb_dn *pdn;
		struct dreplsrv_partition *p;

		pdn = ldb_dn_from_ldb_val(tmp_ctx, s->samdb, &el->values[i]);
		if (pdn == NULL) {
			talloc_free(tmp_ctx);
			return WERR_DS_DRA_INTERNAL_ERROR;
		}
		if (!ldb_dn_validate(pdn)) {
			return WERR_DS_DRA_INTERNAL_ERROR;
		}

		p = talloc_zero(s, struct dreplsrv_partition);
		W_ERROR_HAVE_NO_MEMORY(p);

		p->dn = talloc_steal(p, pdn);
		p->partial_replica = true;
		p->service = s;

		DLIST_ADD(s->partitions, p);

		DEBUG(2, ("dreplsrv_partition[%s] loaded (partial replica)\n", ldb_dn_get_linearized(p->dn)));
	}

	talloc_free(tmp_ctx);

	status = dreplsrv_refresh_partitions(s);
	W_ERROR_NOT_OK_RETURN(status);

	return WERR_OK;
}
Exemple #10
0
/*
  create a RID Set object for the specified DC
 */
static int ridalloc_create_rid_set_ntds(struct ldb_module *module, TALLOC_CTX *mem_ctx,
					struct ldb_dn *rid_manager_dn,
					struct ldb_dn *ntds_dn, struct ldb_dn **dn,
					struct ldb_request *parent)
{
	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
	struct ldb_dn *server_dn, *machine_dn, *rid_set_dn;
	int ret;
	struct ldb_message *msg;
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	static const struct ridalloc_ridset_values o = {
		.alloc_pool	= UINT64_MAX,
		.prev_pool	= UINT64_MAX,
		.next_rid	= UINT32_MAX,
		.used_pool	= UINT32_MAX,
	};
	struct ridalloc_ridset_values n = {
		.alloc_pool	= 0,
		.prev_pool	= 0,
		.next_rid	= 0,
		.used_pool	= 0,
	};

	/*
	  steps:

	  find the machine object for the DC
	  construct the RID Set DN
	  load rIDAvailablePool to find next available set
	  modify RID Manager object to update rIDAvailablePool
	  add the RID Set object
	  link to the RID Set object in machine object
	 */

	server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn);
	if (!server_dn) {
		talloc_free(tmp_ctx);
		return ldb_module_oom(module);
	}

	ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn, parent);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, "Failed to find serverReference in %s - %s",
				       ldb_dn_get_linearized(server_dn), ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	rid_set_dn = ldb_dn_copy(tmp_ctx, machine_dn);
	if (rid_set_dn == NULL) {
		talloc_free(tmp_ctx);
		return ldb_module_oom(module);
	}

	if (! ldb_dn_add_child_fmt(rid_set_dn, "CN=RID Set")) {
		talloc_free(tmp_ctx);
		return ldb_module_oom(module);
	}

	/* grab a pool from the RID Manager object */
	ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, &n.alloc_pool, parent);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}

	/* create the RID Set object */
	msg = ldb_msg_new(tmp_ctx);
	msg->dn = rid_set_dn;

	ret = ldb_msg_add_string(msg, "objectClass", "rIDSet");
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}

	ret = ridalloc_set_ridset_values(module, msg, &o, &n);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}

	/* we need this to go all the way to the top of the module
	 * stack, as we need all the extra attributes added (including
	 * complex ones like ntsecuritydescriptor) */
	ret = dsdb_module_add(module, msg, DSDB_FLAG_TOP_MODULE | DSDB_MODIFY_RELAX, parent);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, "Failed to add RID Set %s - %s",
				       ldb_dn_get_linearized(msg->dn),
				       ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	/* add the rIDSetReferences link */
	msg = ldb_msg_new(tmp_ctx);
	msg->dn = machine_dn;

	ret = ldb_msg_add_string(msg, "rIDSetReferences", ldb_dn_get_linearized(rid_set_dn));
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}
	msg->elements[0].flags = LDB_FLAG_MOD_ADD;

	ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, "Failed to add rIDSetReferences to %s - %s",
				       ldb_dn_get_linearized(msg->dn),
				       ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	(*dn) = talloc_steal(mem_ctx, rid_set_dn);

	talloc_free(tmp_ctx);
	return LDB_SUCCESS;
}


/*
  create a RID Set object for this DC
 */
static int ridalloc_create_own_rid_set(struct ldb_module *module, TALLOC_CTX *mem_ctx,
				       struct ldb_dn **dn, struct ldb_request *parent)
{
	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
	struct ldb_dn *rid_manager_dn, *fsmo_role_dn;
	int ret;
	struct ldb_context *ldb = ldb_module_get_ctx(module);

	/* work out who is the RID Manager */
	ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn, parent);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, "Failed to find RID Manager object - %s",
				       ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	/* find the DN of the RID Manager */
	ret = dsdb_module_reference_dn(module, tmp_ctx, rid_manager_dn, "fSMORoleOwner", &fsmo_role_dn, parent);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, "Failed to find fSMORoleOwner in RID Manager object - %s",
				       ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), fsmo_role_dn) != 0) {
		ridalloc_poke_rid_manager(module);
		ldb_asprintf_errstring(ldb, "Remote RID Set allocation needs refresh");
		talloc_free(tmp_ctx);
		return LDB_ERR_UNWILLING_TO_PERFORM;
	}

	ret = ridalloc_create_rid_set_ntds(module, mem_ctx, rid_manager_dn, fsmo_role_dn, dn, parent);
	talloc_free(tmp_ctx);
	return ret;
}