Esempio n. 1
0
/*
 * Write a key with uin64 value
 */
static int partition_metadata_set_uint64(struct ldb_module *module,
					 const char *key, uint64_t value,
					 bool insert)
{
	struct partition_private_data *data;
	struct tdb_context *tdb;
	TDB_DATA tdb_key, tdb_data;
	int tdb_flag;
	char *value_str;
	TALLOC_CTX *tmp_ctx;

	data = talloc_get_type_abort(ldb_module_get_private(module),
				     struct partition_private_data);

	if (!data || !data->metadata || !data->metadata->db) {
		return ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR,
					"partition_metadata: metadata tdb not initialized");
	}

	tmp_ctx = talloc_new(NULL);
	if (tmp_ctx == NULL) {
		return ldb_module_oom(module);
	}

	tdb = data->metadata->db->tdb;

	value_str = talloc_asprintf(tmp_ctx, "%llu", (unsigned long long)value);
	if (value_str == NULL) {
		talloc_free(tmp_ctx);
		return ldb_module_oom(module);
	}

	tdb_key.dptr = (uint8_t *)discard_const_p(char, key);
	tdb_key.dsize = strlen(key);

	tdb_data.dptr = (uint8_t *)value_str;
	tdb_data.dsize = strlen(value_str);

	if (insert) {
		tdb_flag = TDB_INSERT;
	} else {
		tdb_flag = TDB_MODIFY;
	}

	if (tdb_store(tdb, tdb_key, tdb_data, tdb_flag) != 0) {
		int ret;
		char *error_string = talloc_asprintf(tmp_ctx, "%s: tdb_store of key %s failed: %s",
						     tdb_name(tdb), key, tdb_errorstr(tdb));
		ret = ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR,
				       error_string);
		talloc_free(tmp_ctx);
		return ret;
	}

	talloc_free(tmp_ctx);

	return LDB_SUCCESS;
}
Esempio n. 2
0
/*
 * Read a key with uint64 value
 */
static int partition_metadata_get_uint64(struct ldb_module *module,
					 const char *key, uint64_t *value,
					 uint64_t default_value)
{
	struct partition_private_data *data;
	struct tdb_context *tdb;
	TDB_DATA tdb_key, tdb_data;
	char *value_str;
	TALLOC_CTX *tmp_ctx;

	data = talloc_get_type_abort(ldb_module_get_private(module),
				     struct partition_private_data);

	if (!data || !data->metadata || !data->metadata->db) {
		return ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR,
					"partition_metadata: metadata tdb not initialized");
	}

	tmp_ctx = talloc_new(NULL);
	if (tmp_ctx == NULL) {
		return ldb_module_oom(module);
	}

	tdb = data->metadata->db->tdb;

	tdb_key.dptr = (uint8_t *)discard_const_p(char, key);
	tdb_key.dsize = strlen(key);

	tdb_data = tdb_fetch(tdb, tdb_key);
	if (!tdb_data.dptr) {
		if (tdb_error(tdb) == TDB_ERR_NOEXIST) {
			*value = default_value;
			return LDB_SUCCESS;
		} else {
			return ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR,
						tdb_errorstr(tdb));
		}
	}

	value_str = talloc_strndup(tmp_ctx, (char *)tdb_data.dptr, tdb_data.dsize);
	if (value_str == NULL) {
		SAFE_FREE(tdb_data.dptr);
		talloc_free(tmp_ctx);
		return ldb_module_oom(module);
	}

	*value = strtoull(value_str, NULL, 10);

	SAFE_FREE(tdb_data.dptr);
	talloc_free(tmp_ctx);

	return LDB_SUCCESS;
}
Esempio n. 3
0
/**
 * Writes schema_info structure into schemaInfo
 * attribute on SCHEMA partition
 *
 * @param dsdb_flags 	DSDB_FLAG_... flag of 0
 */
static int dsdb_module_schema_info_write(struct ldb_module *ldb_module,
					 uint32_t dsdb_flags,
					 const struct dsdb_schema_info *schema_info,
					 struct ldb_request *parent)
{
	WERROR werr;
	int ret;
	DATA_BLOB ndr_blob;
	TALLOC_CTX *temp_ctx;

	temp_ctx = talloc_new(ldb_module);
	if (temp_ctx == NULL) {
		return ldb_module_oom(temp_ctx);
	}

