Beispiel #1
0
/*
  connect to the database
*/
static int lldb_connect(struct ldb_context *ldb,
			const char *url,
			unsigned int flags,
			const char *options[],
			struct ldb_module **_module)
{
	struct ldb_module *module;
	struct lldb_private *lldb;
	int version = 3;
	int ret;

	module = ldb_module_new(ldb, ldb, "ldb_ldap backend", &lldb_ops);
	if (!module) return LDB_ERR_OPERATIONS_ERROR;

	lldb = talloc_zero(module, struct lldb_private);
	if (!lldb) {
		ldb_oom(ldb);
		goto failed;
	}
	ldb_module_set_private(module, lldb);

	ret = ldap_initialize(&lldb->ldap, url);
	if (ret != LDAP_SUCCESS) {
		ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_initialize failed for URL '%s' - %s",
			  url, ldap_err2string(ret));
		goto failed;
	}

	talloc_set_destructor(lldb, lldb_destructor);

	ret = ldap_set_option(lldb->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
	if (ret != LDAP_SUCCESS) {
		ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_set_option failed - %s",
			  ldap_err2string(ret));
		goto failed;
	}

	*_module = module;

	ret = lldb_bind(module, options);
	if (ret != LDB_SUCCESS) {
		goto failed;
	}


	return LDB_SUCCESS;

failed:
	talloc_free(module);
	return LDB_ERR_OPERATIONS_ERROR;
}
Beispiel #2
0
/* Split message elements that stay in the local partition from those
 * that are mapped into the remote partition. */
static int ldb_msg_partition(struct ldb_module *module, enum ldb_request_type optype, struct ldb_message *local, struct ldb_message *remote, const struct ldb_message *msg)
{
	/* const char * const names[]; */
	struct ldb_context *ldb;
	unsigned int i;
	int ret;

	ldb = ldb_module_get_ctx(module);

	for (i = 0; i < msg->num_elements; i++) {
		/* Skip 'IS_MAPPED' */
		if (ldb_attr_cmp(msg->elements[i].name, IS_MAPPED) == 0) {
			ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
				  "Skipping attribute '%s'",
				  msg->elements[i].name);
			continue;
		}

		ret = ldb_msg_el_partition(module, optype, local, remote, msg, msg->elements[i].name, &msg->elements[i]);
		if (ret) {
			return ret;
		}
	}

	return 0;
}
Beispiel #3
0
static void ltdb_log_fn(struct tdb_context *tdb, enum tdb_debug_level level, const char *fmt, ...)
{
    va_list ap;
    const char *name = tdb_name(tdb);
    struct ldb_context *ldb = talloc_get_type(tdb_get_logging_private(tdb), struct ldb_context);
    enum ldb_debug_level ldb_level;
    char *message;

    if (ldb == NULL)
        return;

    va_start(ap, fmt);
    message = talloc_vasprintf(ldb, fmt, ap);
    va_end(ap);

    switch (level) {
    case TDB_DEBUG_FATAL:
        ldb_level = LDB_DEBUG_FATAL;
        break;
    case TDB_DEBUG_ERROR:
        ldb_level = LDB_DEBUG_ERROR;
        break;
    case TDB_DEBUG_WARNING:
        ldb_level = LDB_DEBUG_WARNING;
        break;
    case TDB_DEBUG_TRACE:
        ldb_level = LDB_DEBUG_TRACE;
        break;
    default:
        ldb_level = LDB_DEBUG_FATAL;
    }

    ldb_debug(ldb, ldb_level, "ltdb: tdb(%s): %s", name, message);
    talloc_free(message);
}
Beispiel #4
0
/* search the domain related to the provided dn
   allocate a new RID for the domain
   return the new sid string
*/
static int samldb_get_new_sid(struct ldb_module *module, 
			      TALLOC_CTX *mem_ctx, struct ldb_dn *obj_dn,
			      struct dom_sid **sid)
{
	const char * const attrs[2] = { "objectSid", NULL };
	struct ldb_result *res = NULL;
	struct ldb_dn *dom_dn;
	int ret;
	struct dom_sid *dom_sid;

	/* get the domain component part of the provided dn */

	dom_dn = samldb_search_domain(module, mem_ctx, obj_dn);
	if (dom_dn == NULL) {
		ldb_asprintf_errstring(module->ldb,
					"Invalid dn (%s) not child of a domain object!\n",
					ldb_dn_get_linearized(obj_dn));
		return LDB_ERR_CONSTRAINT_VIOLATION;
	}

	/* find the domain sid */

	ret = ldb_search(module->ldb, dom_dn, LDB_SCOPE_BASE, "objectSid=*", attrs, &res);
	if (ret != LDB_SUCCESS) {
		ldb_asprintf_errstring(module->ldb,
					"samldb_get_new_sid: error retrieving domain sid from %s: %s!\n",
					ldb_dn_get_linearized(dom_dn),
					ldb_errstring(module->ldb));
		talloc_free(res);
		return ret;
	}

	if (res->count != 1) {
		ldb_asprintf_errstring(module->ldb,
					"samldb_get_new_sid: error retrieving domain sid from %s: not found!\n",
					ldb_dn_get_linearized(dom_dn));
		talloc_free(res);
		return LDB_ERR_CONSTRAINT_VIOLATION;
	}

	dom_sid = samdb_result_dom_sid(res, res->msgs[0], "objectSid");
	if (dom_sid == NULL) {
		ldb_set_errstring(module->ldb, "samldb_get_new_sid: error parsing domain sid!\n");
		talloc_free(res);
		return LDB_ERR_CONSTRAINT_VIOLATION;
	}

	/* allocate a new Rid for the domain */
	ret = samldb_allocate_next_rid(module, mem_ctx, dom_dn, dom_sid, sid);
	if (ret != 0) {
		ldb_debug(module->ldb, LDB_DEBUG_FATAL, "Failed to increment nextRid of %s: %s\n", ldb_dn_get_linearized(dom_dn), ldb_errstring(module->ldb));
		talloc_free(res);
		return ret;
	}

	talloc_free(res);

