Beispiel #1
0
/*
  make a IRPC call to the drepl task to ask it to get the RID
  Manager to give us another RID pool.

  This function just sends the message to the drepl task then
  returns immediately. It should be called well before we
  completely run out of RIDs
 */
static void ridalloc_poke_rid_manager(struct ldb_module *module)
{
	struct messaging_context *msg;
	struct server_id *server;
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	struct loadparm_context *lp_ctx =
		(struct loadparm_context *)ldb_get_opaque(ldb, "loadparm");
	TALLOC_CTX *tmp_ctx = talloc_new(module);

	msg = messaging_client_init(tmp_ctx, lpcfg_messaging_path(tmp_ctx, lp_ctx),
				    ldb_get_event_context(ldb));
	if (!msg) {
		DEBUG(3,(__location__ ": Failed to create messaging context\n"));
		talloc_free(tmp_ctx);
		return;
	}

	server = irpc_servers_byname(msg, msg, "dreplsrv");
	if (!server) {
		/* this means the drepl service is not running */
		talloc_free(tmp_ctx);
		return;
	}

	messaging_send(msg, server[0], MSG_DREPL_ALLOCATE_RID, NULL);

	/* we don't care if the message got through */
	talloc_free(tmp_ctx);
}
Beispiel #2
0
static enum user_is what_is_user(struct ldb_module *module) 
{
	struct auth_session_info *session_info
		= ldb_get_opaque(module->ldb, "sessionInfo");
	if (!session_info) {
		return ANONYMOUS;
	}
	
	if (security_token_is_system(session_info->security_token)) {
		return SYSTEM;
	}

	if (security_token_is_anonymous(session_info->security_token)) {
		return ANONYMOUS;
	}

	if (security_token_has_builtin_administrators(session_info->security_token)) {
		return ADMINISTRATOR;
	}

	if (security_token_has_nt_authenticated_users(session_info->security_token)) {
		return USER;
	}

	return ANONYMOUS;
}
Beispiel #3
0
/**
 * Make this ldb use a specified schema, already fully calculated and belonging to another ldb
 */