	/* convert schema_info to a blob */
	werr = dsdb_blob_from_schema_info(schema_info, temp_ctx, &ndr_blob);
	if (!W_ERROR_IS_OK(werr)) {
		talloc_free(temp_ctx);
		ldb_asprintf_errstring(ldb_module_get_ctx(ldb_module), __location__ ": failed to get schema_info");
		return ldb_operr(ldb_module_get_ctx(ldb_module));
	}

	/* write serialized schemaInfo into LDB */
	ret = dsdb_module_schema_info_blob_write(ldb_module, dsdb_flags, &ndr_blob, parent);

	talloc_free(temp_ctx);

	return ret;
}
Esempio n. 4
0
static int dsdb_notification_filter_search(struct ldb_module *module,
					  struct ldb_request *req,
					  struct ldb_control *control)
{
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	char *filter_usn = NULL;
	struct ldb_parse_tree *down_tree = NULL;
	struct ldb_request *down_req = NULL;
	struct dsdb_notification_cookie *cookie = NULL;
	int ret;

	if (req->op.search.tree == NULL) {
		return dsdb_module_werror(module, LDB_ERR_OTHER,
					  WERR_DS_NOTIFY_FILTER_TOO_COMPLEX,
					  "Search filter missing.");
	}

	ret = dsdb_notification_verify_tree(req->op.search.tree);
	if (ret != LDB_SUCCESS) {
		return dsdb_module_werror(module, ret,
					  WERR_DS_NOTIFY_FILTER_TOO_COMPLEX,
					  "Search filter too complex.");
	}

	/*
	 * For now we use a very simple design:
	 *
	 * - We don't do fully async ldb_requests,
	 *   the caller needs to retry periodically!
	 * - The only useful caller is the LDAP server, which is a long
	 *   running task that can do periodic retries.
	 * - We use a cookie in order to transfer state between the
	 *   retries.
	 * - We just search the available new objects each time we're
	 *   called.
	 *
	 * As the only valid search filter is '(objectClass=*)' or
	 * something similar that matches every object, we simply
	 * replace it with (uSNChanged >= ) filter.
	 * We could improve this later if required...
	 */

	/*
	 * The ldap_control_handler() decode_flag_request for
	 * LDB_CONTROL_NOTIFICATION_OID. This makes sure
	 * notification_control->data is NULL when comming from
	 * the client.
	 */
	if (control->data == NULL) {
		cookie = talloc_zero(control, struct dsdb_notification_cookie);
		if (cookie == NULL) {
			return ldb_module_oom(module);
		}
		control->data = (uint8_t *)cookie;

		/* mark the control as done */
		control->critical = 0;
	}
Esempio n. 5
0
/*
  construct msDS-keyVersionNumber attr

  TODO:  Make this based on the 'win2k' DS huristics bit...

*/
static int construct_msds_keyversionnumber(struct ldb_module *module,
					   struct ldb_message *msg,
					   enum ldb_scope scope,
					   struct ldb_request *parent)
{
	uint32_t i;
	enum ndr_err_code ndr_err;
	const struct ldb_val *omd_value;
	struct replPropertyMetaDataBlob *omd;
	int ret;

	omd_value = ldb_msg_find_ldb_val(msg, "replPropertyMetaData");
	if (!omd_value) {
		/* We can't make up a key version number without meta data */
		return LDB_SUCCESS;
	}
	if (!omd_value) {
		return LDB_SUCCESS;
	}

	omd = talloc(msg, struct replPropertyMetaDataBlob);
	if (!omd) {
		ldb_module_oom(module);
		return LDB_SUCCESS;
	}

	ndr_err = ndr_pull_struct_blob(omd_value, omd, omd,
				       (ndr_pull_flags_fn_t)ndr_pull_replPropertyMetaDataBlob);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		DEBUG(0,(__location__ ": Failed to parse replPropertyMetaData for %s when trying to add msDS-KeyVersionNumber\n",
			 ldb_dn_get_linearized(msg->dn)));
		return ldb_operr(ldb_module_get_ctx(module));
	}