	return ret;
}
Beispiel #5
0
int ldb_try_load_dso(struct ldb_context *ldb, const char *name)
{
	char *path;
	void *handle;
	int (*init_fn) (void);
	char *modulesdir;

#ifdef HAVE_DLOPEN
	if (getenv("LD_LDB_MODULE_PATH") != NULL) {
		modulesdir = talloc_strdup(ldb, getenv("LD_LDB_MODULE_PATH"));
	} else {
#ifdef _SAMBA_BUILD_
		modulesdir = talloc_asprintf(ldb, "%s/ldb", dyn_MODULESDIR);
#else
		modulesdir = talloc_strdup(ldb, MODULESDIR);
#endif
	}

	path = talloc_asprintf(ldb, "%s/%s.%s", modulesdir, name, SHLIBEXT);

	talloc_free(modulesdir);

	ldb_debug(ldb, LDB_DEBUG_TRACE, "trying to load %s from %s\n", name, path);

	handle = dlopen(path, RTLD_NOW);
	if (handle == NULL) {
		ldb_debug(ldb, LDB_DEBUG_WARNING, "unable to load %s from %s: %s\n", name, path, dlerror());
		return -1;
	}

	init_fn = (int (*)(void))dlsym(handle, "init_module");

	if (init_fn == NULL) {
		ldb_debug(ldb, LDB_DEBUG_ERROR, "no symbol `init_module' found in %s: %s\n", path, dlerror());
		return -1;
	}

	talloc_free(path);

	return init_fn();
#else
	ldb_debug(ldb, LDB_DEBUG_TRACE, "no dlopen() - not trying to load %s module\n", name);
	return -1;
#endif
}
Beispiel #6
0
static struct ldb_val lookup_homedir(struct ldb_module *module, TALLOC_CTX *ctx, const struct ldb_val *val)
{
	struct passwd *pwd; 
	struct ldb_val retval;
	
	pwd = getpwnam((char *)val->data);

	if (!pwd) {
		ldb_debug(module->ldb, LDB_DEBUG_WARNING, "Unable to lookup '%s' in passwd", (char *)val->data);
		return *talloc_zero(ctx, struct ldb_val);
	}
Beispiel #7
0
/* TODO: free old DNs and messages? */
int ldb_next_remote_request(struct ldb_module *module, struct ldb_request *request)
{
	const struct ldb_map_context *data = map_get_context(module);
	struct ldb_context *ldb;
	struct ldb_message *msg;

	ldb = ldb_module_get_ctx(module);

	switch (request->operation) {
	case LDB_SEARCH:
		if (request->op.search.base) {
			request->op.search.base = ldb_dn_rebase_remote(request, data, request->op.search.base);
		} else {
			request->op.search.base = data->remote_base_dn;
			/* TODO: adjust scope? */
		}
		break;

	case LDB_ADD:
		msg = ldb_msg_copy_shallow(request, request->op.add.message);
		if (msg == NULL) {
			return LDB_ERR_OPERATIONS_ERROR;
		}
		msg->dn = ldb_dn_rebase_remote(msg, data, msg->dn);
		request->op.add.message = msg;
		break;

	case LDB_MODIFY:
		msg = ldb_msg_copy_shallow(request, request->op.mod.message);
		if (msg == NULL) {
			return LDB_ERR_OPERATIONS_ERROR;
		}
		msg->dn = ldb_dn_rebase_remote(msg, data, msg->dn);
		request->op.mod.message = msg;
		break;

	case LDB_DELETE:
		request->op.del.dn = ldb_dn_rebase_remote(request, data, request->op.del.dn);
		break;

	case LDB_RENAME:
		request->op.rename.olddn = ldb_dn_rebase_remote(request, data, request->op.rename.olddn);
		request->op.rename.newdn = ldb_dn_rebase_remote(request, data, request->op.rename.newdn);
		break;

	default:
		ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
			  "Invalid remote request!");
		return LDB_ERR_OPERATIONS_ERROR;
	}

	return ldb_next_request(module, request);
}
Beispiel #8
0
/*
  allocate a new id, attempting to do it atomically
  return 0 on failure, the id on success
*/
static int samldb_set_next_rid(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
			       struct ldb_dn *dn, uint32_t old_id, uint32_t new_id)
{
	struct ldb_message msg;
	int ret;
	struct ldb_val vals[2];
	struct ldb_message_element els[2];

