Exemplo n.º 1
0
/*
  see if a attribute value is in the list of indexed attributes
*/
static int ldb_msg_find_idx(const struct ldb_message *msg, const char *attr,
			    unsigned int *v_idx, const char *key)
{
	unsigned int i, j;
	for (i=0;i<msg->num_elements;i++) {
		if (ldb_attr_cmp(msg->elements[i].name, key) == 0) {
			const struct ldb_message_element *el = &msg->elements[i];

			if (attr == NULL) {
				/* in this case we are just looking to see if key is present,
 				   we are not spearching for a specific index */
				return 0;
			}

			for (j=0;j<el->num_values;j++) {
				if (ldb_attr_cmp((char *)el->values[j].data, attr) == 0) {
					if (v_idx) {
						*v_idx = j;
					}
					return i;
				}
			}
		}
	}
	return -1;
}
Exemplo n.º 2
0
/*
  create extra attribute shortcuts
 */
static void dsdb_setup_attribute_shortcuts(struct ldb_context *ldb, struct dsdb_schema *schema)
{
	struct dsdb_attribute *attribute;

	/* setup fast access to one_way_link and DN format */
	for (attribute=schema->attributes; attribute; attribute=attribute->next) {
		attribute->dn_format = dsdb_dn_oid_to_format(attribute->syntax->ldap_oid);

		if (attribute->dn_format == DSDB_INVALID_DN) {
			attribute->one_way_link = false;
			continue;
		}

		/* these are not considered to be one way links for
		   the purpose of DN link fixups */
		if (ldb_attr_cmp("distinguishedName", attribute->lDAPDisplayName) == 0 ||
		    ldb_attr_cmp("objectCategory", attribute->lDAPDisplayName) == 0) {
			attribute->one_way_link = false;
			continue;
		}

		if (attribute->linkID == 0) {
			attribute->one_way_link = true;
			continue;
		}
		/* handle attributes with a linkID but no backlink */
		if ((attribute->linkID & 1) == 0 &&
		    dsdb_attribute_by_linkID(schema, attribute->linkID + 1) == NULL) {
			attribute->one_way_link = true;
			continue;
		}
		attribute->one_way_link = false;
	}
}
Exemplo n.º 3
0
/*
  check special dn's have valid attributes
  currently only @ATTRIBUTES is checked
*/
static int ltdb_check_special_dn(struct ldb_module *module,
				 const struct ldb_message *msg)
{
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	unsigned int i, j;

	if (! ldb_dn_is_special(msg->dn) ||
	    ! ldb_dn_check_special(msg->dn, LTDB_ATTRIBUTES)) {
		return LDB_SUCCESS;
	}

	/* we have @ATTRIBUTES, let's check attributes are fine */
	/* should we check that we deny multivalued attributes ? */
	for (i = 0; i < msg->num_elements; i++) {
		if (ldb_attr_cmp(msg->elements[i].name, "distinguishedName") == 0) continue;

		for (j = 0; j < msg->elements[i].num_values; j++) {
			if (ltdb_check_at_attributes_values(&msg->elements[i].values[j]) != 0) {
				ldb_set_errstring(ldb, "Invalid attribute value in an @ATTRIBUTES entry");
				return LDB_ERR_INVALID_ATTRIBUTE_SYNTAX;
			}
		}
	}

	return LDB_SUCCESS;
}
Exemplo n.º 4
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;
}
Exemplo n.º 5
0
/* Find an attribute mapping by the local name. */
const struct ldb_map_attribute *map_attr_find_local(const struct ldb_map_context *data, const char *name)
{
	int i;

	for (i = 0; data->attribute_maps[i].local_name; i++) {
		if (ldb_attr_cmp(data->attribute_maps[i].local_name, name) == 0) {
			return &data->attribute_maps[i];
		}
	}
	for (i = 0; data->attribute_maps[i].local_name; i++) {
		if (ldb_attr_cmp(data->attribute_maps[i].local_name, "*") == 0) {
			return &data->attribute_maps[i];
		}
	}

	return NULL;
}
Exemplo n.º 6
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);
}
Exemplo n.º 7
0
/*
  find an element by attribute name. At the moment this does a linear search,
  it should be re-coded to use a binary search once all places that modify
  records guarantee sorted order

  return the index of the first matching element if found, otherwise -1
*/
static int find_element(const struct ldb_message *msg, const char *name)
{
	unsigned int i;
	for (i=0;i<msg->num_elements;i++) {
		if (ldb_attr_cmp(msg->elements[i].name, name) == 0) {
			return i;
		}
	}
	return -1;
}
Exemplo n.º 8
0
static int handle_dereference(struct ldb_dn *dn,
			      struct dsdb_openldap_dereference_result **dereference_attrs, 
			      const char *attr, const DATA_BLOB *val)
{
	const struct ldb_val *entryUUIDblob, *sid_blob;
	struct ldb_message fake_msg; /* easier to use routines that expect an ldb_message */
	int j;
	
	fake_msg.num_elements = 0;
			
	/* Look for this attribute in the returned control */
	for (j = 0; dereference_attrs && dereference_attrs[j]; j++) {
		struct ldb_val source_dn = data_blob_string_const(dereference_attrs[j]->dereferenced_dn);
		if (ldb_attr_cmp(dereference_attrs[j]->source_attribute, attr) == 0
		    && data_blob_cmp(&source_dn, val) == 0) {
			fake_msg.num_elements = dereference_attrs[j]->num_attributes;
			fake_msg.elements = dereference_attrs[j]->attributes;
			break;
		}
	}
	if (!fake_msg.num_elements) {
		return LDB_SUCCESS;
	}
	/* Look for an OpenLDAP entryUUID */
	
	entryUUIDblob = ldb_msg_find_ldb_val(&fake_msg, "entryUUID");
	if (entryUUIDblob) {
		NTSTATUS status;
		enum ndr_err_code ndr_err;
		
		struct ldb_val guid_blob;
		struct GUID guid;
		
		status = GUID_from_data_blob(entryUUIDblob, &guid);
		
		if (!NT_STATUS_IS_OK(status)) {
			return LDB_ERR_INVALID_DN_SYNTAX;
		}
		ndr_err = ndr_push_struct_blob(&guid_blob, NULL, NULL, &guid,
					       (ndr_push_flags_fn_t)ndr_push_GUID);
		if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
			return LDB_ERR_INVALID_DN_SYNTAX;
		}
		
		ldb_dn_set_extended_component(dn, "GUID", &guid_blob);
	}
	
	sid_blob = ldb_msg_find_ldb_val(&fake_msg, "objectSID");
	
	/* Look for the objectSID */
	if (sid_blob) {
		ldb_dn_set_extended_component(dn, "SID", sid_blob);
	}
	return LDB_SUCCESS;
}
Exemplo n.º 9
0
/* Find an attribute mapping by the remote name. */
const struct ldb_map_attribute *map_attr_find_remote(const struct ldb_map_context *data, const char *name)
{
	const struct ldb_map_attribute *map;
	const struct ldb_map_attribute *wildcard = NULL;
	int i, j;

	for (i = 0; data->attribute_maps[i].local_name; i++) {
		map = &data->attribute_maps[i];
		if (ldb_attr_cmp(map->local_name, "*") == 0) {
			wildcard = &data->attribute_maps[i];
		}

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

		case MAP_KEEP:
			if (ldb_attr_cmp(map->local_name, name) == 0) {
				return map;
			}
			break;

		case MAP_RENAME:
		case MAP_CONVERT:
			if (ldb_attr_cmp(map->u.rename.remote_name, name) == 0) {
				return map;
			}
			break;

		case MAP_GENERATE:
			for (j = 0; map->u.generate.remote_names && map->u.generate.remote_names[j]; j++) {
				if (ldb_attr_cmp(map->u.generate.remote_names[j], name) == 0) {
					return map;
				}
			}
			break;
		}
	}

	/* We didn't find it, so return the wildcard record if one was configured */
	return wildcard;
}
Exemplo n.º 10
0
/*
  this will be replaced with something that looks at the right part of
  the schema once we know where unique indexing information is hidden
 */