	if (omd->version != 1) {
		DEBUG(0,(__location__ ": bad version %u in replPropertyMetaData for %s when trying to add msDS-KeyVersionNumber\n",
			 omd->version, ldb_dn_get_linearized(msg->dn)));
		talloc_free(omd);
		return LDB_SUCCESS;
	}
	for (i=0; i<omd->ctr.ctr1.count; i++) {
		if (omd->ctr.ctr1.array[i].attid == DRSUAPI_ATTID_unicodePwd) {
			ret = samdb_msg_add_uint(ldb_module_get_ctx(module),
						 msg, msg,
						 "msDS-KeyVersionNumber",
						 omd->ctr.ctr1.array[i].version);
			if (ret != LDB_SUCCESS) {
				talloc_free(omd);
				return ret;
			}
			break;
		}
	}
	return LDB_SUCCESS;

}
Esempio n. 6
0
/*
  refresh a RID Set object for the specified DC
  also returns the first RID for the new pool
 */
static int ridalloc_refresh_rid_set_ntds(struct ldb_module *module,
					 struct ldb_dn *rid_manager_dn,
					 struct ldb_dn *ntds_dn, uint64_t *new_pool)
{
	TALLOC_CTX *tmp_ctx = talloc_new(module);
	struct ldb_dn *server_dn, *machine_dn, *rid_set_dn;
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	int ret;

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

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

	ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn);
	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;
	}

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

	ret = dsdb_module_set_integer(module, rid_set_dn, "rIDAllocationPool", *new_pool);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, "Failed to modify RID Set object %s - %s",
				       ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	talloc_free(tmp_ctx);
	return LDB_SUCCESS;
}
Esempio n. 7
0
/*
 * Initialize metadata. Load metadata.tdb.
 * If missing, create it and fill in sequence number
 */
int partition_metadata_init(struct ldb_module *module)
{
	struct partition_private_data *data;
	int ret;

	data = talloc_get_type_abort(ldb_module_get_private(module),
				     struct partition_private_data);

	data->metadata = talloc_zero(data, struct partition_metadata);
	if (data->metadata == NULL) {
		return ldb_module_oom(module);
	}

	ret = partition_metadata_open(module, false);
	if (ret == LDB_SUCCESS) {
		goto end;
	}

	/* metadata.tdb does not exist, create it */
	DEBUG(2, ("partition_metadata: Migrating partition metadata: "
		  "open of metadata.tdb gave: %s\n",
		  ldb_errstring(ldb_module_get_ctx(module))));
	ret = partition_metadata_open(module, true);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb_module_get_ctx(module),
				       "partition_metadata: "
				       "Migrating partition metadata: "
				       "create of metadata.tdb gave: %s\n",
				       ldb_errstring(ldb_module_get_ctx(module)));
		talloc_free(data->metadata);
		data->metadata = NULL;
		goto end;
	}

	ret = partition_metadata_set_sequence_number(module);
	if (ret != LDB_SUCCESS) {
		talloc_free(data->metadata);
		data->metadata = NULL;
	}

end:
	return ret;
}
Esempio n. 8
0
/**
 * Reads schema_info structure from schemaInfo
 * attribute on SCHEMA partition
 */
static int dsdb_module_schema_info_read(struct ldb_module *ldb_module,
					uint32_t dsdb_flags,
					TALLOC_CTX *mem_ctx,
					struct dsdb_schema_info **_schema_info,
					struct ldb_request *parent)
{
	int ret;
	DATA_BLOB ndr_blob;
	TALLOC_CTX *temp_ctx;
	WERROR werr;

	temp_ctx = talloc_new(mem_ctx);
	if (temp_ctx == NULL) {
		return ldb_module_oom(ldb_module);
	}

	/* read serialized schemaInfo from LDB  */
	ret = dsdb_module_schema_info_blob_read(ldb_module, dsdb_flags, temp_ctx, &ndr_blob, parent);
	if (ret != LDB_SUCCESS) {
		talloc_free(temp_ctx);
		return ret;
	}

	/* convert NDR blob to dsdb_schema_info object */
	werr = dsdb_schema_info_from_blob(&ndr_blob,
					  mem_ctx,
					  _schema_info);
	talloc_free(temp_ctx);

	if (W_ERROR_EQUAL(werr, WERR_DS_NO_ATTRIBUTE_OR_VALUE)) {
		return LDB_ERR_NO_SUCH_ATTRIBUTE;
	}

	if (!W_ERROR_IS_OK(werr)) {
		ldb_asprintf_errstring(ldb_module_get_ctx(ldb_module), __location__ ": failed to get schema_info");
		return ldb_operr(ldb_module_get_ctx(ldb_module));
	}