	if (new_id == 0) {
		/* out of IDs ! */
		ldb_debug(ldb, LDB_DEBUG_FATAL, "Are we out of valid IDs ?\n");
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/* we do a delete and add as a single operation. That prevents
	   a race, in case we are not actually on a transaction db */
	ZERO_STRUCT(msg);
	msg.dn = ldb_dn_copy(mem_ctx, dn);
	if (!msg.dn) {
		return LDB_ERR_OPERATIONS_ERROR;
	}
	msg.num_elements = 2;
	msg.elements = els;

	els[0].num_values = 1;
	els[0].values = &vals[0];
	els[0].flags = LDB_FLAG_MOD_DELETE;
	els[0].name = talloc_strdup(mem_ctx, "nextRid");
	if (!els[0].name) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	els[1].num_values = 1;
	els[1].values = &vals[1];
	els[1].flags = LDB_FLAG_MOD_ADD;
	els[1].name = els[0].name;

	vals[0].data = (uint8_t *)talloc_asprintf(mem_ctx, "%u", old_id);
	if (!vals[0].data) {
		return LDB_ERR_OPERATIONS_ERROR;
	}
	vals[0].length = strlen((char *)vals[0].data);

	vals[1].data = (uint8_t *)talloc_asprintf(mem_ctx, "%u", new_id);
	if (!vals[1].data) {
		return LDB_ERR_OPERATIONS_ERROR;
	}
	vals[1].length = strlen((char *)vals[1].data);

	ret = ldb_modify(ldb, &msg);
	return ret;
}
Beispiel #9
0
int ldb_init_module_chain(struct ldb_context *ldb, struct ldb_module *module) 
{
	while (module && module->ops->init_context == NULL) 
		module = module->next;

	if (module && module->ops->init_context &&
		module->ops->init_context(module) != LDB_SUCCESS) {
		ldb_debug(ldb, LDB_DEBUG_FATAL, "module initialization failed\n");
		return LDB_ERR_OPERATIONS_ERROR;
	}

	return LDB_SUCCESS;
}
Beispiel #10
0
/*
  log a message, and set the ldb error string to the same message
*/
void ldb_debug_set(struct ldb_context *ldb, enum ldb_debug_level level, 
		   const char *fmt, ...)
{
	va_list ap;
	char *msg;
	va_start(ap, fmt);
	msg = talloc_vasprintf(ldb, fmt, ap);
	va_end(ap);
	if (msg != NULL) {
		ldb_set_errstring(ldb, msg);
		ldb_debug(ldb, level, "%s", msg);
	}
	talloc_free(msg);
}
Beispiel #11
0
static int validate_update_message(struct ldb_context *ldb,
				   struct dsdb_schema *schema,
				   const struct ldb_message *msg)
{
	int i;

	for (i=0; i < msg->num_elements; i++) {
		WERROR werr;

		werr = dsdb_attribute_validate_ldb(ldb, schema,
						   &msg->elements[i]);
		if (!W_ERROR_IS_OK(werr)) {
			int j;

			ldb_debug(ldb, LDB_DEBUG_ERROR,
				  "TODO: object[%s] add/modify attribute[%d|%s] num_values[%d] - %s\n",
				  ldb_dn_get_linearized(msg->dn),
				  i, msg->elements[i].name,
				  msg->elements[i].num_values,
				  win_errstr(werr));

			for (j=0; j < msg->elements[i].num_values; j++) {
				ldb_debug(ldb, LDB_DEBUG_ERROR,
					  "TODO: value[%d] len[%d]\n", j,
					  msg->elements[i].values[j].length);
				dump_data(0,
					  msg->elements[i].values[j].data,
					  msg->elements[i].values[j].length);
			}

			return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
		}
	}

	return LDB_SUCCESS;
}
Beispiel #12
0
static int subtree_delete_init(struct ldb_module *module)
{
	struct ldb_context *ldb;
	int ret;

	ldb = ldb_module_get_ctx(module);

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

	return ldb_next_init(module);
}
Beispiel #13
0
static int wins_ldb_verify(struct ldb_module *module, struct ldb_request *req)
{
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	struct winsdb_handle *h = talloc_get_type(ldb_get_opaque(ldb, "winsdb_handle"),
						  struct winsdb_handle);
	const struct ldb_message *msg;

	switch (req->operation) {
	case LDB_ADD:
		msg = req->op.add.message;
		break;
		
	case LDB_MODIFY:
		msg = req->op.mod.message;
		break;

	default:
		return ldb_next_request(module, req);
	}

	/* do not manipulate our control entries */
	if (ldb_dn_is_special(msg->dn)) {
		return ldb_next_request(module, req);
	}

	if (!h) {
		ldb_debug_set(ldb, LDB_DEBUG_FATAL, "%s", "WINS_LDB: INTERNAL ERROR: no winsdb_handle present!");
		return LDB_ERR_OTHER;
	}

	switch (h->caller) {
	case WINSDB_HANDLE_CALLER_NBTD:
	case WINSDB_HANDLE_CALLER_WREPL:
		/* we trust our nbt and wrepl code ... */
		return ldb_next_request(module, req);

	case WINSDB_HANDLE_CALLER_ADMIN:
		ldb_debug(ldb, LDB_DEBUG_WARNING, "%s\n", "WINS_LDB: TODO verify add/modify for WINSDB_HANDLE_CALLER_ADMIN");
		return ldb_next_request(module, req);
	}

	return LDB_ERR_OTHER;
}
Beispiel #14
0
static void ltdb_log_fn(struct tdb_context *tdb,
                        enum tdb_log_level level,
                        const char *message,
                        struct ldb_context *ldb)
{
    enum ldb_debug_level ldb_level;
    const char *name = tdb_name(tdb);

    switch (level) {
    case TDB_LOG_WARNING:
        ldb_level = LDB_DEBUG_WARNING;
    case TDB_LOG_USE_ERROR:
    case TDB_LOG_ERROR:
        ldb_level = LDB_DEBUG_FATAL;
        break;
    default:
        ldb_level = LDB_DEBUG_FATAL;
    }

    ldb_debug(ldb, ldb_level, "ltdb: tdb(%s): %s", name, message);
}
Beispiel #15
0
/*
  we've made a modification to a dn - possibly reindex and
  update sequence number
*/
static int ltdb_modified(struct ldb_module *module, struct ldb_dn *dn)
{
	int ret = LDB_SUCCESS;
	struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);

	/* only allow modifies inside a transaction, otherwise the
	 * ldb is unsafe */
	if (ltdb->in_transaction == 0) {
		ldb_set_errstring(ldb_module_get_ctx(module), "ltdb modify without transaction");
		return LDB_ERR_OPERATIONS_ERROR;
	}

	if (ldb_dn_is_special(dn) &&
	    (ldb_dn_check_special(dn, LTDB_INDEXLIST) ||
	     ldb_dn_check_special(dn, LTDB_ATTRIBUTES)) )
	{
		if (ltdb->warn_reindex) {
			ldb_debug(ldb_module_get_ctx(module),
				LDB_DEBUG_ERROR, "Reindexing %s due to modification on %s",
				tdb_name(ltdb->tdb), ldb_dn_get_linearized(dn));
		}
		ret = ltdb_reindex(module);
	}

	/* If the modify was to a normal record, or any special except @BASEINFO, update the seq number */
	if (ret == LDB_SUCCESS &&
	    !(ldb_dn_is_special(dn) &&
	      ldb_dn_check_special(dn, LTDB_BASEINFO)) ) {
		ret = ltdb_increase_sequence_number(module);
	}

	/* If the modify was to @OPTIONS, reload the cache */
	if (ret == LDB_SUCCESS &&
	    ldb_dn_is_special(dn) &&
	    (ldb_dn_check_special(dn, LTDB_OPTIONS)) ) {
		ret = ltdb_cache_reload(module);
	}

	return ret;
}
Beispiel #16
0
/* Split message elements that stay in the local partition from those
 * that are mapped into the remote partition. */