int dsdb_reference_schema(struct ldb_context *ldb, struct dsdb_schema *schema,
			  bool write_attributes)
{
	int ret;
	struct dsdb_schema *old_schema;
	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 */
	talloc_unlink(ldb, old_schema);

	if (talloc_reference(ldb, schema) == NULL) {
		return ldb_oom(ldb);
	}

	/* Make this ldb use local schema preferably */
	ret = ldb_set_opaque(ldb, "dsdb_use_global_schema", NULL);
	if (ret != LDB_SUCCESS) {
		return ret;
	}

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

	return LDB_SUCCESS;
}
Beispiel #4
0
static DATA_BLOB *get_new_descriptor(struct ldb_module *module,
				     struct ldb_dn *dn,
				     TALLOC_CTX *mem_ctx,
				     const struct dsdb_class *objectclass,
				     const struct ldb_val *parent,
				     const struct ldb_val *object,
				     const struct ldb_val *old_sd,
				     uint32_t sd_flags)
{
	struct security_descriptor *user_descriptor = NULL, *parent_descriptor = NULL;
	struct security_descriptor *old_descriptor = NULL;
	struct security_descriptor *new_sd, *final_sd;
	DATA_BLOB *linear_sd;
	enum ndr_err_code ndr_err;
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	struct auth_session_info *session_info
		= ldb_get_opaque(ldb, "sessionInfo");
	const struct dom_sid *domain_sid = samdb_domain_sid(ldb);
	char *sddl_sd;
	struct dom_sid *default_owner;
	struct dom_sid *default_group;
	struct security_descriptor *default_descriptor = NULL;
	struct GUID *object_list = NULL;

	if (objectclass != NULL) {
		default_descriptor = get_sd_unpacked(module, mem_ctx, objectclass);
		object_list = talloc_zero_array(mem_ctx, struct GUID, 2);
		if (object_list == NULL) {
			return NULL;
		}
		object_list[0] = objectclass->schemaIDGUID;
	}
Beispiel #5
0
static int wins_ldb_init(struct ldb_module *module)
{
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	struct winsdb_handle *h;
	const char *owner;
	struct loadparm_context *lp_ctx = ldb_get_opaque(ldb, "loadparm");

	ldb_module_set_private(module, NULL);

	owner = lpcfg_parm_string(lp_ctx, NULL, "winsdb", "local_owner");
	if (!owner) {
		struct interface *ifaces;
		load_interface_list(module, lp_ctx, &ifaces);
		owner = iface_list_first_v4(ifaces);
		if (!owner) {
			owner = "0.0.0.0";
		}
	}

	h = talloc_zero(module, struct winsdb_handle);
	if (!h) goto failed;
	h->ldb		= ldb;
	h->caller	= WINSDB_HANDLE_CALLER_ADMIN;
	h->local_owner	= talloc_strdup(h, owner);
	if (!h->local_owner) goto failed;

	return ldb_set_opaque(ldb, "winsdb_handle", h);

failed:
	talloc_free(h);
	return LDB_ERR_OTHER;
}
Beispiel #6
0
static enum security_user_level what_is_user(struct ldb_module *module)
{
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	struct auth_session_info *session_info
		= (struct auth_session_info *)ldb_get_opaque(ldb, "sessionInfo");
	return security_session_user_level(session_info);
}
Beispiel #7
0
 char *ldb_relative_path(struct ldb_context *ldb,
			 TALLOC_CTX *mem_ctx,
			 const char *name)
{
	const char *base_url =
		(const char *)ldb_get_opaque(ldb, "ldb_url");
	char *path, *p, *full_name;
	if (name == NULL) {
		return NULL;
	}
	if (strncmp("tdb://", base_url, 6) == 0) {
		base_url = base_url+6;
	}
	path = talloc_strdup(mem_ctx, base_url);
	if (path == NULL) {
		return NULL;
	}
	if ( (p = strrchr(path, '/')) != NULL) {
		p[0] = '\0';
		full_name = talloc_asprintf(mem_ctx, "%s/%s", path, name);
	} else {
		full_name = talloc_asprintf(mem_ctx, "./%s", name);
	}
	talloc_free(path);
	return full_name;
}
Beispiel #8
0
static PyObject *py_dsdb_set_opaque_integer(PyObject *self, PyObject *args)
{
	PyObject *py_ldb;
	int value;
	int *old_val, *new_val;
	char *py_opaque_name, *opaque_name_talloc;
	struct ldb_context *ldb;
	TALLOC_CTX *tmp_ctx;

	if (!PyArg_ParseTuple(args, "Osi", &py_ldb, &py_opaque_name, &value))
		return NULL;

	PyErr_LDB_OR_RAISE(py_ldb, ldb);

	/* see if we have a cached copy */
	old_val = (int *)ldb_get_opaque(ldb, 
					py_opaque_name);

	if (old_val) {
		*old_val = value;
		Py_RETURN_NONE;
	} 

	tmp_ctx = talloc_new(ldb);
	if (tmp_ctx == NULL) {
		goto failed;
	}
	
	new_val = talloc(tmp_ctx, int);
	if (!new_val) {
		goto failed;
	}
	
	opaque_name_talloc = talloc_strdup(tmp_ctx, py_opaque_name);
	if (!opaque_name_talloc) {
		goto failed;
	}
	
	*new_val = value;

	/* cache the domain_sid in the ldb */
	if (ldb_set_opaque(ldb, opaque_name_talloc, new_val) != LDB_SUCCESS) {
		goto failed;
	}

	talloc_steal(ldb, new_val);
	talloc_steal(ldb, opaque_name_talloc);
	talloc_free(tmp_ctx);

	Py_RETURN_NONE;

failed:
	talloc_free(tmp_ctx);
	PyErr_SetString(PyExc_RuntimeError, "Failed to set opaque integer into the ldb!\n");
	return NULL;
}
Beispiel #9
0
static struct security_token *acl_user_token(struct ldb_module *module)
{
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	struct auth_session_info *session_info
		= (struct auth_session_info *)ldb_get_opaque(ldb, "sessionInfo");
	if(!session_info) {
		return NULL;
	}
	return session_info->security_token;
}
Beispiel #10
0
/*
  register the samba ldif handlers
*/
int ldb_register_samba_handlers(struct ldb_context *ldb)
{
	unsigned int i;
	int ret;

	if (ldb_get_opaque(ldb, "SAMBA_HANDLERS_REGISTERED") != NULL) {
		return LDB_SUCCESS;
	}

	ret = ldb_set_opaque(ldb, LDB_SECRET_ATTRIBUTE_LIST_OPAQUE, discard_const_p(char *, secret_attributes));
	if (ret != LDB_SUCCESS) {
		return ret;
	}

	for (i=0; i < ARRAY_SIZE(samba_attributes); i++) {
		const struct ldb_schema_syntax *s = NULL;

		s = ldb_samba_syntax_by_name(ldb, samba_attributes[i].syntax);

		if (!s) {
			s = ldb_standard_syntax_by_name(ldb, samba_attributes[i].syntax);
		}

		if (!s) {
			return LDB_ERR_OPERATIONS_ERROR;
		}

		ret = ldb_schema_attribute_add_with_syntax(ldb, samba_attributes[i].name, LDB_ATTR_FLAG_FIXED, s);
		if (ret != LDB_SUCCESS) {
			return ret;
		}
	}

	for (i=0; i < ARRAY_SIZE(samba_dn_syntax); i++) {
		ret = ldb_dn_extended_add_syntax(ldb, LDB_ATTR_FLAG_FIXED, &samba_dn_syntax[i]);
		if (ret != LDB_SUCCESS) {
			return ret;
		}

	}

	ret = ldb_register_samba_matching_rules(ldb);
	if (ret != LDB_SUCCESS) {
		talloc_free(ldb);
		return LDB_SUCCESS;
	}

	ret = ldb_set_opaque(ldb, "SAMBA_HANDLERS_REGISTERED", (void*)1);
	if (ret != LDB_SUCCESS) {
		return ret;
	}

	return LDB_SUCCESS;
}
Beispiel #11
0
static const char *user_name(TALLOC_CTX *mem_ctx, struct ldb_module *module) 
{
	struct auth_session_info *session_info
		= ldb_get_opaque(module->ldb, "sessionInfo");
	if (!session_info) {
		return "UNKNOWN (NULL)";
	}
	
	return talloc_asprintf(mem_ctx, "%s\\%s",
			       session_info->server_info->domain_name,
			       session_info->server_info->account_name);
}
Beispiel #12
0
struct dsdb_schema *dsdb_get_schema(struct ldb_context *ldb, TALLOC_CTX *reference_ctx)
{
	const void *p;
	struct dsdb_schema *schema_out;
	struct dsdb_schema *schema_in;
	bool use_global_schema;
	TALLOC_CTX *tmp_ctx = talloc_new(reference_ctx);
	if (!tmp_ctx) {
		return NULL;
	}

	/* see if we have a cached copy */
	use_global_schema = dsdb_uses_global_schema(ldb);
	if (use_global_schema) {
		schema_in = global_schema;
	} else {
		p = ldb_get_opaque(ldb, "dsdb_schema");

		schema_in = talloc_get_type(p, struct dsdb_schema);
		if (!schema_in) {
			talloc_free(tmp_ctx);
			return NULL;
		}
	}

	if (schema_in->refresh_fn && !schema_in->refresh_in_progress) {
		if (!talloc_reference(tmp_ctx, schema_in)) {
			/*
			 * ensure that the schema_in->refresh_in_progress
			 * remains valid for the right amount of time
			 */
			talloc_free(tmp_ctx);
			return NULL;
		}
		schema_in->refresh_in_progress = true;
		/* This may change schema, if it needs to reload it from disk */
		schema_out = schema_in->refresh_fn(schema_in->loaded_from_module,
						   schema_in,
						   use_global_schema);
		schema_in->refresh_in_progress = false;
	} else {
		schema_out = schema_in;
	}

	/* This removes the extra reference above */
	talloc_free(tmp_ctx);
	if (!reference_ctx) {
		return schema_out;
	} else {
		return talloc_reference(reference_ctx, schema_out);
	}
}
Beispiel #13
0
/*
  make a IRPC call to the drepl task to ask it to get the RID
  Manager to give us another RID pool.

  This function just sends the message to the drepl task then
  returns immediately. It should be called well before we
  completely run out of RIDs
 */
static int ridalloc_poke_rid_manager(struct ldb_module *module)
{
	struct imessaging_context *msg;
	unsigned num_servers;
	struct server_id *servers;
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	struct loadparm_context *lp_ctx =
		(struct loadparm_context *)ldb_get_opaque(ldb, "loadparm");
	TALLOC_CTX *tmp_ctx = talloc_new(module);
	NTSTATUS status;

	msg = imessaging_client_init(tmp_ctx, lp_ctx,
				    ldb_get_event_context(ldb));
	if (!msg) {
		ldb_asprintf_errstring(ldb_module_get_ctx(module),
				"Failed to send MSG_DREPL_ALLOCATE_RID, "
				"unable init client messaging context");
		DEBUG(3,(__location__ ": Failed to create messaging context\n"));
		talloc_free(tmp_ctx);
		return LDB_ERR_UNWILLING_TO_PERFORM;
	}

	status = irpc_servers_byname(msg, msg, "dreplsrv",
				     &num_servers, &servers);
	if (!NT_STATUS_IS_OK(status)) {
		ldb_asprintf_errstring(ldb_module_get_ctx(module),
				"Failed to send MSG_DREPL_ALLOCATE_RID, "
				"unable to locate dreplsrv");
		/* this means the drepl service is not running */
		talloc_free(tmp_ctx);
		return LDB_ERR_UNWILLING_TO_PERFORM;
	}

	status = imessaging_send(msg, servers[0], MSG_DREPL_ALLOCATE_RID, NULL);

	/* Only error out if an error happened, not on STATUS_MORE_ENTRIES, ie a delayed message */
	if (NT_STATUS_IS_ERR(status)) {
		struct server_id_buf idbuf;
		ldb_asprintf_errstring(ldb_module_get_ctx(module),
				"Failed to send MSG_DREPL_ALLOCATE_RID to dreplsrv at %s: %s",
				server_id_str_buf(*servers, &idbuf),
				nt_errstr(status));
		talloc_free(tmp_ctx);
		return LDB_ERR_UNWILLING_TO_PERFORM;
	}

	talloc_free(tmp_ctx);
	return LDB_SUCCESS;
}
Beispiel #14
0
WERROR dsdb_read_prefixes_from_ldb(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct dsdb_schema_prefixmap **_pfm)
{
	WERROR werr;
	int ldb_ret;
	const struct ldb_val *prefix_val;
	struct smb_iconv_convenience *iconv_convenience;
	struct ldb_dn *schema_dn;
	struct ldb_result *schema_res = NULL;
	static const char *schema_attrs[] = {
		"prefixMap",
		NULL
	};

	schema_dn = samdb_schema_dn(ldb);
	if (!schema_dn) {
		DEBUG(0,("dsdb_read_prefixes_from_ldb: no schema dn present\n"));
		return WERR_FOOBAR;
	}

	ldb_ret = ldb_search(ldb, mem_ctx, &schema_res, schema_dn, LDB_SCOPE_BASE, schema_attrs, NULL);
	if (ldb_ret == LDB_ERR_NO_SUCH_OBJECT) {
		DEBUG(0,("dsdb_read_prefixes_from_ldb: no prefix map present\n"));
		talloc_free(schema_res);
		return WERR_FOOBAR;
	} else if (ldb_ret != LDB_SUCCESS) {
		DEBUG(0,("dsdb_read_prefixes_from_ldb: failed to search the schema head\n"));
		talloc_free(schema_res);
		return WERR_FOOBAR;
	}

	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"));
		talloc_free(schema_res);
		return WERR_FOOBAR;
	}

	iconv_convenience = lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm"));

	werr = _dsdb_prefixmap_from_ldb_val(prefix_val,
					    iconv_convenience,
					    mem_ctx,
					    _pfm);
	talloc_free(schema_res);
	W_ERROR_NOT_OK_RETURN(werr);

	return WERR_OK;
}
Beispiel #15
0
struct dsdb_schema *dsdb_get_schema(struct ldb_context *ldb)
{
	const void *p;
	struct dsdb_schema *schema;