	return LDB_SUCCESS;
}
Esempio n. 9
0
/**
 * Writes schema_info structure into schemaInfo
 * attribute on SCHEMA partition
 *
 * @param dsdb_flags 	DSDB_FLAG_... flag of 0
 */
int dsdb_module_schema_info_blob_write(struct ldb_module *ldb_module,
				       uint32_t dsdb_flags,
				       struct ldb_val *schema_info_blob,
				       struct ldb_request *parent)
{
	int ldb_err;
	struct ldb_message *msg;
	TALLOC_CTX *temp_ctx;

	temp_ctx = talloc_new(ldb_module);
	if (temp_ctx == NULL) {
		return ldb_module_oom(ldb_module);
	}

	/* write serialized schemaInfo into LDB */
	ldb_err = dsdb_schema_info_write_prepare(ldb_module_get_ctx(ldb_module),
						 schema_info_blob,
						 temp_ctx, &msg);
	if (ldb_err != LDB_SUCCESS) {
		talloc_free(temp_ctx);
		return ldb_err;
	}


	ldb_err = dsdb_module_modify(ldb_module, msg, dsdb_flags, parent);

	talloc_free(temp_ctx);

	if (ldb_err != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb_module_get_ctx(ldb_module),
				       "dsdb_module_schema_info_blob_write: dsdb_replace failed: %s (%s)\n",
				       ldb_strerror(ldb_err),
				       ldb_errstring(ldb_module_get_ctx(ldb_module)));
		return ldb_err;
	}

	return LDB_SUCCESS;
}
Esempio n. 10
0
/*
  called by DSDB_EXTENDED_ALLOCATE_RID_POOL extended operation in samldb
 */
int ridalloc_allocate_rid_pool_fsmo(struct ldb_module *module, struct dsdb_fsmo_extended_op *exop,
				    struct ldb_request *parent)
{
	struct ldb_dn *ntds_dn, *server_dn, *machine_dn, *rid_set_dn;
	struct ldb_dn *rid_manager_dn;
	TALLOC_CTX *tmp_ctx = talloc_new(module);
	int ret;
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	struct ldb_result *res;
	struct ldb_message *msg;
	struct ridalloc_ridset_values oridset, nridset;