static int ldb_msg_partition(struct ldb_module *module, struct ldb_message *local, struct ldb_message *remote, const struct ldb_message *msg)
{
	/* const char * const names[]; */
	int i, ret;

	for (i = 0; i < msg->num_elements; i++) {
		/* Skip 'IS_MAPPED' */
		if (ldb_attr_cmp(msg->elements[i].name, IS_MAPPED) == 0) {
			ldb_debug(module->ldb, LDB_DEBUG_WARNING, "ldb_map: "
				  "Skipping attribute '%s'\n",
				  msg->elements[i].name);
			continue;
		}

		ret = ldb_msg_el_partition(module, local, remote, msg, msg->elements[i].name, &msg->elements[i]);
		if (ret) {
			return ret;
		}
	}

	return 0;
}
/* deny instancetype modification */
static int instancetype_mod(struct ldb_module *module, struct ldb_request *req)
{
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	struct ldb_message_element *el;

	/* do not manipulate our control entries */
	if (ldb_dn_is_special(req->op.mod.message->dn)) {
		return ldb_next_request(module, req);
	}

	ldb_debug(ldb, LDB_DEBUG_TRACE, "instancetype_mod\n");

	el = ldb_msg_find_element(req->op.mod.message, "instanceType");
	if (el != NULL) {
		/* Except to allow dbcheck to fix things, this must never be modified */
		if (!ldb_request_get_control(req, DSDB_CONTROL_DBCHECK)) {
			ldb_set_errstring(ldb, "instancetype: the 'instanceType' attribute can never be changed!");
			return LDB_ERR_CONSTRAINT_VIOLATION;
		}
	}
	return ldb_next_request(module, req);
}
Beispiel #18
0
int ldb_load_modules_list(struct ldb_context *ldb, const char **module_list, struct ldb_module *backend, struct ldb_module **out)
{
	struct ldb_module *module;
	int i;
	
	module = backend;

	for (i = 0; module_list[i] != NULL; i++) {
		struct ldb_module *current;
		const struct ldb_module_ops *ops;
		
		ops = ldb_find_module_ops(module_list[i]);
		if (ops == NULL) {
			if (ldb_try_load_dso(ldb, module_list[i]) == 0) {
				ops = ldb_find_module_ops(module_list[i]);
			}
		}
		
		if (ops == NULL) {
			ldb_debug(ldb, LDB_DEBUG_WARNING, "WARNING: Module [%s] not found\n", 
				  module_list[i]);
			continue;
		}
		
		current = talloc_zero(ldb, struct ldb_module);
		if (current == NULL) {
			return LDB_ERR_OPERATIONS_ERROR;
		}
		talloc_set_name(current, "ldb_module: %s", module_list[i]);
		
		current->ldb = ldb;
		current->ops = ops;
		
		DLIST_ADD(module, current);
	}
	*out = module;
	return LDB_SUCCESS;
}
Beispiel #19
0
int ldb_load_modules(struct ldb_context *ldb, const char *options[])
{
	const char **modules = NULL;
	int i;
	int ret;
	TALLOC_CTX *mem_ctx = talloc_new(ldb);
	if (!mem_ctx) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/* find out which modules we are requested to activate */

	/* check if we have a custom module list passd as ldb option */
	if (options) {
		for (i = 0; options[i] != NULL; i++) {
			if (strncmp(options[i], LDB_MODULE_PREFIX, LDB_MODULE_PREFIX_LEN) == 0) {
				modules = ldb_modules_list_from_string(ldb, mem_ctx, &options[i][LDB_MODULE_PREFIX_LEN]);
			}
		}
	}

	/* if not overloaded by options and the backend is not ldap try to load the modules list from ldb */
	if ((modules == NULL) && (strcmp("ldap", ldb->modules->ops->name) != 0)) { 
		const char * const attrs[] = { "@LIST" , NULL};
		struct ldb_result *res = NULL;
		struct ldb_dn *mods_dn;

		mods_dn = ldb_dn_new(mem_ctx, ldb, "@MODULES");
		if (mods_dn == NULL) {
			talloc_free(mem_ctx);
			return -1;
		}

		ret = ldb_search(ldb, mods_dn, LDB_SCOPE_BASE, "", attrs, &res);
		talloc_steal(mods_dn, res);
		if (ret == LDB_SUCCESS && (res->count == 0 || res->msgs[0]->num_elements == 0)) {
			ldb_debug(ldb, LDB_DEBUG_TRACE, "no modules required by the db\n");
		} else {
			if (ret != LDB_SUCCESS) {
				ldb_debug(ldb, LDB_DEBUG_FATAL, "ldb error (%s) occurred searching for modules, bailing out\n", ldb_errstring(ldb));
				talloc_free(mem_ctx);
				return -1;
			}
			if (res->count > 1) {
				ldb_debug(ldb, LDB_DEBUG_FATAL, "Too many records found (%d), bailing out\n", res->count);
				talloc_free(mem_ctx);
				return -1;
			}

			modules = ldb_modules_list_from_string(ldb, mem_ctx,
							       (const char *)res->msgs[0]->elements[0].values[0].data);

		}

		talloc_free(mods_dn);
	}

	if (modules != NULL) {
		ret = ldb_load_modules_list(ldb, modules, ldb->modules, &ldb->modules);
		talloc_free(modules);
		if (ret != LDB_SUCCESS) {
			return ret;
		}
	} else {
		ldb_debug(ldb, LDB_DEBUG_TRACE, "No modules specified for this database\n");
	}

	return ldb_init_module_chain(ldb, ldb->modules);
}
Beispiel #20
0
/*
  connect to the database
*/
static int ltdb_connect(struct ldb_context *ldb, const char *url,
			unsigned int flags, const char *options[],
			struct ldb_module **_module)
{
	struct ldb_module *module;
	const char *path;
	int tdb_flags, open_flags;
	struct ltdb_private *ltdb;

	/* parse the url */
	if (strchr(url, ':')) {
		if (strncmp(url, "tdb://", 6) != 0) {
			ldb_debug(ldb, LDB_DEBUG_ERROR,
				  "Invalid tdb URL '%s'", url);
			return LDB_ERR_OPERATIONS_ERROR;
		}
		path = url+6;
	} else {
		path = url;
	}