	/* see if we have a cached copy */
	p = ldb_get_opaque(ldb, "dsdb_schema");
	if (!p) {
		return NULL;
	}

	schema = talloc_get_type(p, struct dsdb_schema);
	if (!schema) {
		return NULL;
	}

	return schema;
}
Beispiel #16
0
/*
 * @brief Get the directory containing the key files.
 *
 * @param ctx talloc memory context that will own the return value
 * @param ldb ldb context, to allow logging
 *
 * @return zero terminated string, the directory containing the key file
 *         allocated on ctx.
 *
 */
static const char* get_key_directory(TALLOC_CTX *ctx, struct ldb_context *ldb)
{

	const char *sam_ldb_path = NULL;
	const char *private_dir  = NULL;
	char *p = NULL;


	/*
	 * Work out where *our* key file is. It must be in
	 * the same directory as sam.ldb
	 */
	sam_ldb_path = ldb_get_opaque(ldb, "ldb_url");
	if (sam_ldb_path == NULL) {
		ldb_set_errstring(ldb, "Unable to get ldb_url\n");
		return NULL;
	}

	if (strncmp("tdb://", sam_ldb_path, 6) == 0) {
		sam_ldb_path += 6;
	}
	private_dir = talloc_strdup(ctx, sam_ldb_path);
	if (private_dir == NULL) {
		ldb_set_errstring(ldb,
				  "Out of memory building encrypted "
				  "secrets key\n");
		return NULL;
	}

	p = strrchr(private_dir, '/');
	if (p != NULL) {
		*p = '\0';
	} else {
		private_dir = talloc_strdup(ctx, ".");
	}

	return private_dir;
}
Beispiel #17
0
/**
 * 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;
}
Beispiel #18
0
static DATA_BLOB *get_new_descriptor(struct ldb_module *module,
				     struct ldb_dn *dn,
				     TALLOC_CTX *mem_ctx,
				     const struct dsdb_class *objectclass,
				     const struct ldb_val *parent,
				     const struct ldb_val *object,
				     const struct ldb_val *old_sd,
				     uint32_t sd_flags)
{
	struct security_descriptor *user_descriptor = NULL, *parent_descriptor = NULL;
	struct security_descriptor *old_descriptor = NULL;
	struct security_descriptor *new_sd, *final_sd;
	DATA_BLOB *linear_sd;
	enum ndr_err_code ndr_err;
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	struct auth_session_info *session_info
		= ldb_get_opaque(ldb, "sessionInfo");
	const struct dom_sid *domain_sid = samdb_domain_sid(ldb);
	char *sddl_sd;
	struct dom_sid *default_owner;
	struct dom_sid *default_group;

	if (object) {
		user_descriptor = talloc(mem_ctx, struct security_descriptor);
		if (!user_descriptor) {
			return NULL;
		}
		ndr_err = ndr_pull_struct_blob(object, user_descriptor, 
					       user_descriptor,
					       (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);

		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
			talloc_free(user_descriptor);
			return NULL;
		}
	} else {
Beispiel #19
0
static int samba_dsdb_init(struct ldb_module *module)
{
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	int ret, len, i;
	TALLOC_CTX *tmp_ctx = talloc_new(module);
	struct ldb_result *res;
	struct ldb_message *rootdse_msg = NULL, *partition_msg;
	struct ldb_dn *samba_dsdb_dn, *partition_dn;
	struct ldb_module *backend_module, *module_chain;
	const char **final_module_list, **reverse_module_list;
	/*
	  Add modules to the list to activate them by default
	  beware often order is important

	  Some Known ordering constraints:
	  - rootdse must be first, as it makes redirects from "" -> cn=rootdse
	  - extended_dn_in must be before objectclass.c, as it resolves the DN
	  - objectclass must be before password_hash and samldb since these LDB
	    modules require the expanded "objectClass" list
	  - objectclass must be before descriptor and acl, as both assume that
	    objectClass values are sorted
	  - objectclass_attrs must be behind operational in order to see all
	    attributes (the operational module protects and therefore
	    suppresses per default some important ones)
	  - partition must be last
	  - each partition has its own module list then

	  The list is presented here as a set of declarations to show the
	  stack visually - the code below then handles the creation of the list
	  based on the parameters loaded from the database.
	*/
	static const char *modules_list1[] = {"resolve_oids",
					     "rootdse",
					     "schema_load",
					     "lazy_commit",
					     "dirsync",
					     "paged_results",
					     "ranged_results",
					     "anr",
					     "server_sort",
					     "asq",
					     "extended_dn_store",
					     NULL };
	/* extended_dn_in or extended_dn_in_openldap goes here */
	static const char *modules_list1a[] = {"objectclass",
					     "descriptor",
					     "acl",
					     "aclread",
					     "samldb",
					     "password_hash",
					     "operational",
					     "instancetype",
					     "objectclass_attrs",
					     NULL };

	const char **link_modules;
	static const char *fedora_ds_modules[] = {
		"rdn_name", NULL };
	static const char *openldap_modules[] = {
		NULL };
	static const char *tdb_modules_list[] = {
		"rdn_name",
		"subtree_delete",
		"repl_meta_data",
		"subtree_rename",
		"linked_attributes",
		NULL};

	const char *extended_dn_module;
	const char *extended_dn_module_ldb = "extended_dn_out_ldb";
	const char *extended_dn_module_fds = "extended_dn_out_fds";
	const char *extended_dn_module_openldap = "extended_dn_out_openldap";
	const char *extended_dn_in_module = "extended_dn_in";

	static const char *modules_list2[] = {"show_deleted",
					      "new_partition",
					      "partition",
					      NULL };

	const char **backend_modules;
	static const char *fedora_ds_backend_modules[] = {
		"nsuniqueid", "paged_searches", "simple_dn", NULL };
	static const char *openldap_backend_modules[] = {
		"entryuuid", "simple_dn", NULL };

	static const char *samba_dsdb_attrs[] = { "backendType", NULL };
	static const char *partition_attrs[] = { "ldapBackend", NULL };
	const char *backendType, *backendUrl;
	bool use_sasl_external = false;

	if (!tmp_ctx) {
		return ldb_oom(ldb);
	}

	ret = ldb_register_samba_handlers(ldb);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}

	samba_dsdb_dn = ldb_dn_new(tmp_ctx, ldb, "@SAMBA_DSDB");
	if (!samba_dsdb_dn) {
		talloc_free(tmp_ctx);
		return ldb_oom(ldb);
	}

	partition_dn = ldb_dn_new(tmp_ctx, ldb, DSDB_PARTITION_DN);
	if (!partition_dn) {
		talloc_free(tmp_ctx);
		return ldb_oom(ldb);
	}