	ret = dsdb_module_dn_by_guid(module, tmp_ctx, &exop->destination_dsa_guid, &ntds_dn, parent);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, __location__ ": Unable to find NTDS object for guid %s - %s\n",
				       GUID_string(tmp_ctx, &exop->destination_dsa_guid), ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	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, __location__ ": Failed to find serverReference in %s - %s",
				       ldb_dn_get_linearized(server_dn), ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn, parent);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, __location__ ": Failed to find RID Manager object - %s",
				       ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	ret = dsdb_module_reference_dn(module, tmp_ctx, machine_dn, "rIDSetReferences", &rid_set_dn, parent);
	if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
		ret = ridalloc_create_rid_set_ntds(module, tmp_ctx, rid_manager_dn, ntds_dn, &rid_set_dn, parent);
		talloc_free(tmp_ctx);
		return ret;
	}

	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, "Failed to find rIDSetReferences in %s - %s",
				       ldb_dn_get_linearized(machine_dn), ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_set_dn,
				    ridalloc_ridset_attrs, DSDB_FLAG_NEXT_MODULE, parent);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, __location__ ": No RID Set %s",
				       ldb_dn_get_linearized(rid_set_dn));
		talloc_free(tmp_ctx);
		return ret;
	}

	ridalloc_get_ridset_values(res->msgs[0], &oridset);
	if (oridset.alloc_pool == UINT64_MAX) {
		ldb_asprintf_errstring(ldb, __location__ ": Bad RID Set %s",
				       ldb_dn_get_linearized(rid_set_dn));
		talloc_free(tmp_ctx);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	nridset = oridset;

	if (exop->fsmo_info != 0) {

		if (nridset.alloc_pool != exop->fsmo_info) {
			/* it has already been updated */
			DEBUG(2,(__location__ ": rIDAllocationPool fsmo_info mismatch - already changed (0x%llx 0x%llx)\n",
				 (unsigned long long)exop->fsmo_info,
				 (unsigned long long)nridset.alloc_pool));
			talloc_free(tmp_ctx);
			return LDB_SUCCESS;
		}
	}

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

	/*
	 * update the values
	 */
	msg = ldb_msg_new(tmp_ctx);
	if (msg == NULL) {
		return ldb_module_oom(module);
	}
	msg->dn = rid_set_dn;

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

	ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, "Failed to modify RID Set object %s - %s",
				       ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	talloc_free(tmp_ctx);
	return LDB_SUCCESS;
}
Esempio n. 11
0
/* allocate a RID using our RID Set
   If we run out of RIDs then allocate a new pool
   either locally or by contacting the RID Manager
*/
int ridalloc_allocate_rid(struct ldb_module *module, uint32_t *rid, struct ldb_request *parent)
{
	struct ldb_context *ldb;
	int ret;
	struct ldb_dn *rid_set_dn;
	struct ldb_result *res;
	struct ldb_message *msg;
	struct ridalloc_ridset_values oridset;
	struct ridalloc_ridset_values nridset;
	uint32_t prev_pool_lo, prev_pool_hi;
	TALLOC_CTX *tmp_ctx = talloc_new(module);

	(*rid) = 0;
	ldb = ldb_module_get_ctx(module);

	ret = samdb_rid_set_dn(ldb, tmp_ctx, &rid_set_dn);
	if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
		ret = ridalloc_create_own_rid_set(module, tmp_ctx, &rid_set_dn, parent);
	}
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, __location__ ": No RID Set DN - %s",
				       ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}

	ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_set_dn,
				    ridalloc_ridset_attrs, DSDB_FLAG_NEXT_MODULE, parent);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, __location__ ": No RID Set %s",
				       ldb_dn_get_linearized(rid_set_dn));
		talloc_free(tmp_ctx);
		return ret;
	}

	ridalloc_get_ridset_values(res->msgs[0], &oridset);
	if (oridset.alloc_pool == UINT64_MAX) {
		ldb_asprintf_errstring(ldb, __location__ ": Bad RID Set %s",
				       ldb_dn_get_linearized(rid_set_dn));
		talloc_free(tmp_ctx);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	nridset = oridset;

	/*
	 * If we never used a pool, setup out first pool
	 */
	if (nridset.prev_pool == UINT64_MAX ||
	    nridset.next_rid == UINT32_MAX) {
		nridset.prev_pool = nridset.alloc_pool;
		nridset.next_rid = nridset.prev_pool & 0xFFFFFFFF;
	}

	/*
	 * Now check if our current pool is still usable
	 */
	nridset.next_rid += 1;
	prev_pool_lo = nridset.prev_pool & 0xFFFFFFFF;
	prev_pool_hi = nridset.prev_pool >> 32;
	if (nridset.next_rid > prev_pool_hi) {
		/*
		 * We need a new pool, check if we already have a new one
		 * Otherwise we need to get a new pool.
		 */
		if (nridset.alloc_pool == nridset.prev_pool) {
			/*
			 * if we are the RID Manager,
			 * we can get a new pool localy.
			 * Otherwise we fail the operation and
			 * ask async for a new pool.
			 */
			ret = ridalloc_new_own_pool(module, &nridset.alloc_pool, parent);
			if (ret == LDB_ERR_UNWILLING_TO_PERFORM) {
				ridalloc_poke_rid_manager(module);
				talloc_free(tmp_ctx);
				return ret;
			}
			if (ret != LDB_SUCCESS) {
				talloc_free(tmp_ctx);
				return ret;
			}
		}

		/*
		 * increment the rIDUsedPool attribute
		 *
		 * Note: w2k8r2 doesn't update this attribute,
		 *       at least if it's itself the rid master.
		 */
		nridset.used_pool += 1;

		/* now use the new pool */
		nridset.prev_pool = nridset.alloc_pool;
		prev_pool_lo = nridset.prev_pool & 0xFFFFFFFF;
		prev_pool_hi = nridset.prev_pool >> 32;
		nridset.next_rid = prev_pool_lo;
	}

	if (nridset.next_rid < prev_pool_lo || nridset.next_rid > prev_pool_hi) {
		ldb_asprintf_errstring(ldb, __location__ ": Bad rid chosen %u from range %u-%u",
				       (unsigned)nridset.next_rid,
				       (unsigned)prev_pool_lo,
				       (unsigned)prev_pool_hi);
		talloc_free(tmp_ctx);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/*
	 * if we are half-exhausted then try to get a new pool.
	 */
	if (nridset.next_rid > (prev_pool_hi + prev_pool_lo)/2) {
		/*
		 * if we are the RID Manager,
		 * we can get a new pool localy.
		 * Otherwise we fail the operation and
		 * ask async for a new pool.
		 */
		ret = ridalloc_new_own_pool(module, &nridset.alloc_pool, parent);
		if (ret == LDB_ERR_UNWILLING_TO_PERFORM) {
			ridalloc_poke_rid_manager(module);
			ret = LDB_SUCCESS;
		}
		if (ret != LDB_SUCCESS) {
			talloc_free(tmp_ctx);
			return ret;
		}
	}

	/*
	 * update the values
	 */
	msg = ldb_msg_new(tmp_ctx);
	if (msg == NULL) {
		return ldb_module_oom(module);
	}
	msg->dn = rid_set_dn;

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

	ret = dsdb_module_modify(module, msg, DSDB_FLAG_NEXT_MODULE, parent);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}

	talloc_free(tmp_ctx);
	*rid = nridset.next_rid;
	return LDB_SUCCESS;
}
Esempio n. 12
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)
{
	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
	struct ldb_dn *server_dn, *machine_dn, *rid_set_dn;
	int ret;
	uint64_t dc_pool;
	struct ldb_message *msg;
	struct ldb_context *ldb = ldb_module_get_ctx(module);

	/*
	  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) {
		ldb_module_oom(module);
		talloc_free(tmp_ctx);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn);
	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) {
		ldb_module_oom(module);
		return LDB_ERR_OPERATIONS_ERROR;
	}

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

	/* grab a pool from the RID Manager object */
	ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, &dc_pool);
	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 = ldb_msg_add_fmt(msg, "rIDAllocationPool", "%llu", (unsigned long long)dc_pool);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}

	/* w2k8-r2 sets these to zero when first created */
	ret = ldb_msg_add_fmt(msg, "rIDPreviousAllocationPool", "0");
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}
	ret = ldb_msg_add_fmt(msg, "rIDUsedPool", "0");
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}
	ret = ldb_msg_add_fmt(msg, "rIDNextRID", "0");
	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);
	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, 0);
	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;
}
Esempio n. 13
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,
	};
	const char *no_attrs[] = { NULL };
	struct ldb_result *res;

	/*
	  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).  We must do this
	 * as system, otherwise a user might end up owning the RID
	 * set, and that would be bad... */
	ret = dsdb_module_add(module, msg,
			      DSDB_FLAG_TOP_MODULE | DSDB_FLAG_AS_SYSTEM
			      | 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;

	/* we need the extended DN of the RID Set object for
	 * rIDSetReferences */
	ret = dsdb_module_search_dn(module, msg, &res, rid_set_dn, no_attrs,
				    DSDB_FLAG_NEXT_MODULE | DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT, parent);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb, "Failed to find extended DN of RID Set %s - %s",
				       ldb_dn_get_linearized(msg->dn),
				       ldb_errstring(ldb));
		talloc_free(tmp_ctx);
		return ret;
	}
	rid_set_dn = res->msgs[0]->dn;


	ret = ldb_msg_add_string(msg, "rIDSetReferences", ldb_dn_get_extended_linearized(msg, rid_set_dn, 1));
	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
 */
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);
	struct GUID fsmo_role_guid;
	const struct GUID *our_ntds_guid;
	NTSTATUS status;

	/* 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;
	}

	status = dsdb_get_extended_dn_guid(fsmo_role_dn, &fsmo_role_guid, "GUID");
	if (!NT_STATUS_IS_OK(status)) {
		talloc_free(tmp_ctx);
		return ldb_operr(ldb_module_get_ctx(module));
	}

	our_ntds_guid = samdb_ntds_objectGUID(ldb_module_get_ctx(module));
	if (!our_ntds_guid) {
		talloc_free(tmp_ctx);
		return ldb_operr(ldb_module_get_ctx(module));
	}

	if (!GUID_equal(&fsmo_role_guid, our_ntds_guid)) {
		ret = ridalloc_poke_rid_manager(module);
		if (ret != LDB_SUCCESS) {
			ldb_asprintf_errstring(ldb,
					"Request for remote creation of "
					"RID Set for this DC failed: %s",
					ldb_errstring(ldb));
		} else {
			ldb_asprintf_errstring(ldb,
					"Remote RID Set creation needed");
		}
		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;
}
Esempio n. 14
0
/**
 * Increments schemaInfo revision and save it to DB
 * setting our invocationID in the process
 * NOTE: this function should be called in a transaction
 * much in the same way prefixMap update function is called
 *
 * @param ldb_module 	current module
 * @param schema 	schema cache
 * @param dsdb_flags 	DSDB_FLAG_... flag of 0
 */