	tdb_flags = TDB_DEFAULT | TDB_SEQNUM;

	/* check for the 'nosync' option */
	if (flags & LDB_FLG_NOSYNC) {
		tdb_flags |= TDB_NOSYNC;
	}

	/* and nommap option */
	if (flags & LDB_FLG_NOMMAP) {
		tdb_flags |= TDB_NOMMAP;
	}

	if (flags & LDB_FLG_RDONLY) {
		open_flags = O_RDONLY;
	} else {
		open_flags = O_CREAT | O_RDWR;
	}

	ltdb = talloc_zero(ldb, struct ltdb_private);
	if (!ltdb) {
		ldb_oom(ldb);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/* note that we use quite a large default hash size */
	ltdb->tdb = ltdb_wrap_open(ltdb, path, 10000,
				   tdb_flags, open_flags,
				   ldb_get_create_perms(ldb), ldb);
	if (!ltdb->tdb) {
		ldb_asprintf_errstring(ldb,
				       "Unable to open tdb '%s': %s", path, strerror(errno));
		ldb_debug(ldb, LDB_DEBUG_ERROR,
			  "Unable to open tdb '%s': %s", path, strerror(errno));
		talloc_free(ltdb);
		if (errno == EACCES || errno == EPERM) {
			return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS;
		}
		return LDB_ERR_OPERATIONS_ERROR;
	}

	if (getenv("LDB_WARN_UNINDEXED")) {
		ltdb->warn_unindexed = true;
	}

	if (getenv("LDB_WARN_REINDEX")) {
		ltdb->warn_reindex = true;
	}

	ltdb->sequence_number = 0;

	module = ldb_module_new(ldb, ldb, "ldb_tdb backend", &ltdb_ops);
	if (!module) {
		ldb_oom(ldb);
		talloc_free(ltdb);
		return LDB_ERR_OPERATIONS_ERROR;
	}
	ldb_module_set_private(module, ltdb);
	talloc_steal(module, ltdb);

	if (ltdb_cache_load(module) != 0) {
		ldb_asprintf_errstring(ldb,
				       "Unable to load ltdb cache records of tdb '%s'", path);
		talloc_free(module);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	*_module = module;
	return LDB_SUCCESS;
}
Beispiel #21
0
/* Add a message element either to a local or to a remote message,
 * depending on whether it goes into the local or remote partition. */
static int ldb_msg_el_partition(struct ldb_module *module, struct ldb_message *local, struct ldb_message *remote, const struct ldb_message *msg, const char *attr_name, /* const char * const names[], */ const struct ldb_message_element *old)
{
	const struct ldb_map_context *data = map_get_context(module);
	const struct ldb_map_attribute *map = map_attr_find_local(data, attr_name);
	struct ldb_message_element *el=NULL;

	/* Unknown attribute: ignore */
	if (map == NULL) {
		ldb_debug(module->ldb, LDB_DEBUG_WARNING, "ldb_map: "
			  "Not mapping attribute '%s': no mapping found\n",
			  old->name);
		goto local;
	}

	switch (map->type) {
	case MAP_IGNORE:
		goto local;

	case MAP_CONVERT:
		if (map->u.convert.convert_local == NULL) {
			ldb_debug(module->ldb, LDB_DEBUG_WARNING, "ldb_map: "
				  "Not mapping attribute '%s': "
				  "'convert_local' not set\n",
				  map->local_name);
			goto local;
		}
		/* fall through */
	case MAP_KEEP:
	case MAP_RENAME:
		el = ldb_msg_el_map_local(module, remote, map, old);
		break;

	case MAP_GENERATE:
		if (map->u.generate.generate_remote == NULL) {
			ldb_debug(module->ldb, LDB_DEBUG_WARNING, "ldb_map: "
				  "Not mapping attribute '%s': "
				  "'generate_remote' not set\n",
				  map->local_name);
			goto local;
		}

		/* TODO: if this attr requires context:
		 *	 make sure all context attrs are mappable (in 'names')
		 *	 make sure all context attrs have already been mapped?
		 *	 maybe postpone generation until they have been mapped?
		 */

		map->u.generate.generate_remote(module, map->local_name, msg, remote, local);
		return 0;
	}

	if (el == NULL) {
		return -1;
	}

	return ldb_msg_add(remote, el, old->flags);

local:
	el = talloc(local, struct ldb_message_element);
	if (el == NULL) {
		map_oom(module);
		return -1;
	}

	*el = *old;			/* copy the old element */

	return ldb_msg_add(local, el, old->flags);
}
Beispiel #22
0
/* Map a DN into the local partition. */
struct ldb_dn *ldb_dn_map_remote(struct ldb_module *module, void *mem_ctx, const struct ldb_dn *dn)
{
	const struct ldb_map_context *data = map_get_context(module);
	struct ldb_dn *newdn;
	const struct ldb_map_attribute *map;
	enum ldb_map_attr_type map_type;
	const char *name;
	struct ldb_val value;
	int i, ret;

	if (dn == NULL) {
		return NULL;
	}

	newdn = ldb_dn_copy(mem_ctx, dn);
	if (newdn == NULL) {
		map_oom(module);
		return NULL;
	}

	/* For each RDN, map the component name and possibly the value */
	for (i = 0; i < ldb_dn_get_comp_num(newdn); i++) {
		map = map_attr_find_remote(data, ldb_dn_get_component_name(dn, i));

		/* Unknown attribute - leave this RDN as is and hope the best... */
		if (map == NULL) {
			map_type = MAP_KEEP;
		} else {
			map_type = map->type;
		}

		switch (map_type) {
		case MAP_IGNORE:
		case MAP_GENERATE:
			ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: "
				  "MAP_IGNORE/MAP_GENERATE attribute '%s' "
				  "used in DN!\n", ldb_dn_get_component_name(dn, i));
			goto failed;

		case MAP_CONVERT:
			if (map->u.convert.convert_remote == NULL) {
				ldb_debug(module->ldb, LDB_DEBUG_ERROR, "ldb_map: "
					  "'convert_remote' not set for attribute '%s' "
					  "used in DN!\n", ldb_dn_get_component_name(dn, i));
				goto failed;
			}
			/* fall through */
		case MAP_KEEP:
		case MAP_RENAME:
			name = map_attr_map_remote(newdn, map, ldb_dn_get_component_name(dn, i));
			if (name == NULL) goto failed;

			value = ldb_val_map_remote(module, newdn, map, ldb_dn_get_component_val(dn, i));
			if (value.data == NULL) goto failed;

			ret = ldb_dn_set_component(newdn, i, name, value);
			if (ret != LDB_SUCCESS) {
				goto failed;
			}

			break;
		}
	}

	return newdn;

failed:
	talloc_free(newdn);
	return NULL;
}
Beispiel #23
0
static int samldb_add(struct ldb_module *module, struct ldb_request *req)
{
	const struct ldb_message *msg = req->op.add.message;
	struct ldb_message *msg2 = NULL;
	struct ldb_request *down_req;
	int ret;

	ldb_debug(module->ldb, LDB_DEBUG_TRACE, "samldb_add_record\n");

	if (ldb_dn_is_special(msg->dn)) { /* do not manipulate our control entries */
		return ldb_next_request(module, req);
	}

	/* is user or computer? */
	if ((samdb_find_attribute(module->ldb, msg, "objectclass", "user") != NULL) ||
	    (samdb_find_attribute(module->ldb, msg, "objectclass", "computer") != NULL)) {
		/*  add all relevant missing objects */
		ret = samldb_fill_user_or_computer_object(module, msg, &msg2);
		if (ret) {
			return ret;
		}
	}

	/* is group? add all relevant missing objects */
	if ( ! msg2 ) {
		if (samdb_find_attribute(module->ldb, msg, "objectclass", "group") != NULL) {
			ret = samldb_fill_group_object(module, msg, &msg2);
			if (ret) {
				return ret;
			}
		}
	}

	/* perhaps a foreignSecurityPrincipal? */
	if ( ! msg2 ) {
		if (samdb_find_attribute(module->ldb, msg, "objectclass", "foreignSecurityPrincipal") != NULL) {
			ret = samldb_fill_foreignSecurityPrincipal_object(module, msg, &msg2);
			if (ret) {
				return ret;
			}
		}
	}

	if (msg2 == NULL) {
		return ldb_next_request(module, req);
	}

	down_req = talloc(req, struct ldb_request);
	if (down_req == NULL) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	*down_req = *req;
	
	down_req->op.add.message = talloc_steal(down_req, msg2);

	ldb_set_timeout_from_prev_req(module->ldb, req, down_req);

	/* go on with the call chain */
	ret = ldb_next_request(module, down_req);

	/* do not free down_req as the call results may be linked to it,
	 * it will be freed when the upper level request get freed */
	if (ret == LDB_SUCCESS) {
		req->handle = down_req->handle;
	}

	return ret;
}
Beispiel #24
0
static int samldb_fill_foreignSecurityPrincipal_object(struct ldb_module *module, const struct ldb_message *msg, 
						       struct ldb_message **ret_msg)
{
	struct ldb_message *msg2;
	const char *rdn_name;
	struct dom_sid *dom_sid;
	struct dom_sid *sid;
	const char *dom_attrs[] = { "name", NULL };
	struct ldb_message **dom_msgs;
	const char *errstr;
	int ret;