#define CHECK_LDB_RET(check_ret)				\
	do {							\
		if (check_ret != LDB_SUCCESS) {			\
			talloc_free(tmp_ctx);			\
			return check_ret;			\
		}						\
	} while (0)

	ret = dsdb_module_search_dn(module, tmp_ctx, &res, samba_dsdb_dn,
	                            samba_dsdb_attrs, DSDB_FLAG_NEXT_MODULE, NULL);
	if (ret == LDB_ERR_NO_SUCH_OBJECT) {
		backendType = "ldb";
	} else if (ret == LDB_SUCCESS) {
		backendType = ldb_msg_find_attr_as_string(res->msgs[0], "backendType", "ldb");
	} else {
		talloc_free(tmp_ctx);
		return ret;
	}

	backend_modules = NULL;
	if (strcasecmp(backendType, "ldb") == 0) {
		extended_dn_module = extended_dn_module_ldb;
		link_modules = tdb_modules_list;
	} else {
		struct cli_credentials *cred;
		bool is_ldapi = false;

		ret = dsdb_module_search_dn(module, tmp_ctx, &res, partition_dn,
					    partition_attrs, DSDB_FLAG_NEXT_MODULE, NULL);
		if (ret == LDB_SUCCESS) {
			backendUrl = ldb_msg_find_attr_as_string(res->msgs[0], "ldapBackend", "ldapi://");
			if (!strncasecmp(backendUrl, "ldapi://", sizeof("ldapi://")-1)) {
				is_ldapi = true;
			}
		} else if (ret != LDB_ERR_NO_SUCH_OBJECT) {
			talloc_free(tmp_ctx);
			return ret;
		}
		if (strcasecmp(backendType, "fedora-ds") == 0) {
			link_modules = fedora_ds_modules;
			backend_modules = fedora_ds_backend_modules;
			extended_dn_module = extended_dn_module_fds;
		} else if (strcasecmp(backendType, "openldap") == 0) {
			link_modules = openldap_modules;
			backend_modules = openldap_backend_modules;
			extended_dn_module = extended_dn_module_openldap;
			extended_dn_in_module = "extended_dn_in_openldap";
			if (is_ldapi) {
				use_sasl_external = true;
			}
		} else {
			return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR, "invalid backend type");
		}
		ret = ldb_set_opaque(ldb, "readOnlySchema", (void*)1);
		if (ret != LDB_SUCCESS) {
			ldb_set_errstring(ldb, "Failed to set readOnlySchema opaque");
		}

		cred = ldb_get_opaque(ldb, "credentials");
		if (!cred || !cli_credentials_authentication_requested(cred)) {
			ret = set_ldap_credentials(ldb, use_sasl_external);
			if (ret != LDB_SUCCESS) {
				return ret;
			}
		}
	}

#define CHECK_MODULE_LIST \
	do {							\
		if (!final_module_list) {			\
			talloc_free(tmp_ctx);			\
			return ldb_oom(ldb);			\
		}						\
	} while (0)

	final_module_list = str_list_copy_const(tmp_ctx, modules_list1);
	CHECK_MODULE_LIST;

	final_module_list = str_list_add_const(final_module_list, extended_dn_in_module);
	CHECK_MODULE_LIST;

	final_module_list = str_list_append_const(final_module_list, modules_list1a);
	CHECK_MODULE_LIST;

	final_module_list = str_list_append_const(final_module_list, link_modules);
	CHECK_MODULE_LIST;

	final_module_list = str_list_add_const(final_module_list, extended_dn_module);
	CHECK_MODULE_LIST;

	final_module_list = str_list_append_const(final_module_list, modules_list2);
	CHECK_MODULE_LIST;


	ret = read_at_rootdse_record(ldb, module, tmp_ctx, &rootdse_msg, NULL);
	CHECK_LDB_RET(ret);

	partition_msg = ldb_msg_new(tmp_ctx);
	partition_msg->dn = ldb_dn_new(partition_msg, ldb, "@" DSDB_OPAQUE_PARTITION_MODULE_MSG_OPAQUE_NAME);

	ret = prepare_modules_line(ldb, tmp_ctx,
				   rootdse_msg,
				   partition_msg, "schemaNamingContext",
				   "schema_data", backend_modules);
	CHECK_LDB_RET(ret);

	ret = prepare_modules_line(ldb, tmp_ctx,
				   rootdse_msg,
				   partition_msg, NULL,
				   NULL, backend_modules);
	CHECK_LDB_RET(ret);

	ret = ldb_set_opaque(ldb, DSDB_OPAQUE_PARTITION_MODULE_MSG_OPAQUE_NAME, partition_msg);
	CHECK_LDB_RET(ret);

	talloc_steal(ldb, partition_msg);

	/* Now prepare the module chain.  Oddly, we must give it to ldb_load_modules_list in REVERSE */
	for (len = 0; final_module_list[len]; len++) { /* noop */};

	reverse_module_list = talloc_array(tmp_ctx, const char *, len+1);
	if (!reverse_module_list) {
		talloc_free(tmp_ctx);
		return ldb_oom(ldb);
	}
	for (i=0; i < len; i++) {
		reverse_module_list[i] = final_module_list[(len - 1) - i];
	}
	reverse_module_list[i] = NULL;

	/* The backend (at least until the partitions module
	 * reconfigures things) is the next module in the currently
	 * loaded chain */
	backend_module = ldb_module_next(module);
	ret = ldb_module_load_list(ldb, reverse_module_list, backend_module, &module_chain);
	CHECK_LDB_RET(ret);

	talloc_free(tmp_ctx);
	/* Set this as the 'next' module, so that we effectivly append it to module chain */
	ldb_module_set_next(module, module_chain);

	return ldb_next_init(module);
}
Beispiel #20
0
/**
 * Retrieve the domain SID from the secrets database.
 * @return pointer to a SID object if the SID could be obtained, NULL otherwise
 */