int dsdb_module_schema_info_update(struct ldb_module *ldb_module,
				   struct dsdb_schema *schema,
				   int dsdb_flags, struct ldb_request *parent)
{
	int ret;
	const struct GUID *invocation_id;
	DATA_BLOB ndr_blob;
	struct dsdb_schema_info *schema_info;
	const char *schema_info_str;
	WERROR werr;
	TALLOC_CTX *temp_ctx = talloc_new(schema);
	if (temp_ctx == NULL) {
		return ldb_module_oom(ldb_module);
	}

	invocation_id = samdb_ntds_invocation_id(ldb_module_get_ctx(ldb_module));
	if (!invocation_id) {
		talloc_free(temp_ctx);
		return ldb_operr(ldb_module_get_ctx(ldb_module));
	}

	/* read serialized schemaInfo from LDB  */
	ret = dsdb_module_schema_info_read(ldb_module, dsdb_flags, temp_ctx, &schema_info, parent);
	if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
		/* make default value in case
		 * we have no schemaInfo value yet */
		werr = dsdb_schema_info_new(temp_ctx, &schema_info);
		if (!W_ERROR_IS_OK(werr)) {
			talloc_free(temp_ctx);
			return ldb_module_oom(ldb_module);
		}
		ret = LDB_SUCCESS;
	}
	if (ret != LDB_SUCCESS) {
		talloc_free(temp_ctx);
		return ret;
	}

	/* update schemaInfo */
	schema_info->revision++;
	schema_info->invocation_id = *invocation_id;

	ret = dsdb_module_schema_info_write(ldb_module, dsdb_flags, schema_info, parent);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(ldb_module_get_ctx(ldb_module),
				       "dsdb_module_schema_info_update: failed to save schemaInfo - %s\n",
				       ldb_strerror(ret));
		talloc_free(temp_ctx);
		return ret;
	}

	/* finally, update schema_info in the cache */
	werr = dsdb_blob_from_schema_info(schema_info, temp_ctx, &ndr_blob);
	if (!W_ERROR_IS_OK(werr)) {
		ldb_asprintf_errstring(ldb_module_get_ctx(ldb_module), "Failed to get schema info");
		talloc_free(temp_ctx);
		return ldb_operr(ldb_module_get_ctx(ldb_module));
	}

	schema_info_str = hex_encode_talloc(schema, ndr_blob.data, ndr_blob.length);
	if (!schema_info_str) {
		talloc_free(temp_ctx);
		return ldb_module_oom(ldb_module);
	}

	talloc_unlink(schema, discard_const(schema->schema_info));
	schema->schema_info = schema_info_str;

	talloc_free(temp_ctx);
	return LDB_SUCCESS;
}
Esempio n. 15
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;
}
Esempio n. 16
0
File: util.c Progetto: endisd/samba
/*
  add a set of controls to a ldb_request structure based on a set of
  flags. See util.h for a list of available flags
 */