static bool dsdb_schema_unique_attribute(const char *attr)
{
	const char *attrs[] = { "objectGUID", "objectSid" , NULL };
	unsigned int i;
	for (i=0;attrs[i];i++) {
		if (ldb_attr_cmp(attr, attrs[i]) == 0) {
			return true;
		}
	}
	return false;
}
Exemplo n.º 11
0
/*
  find an element in a message by attribute name
*/
struct ldb_message_element *ldb_msg_find_element(const struct ldb_message *msg,
						 const char *attr_name)
{
	unsigned int i;
	for (i=0;i<msg->num_elements;i++) {
		if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
			return &msg->elements[i];
		}
	}
	return NULL;
}
Exemplo n.º 12
0
static bool is_attr_in_list(const char * const * attrs, const char *attr)
{
	int i;

	for (i = 0; attrs[i]; i++) {
		if (ldb_attr_cmp(attrs[i], attr) == 0)
			return true;
	}

	return false;
}
Exemplo n.º 13
0
static struct ldb_message_element *rdn_name_find_attribute(const struct ldb_message *msg, const char *name)
{
	int i;

	for (i = 0; i < msg->num_elements; i++) {
		if (ldb_attr_cmp(name, msg->elements[i].name) == 0) {
			return &msg->elements[i];
		}
	}

