示例#1
0
static int read_at_rootdse_record(struct ldb_context *ldb, struct ldb_module *module, TALLOC_CTX *mem_ctx,
				  struct ldb_message **msg, struct ldb_request *parent)
{
	int ret;
	static const char *rootdse_attrs[] = { "defaultNamingContext", "configurationNamingContext", "schemaNamingContext", NULL };
	struct ldb_result *rootdse_res;
	struct ldb_dn *rootdse_dn;
	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
	if (!tmp_ctx) {
		return ldb_oom(ldb);
	}

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

	ret = dsdb_module_search_dn(module, tmp_ctx, &rootdse_res, rootdse_dn,
	                            rootdse_attrs, DSDB_FLAG_NEXT_MODULE, parent);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}

	talloc_steal(mem_ctx, rootdse_res->msgs);
	*msg = rootdse_res->msgs[0];

	talloc_free(tmp_ctx);

	return ret;
}
示例#2
0
/*
  add to the list of ldif handlers for this ldb context
*/
int ldb_set_attrib_handlers(struct ldb_context *ldb, 
			    const struct ldb_attrib_handler *handlers, 
			    unsigned num_handlers)
{
	int i;
	struct ldb_attrib_handler *h;
	h = talloc_realloc(ldb, ldb->schema.attrib_handlers,
			   struct ldb_attrib_handler,
			   ldb->schema.num_attrib_handlers + num_handlers);
	if (h == NULL) {
		ldb_oom(ldb);
		return -1;
	}
	ldb->schema.attrib_handlers = h;
	memcpy(h + ldb->schema.num_attrib_handlers, 
	       handlers, sizeof(*h) * num_handlers);
	for (i=0;i<num_handlers;i++) {
		if (h[ldb->schema.num_attrib_handlers+i].flags & LDB_ATTR_FLAG_ALLOCATED) {
			h[ldb->schema.num_attrib_handlers+i].attr = talloc_strdup(ldb->schema.attrib_handlers,
										  h[ldb->schema.num_attrib_handlers+i].attr);
			if (h[ldb->schema.num_attrib_handlers+i].attr == NULL) {
				ldb_oom(ldb);
				return -1;
			}
		}
	}
	ldb->schema.num_attrib_handlers += num_handlers;
	return 0;
}
示例#3
0
/* Generate a remote message with a mapped objectClass. */
static void map_objectclass_generate_remote(struct ldb_module *module, const char *local_attr, const struct ldb_message *old, struct ldb_message *remote, struct ldb_message *local)
{
	const struct ldb_map_context *data = map_get_context(module);
	struct ldb_context *ldb;
	struct ldb_message_element *el, *oc;
	struct ldb_val val;
	bool found_extensibleObject = false;
	unsigned int i;

	ldb = ldb_module_get_ctx(module);

	/* Find old local objectClass */
	oc = ldb_msg_find_element(old, "objectClass");
	if (oc == NULL) {
		return;
	}

	/* Prepare new element */
	el = talloc_zero(remote, struct ldb_message_element);
	if (el == NULL) {
		ldb_oom(ldb);
		return;			/* TODO: fail? */
	}

	/* Copy local objectClass element, reverse space for an extra value */
	el->num_values = oc->num_values + 1;
	el->values = talloc_array(el, struct ldb_val, el->num_values);
	if (el->values == NULL) {
		talloc_free(el);
		ldb_oom(ldb);
		return;			/* TODO: fail? */
	}

	/* Copy local element name "objectClass" */
	el->name = talloc_strdup(el, local_attr);

	/* Convert all local objectClasses */
	for (i = 0; i < el->num_values - 1; i++) {
		el->values[i] = map_objectclass_convert_local(module, el->values, &oc->values[i]);
		if (ldb_attr_cmp((char *)el->values[i].data, data->add_objectclass) == 0) {
			found_extensibleObject = true;
		}
	}

	if (!found_extensibleObject) {
		val.data = (uint8_t *)talloc_strdup(el->values, data->add_objectclass);
		val.length = strlen((char *)val.data);

		/* Append additional objectClass data->add_objectclass */
		el->values[i] = val;
	} else {
		el->num_values--;
	}

	/* Add new objectClass to remote message */
	ldb_msg_add(remote, el, 0);
}
示例#4
0
static int prepare_modules_line(struct ldb_context *ldb,
				TALLOC_CTX *mem_ctx,
				const struct ldb_message *rootdse_msg,
				struct ldb_message *msg, const char *backend_attr,
				const char *backend_mod, const char **backend_mod_list)
{
	int ret;
	const char **backend_full_list;
	const char *backend_dn;
	char *mod_list_string;
	char *full_string;
	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
	if (!tmp_ctx) {
		return ldb_oom(ldb);
	}

	if (backend_attr) {
		backend_dn = ldb_msg_find_attr_as_string(rootdse_msg, backend_attr, NULL);
		if (!backend_dn) {
			ldb_asprintf_errstring(ldb,
					       "samba_dsdb_init: "
					       "unable to read %s from %s:%s",
					       backend_attr, ldb_dn_get_linearized(rootdse_msg->dn),
					       ldb_errstring(ldb));
			return LDB_ERR_CONSTRAINT_VIOLATION;
		}
	} else {
		backend_dn = "*";
	}

	if (backend_mod) {
		backend_full_list = (const char **)str_list_make_single(tmp_ctx, backend_mod);
	} else {
		backend_full_list = (const char **)str_list_make_empty(tmp_ctx);
	}
	if (!backend_full_list) {
		talloc_free(tmp_ctx);
		return ldb_oom(ldb);
	}

	backend_full_list = str_list_append_const(backend_full_list, backend_mod_list);
	if (!backend_full_list) {
		talloc_free(tmp_ctx);
		return ldb_oom(ldb);
	}

	mod_list_string = str_list_join(tmp_ctx, backend_full_list, ',');
	if (!mod_list_string) {
		talloc_free(tmp_ctx);
		return ldb_oom(ldb);
	}

	full_string = talloc_asprintf(tmp_ctx, "%s:%s", backend_dn, mod_list_string);
	ret = ldb_msg_add_steal_string(msg, "modules", full_string);
	talloc_free(tmp_ctx);
	return ret;
}
示例#5
0
/* Generate a local message with a mapped objectClass. */
static struct ldb_message_element *map_objectclass_generate_local(struct ldb_module *module, void *mem_ctx, const char *local_attr, const struct ldb_message *remote)
{
	const struct ldb_map_context *data = map_get_context(module);
	struct ldb_context *ldb;
	struct ldb_message_element *el, *oc;
	struct ldb_val val;
	unsigned int i;