int dsdb_request_add_controls(struct ldb_module *module, struct ldb_request *req, uint32_t dsdb_flags)
{
	int ret;
	if (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) {
		struct ldb_search_options_control *options;
		/* Using the phantom root control allows us to search all partitions */
		options = talloc(req, struct ldb_search_options_control);
		if (options == NULL) {
			ldb_module_oom(module);
			return LDB_ERR_OPERATIONS_ERROR;
		}
		options->search_options = LDB_SEARCH_OPTION_PHANTOM_ROOT;
		
		ret = ldb_request_add_control(req,
					      LDB_CONTROL_SEARCH_OPTIONS_OID,
					      true, options);
		if (ret != LDB_SUCCESS) {
			return ret;
		}
	}

	if (dsdb_flags & DSDB_SEARCH_SHOW_DELETED) {
		ret = ldb_request_add_control(req, LDB_CONTROL_SHOW_DELETED_OID, true, NULL);
		if (ret != LDB_SUCCESS) {
			return ret;
		}
	}

	if (dsdb_flags & DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT) {
		ret = ldb_request_add_control(req, DSDB_CONTROL_DN_STORAGE_FORMAT_OID, true, NULL);
		if (ret != LDB_SUCCESS) {
			return ret;
		}
	}

	if (dsdb_flags & DSDB_SEARCH_SHOW_EXTENDED_DN) {
		struct ldb_extended_dn_control *extended_ctrl = talloc(req, struct ldb_extended_dn_control);
		if (!extended_ctrl) {
			ldb_module_oom(module);
			return LDB_ERR_OPERATIONS_ERROR;
		}
		extended_ctrl->type = 1;
		
		ret = ldb_request_add_control(req, LDB_CONTROL_EXTENDED_DN_OID, true, extended_ctrl);
		if (ret != LDB_SUCCESS) {
			return ret;
		}
	}

	if (dsdb_flags & DSDB_SEARCH_REVEAL_INTERNALS) {
		ret = ldb_request_add_control(req, LDB_CONTROL_REVEAL_INTERNALS, false, NULL);
		if (ret != LDB_SUCCESS) {
			return ret;
		}
	}

	if (dsdb_flags & DSDB_MODIFY_RELAX) {
		ret = ldb_request_add_control(req, LDB_CONTROL_RELAX_OID, false, NULL);
		if (ret != LDB_SUCCESS) {
			return ret;
		}
	}

	return LDB_SUCCESS;
}
Esempio n. 17
0
/*
 * Open sam.ldb.d/metadata.tdb.
 */