	TALLOC_CTX *mem_ctx = talloc_new(msg);
	if (!mem_ctx) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/* build the new msg */
	msg2 = ldb_msg_copy(mem_ctx, msg);
	if (!msg2) {
		ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_foreignSecurityPrincpal_object: ldb_msg_copy failed!\n");
		talloc_free(mem_ctx);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	ret = samdb_copy_template(module->ldb, msg2, 
				  "(&(CN=TemplateForeignSecurityPrincipal)(objectclass=foreignSecurityPrincipalTemplate))",
				  &errstr);
	if (ret != 0) {
		ldb_asprintf_errstring(module->ldb, 
				       "samldb_fill_foreignSecurityPrincipal_object: "
				       "Error copying template: %s",
				    errstr);
		talloc_free(mem_ctx);
		return ret;
	}

	rdn_name = ldb_dn_get_rdn_name(msg2->dn);

	if (strcasecmp(rdn_name, "cn") != 0) {
		ldb_asprintf_errstring(module->ldb, "Bad RDN (%s=) for ForeignSecurityPrincipal, should be CN=!", rdn_name);
		talloc_free(mem_ctx);
		return LDB_ERR_CONSTRAINT_VIOLATION;
	}

	/* Slightly different for the foreign sids.  We don't want
	 * domain SIDs ending up there, it would cause all sorts of
	 * pain */

	sid = dom_sid_parse_talloc(msg2, (const char *)ldb_dn_get_rdn_val(msg2->dn)->data);
	if (!sid) {
		ldb_set_errstring(module->ldb, "No valid found SID in ForeignSecurityPrincipal CN!");
		talloc_free(mem_ctx);
		return LDB_ERR_CONSTRAINT_VIOLATION;
	}

	if ( ! samldb_msg_add_sid(module, msg2, "objectSid", sid)) {
		talloc_free(sid);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	dom_sid = dom_sid_dup(mem_ctx, sid);
	if (!dom_sid) {
		talloc_free(mem_ctx);
		return LDB_ERR_OPERATIONS_ERROR;
	}
	/* get the domain component part of the provided SID */
	dom_sid->num_auths--;

	/* find the domain DN */

	ret = gendb_search(module->ldb,
			   mem_ctx, NULL, &dom_msgs, dom_attrs,
			   "(&(objectSid=%s)(objectclass=domain))",
			   ldap_encode_ndr_dom_sid(mem_ctx, dom_sid));
	if (ret >= 1) {
		/* We don't really like the idea of foreign sids that are not foreign, but it happens */
		const char *name = samdb_result_string(dom_msgs[0], "name", NULL);
		ldb_debug(module->ldb, LDB_DEBUG_TRACE, "NOTE (strange but valid): Adding foreign SID record with SID %s, but this domian (%s) is already in the database", 
			  dom_sid_string(mem_ctx, sid), name); 
	} else if (ret == -1) {
		ldb_asprintf_errstring(module->ldb,
					"samldb_fill_foreignSecurityPrincipal_object: error searching for a domain with this sid: %s\n", 
					dom_sid_string(mem_ctx, dom_sid));
		talloc_free(dom_msgs);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/* This isn't an operation on a domain we know about, so just
	 * check for the SID, looking for duplicates via the common
	 * code */
	ret = samldb_notice_sid(module, msg2, sid);
	if (ret == 0) {
		talloc_steal(msg, msg2);
		*ret_msg = msg2;
	}
	
	return ret;
}
Beispiel #25
0
static int samldb_fill_user_or_computer_object(struct ldb_module *module, const struct ldb_message *msg,
							       struct ldb_message **ret_msg)
{
	int ret;
	char *name;
	struct ldb_message *msg2;
	const char *rdn_name;
	TALLOC_CTX *mem_ctx = talloc_new(msg);
	const char *errstr;
	if (!mem_ctx) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/* build the new msg */
	msg2 = ldb_msg_copy(mem_ctx, msg);
	if (!msg2) {
		ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_group_object: ldb_msg_copy failed!\n");
		talloc_free(mem_ctx);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	if (samdb_find_attribute(module->ldb, msg, "objectclass", "computer") != NULL) {

		ret = samdb_copy_template(module->ldb, msg2, 
					  "(&(CN=TemplateComputer)(objectclass=userTemplate))", 
					  &errstr);
		if (ret) {
			ldb_asprintf_errstring(module->ldb, 
					       "samldb_fill_user_or_computer_object: "
					       "Error copying computer template: %s",
					       errstr);
			talloc_free(mem_ctx);
			return ret;
		}

		/* readd user and then computer objectclasses */
		ret = samdb_find_or_add_value(module->ldb, msg2, "objectclass", "user");
		if (ret) {
			talloc_free(mem_ctx);
			return ret;
		}
		ret = samdb_find_or_add_value(module->ldb, msg2, "objectclass", "computer");
		if (ret) {
			talloc_free(mem_ctx);
			return ret;
		}
		
	} else {
		ret = samdb_copy_template(module->ldb, msg2, 
					  "(&(CN=TemplateUser)(objectclass=userTemplate))", 
					  &errstr);
		if (ret) {
			ldb_asprintf_errstring(module->ldb, 
					       "samldb_fill_user_or_computer_object: Error copying user template: %s\n",
					       errstr);
			talloc_free(mem_ctx);
			return ret;
		}
		/* readd user objectclass */
		ret = samdb_find_or_add_value(module->ldb, msg2, "objectclass", "user");
		if (ret) {
			talloc_free(mem_ctx);
			return ret;
		}
	}

	rdn_name = ldb_dn_get_rdn_name(msg2->dn);

	if (strcasecmp(rdn_name, "cn") != 0) {
		ldb_asprintf_errstring(module->ldb, "Bad RDN (%s=) for user/computer, should be CN=!\n", rdn_name);
		talloc_free(mem_ctx);
		return LDB_ERR_CONSTRAINT_VIOLATION;
	}

	if (ldb_msg_find_element(msg2, "samAccountName") == NULL) {
		name = samldb_generate_samAccountName(module, mem_ctx);
		if (!name) {
			talloc_free(mem_ctx);
			return LDB_ERR_OPERATIONS_ERROR;
		}
		ret = samdb_find_or_add_attribute(module->ldb, msg2, "sAMAccountName", name);
		if (ret) {
			talloc_free(mem_ctx);
			return ret;
		}
	}

	/*
	  TODO: useraccountcontrol: setting value 0 gives 0x200 for users
	*/

	/* Manage SID allocation, conflicts etc */
	ret = samldb_handle_sid(module, mem_ctx, msg2); 

	/* TODO: objectCategory, userAccountControl, badPwdCount, codePage, countryCode, badPasswordTime, lastLogoff, lastLogon, pwdLastSet, primaryGroupID, accountExpires, logonCount */

	if (ret == 0) {
		*ret_msg = msg2;
		talloc_steal(msg, msg2);
	}
	talloc_free(mem_ctx);
	return ret;
}
Beispiel #26
0
static int samldb_fill_group_object(struct ldb_module *module, const struct ldb_message *msg,
						    struct ldb_message **ret_msg)
{
	int ret;
	const char *name;
	struct ldb_message *msg2;
	const char *rdn_name;
	TALLOC_CTX *mem_ctx = talloc_new(msg);
	const char *errstr;
	if (!mem_ctx) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	/* build the new msg */
	msg2 = ldb_msg_copy(mem_ctx, msg);
	if (!msg2) {
		ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_group_object: ldb_msg_copy failed!\n");
		talloc_free(mem_ctx);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	ret = samdb_copy_template(module->ldb, msg2, 
				  "(&(CN=TemplateGroup)(objectclass=groupTemplate))",
				  &errstr);
	if (ret != 0) {
		
		talloc_free(mem_ctx);
		return ret;
	}

	rdn_name = ldb_dn_get_rdn_name(msg2->dn);

	if (strcasecmp(rdn_name, "cn") != 0) {
		ldb_debug(module->ldb, LDB_DEBUG_FATAL, "samldb_fill_group_object: Bad RDN (%s) for group!\n", rdn_name);
		talloc_free(mem_ctx);
		return LDB_ERR_CONSTRAINT_VIOLATION;
	}

	/* Generate a random name, if no samAccountName was supplied */
	if (ldb_msg_find_element(msg2, "samAccountName") == NULL) {
		name = samldb_generate_samAccountName(module, mem_ctx);
		if (!name) {
			talloc_free(mem_ctx);
			return LDB_ERR_OPERATIONS_ERROR;
		}
		ret = samdb_find_or_add_attribute(module->ldb, msg2, "sAMAccountName", name);
		if (ret) {
			talloc_free(mem_ctx);
			return ret;
		}
	}
	
	/* Manage SID allocation, conflicts etc */
	ret = samldb_handle_sid(module, mem_ctx, msg2); 

	if (ret == LDB_SUCCESS) {
		talloc_steal(msg, msg2);
		*ret_msg = msg2;
	}
	talloc_free(mem_ctx);
	return ret;
}
Beispiel #27
0
/*
  extended match, handles things like bitops
*/
static int ldb_match_extended(struct ldb_context *ldb, 
			      const struct ldb_message *msg,
			      const struct ldb_parse_tree *tree,
			      enum ldb_scope scope, bool *matched)
{
	unsigned int i;
	const struct {
		const char *oid;
		int (*comparator)(const char *, const struct ldb_val *, const struct ldb_val *, bool *);
	} rules[] = {
		{ LDB_OID_COMPARATOR_AND, ldb_comparator_bitmask},
		{ LDB_OID_COMPARATOR_OR, ldb_comparator_bitmask},
		{ SAMBA_LDAP_MATCH_ALWAYS_FALSE, ldb_comparator_false}
	};
	int (*comp)(const char *,const struct ldb_val *, const struct ldb_val *, bool *) = NULL;
	struct ldb_message_element *el;

	if (tree->u.extended.dnAttributes) {
		/* FIXME: We really need to find out what this ":dn" part in
		 * an extended match means and how to handle it. For now print
		 * only a warning to have s3 winbind and other tools working
		 * against us. - Matthias */
		ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb: dnAttributes extended match not supported yet");
	}
	if (tree->u.extended.rule_id == NULL) {
		ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: no-rule extended matches not supported yet");
		return LDB_ERR_INAPPROPRIATE_MATCHING;
	}
	if (tree->u.extended.attr == NULL) {
		ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: no-attribute extended matches not supported yet");
		return LDB_ERR_INAPPROPRIATE_MATCHING;
	}

	for (i=0;i<ARRAY_SIZE(rules);i++) {
		if (strcmp(rules[i].oid, tree->u.extended.rule_id) == 0) {
			comp = rules[i].comparator;
			break;
		}
	}
	if (comp == NULL) {
		ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: unknown extended rule_id %s",
			  tree->u.extended.rule_id);
		return LDB_ERR_INAPPROPRIATE_MATCHING;
	}

	/* find the message element */
	el = ldb_msg_find_element(msg, tree->u.extended.attr);
	if (el == NULL) {
		*matched = false;
		return LDB_SUCCESS;
	}

	for (i=0;i<el->num_values;i++) {
		int ret = comp(tree->u.extended.rule_id, &el->values[i], &tree->u.extended.value, matched);
		if (ret != LDB_SUCCESS) return ret;
		if (*matched) return LDB_SUCCESS;
	}

	*matched = false;
	return LDB_SUCCESS;
}
Beispiel #28
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 #29
0
static int pdc_fsmo_init(struct ldb_module *module)
{
	struct ldb_context *ldb;
	TALLOC_CTX *mem_ctx;
	struct ldb_dn *pdc_dn;
	struct dsdb_pdc_fsmo *pdc_fsmo;
	struct ldb_result *pdc_res;
	int ret;
	static const char *pdc_attrs[] = {
		"fSMORoleOwner",
		NULL
	};

	ldb = ldb_module_get_ctx(module);

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

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

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

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

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

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

	talloc_steal(module, pdc_fsmo);

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

	talloc_free(mem_ctx);
	return ldb_next_init(module);
}
Beispiel #30
0
/*
 * @brief Load the keys into the encrypted secrets module context.
 *
 * @param module the current ldb module
 * @param data the private data for the current module
 *
 * Currently the keys are stored in a binary file in the same directory
 * as the database.
 *
 * @return an LDB result code.
 *
 */
static int load_keys(struct ldb_module *module, struct es_data *data)
{

	const char *key_dir  = NULL;
	const char *key_path = NULL;

	struct ldb_context *ldb = NULL;
	FILE *fp = NULL;
	const int key_size = 16;
	int read;
	DATA_BLOB key = data_blob_null;

	TALLOC_CTX *frame = talloc_stackframe();

	ldb = ldb_module_get_ctx(module);
	key_dir = get_key_directory(frame, ldb);
	if (key_dir == NULL) {
		TALLOC_FREE(frame);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	key_path = talloc_asprintf(frame, "%s/%s", key_dir, SECRETS_KEY_FILE);
	if (key_path == NULL) {
		TALLOC_FREE(frame);
		return ldb_oom(ldb);
	}


	key = data_blob_talloc_zero(module, key_size);
	key.length = key_size;

	fp = fopen(key_path, "rb");
	if (fp == NULL) {
		TALLOC_FREE(frame);
		data_blob_free(&key);
		if (errno == ENOENT) {
			ldb_debug(ldb,
				  LDB_DEBUG_WARNING,
				  "No encrypted secrets key file. "
				  "Secret attributes will not be encrypted or "
				  "decrypted\n");
			data->encrypt_secrets = false;
			return LDB_SUCCESS;
		} else {
			log_error(ldb,
				  errno,
				  "Opening encrypted_secrets key file\n");
			return LDB_ERR_OPERATIONS_ERROR;
		}
	}

	read = fread(key.data, 1, key.length, fp);
	fclose(fp);
	if (read == 0) {
		TALLOC_FREE(frame);
		ldb_debug(ldb,
			  LDB_DEBUG_WARNING,
			  "Zero length encrypted secrets key file. "
			  "Secret attributes will not be encrypted or "
			  "decrypted\n");
		data->encrypt_secrets = false;
		return LDB_SUCCESS;
	}
	if (read != key.length) {
		TALLOC_FREE(frame);
		if (errno) {
			log_error(ldb,
				  errno,
				  "Reading encrypted_secrets key file\n");
		} else {
			ldb_debug(ldb,
				  LDB_DEBUG_ERROR,
				  "Invalid encrypted_secrets key file, "
				  "only %d bytes read should be %d bytes\n",
				  read,
				  key_size);
		}
		return LDB_ERR_OPERATIONS_ERROR;
	}

	data->keys[0] = key;
	data->encrypt_secrets = true;
#ifdef BUILD_WITH_GNUTLS_AEAD
	data->encryption_algorithm = GNUTLS_CIPHER_AES_128_GCM;
#endif
	TALLOC_FREE(frame);

	return LDB_SUCCESS;

}