	return NULL;
}
Exemplo n.º 14
0
/* Find an objectClass mapping by the remote name. */
static const struct ldb_map_objectclass *map_objectclass_find_remote(const struct ldb_map_context *data, const char *name)
{
	int i;

	for (i = 0; data->objectclass_maps && data->objectclass_maps[i].remote_name; i++) {
		if (ldb_attr_cmp(data->objectclass_maps[i].remote_name, name) == 0) {
			return &data->objectclass_maps[i];
		}
	}

	return NULL;
}
Exemplo n.º 15
0
int ldb_match_msg_objectclass(const struct ldb_message *msg,
			      const char *objectclass)
{
	unsigned int i;
	struct ldb_message_element *el = ldb_msg_find_element(msg, "objectClass");
	if (!el) {
		return 0;
	}
	for (i=0; i < el->num_values; i++) {
		if (ldb_attr_cmp((const char *)el->values[i].data, objectclass) == 0) {
			return 1;
		}
	}
	return 0;
}
Exemplo n.º 16
0
/*
  return the attribute handlers for a given attribute
*/
const struct ldb_attrib_handler *ldb_attrib_handler(struct ldb_context *ldb,
						    const char *attrib)
{
	int i;
	const struct ldb_attrib_handler *def = &ldb_default_attrib_handler;
	/* TODO: should be replaced with a binary search, with a sort on add */
	for (i=0;i<ldb->schema.num_attrib_handlers;i++) {
		if (strcmp(ldb->schema.attrib_handlers[i].attr, "*") == 0) {
			def = &ldb->schema.attrib_handlers[i];
		}
		if (ldb_attr_cmp(attrib, ldb->schema.attrib_handlers[i].attr) == 0) {
			return &ldb->schema.attrib_handlers[i];
		}
	}
	return def;
}
Exemplo n.º 17
0
/*
  post process a search result record. For any search_sub[] attributes that were
  asked for, we need to call the appropriate copy routine to copy the result
  into the message, then remove any attributes that we added to the search but
  were not asked for by the user
*/
static int operational_search_post_process(struct ldb_module *module,
					   struct ldb_message *msg,
					   const char * const *attrs)
{
	struct ldb_context *ldb;
	int i, a=0;

	ldb = ldb_module_get_ctx(module);

	for (a=0;attrs && attrs[a];a++) {
		for (i=0;i<ARRAY_SIZE(search_sub);i++) {
			if (ldb_attr_cmp(attrs[a], search_sub[i].attr) != 0) {
				continue;
			}

			/* construct the new attribute, using either a supplied
			   constructor or a simple copy */
			if (search_sub[i].constructor) {
				if (search_sub[i].constructor(module, msg) != 0) {
					goto failed;
				}
			} else if (ldb_msg_copy_attr(msg,
						     search_sub[i].replace,
						     search_sub[i].attr) != 0) {
				goto failed;
			}

			/* remove the added search attribute, unless it was
 			   asked for by the user */
			if (search_sub[i].replace == NULL ||
			    ldb_attr_in_list(attrs, search_sub[i].replace) ||
			    ldb_attr_in_list(attrs, "*")) {
				continue;
			}

			ldb_msg_remove_attr(msg, search_sub[i].replace);
		}
	}

	return 0;

failed:
	ldb_debug_set(ldb, LDB_DEBUG_WARNING,
		      "operational_search_post_process failed for attribute '%s'",
		      attrs[a]);
	return -1;
}
Exemplo n.º 18
0
/* Obtain the site name from a server DN */
static const char *result_site_name(struct ldb_dn *site_dn)
{
	/* Format is cn=<NETBIOS name>,cn=Servers,cn=<site>,cn=sites.... */
	const struct ldb_val *val = ldb_dn_get_component_val(site_dn, 2);
	const char *name = ldb_dn_get_component_name(site_dn, 2);

	if (!name || (ldb_attr_cmp(name, "cn") != 0)) {
		/* Ensure this matches the format.  This gives us a
		 * bit more confidence that a 'cn' value will be a
		 * ascii string */
		return NULL;
	}
	if (val) {
		return (char *)val->data;
	}
	return NULL;
}
Exemplo n.º 19
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;
}
Exemplo n.º 20
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;
	}