static int partition_metadata_open(struct ldb_module *module, bool create)
{
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	TALLOC_CTX *tmp_ctx;
	struct partition_private_data *data;
	struct loadparm_context *lp_ctx;
	const char *sam_name;
	char *filename, *dirname;
	int open_flags;
	struct stat statbuf;

	data = talloc_get_type_abort(ldb_module_get_private(module),
				     struct partition_private_data);
	if (!data || !data->metadata) {
		return ldb_module_error(module, LDB_ERR_OPERATIONS_ERROR,
					"partition_metadata: metadata not initialized");
	}

	tmp_ctx = talloc_new(NULL);
	if (tmp_ctx == NULL) {
		return ldb_module_oom(module);
	}

	sam_name = (const char *)ldb_get_opaque(ldb, "ldb_url");
	if (!sam_name) {
		talloc_free(tmp_ctx);
		return ldb_operr(ldb);
	}
	if (strncmp("tdb://", sam_name, 6) == 0) {
		sam_name += 6;
	}
	filename = talloc_asprintf(tmp_ctx, "%s.d/metadata.tdb", sam_name);
	if (!filename) {
		talloc_free(tmp_ctx);
		return ldb_oom(ldb);
	}

	open_flags = O_RDWR;
	if (create) {
		open_flags |= O_CREAT;

		/* While provisioning, sam.ldb.d directory may not exist,
		 * so create it. Ignore errors, if it already exists. */
		dirname = talloc_asprintf(tmp_ctx, "%s.d", sam_name);
		if (!dirname) {
			talloc_free(tmp_ctx);
			return ldb_oom(ldb);
		}

		mkdir(dirname, 0700);
		talloc_free(dirname);
	} else {
		if (stat(filename, &statbuf) != 0) {
			talloc_free(tmp_ctx);
			return LDB_ERR_OPERATIONS_ERROR;
		}
	}

	lp_ctx = talloc_get_type_abort(ldb_get_opaque(ldb, "loadparm"),
				       struct loadparm_context);

	data->metadata->db = tdb_wrap_open(
		data->metadata, filename, 10,
		lpcfg_tdb_flags(lp_ctx, TDB_DEFAULT), open_flags, 0660);
	if (data->metadata->db == NULL) {
		talloc_free(tmp_ctx);
		if (create) {
			ldb_asprintf_errstring(ldb, "partition_metadata: Unable to create %s: %s",
					       filename, strerror(errno));
		} else {
			ldb_asprintf_errstring(ldb, "partition_metadata: Unable to open %s: %s",
					       filename, strerror(errno));
		}
		if (errno == EACCES || errno == EPERM) {
			return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
		}
		return LDB_ERR_OPERATIONS_ERROR;
	}

	talloc_free(tmp_ctx);
	return LDB_SUCCESS;
}