struct dom_sid *secrets_get_domain_sid(TALLOC_CTX *mem_ctx,
				       struct loadparm_context *lp_ctx,
				       const char *domain,
				       enum netr_SchannelType *sec_channel_type,
				       char **errstring)
{
	struct ldb_context *ldb;
	struct ldb_message *msg;
	int ldb_ret;
	const char *attrs[] = { "objectSid", "secureChannelType", NULL };
	struct dom_sid *result = NULL;
	const struct ldb_val *v;
	enum ndr_err_code ndr_err;

	*errstring = NULL;

	ldb = secrets_db_connect(mem_ctx, lp_ctx);
	if (ldb == NULL) {
		DEBUG(5, ("secrets_db_connect failed\n"));
		return NULL;
	}

	ldb_ret = dsdb_search_one(ldb, ldb, &msg,
			      ldb_dn_new(mem_ctx, ldb, SECRETS_PRIMARY_DOMAIN_DN),
			      LDB_SCOPE_ONELEVEL,
			      attrs, 0, SECRETS_PRIMARY_DOMAIN_FILTER, domain);

	if (ldb_ret != LDB_SUCCESS) {
		*errstring = talloc_asprintf(mem_ctx, "Failed to find record for %s in %s: %s: %s", 
					     domain, (char *) ldb_get_opaque(ldb, "ldb_url"),
					     ldb_strerror(ldb_ret), ldb_errstring(ldb));
		return NULL;
	}
	v = ldb_msg_find_ldb_val(msg, "objectSid");
	if (v == NULL) {
		*errstring = talloc_asprintf(mem_ctx, "Failed to find a SID on record for %s in %s", 
					     domain, (char *) ldb_get_opaque(ldb, "ldb_url"));
		return NULL;
	}

	if (sec_channel_type) {
		int t;
		t = ldb_msg_find_attr_as_int(msg, "secureChannelType", -1);
		if (t == -1) {
			*errstring = talloc_asprintf(mem_ctx, "Failed to find secureChannelType for %s in %s",
						     domain, (char *) ldb_get_opaque(ldb, "ldb_url"));
			return NULL;
		}
		*sec_channel_type = t;
	}

	result = talloc(mem_ctx, struct dom_sid);
	if (result == NULL) {
		talloc_free(ldb);
		return NULL;
	}

	ndr_err = ndr_pull_struct_blob(v, result, result,
				       (ndr_pull_flags_fn_t)ndr_pull_dom_sid);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		*errstring = talloc_asprintf(mem_ctx, "Failed to parse SID on record for %s in %s", 
					     domain, (char *) ldb_get_opaque(ldb, "ldb_url"));
		talloc_free(result);
		talloc_free(ldb);
		return NULL;
	}

	return result;
}
Beispiel #21
0
WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
                          uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
                          const char *name, struct drsuapi_DsNameInfo1 *info1)
{
    krb5_error_code ret;
    const char *domain_filter = NULL;
    const char *result_filter = NULL;
    struct ldb_dn *name_dn = NULL;

    struct smb_krb5_context *smb_krb5_context = NULL;

    info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
    info1->dns_domain_name = NULL;
    info1->result_name = NULL;

    if (!name) {
        return WERR_INVALID_PARAM;
    }

    /* TODO: - fill the correct names in all cases!
     *       - handle format_flags
     */

    /* here we need to set the domain_filter and/or the result_filter */
    switch (format_offered) {
    case DRSUAPI_DS_NAME_FORMAT_UNKNOWN:
    {
        int i;
        enum drsuapi_DsNameFormat formats[] = {
            DRSUAPI_DS_NAME_FORMAT_FQDN_1779, DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL,
            DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT, DRSUAPI_DS_NAME_FORMAT_CANONICAL,
            DRSUAPI_DS_NAME_FORMAT_GUID, DRSUAPI_DS_NAME_FORMAT_DISPLAY,
            DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL,
            DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY,
            DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX
        };
        WERROR werr;
        for (i=0; i < ARRAY_SIZE(formats); i++) {
            werr = DsCrackNameOneName(sam_ctx, mem_ctx, format_flags, formats[i], format_desired, name, info1);
            if (!W_ERROR_IS_OK(werr)) {
                return werr;
            }
            if (info1->status != DRSUAPI_DS_NAME_STATUS_NOT_FOUND) {
                return werr;
            }
        }
        return werr;
    }

    case DRSUAPI_DS_NAME_FORMAT_CANONICAL:
    case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX:
    {
        char *str, *s, *account;

        if (strlen(name) == 0) {
            info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
            return WERR_OK;
        }

        str = talloc_strdup(mem_ctx, name);
        W_ERROR_HAVE_NO_MEMORY(str);

        if (format_offered == DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX) {
            /* Look backwards for the \n, and replace it with / */
            s = strrchr(str, '\n');
            if (!s) {
                info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
                return WERR_OK;
            }
            s[0] = '/';
        }

        s = strchr(str, '/');
        if (!s) {
            /* there must be at least one / */
            info1->status = DRSUAPI_DS_NAME_STATUS_RESOLVE_ERROR;
            return WERR_OK;
        }

        s[0] = '\0';
        s++;

        domain_filter = talloc_asprintf(mem_ctx, "(&(objectClass=crossRef)(ncName=%s))",
                                        ldb_dn_get_linearized(samdb_dns_domain_to_dn(sam_ctx, mem_ctx, str)));
        W_ERROR_HAVE_NO_MEMORY(domain_filter);

        /* There may not be anything after the domain component (search for the domain itself) */
        if (s[0]) {

            account = strrchr(s, '/');
            if (!account) {
                account = s;
            } else {
                account++;
            }
            account = ldb_binary_encode_string(mem_ctx, account);
            W_ERROR_HAVE_NO_MEMORY(account);
            result_filter = talloc_asprintf(mem_ctx, "(name=%s)",
                                            account);
            W_ERROR_HAVE_NO_MEMORY(result_filter);
        }
        break;
    }
    case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT: {
        char *p;
        char *domain;
        const char *account = NULL;

        domain = talloc_strdup(mem_ctx, name);
        W_ERROR_HAVE_NO_MEMORY(domain);

        p = strchr(domain, '\\');
        if (!p) {
            /* invalid input format */
            info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
            return WERR_OK;
        }
        p[0] = '\0';

        if (p[1]) {
            account = &p[1];
        }

        domain_filter = talloc_asprintf(mem_ctx,
                                        "(&(&(nETBIOSName=%s)(objectclass=crossRef))(ncName=*))",
                                        ldb_binary_encode_string(mem_ctx, domain));
        W_ERROR_HAVE_NO_MEMORY(domain_filter);
        if (account) {
            result_filter = talloc_asprintf(mem_ctx, "(sAMAccountName=%s)",
                                            ldb_binary_encode_string(mem_ctx, account));
            W_ERROR_HAVE_NO_MEMORY(result_filter);
        }

        talloc_free(domain);
        break;
    }

    /* A LDAP DN as a string */
    case DRSUAPI_DS_NAME_FORMAT_FQDN_1779: {
        domain_filter = NULL;
        name_dn = ldb_dn_new(mem_ctx, sam_ctx, name);
        if (! ldb_dn_validate(name_dn)) {
            info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
            return WERR_OK;
        }
        break;
    }

    /* A GUID as a string */
    case DRSUAPI_DS_NAME_FORMAT_GUID: {
        struct GUID guid;
        char *ldap_guid;
        NTSTATUS nt_status;
        domain_filter = NULL;

        nt_status = GUID_from_string(name, &guid);
        if (!NT_STATUS_IS_OK(nt_status)) {
            info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
            return WERR_OK;
        }

        ldap_guid = ldap_encode_ndr_GUID(mem_ctx, &guid);
        if (!ldap_guid) {
            return WERR_NOMEM;
        }
        result_filter = talloc_asprintf(mem_ctx, "(objectGUID=%s)",
                                        ldap_guid);
        W_ERROR_HAVE_NO_MEMORY(result_filter);
        break;
    }
    case DRSUAPI_DS_NAME_FORMAT_DISPLAY: {
        domain_filter = NULL;

        result_filter = talloc_asprintf(mem_ctx, "(|(displayName=%s)(samAccountName=%s))",
                                        ldb_binary_encode_string(mem_ctx, name),
                                        ldb_binary_encode_string(mem_ctx, name));
        W_ERROR_HAVE_NO_MEMORY(result_filter);
        break;
    }

    /* A S-1234-5678 style string */
    case DRSUAPI_DS_NAME_FORMAT_SID_OR_SID_HISTORY: {
        struct dom_sid *sid = dom_sid_parse_talloc(mem_ctx, name);
        char *ldap_sid;

        domain_filter = NULL;
        if (!sid) {
            info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
            return WERR_OK;
        }
        ldap_sid = ldap_encode_ndr_dom_sid(mem_ctx,
                                           sid);
        if (!ldap_sid) {
            return WERR_NOMEM;
        }
        result_filter = talloc_asprintf(mem_ctx, "(objectSid=%s)",
                                        ldap_sid);
        W_ERROR_HAVE_NO_MEMORY(result_filter);
        break;
    }
    case DRSUAPI_DS_NAME_FORMAT_USER_PRINCIPAL: {
        krb5_principal principal;
        char *unparsed_name;

        ret = smb_krb5_init_context(mem_ctx,
                                    ldb_get_event_context(sam_ctx),
                                    (struct loadparm_context *)ldb_get_opaque(sam_ctx, "loadparm"),
                                    &smb_krb5_context);

        if (ret) {
            return WERR_NOMEM;
        }

        /* Ensure we reject compleate junk first */
        ret = krb5_parse_name(smb_krb5_context->krb5_context, name, &principal);
        if (ret) {
            info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
            return WERR_OK;
        }

        domain_filter = NULL;

        /* By getting the unparsed name here, we ensure the escaping is correct (and trust the client less) */
        ret = krb5_unparse_name(smb_krb5_context->krb5_context, principal, &unparsed_name);
        if (ret) {
            krb5_free_principal(smb_krb5_context->krb5_context, principal);
            return WERR_NOMEM;
        }

        krb5_free_principal(smb_krb5_context->krb5_context, principal);

        /* The ldb_binary_encode_string() here avoid LDAP filter injection attacks */
        result_filter = talloc_asprintf(mem_ctx, "(&(objectClass=user)(userPrincipalName=%s))",
                                        ldb_binary_encode_string(mem_ctx, unparsed_name));

        free(unparsed_name);
        W_ERROR_HAVE_NO_MEMORY(result_filter);
        break;
    }
    case DRSUAPI_DS_NAME_FORMAT_SERVICE_PRINCIPAL: {
        krb5_principal principal;
        char *unparsed_name_short;
        char *service;

        ret = smb_krb5_init_context(mem_ctx,
                                    ldb_get_event_context(sam_ctx),
                                    (struct loadparm_context *)ldb_get_opaque(sam_ctx, "loadparm"),
                                    &smb_krb5_context);

        if (ret) {
            return WERR_NOMEM;
        }

        ret = krb5_parse_name(smb_krb5_context->krb5_context, name, &principal);
        if (ret == 0 && principal->name.name_string.len < 2) {
            info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
            krb5_free_principal(smb_krb5_context->krb5_context, principal);
            return WERR_OK;
        }
        ret = krb5_parse_name_flags(smb_krb5_context->krb5_context, name,
                                    KRB5_PRINCIPAL_PARSE_NO_REALM, &principal);
        if (ret) {
            krb5_free_principal(smb_krb5_context->krb5_context, principal);

            return dns_domain_from_principal(mem_ctx, smb_krb5_context,
                                             name, info1);
        }

        domain_filter = NULL;

        ret = krb5_unparse_name_flags(smb_krb5_context->krb5_context, principal,
                                      KRB5_PRINCIPAL_UNPARSE_NO_REALM, &unparsed_name_short);
        if (ret) {
            krb5_free_principal(smb_krb5_context->krb5_context, principal);
            return WERR_NOMEM;
        }

        service = principal->name.name_string.val[0];
        if ((principal->name.name_string.len == 2) && (strcasecmp(service, "host") == 0)) {
            /* the 'cn' attribute is just the leading part of the name */
            char *computer_name;
            computer_name = talloc_strndup(mem_ctx, principal->name.name_string.val[1],
                                           strcspn(principal->name.name_string.val[1], "."));
            if (computer_name == NULL) {
                return WERR_NOMEM;
            }

            result_filter = talloc_asprintf(mem_ctx, "(|(&(servicePrincipalName=%s)(objectClass=user))(&(cn=%s)(objectClass=computer)))",
                                            ldb_binary_encode_string(mem_ctx, unparsed_name_short),
                                            ldb_binary_encode_string(mem_ctx, computer_name));
        } else {
            result_filter = talloc_asprintf(mem_ctx, "(&(servicePrincipalName=%s)(objectClass=user))",
                                            ldb_binary_encode_string(mem_ctx, unparsed_name_short));
        }
        krb5_free_principal(smb_krb5_context->krb5_context, principal);
        free(unparsed_name_short);
        W_ERROR_HAVE_NO_MEMORY(result_filter);

        break;
    }
    default: {
        info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
        return WERR_OK;
    }

    }

    if (format_flags & DRSUAPI_DS_NAME_FLAG_SYNTACTICAL_ONLY) {
        return DsCrackNameOneSyntactical(mem_ctx, format_offered, format_desired,
                                         name_dn, name, info1);
    }

    return DsCrackNameOneFilter(sam_ctx, mem_ctx,
                                smb_krb5_context,
                                format_flags, format_offered, format_desired,
                                name_dn, name,
                                domain_filter, result_filter,
                                info1);
}
Beispiel #22
0
bool dsdb_uses_global_schema(struct ldb_context *ldb)
{
	return (ldb_get_opaque(ldb, "dsdb_use_global_schema") != NULL);
}
Beispiel #23
0
static int acl_module_init(struct ldb_module *module)
{
	struct ldb_context *ldb;
	struct acl_private *data;
	int ret, i;
	TALLOC_CTX *mem_ctx = talloc_new(module);
	static const char *attrs[] = { "passwordAttribute", NULL };
	struct ldb_result *res;
	struct ldb_message *msg;
	struct ldb_message_element *password_attributes;

	ldb = ldb_module_get_ctx(module);

	ret = ldb_mod_register_control(module, LDB_CONTROL_SD_FLAGS_OID);
	if (ret != LDB_SUCCESS) {
		ldb_debug(ldb, LDB_DEBUG_ERROR,
			  "acl_module_init: Unable to register control with rootdse!\n");
		return LDB_ERR_OPERATIONS_ERROR;
	}

	data = talloc(module, struct acl_private);
	if (data == NULL) {
		ldb_oom(ldb);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	data->password_attrs = NULL;
	data->acl_perform = lp_parm_bool(ldb_get_opaque(ldb, "loadparm"),
					 NULL, "acl", "perform", false);
	ldb_module_set_private(module, data);

	if (!mem_ctx) {
		ldb_oom(ldb);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	ret = ldb_search(ldb, mem_ctx, &res,
			 ldb_dn_new(mem_ctx, ldb, "@KLUDGEACL"),
			 LDB_SCOPE_BASE, attrs, NULL);
	if (ret != LDB_SUCCESS) {
		goto done;
	}
	if (res->count == 0) {
		goto done;
	}

	if (res->count > 1) {
		talloc_free(mem_ctx);
		return LDB_ERR_CONSTRAINT_VIOLATION;
	}

	msg = res->msgs[0];

	password_attributes = ldb_msg_find_element(msg, "passwordAttribute");
	if (!password_attributes) {
		goto done;
	}
	data->password_attrs = talloc_array(data, const char *, password_attributes->num_values + 1);
	if (!data->password_attrs) {
		talloc_free(mem_ctx);
		ldb_oom(ldb);
		return LDB_ERR_OPERATIONS_ERROR;
	}
	for (i=0; i < password_attributes->num_values; i++) {
		data->password_attrs[i] = (const char *)password_attributes->values[i].data;
		talloc_steal(data->password_attrs, password_attributes->values[i].data);
	}
	data->password_attrs[i] = NULL;

done:
	talloc_free(mem_ctx);
	return ldb_next_init(module);
}
Beispiel #24
0
WERROR dsdb_set_schema_from_ldif(struct ldb_context *ldb, const char *pf, const char *df)
{
	struct ldb_ldif *ldif;
	struct ldb_message *msg;
	TALLOC_CTX *mem_ctx;
	WERROR status;
	int ret;
	struct dsdb_schema *schema;
	const struct ldb_val *prefix_val;
	const struct ldb_val *info_val;
	struct ldb_val info_val_default;


	mem_ctx = talloc_new(ldb);
	if (!mem_ctx) {
		goto nomem;
	}

	schema = dsdb_new_schema(mem_ctx, lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")));

	schema->fsmo.we_are_master = true;
	schema->fsmo.master_dn = ldb_dn_new_fmt(schema, ldb, "@PROVISION_SCHEMA_MASTER");
	if (!schema->fsmo.master_dn) {
		goto nomem;
	}

	/*
	 * load the prefixMap attribute from pf
	 */
	ldif = ldb_ldif_read_string(ldb, &pf);
	if (!ldif) {
		status = WERR_INVALID_PARAM;
		goto failed;
	}
	talloc_steal(mem_ctx, ldif);

	msg = ldb_msg_canonicalize(ldb, ldif->msg);
	if (!msg) {
		goto nomem;
	}
	talloc_steal(mem_ctx, msg);
	talloc_free(ldif);

	prefix_val = ldb_msg_find_ldb_val(msg, "prefixMap");
	if (!prefix_val) {
	    	status = WERR_INVALID_PARAM;
		goto failed;
	}

	info_val = ldb_msg_find_ldb_val(msg, "schemaInfo");
	if (!info_val) {
		info_val_default = strhex_to_data_blob(mem_ctx, "FF0000000000000000000000000000000000000000");
		if (!info_val_default.data) {
			goto nomem;
		}
		info_val = &info_val_default;
	}

	status = dsdb_load_oid_mappings_ldb(schema, prefix_val, info_val);
	if (!W_ERROR_IS_OK(status)) {
		goto failed;
	}

	/*
	 * load the attribute and class definitions outof df
	 */
	while ((ldif = ldb_ldif_read_string(ldb, &df))) {
		talloc_steal(mem_ctx, ldif);

		msg = ldb_msg_canonicalize(ldb, ldif->msg);
		if (!msg) {
			goto nomem;
		}

		status = dsdb_schema_set_el_from_ldb_msg(ldb, schema, msg);
		talloc_free(ldif);
		if (!W_ERROR_IS_OK(status)) {
			goto failed;
		}
	}

	ret = dsdb_set_schema(ldb, schema);
	if (ret != LDB_SUCCESS) {
		status = WERR_FOOBAR;
		goto failed;
	}

	ret = dsdb_schema_fill_extended_dn(ldb, schema);
	if (ret != LDB_SUCCESS) {
		status = WERR_FOOBAR;
		goto failed;
	}

	goto done;

nomem:
	status = WERR_NOMEM;
failed:
done:
	talloc_free(mem_ctx);
	return status;
}
Beispiel #25
0
static int set_ldap_credentials(struct ldb_context *ldb, bool use_external)
{
	const char *secrets_ldb_path, *sam_ldb_path;
	char *private_dir, *p, *error_string;
	struct ldb_context *secrets_ldb;
	struct cli_credentials *cred;
	struct loadparm_context *lp_ctx = ldb_get_opaque(ldb, "loadparm");
	TALLOC_CTX *tmp_ctx = talloc_new(ldb);

	if (!tmp_ctx) {
		return ldb_oom(ldb);
	}

	cred = cli_credentials_init(ldb);
	if (!cred) {
		talloc_free(tmp_ctx);
		return ldb_oom(ldb);
	}
	cli_credentials_set_anonymous(cred);
	if (use_external) {
		cli_credentials_set_forced_sasl_mech(cred, "EXTERNAL");
	} else {
		cli_credentials_set_forced_sasl_mech(cred, "DIGEST-MD5");

		/*
		 * We don't want to use krb5 to talk to our samdb - recursion
		 * here would be bad, and this account isn't in the KDC
		 * anyway
		 */
		cli_credentials_set_kerberos_state(cred, CRED_DONT_USE_KERBEROS);

		/*
		 * Work out where *our* secrets.ldb is.  It must be in
		 * the same directory as sam.ldb
		 */
		sam_ldb_path = (const char *)ldb_get_opaque(ldb, "ldb_url");
		if (!sam_ldb_path) {
			talloc_free(tmp_ctx);
			return ldb_operr(ldb);
		}
		if (strncmp("tdb://", sam_ldb_path, 6) == 0) {
			sam_ldb_path += 6;
		}
		private_dir = talloc_strdup(tmp_ctx, sam_ldb_path);
		p = strrchr(private_dir, '/');
		if (p) {
			*p = '\0';
		} else {
			private_dir = talloc_strdup(tmp_ctx, ".");
		}

		secrets_ldb_path = talloc_asprintf(private_dir, "tdb://%s/secrets.ldb",
						   private_dir);

		if (!secrets_ldb_path) {
			talloc_free(tmp_ctx);
			return ldb_oom(ldb);
		}

		/*
		 * Now that we have found the location, connect to
		 * secrets.ldb so we can read the SamDB Credentials
		 * record
		 */
		secrets_ldb = ldb_wrap_connect(tmp_ctx, NULL, lp_ctx, secrets_ldb_path,
					       NULL, NULL, 0);

		if (!NT_STATUS_IS_OK(cli_credentials_set_secrets(cred, NULL, secrets_ldb, NULL,
								 SECRETS_LDAP_FILTER, &error_string))) {
			ldb_asprintf_errstring(ldb, "Failed to read LDAP backend password from %s", secrets_ldb_path);
			talloc_free(tmp_ctx);
			return LDB_ERR_STRONG_AUTH_REQUIRED;
		}
	}

	/*
	 * Finally overwrite any supplied credentials with
	 * these ones, as only secrets.ldb contains the magic
	 * credentials to talk on the ldapi socket
	 */
	if (ldb_set_opaque(ldb, "credentials", cred)) {
		talloc_free(tmp_ctx);
		return ldb_operr(ldb);
	}
	talloc_free(tmp_ctx);
	return LDB_SUCCESS;
}
Beispiel #26
0
/* XXX: This function really should be in libldb's pyldb.c */
static PyObject *py_ldb_set_opaque_integer(PyObject *self, PyObject *args)
{
	int value;
	int *old_val, *new_val;
	char *py_opaque_name, *opaque_name_talloc;
	struct ldb_context *ldb;
	int ret;
	TALLOC_CTX *tmp_ctx;

	if (!PyArg_ParseTuple(args, "si", &py_opaque_name, &value))
		return NULL;

	ldb = pyldb_Ldb_AsLdbContext(self);

	/* see if we have a cached copy */
	old_val = (int *)ldb_get_opaque(ldb, py_opaque_name);
	/* XXX: We shouldn't just blindly assume that the value that is 
	 * already present has the size of an int and is not shared 
	 * with other code that may rely on it not changing. 
	 * JRV 20100403 */

	if (old_val) {
		*old_val = value;
		Py_RETURN_NONE;
	}

	tmp_ctx = talloc_new(ldb);
	if (tmp_ctx == NULL) {
		PyErr_NoMemory();
		return NULL;
	}

	new_val = talloc(tmp_ctx, int);
	if (new_val == NULL) {
		talloc_free(tmp_ctx);
		PyErr_NoMemory();
		return NULL;
	}

	opaque_name_talloc = talloc_strdup(tmp_ctx, py_opaque_name);
	if (opaque_name_talloc == NULL) {
		talloc_free(tmp_ctx);
		PyErr_NoMemory();
		return NULL;
	}

	*new_val = value;

	/* cache the domain_sid in the ldb */
	ret = ldb_set_opaque(ldb, opaque_name_talloc, new_val);

	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		PyErr_SetLdbError(py_ldb_error, ret, ldb);
		return NULL;
	}

	talloc_steal(ldb, new_val);
	talloc_steal(ldb, opaque_name_talloc);
	talloc_free(tmp_ctx);

	Py_RETURN_NONE;
}
Beispiel #27
0
WERROR dsdb_write_prefixes_from_schema_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb,
					      const struct dsdb_schema *schema)
{
	WERROR status;
	int ldb_ret;
	struct ldb_message *msg;
	struct ldb_dn *schema_dn;
	struct prefixMapBlob pfm_blob;
	struct ldb_val ndr_blob;
	enum ndr_err_code ndr_err;
	TALLOC_CTX *temp_ctx;
	struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;

	schema_dn = samdb_schema_dn(ldb);
	if (!schema_dn) {
		DEBUG(0,("dsdb_write_prefixes_from_schema_to_ldb: no schema dn present\n"));
		return WERR_FOOBAR;
	}

	temp_ctx = talloc_new(mem_ctx);
	W_ERROR_HAVE_NO_MEMORY(temp_ctx);

	/* convert schema_prefixMap to prefixMap blob */
	status = dsdb_get_oid_mappings_drsuapi(schema, false, temp_ctx, &ctr);
	if (!W_ERROR_IS_OK(status)) {
		talloc_free(temp_ctx);
		return status;
	}

	pfm_blob.version	= PREFIX_MAP_VERSION_DSDB;
	pfm_blob.ctr.dsdb	= *ctr;

	ndr_err = ndr_push_struct_blob(&ndr_blob, temp_ctx,
				       lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
				       &pfm_blob,
				       (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		talloc_free(temp_ctx);
		return WERR_FOOBAR;
	}
 
	/* write serialized prefixMap into LDB */
	msg = ldb_msg_new(temp_ctx);
	if (!msg) {
		talloc_free(temp_ctx);
		return WERR_NOMEM;
	}

	msg->dn = schema_dn;
	ldb_ret = ldb_msg_add_value(msg, "prefixMap", &ndr_blob, NULL);
	if (ldb_ret != 0) {
		talloc_free(temp_ctx);
		DEBUG(0,("dsdb_write_prefixes_from_schema_to_ldb: ldb_msg_add_value failed\n"));	
		return WERR_NOMEM;
 	}
 
	ldb_ret = samdb_replace_as_system(ldb, temp_ctx, msg);

	talloc_free(temp_ctx);

	if (ldb_ret != 0) {
		DEBUG(0,("dsdb_write_prefixes_from_schema_to_ldb: samdb_replace failed\n"));	
		return WERR_FOOBAR;
 	}
 
	return WERR_OK;
}
/*
 * 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;
}