	ldb = ldb_module_get_ctx(module);

	/* Find old remote objectClass */
	oc = ldb_msg_find_element(remote, "objectClass");
	if (oc == NULL) {
		return NULL;
	}

	/* Prepare new element */
	el = talloc_zero(mem_ctx, struct ldb_message_element);
	if (el == NULL) {
		ldb_oom(ldb);
		return NULL;
	}

	/* Copy remote objectClass element */
	el->num_values = oc->num_values;
	el->values = talloc_array(el, struct ldb_val, el->num_values);
	if (el->values == NULL) {
		talloc_free(el);
		ldb_oom(ldb);
		return NULL;
	}

	/* Copy remote element name "objectClass" */
	el->name = talloc_strdup(el, local_attr);

	/* Convert all remote objectClasses */
	for (i = 0; i < el->num_values; i++) {
		el->values[i] = map_objectclass_convert_remote(module, el->values, &oc->values[i]);
	}

	val.data = (uint8_t *)talloc_strdup(el->values, data->add_objectclass);
	val.length = strlen((char *)val.data);

	/* Remove last value if it was the string in data->add_objectclass (eg samba4top, extensibleObject) */
	if (ldb_val_equal_exact(&val, &el->values[i-1])) {
		el->num_values--;
		el->values = talloc_realloc(el, el->values, struct ldb_val, el->num_values);
		if (el->values == NULL) {
			talloc_free(el);
			ldb_oom(ldb);
			return NULL;
		}
	}
示例#6
0
static int samba_secrets_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_module *backend_module, *module_chain;
	const char **reverse_module_list;
	/*
	  Add modules to the list to activate them by default
	  beware often order is important
	  
	  The list is presented here as a set of declarations to show the
	  stack visually
	*/
	static const char *modules_list[] = {"update_keytab",
					     "secrets_tdb_sync",
					     "objectguid",
					     "rdn_name",
					     NULL };

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

	/* Now prepare the module chain.  Oddly, we must give it to ldb_load_modules_list in REVERSE */
	for (len = 0; modules_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] = modules_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);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return 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);
}
示例#7
0
int dsdb_get_sd_from_ldb_message(struct ldb_context *ldb,
				 TALLOC_CTX *mem_ctx,
				 struct ldb_message *acl_res,
				 struct security_descriptor **sd)
{
	struct ldb_message_element *sd_element;
	enum ndr_err_code ndr_err;