Exemplo n.º 21
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) {
Exemplo n.º 22
0
static char *print_schema_recursive(char *append_to_string, struct dsdb_schema *schema, const char *print_class,
				    enum dsdb_schema_convert_target target, 
				    const char **attrs_skip, const struct attr_map *attr_map, const struct oid_map *oid_map) 
{
	char *out = append_to_string;
	const struct dsdb_class *objectclass;
	objectclass = dsdb_class_by_lDAPDisplayName(schema, print_class);
	if (!objectclass) {
		DEBUG(0, ("Cannot find class %s in schema\n", print_class));
		return NULL;
	}

	do {
		TALLOC_CTX *mem_ctx = talloc_new(append_to_string);
		const char *name = objectclass->lDAPDisplayName;
		const char *oid = objectclass->governsID_oid;
		const char *subClassOf = objectclass->subClassOf;
		int objectClassCategory = objectclass->objectClassCategory;
		const char **must;
		const char **may;
		char *schema_entry = NULL;
		const char *objectclass_name_as_list[] = {
			objectclass->lDAPDisplayName,
			NULL
		};
		int j;
		int attr_idx;
		
		if (!mem_ctx) {
			DEBUG(0, ("Failed to create new talloc context\n"));
			return NULL;
		}

		/* We have been asked to skip some attributes/objectClasses */
		if (attrs_skip && str_list_check_ci(attrs_skip, name)) {
			continue;
		}

		/* We might have been asked to remap this oid, due to a conflict */
		for (j=0; oid_map && oid_map[j].old_oid; j++) {
			if (strcasecmp(oid, oid_map[j].old_oid) == 0) {
				oid =  oid_map[j].new_oid;
				break;
			}
		}
		
		/* We might have been asked to remap this name, due to a conflict */
		for (j=0; name && attr_map && attr_map[j].old_attr; j++) {
			if (strcasecmp(name, attr_map[j].old_attr) == 0) {
				name =  attr_map[j].new_attr;
				break;
			}
		}
		
		may = dsdb_full_attribute_list(mem_ctx, schema, objectclass_name_as_list, DSDB_SCHEMA_ALL_MAY);

		for (j=0; may && may[j]; j++) {
			/* We might have been asked to remap this name, due to a conflict */ 
			for (attr_idx=0; attr_map && attr_map[attr_idx].old_attr; attr_idx++) { 
				if (strcasecmp(may[j], attr_map[attr_idx].old_attr) == 0) { 
					may[j] =  attr_map[attr_idx].new_attr; 
					break;				
				}					
			}						
		}

		must = dsdb_full_attribute_list(mem_ctx, schema, objectclass_name_as_list, DSDB_SCHEMA_ALL_MUST);

		for (j=0; must && must[j]; j++) {
			/* We might have been asked to remap this name, due to a conflict */ 
			for (attr_idx=0; attr_map && attr_map[attr_idx].old_attr; attr_idx++) { 
				if (strcasecmp(must[j], attr_map[attr_idx].old_attr) == 0) { 
					must[j] =  attr_map[attr_idx].new_attr; 
					break;				
				}					
			}						
		}

		schema_entry = schema_class_description(mem_ctx, target, 
							SEPERATOR,
							oid, 
							name,
							NULL, 
							subClassOf,
							objectClassCategory,
							must,
							may,
							NULL);
		if (schema_entry == NULL) {
			DEBUG(0, ("failed to generate schema description for %s\n", name));
			return NULL;
		}

		switch (target) {
		case TARGET_OPENLDAP:
			out = talloc_asprintf_append(out, "objectclass %s\n\n", schema_entry);
			break;
		case TARGET_FEDORA_DS:
			out = talloc_asprintf_append(out, "objectClasses: %s\n", schema_entry);
			break;
		}
		talloc_free(mem_ctx);
	} while (0);

	
	for (objectclass=schema->classes; objectclass; objectclass = objectclass->next) {
		if (ldb_attr_cmp(objectclass->subClassOf, print_class) == 0 
		    && ldb_attr_cmp(objectclass->lDAPDisplayName, print_class) != 0) {
			out = print_schema_recursive(out, schema, objectclass->lDAPDisplayName, 
						     target, attrs_skip, attr_map, oid_map);
		}
	}
	return out;
}
Exemplo n.º 23
0
Arquivo: pydsdb.c Projeto: GSam/samba
/*
  normalise a ldb attribute list
 */
static PyObject *py_dsdb_normalise_attributes(PyObject *self, PyObject *args)
{
	PyObject *py_ldb, *el_list, *py_ret;
	struct ldb_context *ldb;
	char *ldap_display_name;
	const struct dsdb_attribute *a;
	struct dsdb_schema *schema;
	struct dsdb_syntax_ctx syntax_ctx;
	struct ldb_message_element *el, *new_el;
	struct drsuapi_DsReplicaAttribute *attr;
	PyLdbMessageElementObject *ret;
	TALLOC_CTX *tmp_ctx;
	WERROR werr;
	Py_ssize_t i;
	PyTypeObject *py_type = NULL;
	PyObject *module = NULL;

	if (!PyArg_ParseTuple(args, "OsO", &py_ldb, &ldap_display_name, &el_list)) {
		return NULL;
	}

	PyErr_LDB_OR_RAISE(py_ldb, ldb);

	schema = dsdb_get_schema(ldb, NULL);
	if (!schema) {
		PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb");
		return NULL;
	}

	a = dsdb_attribute_by_lDAPDisplayName(schema, ldap_display_name);
	if (a == NULL) {
		PyErr_Format(PyExc_KeyError, "Failed to find attribute '%s'", ldap_display_name);
		return NULL;
	}

	dsdb_syntax_ctx_init(&syntax_ctx, ldb, schema);
	syntax_ctx.is_schema_nc = false;

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

	if (!PyList_Check(el_list)) {
		if (!py_check_dcerpc_type(el_list, "ldb", "MessageElement")) {
			PyErr_SetString(py_ldb_get_exception(),
					"list of strings or ldb MessageElement object required");
			return NULL;
		}
		/*
		 * NOTE:
		 * el may not be a valid talloc context, it
		 * could be part of an array
		 */
		el = pyldb_MessageElement_AsMessageElement(el_list);
	} else {
		el = talloc_zero(tmp_ctx, struct ldb_message_element);
		if (el == NULL) {
			PyErr_NoMemory();
			talloc_free(tmp_ctx);
			return NULL;
		}

		el->name = ldap_display_name;
		el->num_values = PyList_Size(el_list);

		el->values = talloc_array(el, struct ldb_val, el->num_values);
		if (el->values == NULL) {
			PyErr_NoMemory();
			talloc_free(tmp_ctx);
			return NULL;
		}

		for (i = 0; i < el->num_values; i++) {
			PyObject *item = PyList_GetItem(el_list, i);
			if (!PyString_Check(item)) {
				PyErr_Format(PyExc_TypeError, "ldif_elements should be strings");
				talloc_free(tmp_ctx);
				return NULL;
			}
			el->values[i].data = (uint8_t *)PyString_AsString(item);
			el->values[i].length = PyString_Size(item);
		}
	}

	new_el = talloc_zero(tmp_ctx, struct ldb_message_element);
	if (new_el == NULL) {
		PyErr_NoMemory();
		talloc_free(tmp_ctx);
		return NULL;
	}

	/* Normalise "objectClass" attribute if needed */
	if (ldb_attr_cmp(a->lDAPDisplayName, "objectClass") == 0) {
		int iret;
		iret = dsdb_sort_objectClass_attr(ldb, schema, el, new_el, new_el);
		if (iret != LDB_SUCCESS) {
			PyErr_SetString(PyExc_RuntimeError, ldb_errstring(ldb));
			talloc_free(tmp_ctx);
			return NULL;
		}
	}

	/* first run ldb_to_drsuapi, then convert back again. This has
	 * the effect of normalising the attributes
	 */

	attr = talloc_zero(tmp_ctx, struct drsuapi_DsReplicaAttribute);
	if (attr == NULL) {
		PyErr_NoMemory();
		talloc_free(tmp_ctx);
		return NULL;
	}

	werr = a->syntax->ldb_to_drsuapi(&syntax_ctx, a, el, attr, attr);
	PyErr_WERROR_NOT_OK_RAISE(werr);

	/* now convert back again */
	werr = a->syntax->drsuapi_to_ldb(&syntax_ctx, a, attr, new_el, new_el);
	PyErr_WERROR_NOT_OK_RAISE(werr);

	module = PyImport_ImportModule("ldb");
	if (module == NULL) {
		return NULL;
	}

	py_type = (PyTypeObject *)PyObject_GetAttrString(module, "MessageElement");
	if (py_type == NULL) {
		return NULL;
	}
	py_ret = py_type->tp_alloc(py_type, 0);
	ret = (PyLdbMessageElementObject *)py_ret;

	ret->mem_ctx = talloc_new(NULL);
	if (talloc_reference(ret->mem_ctx, new_el) == NULL) {
		PyErr_NoMemory();
		return NULL;
	}
	ret->el = new_el;

	talloc_free(tmp_ctx);

	return py_ret;
}
Exemplo n.º 24
0
static bool check_keep_control_for_attribute(struct op_controls_flags* controls_flags, const char* attr) {
	if (controls_flags->bypassoperational && ldb_attr_cmp(attr, "msDS-KeyVersionNumber") == 0 ) {
		return true;
	}
	return false;
}
Exemplo n.º 25
0
/*
  compare two ldb_message_element structures
  comparing by element name
*/
int ldb_msg_element_compare_name(struct ldb_message_element *el1,
				 struct ldb_message_element *el2)
{
	return ldb_attr_cmp(el1->name, el2->name);
}
Exemplo n.º 26
0
/*
  post process a search result record. For any search_sub[] attributes that were
  asked for, we need to call the appropriate copy routine to copy the result
  into the message, then remove any attributes that we added to the search but
  were not asked for by the user
*/
static int operational_search_post_process(struct ldb_module *module,
					   struct ldb_message *msg,
					   enum ldb_scope scope,
					   const char * const *attrs_from_user,
					   const char * const *attrs_searched_for,
					   struct op_controls_flags* controls_flags,
					   struct ldb_request *parent)
{
	struct ldb_context *ldb;
	unsigned int i, a = 0;
	bool constructed_attributes = false;

	ldb = ldb_module_get_ctx(module);

	/* removed any attrs that should not be shown to the user */
	for (i=0; i<ARRAY_SIZE(operational_remove); i++) {
		switch (operational_remove[i].op) {
		case OPERATIONAL_REMOVE_UNASKED:
			if (ldb_attr_in_list(attrs_from_user, operational_remove[i].attr)) {
				continue;
			}
			if (ldb_attr_in_list(attrs_searched_for, operational_remove[i].attr)) {
				continue;
			}
		case OPERATIONAL_REMOVE_ALWAYS:
			ldb_msg_remove_attr(msg, operational_remove[i].attr);
			break;
		case OPERATIONAL_REMOVE_UNLESS_CONTROL:
			if (!check_keep_control_for_attribute(controls_flags, operational_remove[i].attr)) {
				ldb_msg_remove_attr(msg, operational_remove[i].attr);
				break;
			} else {
				continue;
			}
		case OPERATIONAL_SD_FLAGS:
			if (controls_flags->sd ||
			    ldb_attr_in_list(attrs_from_user, operational_remove[i].attr)) {
				continue;
			}
			ldb_msg_remove_attr(msg, operational_remove[i].attr);
			break;
		}
	}

	for (a=0;attrs_from_user && attrs_from_user[a];a++) {
		if (check_keep_control_for_attribute(controls_flags, attrs_from_user[a])) {
			continue;
		}
		for (i=0;i<ARRAY_SIZE(search_sub);i++) {
			if (ldb_attr_cmp(attrs_from_user[a], search_sub[i].attr) != 0) {
				continue;
			}

			/* construct the new attribute, using either a supplied
			   constructor or a simple copy */
			constructed_attributes = true;
			if (search_sub[i].constructor != NULL) {
				if (search_sub[i].constructor(module, msg, scope, parent) != LDB_SUCCESS) {
					goto failed;
				}
			} else if (ldb_msg_copy_attr(msg,
						     search_sub[i].replace,
						     search_sub[i].attr) != LDB_SUCCESS) {
				goto failed;
			}
		}
	}

	/* Deletion of the search helper attributes are needed if:
	 * - we generated constructed attributes and
	 * - we aren't requesting all attributes
	 */
	if ((constructed_attributes) && (!ldb_attr_in_list(attrs_from_user, "*"))) {
		for (i=0;i<ARRAY_SIZE(search_sub);i++) {
			/* remove the added search helper attributes, unless
			 * they were asked for by the user */
			if (search_sub[i].replace != NULL && 
			    !ldb_attr_in_list(attrs_from_user, search_sub[i].replace)) {
				ldb_msg_remove_attr(msg, search_sub[i].replace);
			}
			if (search_sub[i].extra_attr != NULL && 
			    !ldb_attr_in_list(attrs_from_user, search_sub[i].extra_attr)) {
				ldb_msg_remove_attr(msg, search_sub[i].extra_attr);
			}
		}
	}

	return 0;

failed:
	ldb_debug_set(ldb, LDB_DEBUG_WARNING,
		      "operational_search_post_process failed for attribute '%s' - %s",
		      attrs_from_user[a], ldb_errstring(ldb));
	return -1;
}
Exemplo n.º 27
0
/*
  normalise a ldb attribute list
 */
static PyObject *py_dsdb_normalise_attributes(PyObject *self, PyObject *args)
{
	PyObject *py_ldb, *el_list, *ret;
	struct ldb_context *ldb;
	char *ldap_display_name;
	const struct dsdb_attribute *a;
	struct dsdb_schema *schema;
	struct dsdb_syntax_ctx syntax_ctx;
	struct ldb_message_element *el;
	struct drsuapi_DsReplicaAttribute *attr;
	TALLOC_CTX *tmp_ctx;
	WERROR werr;
	Py_ssize_t i;

	if (!PyArg_ParseTuple(args, "OsO", &py_ldb, &ldap_display_name, &el_list)) {
		return NULL;
	}

	PyErr_LDB_OR_RAISE(py_ldb, ldb);

	if (!PyList_Check(el_list)) {
		PyErr_Format(PyExc_TypeError, "ldif_elements must be a list");
		return NULL;
	}

	schema = dsdb_get_schema(ldb, NULL);
	if (!schema) {
		PyErr_SetString(PyExc_RuntimeError, "Failed to find a schema from ldb");
		return NULL;
	}

	a = dsdb_attribute_by_lDAPDisplayName(schema, ldap_display_name);
	if (a == NULL) {
		PyErr_Format(PyExc_KeyError, "Failed to find attribute '%s'", ldap_display_name);
		return NULL;
	}

	dsdb_syntax_ctx_init(&syntax_ctx, ldb, schema);
	syntax_ctx.is_schema_nc = false;

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

	el = talloc_zero(tmp_ctx, struct ldb_message_element);
	if (el == NULL) {
		PyErr_NoMemory();
		talloc_free(tmp_ctx);
		return NULL;
	}

	el->name = ldap_display_name;
	el->num_values = PyList_Size(el_list);

	el->values = talloc_array(el, struct ldb_val, el->num_values);
	if (el->values == NULL) {
		PyErr_NoMemory();
		talloc_free(tmp_ctx);
		return NULL;
	}

	for (i = 0; i < el->num_values; i++) {
		PyObject *item = PyList_GetItem(el_list, i);
		if (!PyString_Check(item)) {
			PyErr_Format(PyExc_TypeError, "ldif_elements should be strings");
			talloc_free(tmp_ctx);
			return NULL;
		}
		el->values[i].data = (uint8_t *)PyString_AsString(item);
		el->values[i].length = PyString_Size(item);
	}

	/* Normalise "objectClass" attribute if needed */
	if (ldb_attr_cmp(a->lDAPDisplayName, "objectClass") == 0) {
		int iret;
		iret = dsdb_sort_objectClass_attr(ldb, schema, el, tmp_ctx, el);
		if (iret != LDB_SUCCESS) {
			PyErr_SetString(PyExc_RuntimeError, ldb_errstring(ldb));
			talloc_free(tmp_ctx);
			return NULL;
		}
	}

	/* first run ldb_to_drsuapi, then convert back again. This has
	 * the effect of normalising the attributes
	 */

	attr = talloc_zero(tmp_ctx, struct drsuapi_DsReplicaAttribute);
	if (attr == NULL) {
		PyErr_NoMemory();
		talloc_free(tmp_ctx);
		return NULL;
	}

	werr = a->syntax->ldb_to_drsuapi(&syntax_ctx, a, el, attr, attr);
	PyErr_WERROR_NOT_OK_RAISE(werr);

	/* now convert back again */
	werr = a->syntax->drsuapi_to_ldb(&syntax_ctx, a, attr, el, el);
	PyErr_WERROR_NOT_OK_RAISE(werr);

	ret = py_return_ndr_struct("ldb", "MessageElement", el, el);

	talloc_free(tmp_ctx);

	return ret;
}
Exemplo n.º 28
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_message *msg2;
	unsigned i, j;
	int ret = LDB_SUCCESS, idx;

	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 = talloc(tdb_key.dptr, struct ldb_message);
	if (msg2 == NULL) {
		free(tdb_data.dptr);
		ret = LDB_ERR_OTHER;
		goto done;
	}

	ret = ltdb_unpack_data(module, &tdb_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;

		if (ldb_attr_cmp(el->name, "distinguishedName") == 0) {
			ldb_asprintf_errstring(ldb, "it is not permitted to perform a modify on 'distinguishedName' (use rename instead): %s",
					       ldb_dn_get_linearized(msg2->dn));
			ret = LDB_ERR_CONSTRAINT_VIOLATION;
			goto done;
		}

		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 on %s specified, but with 0 values (illigal)",
						       el->name, ldb_dn_get_linearized(msg2->dn));
				ret = LDB_ERR_CONSTRAINT_VIOLATION;
				goto done;
			}

			if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) {
				if (el->num_values > 1) {
					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 {
				/* We cannot add another value on a existing one
				   if the attribute is single-valued */
				if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) {
					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;
				}

				el2 = &(msg2->elements[idx]);

				/* Check that values don't exist yet on multi-
				   valued attributes or aren't provided twice */
				for (j=0; j<el->num_values; j++) {
					if (ldb_msg_find_val(el2, &el->values[j]) != NULL) {
						ldb_asprintf_errstring(ldb, "%s: value #%d already exists", el->name, j);
						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, "%s: value #%d provided more than once", el->name, j);
						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 (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) {
				/* the RELAX control overrides this
				   check for replace. This is needed as
				   DRS replication can produce multiple
				   values here for a single valued
				   attribute when the values are deleted
				   links
				*/
				if (el->num_values > 1 &&
				    (!req || !ldb_request_get_control(req, LDB_CONTROL_RELAX_OID))) {
					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, "%s: value #%d provided more than once", el->name, j);
					ret = LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
					goto done;
				}
			}

			idx = find_element(msg2, el->name);
			if (idx != -1) {
				el2 = &(msg2->elements[idx]);
				if (ldb_msg_element_compare(el, el2) == 0) {
					/* we are replacing with the same values */
					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 */
				if (msg_delete_attribute(module, ldb, msg2,
							 msg->elements[i].name) != 0) {
					ldb_asprintf_errstring(ldb, "No such attribute: %s for delete on %s",
							       msg->elements[i].name, dn);
					ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
					goto done;
				}
			} else {
				/* Delete specified values from an attribute */
				for (j=0; j < msg->elements[i].num_values; j++) {
					if (msg_delete_element(module,
							       msg2,
							       msg->elements[i].name,
							       &msg->elements[i].values[j]) != 0) {
						ldb_asprintf_errstring(ldb, "No matching attribute value when deleting attribute: %s on %s",
								       msg->elements[i].name, dn);
						ret = LDB_ERR_NO_SUCH_ATTRIBUTE;
						goto done;
					}
				}
			}
			break;
		default:
			ldb_asprintf_errstring(ldb,
				"Invalid ldb_modify flags on %s: 0x%x",
				msg->elements[i].name,
				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;
}