	sd_element = ldb_msg_find_element(acl_res, "nTSecurityDescriptor");
	if (sd_element == NULL) {
		return ldb_error(ldb, LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS,
				 "nTSecurityDescriptor is missing");
	}
	*sd = talloc(mem_ctx, struct security_descriptor);
	if(!*sd) {
		return ldb_oom(ldb);
	}
	ndr_err = ndr_pull_struct_blob(&sd_element->values[0], *sd, *sd,
				       (ndr_pull_flags_fn_t)ndr_pull_security_descriptor);

	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		return ldb_operr(ldb);
	}

	return LDB_SUCCESS;
}
示例#8
0
/*
  read a 64 bit 2-part range
*/
static int ldif_read_range64(struct ldb_context *ldb, void *mem_ctx,
			      const struct ldb_val *in, struct ldb_val *out)
{
	unsigned long high, low;
	char buf[64];

	if (memchr(in->data, '-', in->length) == NULL) {
		return ldb_handler_copy(ldb, mem_ctx, in, out);
	}

	if (in->length > sizeof(buf)-1) {
		return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
	}
	strncpy(buf, (const char *)in->data, in->length);
	buf[in->length] = 0;

	if (sscanf(buf, "%lu-%lu", &low, &high) != 2) {
		return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
	}

	out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%llu",
					       (unsigned long long)(((uint64_t)high)<<32) | (low));

	if (out->data == NULL) {
		ldb_oom(ldb);
		return LDB_ERR_OPERATIONS_ERROR;
	}
	out->length = strlen((char *)out->data);
	return LDB_SUCCESS;
}
示例#9
0
static int prepare_modules_line(struct ldb_context *ldb,
				TALLOC_CTX *mem_ctx,
				const struct ldb_message *rootdse_msg,
				struct ldb_message *msg, const char *backend_attr,
				const char *backend_mod, const char **backend_mod_list)
{
	int ret;
	const char **backend_full_list;
	const char *backend_dn;
	char *mod_list_string;
	char *full_string;
	TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
	if (!tmp_ctx) {
		return ldb_oom(ldb);
	}

	if (backend_attr) {
		backend_dn = ldb_msg_find_attr_as_string(rootdse_msg, backend_attr, NULL);
		if (!backend_dn) {
			ldb_asprintf_errstring(ldb,
					       "samba_dsdb_init: "
					       "unable to read %s from %s:%s",
					       backend_attr, ldb_dn_get_linearized(rootdse_msg->dn),
					       ldb_errstring(ldb));
			return LDB_ERR_CONSTRAINT_VIOLATION;
		}
	} else {
		backend_dn = "*";
	}

	if (backend_mod) {
		char **b = str_list_make_single(tmp_ctx, backend_mod);
		backend_full_list = discard_const_p(const char *, b);
	} else {
示例#10
0
static void ltdb_request_extended_done(struct ltdb_context *ctx,
					struct ldb_extended *ext,
					int error)
{
	struct ldb_context *ldb;
	struct ldb_request *req;
	struct ldb_reply *ares;

	ldb = ldb_module_get_ctx(ctx->module);
	req = ctx->req;

	/* if we already returned an error just return */
	if (ldb_request_get_status(req) != LDB_SUCCESS) {
		return;
	}

	ares = talloc_zero(req, struct ldb_reply);
	if (!ares) {
		ldb_oom(ldb);
		req->callback(req, NULL);
		return;
	}
	ares->type = LDB_REPLY_DONE;
	ares->response = ext;
	ares->error = error;

	req->callback(req, ares);
}
示例#11
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;
}
示例#12
0
文件: acl.c 项目: 0x24bin/winexe-1
static int acl_search(struct ldb_module *module, struct ldb_request *req)
{
	struct ldb_context *ldb;
	struct acl_context *ac;
	struct ldb_request *down_req;
	struct acl_private *data;
	int ret, i;

	ldb = ldb_module_get_ctx(module);

	ac = talloc_zero(req, struct acl_context);
	if (ac == NULL) {
		ldb_oom(ldb);
		return LDB_ERR_OPERATIONS_ERROR;
	}
	data = talloc_get_type(ldb_module_get_private(module), struct acl_private);

	ac->module = module;
	ac->req = req;
	ac->user_type = what_is_user(module);
	ac->allowedAttributes = ldb_attr_in_list(req->op.search.attrs, "allowedAttributes");
	ac->allowedAttributesEffective = ldb_attr_in_list(req->op.search.attrs, "allowedAttributesEffective");
	ac->allowedChildClasses = ldb_attr_in_list(req->op.search.attrs, "allowedChildClasses");
	ac->allowedChildClassesEffective = ldb_attr_in_list(req->op.search.attrs, "allowedChildClassesEffective");
	ac->sDRightsEffective = ldb_attr_in_list(req->op.search.attrs, "sDRightsEffective");

	/* replace any attributes in the parse tree that are private,
	   so we don't allow a search for 'userPassword=penguin',
	   just as we would not allow that attribute to be returned */
	if (ac->user_type != SECURITY_SYSTEM) {
		/* FIXME: We should copy the tree and keep the original unmodified. */
		/* remove password attributes */
		if (data && data->password_attrs) {
			for (i = 0; data->password_attrs[i]; i++) {
				ldb_parse_tree_attr_replace(req->op.search.tree,
							    data->password_attrs[i],
							    "kludgeACLredactedattribute");
			}
		}
	}
	ret = ldb_build_search_req_ex(&down_req,
				      ldb, ac,
				      req->op.search.base,
				      req->op.search.scope,
				      req->op.search.tree,
				      req->op.search.attrs,
				      req->controls,
				      ac, acl_search_callback,
				      req);
	if (ret != LDB_SUCCESS) {
		return ret;
	}
	/* perform the search */
	return ldb_next_request(module, down_req);
}
示例#13
0
/*
  return a list of dn's that might match a leaf indexed search
 */
static int ltdb_index_dn_leaf(struct ldb_module *module, 
			      const struct ldb_parse_tree *tree,
			      const struct ldb_message *index_list,
			      struct dn_list *list)
{
	if (ldb_attr_cmp(tree->u.equality.attr, LTDB_OBJECTCLASS) == 0) {
		return ltdb_index_dn_objectclass(module, tree, index_list, list);
	}
	if (ldb_attr_dn(tree->u.equality.attr) == 0) {
		list->dn = talloc_array(list, char *, 1);
		if (list->dn == NULL) {
			ldb_oom(module->ldb);
			return LDB_ERR_OPERATIONS_ERROR;
		}
		list->dn[0] = talloc_strdup(list->dn, (char *)tree->u.equality.value.data);
		if (list->dn[0] == NULL) {
			ldb_oom(module->ldb);
			return LDB_ERR_OPERATIONS_ERROR;
		}
		list->count = 1;
		return LDB_SUCCESS;
	}
示例#14
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;
}
示例#15
0
/* Canonicalisation of two 64-bit integers */
static int ldif_canonicalise_int64(struct ldb_context *ldb, void *mem_ctx,
				   const struct ldb_val *in, struct ldb_val *out)
{
	int64_t i;
	int ret;

	ret = val_to_int64(in, &i);
	if (ret != LDB_SUCCESS) {
		return ret;
	}
	out->data = (uint8_t *) talloc_asprintf(mem_ctx, "%lld", (long long)i);
	if (out->data == NULL) {
		ldb_oom(ldb);
		return LDB_ERR_OPERATIONS_ERROR;
	}
	out->length = strlen((char *)out->data);
	return 0;
}
示例#16
0
/*
  when this operator_fn is set for a syntax, the backend calls is in
  preference to the comparison function. We are told the exact
  comparison operation that is needed, and we can return errors
 */
static int samba_syntax_operator_fn(struct ldb_context *ldb, enum ldb_parse_op operation,
				    const struct ldb_schema_attribute *a,
				    const struct ldb_val *v1, const struct ldb_val *v2, bool *matched)
{
	switch (operation) {
	case LDB_OP_AND:
	case LDB_OP_OR:
	case LDB_OP_NOT:
	case LDB_OP_SUBSTRING:
	case LDB_OP_APPROX:
	case LDB_OP_EXTENDED:
		/* handled in the backends */
		return LDB_ERR_INAPPROPRIATE_MATCHING;

	case LDB_OP_GREATER:
	case LDB_OP_LESS:
	case LDB_OP_EQUALITY:
	{
		TALLOC_CTX *tmp_ctx = talloc_new(ldb);
		int ret;
		if (tmp_ctx == NULL) {
			return ldb_oom(ldb);
		}
		ret = a->syntax->comparison_fn(ldb, tmp_ctx, v1, v2);
		talloc_free(tmp_ctx);
		if (operation == LDB_OP_GREATER) {
			*matched = (ret > 0);
		} else if (operation == LDB_OP_LESS) {
			*matched = (ret < 0);
		} else {
			*matched = (ret == 0);
		}
		return LDB_SUCCESS;
	}

	case LDB_OP_PRESENT:
		*matched = true;
		return LDB_SUCCESS;
	}

	/* we shouldn't get here */
	return LDB_ERR_INAPPROPRIATE_MATCHING;
}
示例#17
0
/*
  write a 64 bit 2-part range
*/
static int ldif_write_range64(struct ldb_context *ldb, void *mem_ctx,
			      const struct ldb_val *in, struct ldb_val *out)
{
	int64_t v;
	int ret;
	ret = val_to_int64(in, &v);
	if (ret != LDB_SUCCESS) {
		return ret;
	}
	out->data = (uint8_t *)talloc_asprintf(mem_ctx, "%lu-%lu",
					       (unsigned long)(v&0xFFFFFFFF),
					       (unsigned long)(v>>32));
	if (out->data == NULL) {
		ldb_oom(ldb);
		return LDB_ERR_OPERATIONS_ERROR;
	}
	out->length = strlen((char *)out->data);
	return LDB_SUCCESS;
}
示例#18
0
/*
  setup the ldb_schema_attribute field for a dsdb_attribute
 */
static int dsdb_schema_setup_ldb_schema_attribute(struct ldb_context *ldb, 
						  struct dsdb_attribute *attr)
{
	const char *syntax = attr->syntax->ldb_syntax;
	const struct ldb_schema_syntax *s;
	struct ldb_schema_attribute *a;

	if (!syntax) {
		syntax = attr->syntax->ldap_oid;
	}

	s = ldb_samba_syntax_by_lDAPDisplayName(ldb, attr->lDAPDisplayName);
	if (s == NULL) {
		s = ldb_samba_syntax_by_name(ldb, syntax);
	}
	if (s == NULL) {
		s = ldb_standard_syntax_by_name(ldb, syntax);
	}

	if (s == NULL) {
		return LDB_ERR_OPERATIONS_ERROR;		
	}

	attr->ldb_schema_attribute = a = talloc(attr, struct ldb_schema_attribute);
	if (attr->ldb_schema_attribute == NULL) {
		ldb_oom(ldb);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	a->name = attr->lDAPDisplayName;
	a->flags = 0;
	a->syntax = s;

	if (dsdb_schema_unique_attribute(a->name)) {
		a->flags |= LDB_ATTR_FLAG_UNIQUE_INDEX;
	}
	if (attr->isSingleValued) {
		a->flags |= LDB_ATTR_FLAG_SINGLE_VALUE;
	}
	
	
	return LDB_SUCCESS;
}
示例#19
0
static void lldb_request_done(struct lldb_context *ac,
			struct ldb_control **ctrls, int error)
{
	struct ldb_request *req;
	struct ldb_reply *ares;

	req = ac->req;

	ares = talloc_zero(req, struct ldb_reply);
	if (!ares) {
		ldb_oom(ldb_module_get_ctx(ac->module));
		req->callback(req, NULL);
		return;
	}
	ares->type = LDB_REPLY_DONE;
	ares->controls = talloc_steal(ares, ctrls);
	ares->error = error;

	req->callback(req, ares);
}
示例#20
0
/*
  fill in an attribute to the ldb_schema into the supplied buffer

  if flags contains LDB_ATTR_FLAG_ALLOCATED
  the attribute name string will be copied using
  talloc_strdup(), otherwise it needs to be a static const
  string at least with a lifetime longer than the ldb struct!

  the ldb_schema_syntax structure should be a pointer
  to a static const struct or at least it needs to be
  a struct with a longer lifetime than the ldb context!

*/
int ldb_schema_attribute_fill_with_syntax(struct ldb_context *ldb,
					  TALLOC_CTX *mem_ctx,
					  const char *attribute,
					  unsigned flags,
					  const struct ldb_schema_syntax *syntax,
					  struct ldb_schema_attribute *a)
{
	a->name	= attribute;
	a->flags	= flags;
	a->syntax	= syntax;

	if (a->flags & LDB_ATTR_FLAG_ALLOCATED) {
		a->name = talloc_strdup(mem_ctx, a->name);
		if (a->name == NULL) {
			ldb_oom(ldb);
			return -1;
		}
	}

	return 0;
}
示例#21
0
/**
 * Prepares ldb_msg to be used for updating schemaInfo value in DB
 */
static int dsdb_schema_info_write_prepare(struct ldb_context *ldb,
					  struct ldb_val *schema_info_blob,
					  TALLOC_CTX *mem_ctx,
					  struct ldb_message **_msg)
{
	int ldb_err;
	struct ldb_message *msg;
	struct ldb_dn *schema_dn;
	struct ldb_message_element *return_el;

	schema_dn = ldb_get_schema_basedn(ldb);
	if (!schema_dn) {
		DEBUG(0,("dsdb_schema_info_write_prepare: no schema dn present\n"));
		return ldb_operr(ldb);
	}

	/* prepare ldb_msg to update schemaInfo */
	msg = ldb_msg_new(mem_ctx);
	if (msg == NULL) {
		return ldb_oom(ldb);
	}

	msg->dn = schema_dn;
	ldb_err = ldb_msg_add_value(msg, "schemaInfo", schema_info_blob, &return_el);
	if (ldb_err != 0) {
		ldb_asprintf_errstring(ldb, "dsdb_schema_info_write_prepare: ldb_msg_add_value failed - %s\n",
				       ldb_strerror(ldb_err));
		talloc_free(msg);
		return ldb_err;
	}

	/* mark schemaInfo element for replacement */
	return_el->flags = LDB_FLAG_MOD_REPLACE;

	*_msg = msg;

	return LDB_SUCCESS;
}
示例#22
0
/**
 * Make this ldb use the 'global' schema, setup to avoid having multiple copies in this process
 */
int dsdb_set_global_schema(struct ldb_context *ldb)
{
	int ret;
	void *use_global_schema = (void *)1;
	if (!global_schema) {
		return LDB_SUCCESS;
	}
	ret = ldb_set_opaque(ldb, "dsdb_use_global_schema", use_global_schema);
	if (ret != LDB_SUCCESS) {
		return ret;
	}

	/* Set the new attributes based on the new schema */
	ret = dsdb_schema_set_attributes(ldb, global_schema, false /* Don't write attributes, it's expensive */);
	if (ret == LDB_SUCCESS) {
		/* Keep a reference to this schema, just in case the original copy is replaced */
		if (talloc_reference(ldb, global_schema) == NULL) {
			return ldb_oom(ldb);
		}
	}

	return ret;
}
示例#23
0
/*
  add a attribute to the ldb_schema

  if flags contains LDB_ATTR_FLAG_ALLOCATED
  the attribute name string will be copied using
  talloc_strdup(), otherwise it needs to be a static const
  string at least with a lifetime longer than the ldb struct!
  
  the ldb_schema_syntax structure should be a pointer
  to a static const struct or at least it needs to be
  a struct with a longer lifetime than the ldb context!

*/
int ldb_schema_attribute_add_with_syntax(struct ldb_context *ldb, 
					 const char *attribute,
					 unsigned flags,
					 const struct ldb_schema_syntax *syntax)
{
	unsigned int i, n;
	struct ldb_schema_attribute *a;

	if (!syntax) {
		return LDB_ERR_OPERATIONS_ERROR;
	}

	n = ldb->schema.num_attributes + 1;

	a = talloc_realloc(ldb, ldb->schema.attributes,
			   struct ldb_schema_attribute, n);
	if (a == NULL) {
		ldb_oom(ldb);
		return -1;
	}
	ldb->schema.attributes = a;

	for (i = 0; i < ldb->schema.num_attributes; i++) {
		int cmp = ldb_attr_cmp(attribute, a[i].name);
		if (cmp == 0) {
			/* silently ignore attempts to overwrite fixed attributes */
			if (a[i].flags & LDB_ATTR_FLAG_FIXED) {
				return 0;
			}
			if (a[i].flags & LDB_ATTR_FLAG_ALLOCATED) {
				talloc_free(discard_const_p(char, a[i].name));
			}
			/* To cancel out increment below */
			ldb->schema.num_attributes--;
			break;
		} else if (cmp < 0) {
示例#24
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);
}
示例#25
0
文件: acl.c 项目: 0x24bin/winexe-1
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);
}
示例#26
0
文件: acl.c 项目: 0x24bin/winexe-1
static int acl_allowedAttributes(struct ldb_module *module,
				 struct ldb_message *sd_msg,
				 struct ldb_message *msg,
				 struct acl_context *ac)
{
	struct ldb_message_element *oc_el;
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	const struct dsdb_schema *schema = dsdb_get_schema(ldb);
	TALLOC_CTX *mem_ctx;
	const char **attr_list;
	int i, ret;

	/* If we don't have a schema yet, we can't do anything... */
	if (schema == NULL) {
		return LDB_SUCCESS;
	}

	/* Must remove any existing attribute */
	if (ac->allowedAttributes) {
		ldb_msg_remove_attr(msg, "allowedAttributes");
	}

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

	oc_el = ldb_msg_find_element(sd_msg, "objectClass");
	attr_list = dsdb_full_attribute_list(mem_ctx, schema, oc_el, DSDB_SCHEMA_ALL);
	if (!attr_list) {
		ldb_asprintf_errstring(ldb, "acl: Failed to get list of attributes");
		talloc_free(mem_ctx);
		return LDB_ERR_OPERATIONS_ERROR;
	}
	if (ac->allowedAttributes) {
		for (i=0; attr_list && attr_list[i]; i++) {
			ldb_msg_add_string(msg, "allowedAttributes", attr_list[i]);
		}
	}
	if (ac->allowedAttributesEffective) {
		struct security_descriptor *sd;
		struct dom_sid *sid = NULL;
		ldb_msg_remove_attr(msg, "allowedAttributesEffective");
		if (ac->user_type == SECURITY_SYSTEM) {
			for (i=0; attr_list && attr_list[i]; i++) {
				ldb_msg_add_string(msg, "allowedAttributesEffective", attr_list[i]);
			}
			return LDB_SUCCESS;
		}

		ret = get_sd_from_ldb_message(mem_ctx, sd_msg, &sd);

		if (ret != LDB_SUCCESS) {
			return ret;
		}
		ret = get_dom_sid_from_ldb_message(mem_ctx, sd_msg, &sid);

		if (ret != LDB_SUCCESS) {
			return ret;
		}
		for (i=0; attr_list && attr_list[i]; i++) {
			struct dsdb_attribute *attr = dsdb_attribute_by_lDAPDisplayName(schema,
											attr_list[i]);
			if (!attr) {
				return LDB_ERR_OPERATIONS_ERROR;
			}
			/* remove constructed attributes */
			if (attr->systemFlags & DS_FLAG_ATTR_IS_CONSTRUCTED
			    || attr->systemOnly
			    || (attr->linkID != 0 && attr->linkID % 2 != 0 )) {
				continue;
			}
			ret = acl_check_access_on_attribute(module,
							    msg,
							    sd,
							    sid,
							    SEC_ADS_WRITE_PROP,
							    attr);
			if (ret == LDB_SUCCESS) {
				ldb_msg_add_string(msg, "allowedAttributesEffective", attr_list[i]);
			}
		}
	}
	return LDB_SUCCESS;
}
示例#27
0
/*
  modify a record - internal interface

  yuck - this is O(n^2). Luckily n is usually small so we probably
  get away with it, but if we ever have really large attribute lists
  then we'll need to look at this again

  'req' is optional, and is used to specify controls if supplied
*/
int ltdb_modify_internal(struct ldb_module *module,
			 const struct ldb_message *msg,
			 struct ldb_request *req)
{
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	void *data = ldb_module_get_private(module);
	struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
	TDB_DATA tdb_key, tdb_data;
	struct ldb_val ldb_data;
	struct ldb_message *msg2;
	unsigned int i, j, k;
	int ret = LDB_SUCCESS, idx;
	struct ldb_control *control_permissive = NULL;

	if (req) {
		control_permissive = ldb_request_get_control(req,
					LDB_CONTROL_PERMISSIVE_MODIFY_OID);
	}

	tdb_key = ltdb_key(module, msg->dn);
	if (!tdb_key.dptr) {
		return LDB_ERR_OTHER;
	}

	tdb_data = tdb_fetch(ltdb->tdb, tdb_key);
	if (!tdb_data.dptr) {
		talloc_free(tdb_key.dptr);
		return ltdb_err_map(tdb_error(ltdb->tdb));
	}

	msg2 = ldb_msg_new(tdb_key.dptr);
	if (msg2 == NULL) {
		free(tdb_data.dptr);
		ret = LDB_ERR_OTHER;
		goto done;
	}

	ldb_data.data = tdb_data.dptr;
	ldb_data.length = tdb_data.dsize;

	ret = ldb_unpack_data(ldb_module_get_ctx(module), &ldb_data, msg2);
	free(tdb_data.dptr);
	if (ret == -1) {
		ret = LDB_ERR_OTHER;
		goto done;
	}

	if (!msg2->dn) {
		msg2->dn = msg->dn;
	}

	for (i=0; i<msg->num_elements; i++) {
		struct ldb_message_element *el = &msg->elements[i], *el2;
		struct ldb_val *vals;
		const struct ldb_schema_attribute *a = ldb_schema_attribute_by_name(ldb, el->name);
		const char *dn;

		switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
		case LDB_FLAG_MOD_ADD:

			if (el->num_values == 0) {
				ldb_asprintf_errstring(ldb,
						       "attribute '%s': attribute on '%s' specified, but with 0 values (illegal)",
						       el->name, ldb_dn_get_linearized(msg2->dn));
				ret = LDB_ERR_CONSTRAINT_VIOLATION;
				goto done;
			}

			/* make a copy of the array so that a permissive
			 * control can remove duplicates without changing the
			 * original values, but do not copy data as we do not
			 * need to keep it around once the operation is
			 * finished */
			if (control_permissive) {
				el = talloc(msg2, struct ldb_message_element);
				if (!el) {
					ret = LDB_ERR_OTHER;
					goto done;
				}
				*el = msg->elements[i];
				el->values = talloc_array(el, struct ldb_val, el->num_values);
				if (el->values == NULL) {
					ret = LDB_ERR_OTHER;
					goto done;
				}
				for (j = 0; j < el->num_values; j++) {
					el->values[j] = msg->elements[i].values[j];
				}
			}

			if (el->num_values > 1 && ldb_tdb_single_valued(a, el)) {
				ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s specified more than once",
						       el->name, ldb_dn_get_linearized(msg2->dn));
				ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
				goto done;
			}

			/* Checks if element already exists */
			idx = find_element(msg2, el->name);
			if (idx == -1) {
				if (ltdb_msg_add_element(ldb, msg2, el) != 0) {
					ret = LDB_ERR_OTHER;
					goto done;
				}
				ret = ltdb_index_add_element(module, msg2->dn,
							     el);
				if (ret != LDB_SUCCESS) {
					goto done;
				}
			} else {
				j = (unsigned int) idx;
				el2 = &(msg2->elements[j]);

				/* We cannot add another value on a existing one
				   if the attribute is single-valued */
				if (ldb_tdb_single_valued(a, el)) {
					ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s specified more than once",
						               el->name, ldb_dn_get_linearized(msg2->dn));
					ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
					goto done;
				}

				/* Check that values don't exist yet on multi-
				   valued attributes or aren't provided twice */
				/* TODO: This is O(n^2) - replace with more efficient check */
				for (j = 0; j < el->num_values; j++) {
					if (ldb_msg_find_val(el2, &el->values[j]) != NULL) {
						if (control_permissive) {
							/* remove this one as if it was never added */
							el->num_values--;
							for (k = j; k < el->num_values; k++) {
								el->values[k] = el->values[k + 1];
							}
							j--; /* rewind */

							continue;
						}

						ldb_asprintf_errstring(ldb,
								       "attribute '%s': value #%u on '%s' already exists",
								       el->name, j, ldb_dn_get_linearized(msg2->dn));
						ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
						goto done;
					}
					if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) {
						ldb_asprintf_errstring(ldb,
								       "attribute '%s': value #%u on '%s' provided more than once",
								       el->name, j, ldb_dn_get_linearized(msg2->dn));
						ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
						goto done;
					}
				}

				/* Now combine existing and new values to a new
				   attribute record */
				vals = talloc_realloc(msg2->elements,
						      el2->values, struct ldb_val,
						      el2->num_values + el->num_values);
				if (vals == NULL) {
					ldb_oom(ldb);
					ret = LDB_ERR_OTHER;
					goto done;
				}

				for (j=0; j<el->num_values; j++) {
					vals[el2->num_values + j] =
						ldb_val_dup(vals, &el->values[j]);
				}

				el2->values = vals;
				el2->num_values += el->num_values;

				ret = ltdb_index_add_element(module, msg2->dn, el);
				if (ret != LDB_SUCCESS) {
					goto done;
				}
			}

			break;

		case LDB_FLAG_MOD_REPLACE:

			if (el->num_values > 1 && ldb_tdb_single_valued(a, el)) {
				ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s specified more than once",
						       el->name, ldb_dn_get_linearized(msg2->dn));
				ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
				goto done;
			}

			/* TODO: This is O(n^2) - replace with more efficient check */
			for (j=0; j<el->num_values; j++) {
				if (ldb_msg_find_val(el, &el->values[j]) != &el->values[j]) {
					ldb_asprintf_errstring(ldb,
							       "attribute '%s': value #%u on '%s' provided more than once",
							       el->name, j, ldb_dn_get_linearized(msg2->dn));
					ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
					goto done;
				}
			}

			/* Checks if element already exists */
			idx = find_element(msg2, el->name);
			if (idx != -1) {
				j = (unsigned int) idx;
				el2 = &(msg2->elements[j]);

				/* we consider two elements to be
				 * equal only if the order
				 * matches. This allows dbcheck to
				 * fix the ordering on attributes
				 * where order matters, such as
				 * objectClass
				 */
				if (ldb_msg_element_equal_ordered(el, el2)) {
					continue;
				}

				/* Delete the attribute if it exists in the DB */
				if (msg_delete_attribute(module, ldb, msg2,
							 el->name) != 0) {
					ret = LDB_ERR_OTHER;
					goto done;
				}
			}

			/* Recreate it with the new values */
			if (ltdb_msg_add_element(ldb, msg2, el) != 0) {
				ret = LDB_ERR_OTHER;
				goto done;
			}

			ret = ltdb_index_add_element(module, msg2->dn, el);
			if (ret != LDB_SUCCESS) {
				goto done;
			}

			break;

		case LDB_FLAG_MOD_DELETE:
			dn = ldb_dn_get_linearized(msg2->dn);
			if (dn == NULL) {
				ret = LDB_ERR_OTHER;
				goto done;
			}

			if (msg->elements[i].num_values == 0) {
				/* Delete the whole attribute */
				ret = msg_delete_attribute(module, ldb, msg2,
							   msg->elements[i].name);
				if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE &&
				    control_permissive) {
					ret = LDB_SUCCESS;
				} else {
					ldb_asprintf_errstring(ldb,
							       "attribute '%s': no such attribute for delete on '%s'",
							       msg->elements[i].name, dn);
				}
				if (ret != LDB_SUCCESS) {
					goto done;
				}
			} else {
				/* Delete specified values from an attribute */
				for (j=0; j < msg->elements[i].num_values; j++) {
					ret = msg_delete_element(module,
							         msg2,
							         msg->elements[i].name,
							         &msg->elements[i].values[j]);
					if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE &&
					    control_permissive) {
						ret = LDB_SUCCESS;
					} else {
						ldb_asprintf_errstring(ldb,
								       "attribute '%s': no matching attribute value while deleting attribute on '%s'",
								       msg->elements[i].name, dn);
					}
					if (ret != LDB_SUCCESS) {
						goto done;
					}
				}
			}
			break;
		default:
			ldb_asprintf_errstring(ldb,
					       "attribute '%s': invalid modify flags on '%s': 0x%x",
					       msg->elements[i].name, ldb_dn_get_linearized(msg->dn),
					       msg->elements[i].flags & LDB_FLAG_MOD_MASK);
			ret = LDB_ERR_PROTOCOL_ERROR;
			goto done;
		}
	}

	ret = ltdb_store(module, msg2, TDB_MODIFY);
	if (ret != LDB_SUCCESS) {
		goto done;
	}

	ret = ltdb_modified(module, msg2->dn);
	if (ret != LDB_SUCCESS) {
		goto done;
	}

done:
	talloc_free(tdb_key.dptr);
	return ret;
}
示例#28
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;
}
示例#29
0
static int ltdb_handle_request(struct ldb_module *module,
			       struct ldb_request *req)
{
	struct ldb_control *control_permissive;
	struct ldb_context *ldb;
	struct tevent_context *ev;
	struct ltdb_context *ac;
	struct tevent_timer *te;
	struct timeval tv;
	unsigned int i;

	ldb = ldb_module_get_ctx(module);

	control_permissive = ldb_request_get_control(req,
					LDB_CONTROL_PERMISSIVE_MODIFY_OID);

	for (i = 0; req->controls && req->controls[i]; i++) {
		if (req->controls[i]->critical &&
		    req->controls[i] != control_permissive) {
			ldb_asprintf_errstring(ldb, "Unsupported critical extension %s",
					       req->controls[i]->oid);
			return LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION;
		}
	}

	if (req->starttime == 0 || req->timeout == 0) {
		ldb_set_errstring(ldb, "Invalid timeout settings");
		return LDB_ERR_TIME_LIMIT_EXCEEDED;
	}

	ev = ldb_get_event_context(ldb);

	ac = talloc_zero(ldb, struct ltdb_context);
	if (ac == NULL) {
		ldb_oom(ldb);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	ac->module = module;
	ac->req = req;

	tv.tv_sec = 0;
	tv.tv_usec = 0;
	te = tevent_add_timer(ev, ac, tv, ltdb_callback, ac);
	if (NULL == te) {
		talloc_free(ac);
		return LDB_ERR_OPERATIONS_ERROR;
	}

	if (req->timeout > 0) {
		tv.tv_sec = req->starttime + req->timeout;
		tv.tv_usec = 0;
		ac->timeout_event = tevent_add_timer(ev, ac, tv,
						     ltdb_timeout, ac);
		if (NULL == ac->timeout_event) {
			talloc_free(ac);
			return LDB_ERR_OPERATIONS_ERROR;
		}
	}

	/* set a spy so that we do not try to use the request context
	 * if it is freed before ltdb_callback fires */
	ac->spy = talloc(req, struct ltdb_req_spy);
	if (NULL == ac->spy) {
		talloc_free(ac);
		return LDB_ERR_OPERATIONS_ERROR;
	}
	ac->spy->ctx = ac;

	talloc_set_destructor((TALLOC_CTX *)ac->spy, ltdb_request_destructor);

	return LDB_SUCCESS;
}
示例#30
0
/*
  search for attrs on one DN, in the modules below
 */
int dsdb_module_search_dn(struct ldb_module *module,
			  TALLOC_CTX *mem_ctx,
			  struct ldb_result **_res,
			  struct ldb_dn *basedn,
			  const char * const *attrs,
			  uint32_t dsdb_flags,
			  struct ldb_request *parent)
{
	int ret;
	struct ldb_request *req;
	TALLOC_CTX *tmp_ctx;
	struct ldb_result *res;

	tmp_ctx = talloc_new(mem_ctx);

	res = talloc_zero(tmp_ctx, struct ldb_result);
	if (!res) {
		talloc_free(tmp_ctx);
		return ldb_oom(ldb_module_get_ctx(module));
	}

	ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
				   basedn,
				   LDB_SCOPE_BASE,
				   NULL,
				   attrs,
				   NULL,
				   res,
				   ldb_search_default_callback,
				   parent);
	LDB_REQ_SET_LOCATION(req);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}

	ret = dsdb_request_add_controls(req, dsdb_flags);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}

	if (dsdb_flags & DSDB_FLAG_TRUSTED) {
		ldb_req_mark_trusted(req);
	}

	/* Run the new request */
	if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
		ret = ldb_next_request(module, req);
	} else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
		ret = ldb_request(ldb_module_get_ctx(module), req);
	} else {
		const struct ldb_module_ops *ops = ldb_module_get_ops(module);
		SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
		ret = ops->search(module, req);
	}
	if (ret == LDB_SUCCESS) {
		ret = ldb_wait(req->handle, LDB_WAIT_ALL);
	}

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

	if (res->count != 1) {
		/* we may be reading a DB that does not have the 'check base on search' option... */
		ret = LDB_ERR_NO_SUCH_OBJECT;
		ldb_asprintf_errstring(ldb_module_get_ctx(module), 
				       "dsdb_module_search_dn: did not find base dn %s (%d results)", 
				       ldb_dn_get_linearized(basedn), res->count);
	} else {
		*_res = talloc_steal(mem_ctx, res);
	}
	talloc_free(tmp_ctx);
	return ret;
}