Commit ebc781f3 authored by Jelmer Vernooij's avatar Jelmer Vernooij

Merge tag 'upstream/1.1.29'

Upstream version 1.1.29
parents a23a97c6 be03fa68
This diff is collapsed.
This diff is collapsed.
pyldb_Dn_FromDn: PyObject *(struct ldb_dn *)
pyldb_Object_AsDn: bool (TALLOC_CTX *, PyObject *, struct ldb_context *, struct ldb_dn **)
pyldb_Dn_FromDn: PyObject *(struct ldb_dn *)
pyldb_Object_AsDn: bool (TALLOC_CTX *, PyObject *, struct ldb_context *, struct ldb_dn **)
pyldb_Dn_FromDn: PyObject *(struct ldb_dn *)
pyldb_Object_AsDn: bool (TALLOC_CTX *, PyObject *, struct ldb_context *, struct ldb_dn **)
pyldb_Dn_FromDn: PyObject *(struct ldb_dn *)
pyldb_Object_AsDn: bool (TALLOC_CTX *, PyObject *, struct ldb_context *, struct ldb_dn **)
......@@ -708,6 +708,7 @@ def SAMBA_CONFIG_H(conf, path=None):
testflags=True)
conf.ADD_CFLAGS('-Wformat=2 -Wno-format-y2k', testflags=True)
conf.ADD_CFLAGS('-Werror=format-security -Wformat-security', testflags=True)
# This check is because for ldb_search(), a NULL format string
# is not an error, but some compilers complain about that.
if CHECK_CFLAGS(conf, ["-Werror=format", "-Wformat=2"], '''
......
......@@ -49,7 +49,8 @@ def SAMBA_CHECK_PERL(conf, mandatory=True, version=(5,0,0)):
conf.env.PERL_LIB_INSTALL_DIR = perl_lib_install_dir
perl_inc = read_perl_config_var('print "@INC"')
perl_inc.remove('.')
if '.' in perl_inc:
perl_inc.remove('.')
conf.start_msg("PERL_INC: ")
conf.end_msg("%s" % (perl_inc), 'GREEN')
conf.env.PERL_INC = perl_inc
......@@ -31,6 +31,41 @@
#include "ldb_private.h"
#include "ldb_handlers.h"
/*
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;
}
/*
add a attribute to the ldb_schema
......@@ -215,6 +250,39 @@ void ldb_schema_attribute_remove(struct ldb_context *ldb, const char *name)
ldb->schema.num_attributes--;
}
/*
remove attributes with a specified flag (eg LDB_ATTR_FLAG_FROM_DB) for this ldb context
This is to permit correct reloads
*/
void ldb_schema_attribute_remove_flagged(struct ldb_context *ldb, unsigned int flag)
{
ptrdiff_t i;
for (i = 0; i < ldb->schema.num_attributes;) {
const struct ldb_schema_attribute *a
= &ldb->schema.attributes[i];
/* FIXED attributes are never removed */
if (a->flags & LDB_ATTR_FLAG_FIXED) {
i++;
continue;
}
if ((a->flags & flag) == 0) {
i++;
continue;
}
if (a->flags & LDB_ATTR_FLAG_ALLOCATED) {
talloc_free(discard_const_p(char, a->name));
}
if (i < ldb->schema.num_attributes - 1) {
memmove(&ldb->schema.attributes[i],
a+1, sizeof(*a) * (ldb->schema.num_attributes-(i+1)));
}
ldb->schema.num_attributes--;
}
}
/*
setup a attribute handler using a standard syntax
*/
......
......@@ -1699,7 +1699,7 @@ bool ldb_dn_remove_child_components(struct ldb_dn *dn, unsigned int num)
*/
bool ldb_dn_replace_components(struct ldb_dn *dn, struct ldb_dn *new_dn)
{
int i;
unsigned int i;
if ( ! ldb_dn_validate(dn) || ! ldb_dn_validate(new_dn)) {
return false;
......@@ -1904,11 +1904,11 @@ int ldb_dn_set_component(struct ldb_dn *dn, int num,
return LDB_ERR_OTHER;
}
if (num >= dn->comp_num) {
if (num < 0) {
return LDB_ERR_OTHER;
}
if (num < 0) {
if ((unsigned)num >= dn->comp_num) {
return LDB_ERR_OTHER;
}
......
......@@ -693,9 +693,7 @@ _PRIVATE_ int ldb_register_extended_match_rules(struct ldb_context *ldb)
}
/*
register a new ldb backend
if override is true, then override any existing backend for this prefix
register a new ldb extended matching rule
*/
int ldb_register_extended_match_rule(struct ldb_context *ldb,
const struct ldb_extended_match_rule *rule)
......
......@@ -901,7 +901,10 @@ static int ldb_modules_load_path(const char *path, const char *version)
} *loaded;
struct loaded *le;
int dlopen_flags;
#ifdef RTLD_DEEPBIND
bool deepbind_enabled = (getenv("LDB_MODULES_DISABLE_DEEPBIND") == NULL);
#endif
ret = stat(path, &st);
if (ret != 0) {
......@@ -937,13 +940,13 @@ static int ldb_modules_load_path(const char *path, const char *version)
#ifdef RTLD_DEEPBIND
/*
* use deepbind if possible, to avoid issues with different
* system library varients, for example ldb modules may be linked
* system library variants, for example ldb modules may be linked
* against Heimdal while the application may use MIT kerberos.
*
* See the dlopen manpage for details.
*
* One typical user is the bind_dlz module of Samba,
* but symbol versioniong might be enough...
* but symbol versioning might be enough...
*
* We need a way to disable this in order to allow the
* ldb_*ldap modules to work with a preloaded socket wrapper.
......
......@@ -185,8 +185,7 @@ static bool ldb_consume_element_data(uint8_t **pp, size_t *premaining)
unsigned int remaining = *premaining;
uint8_t *p = *pp;
uint32_t num_values = pull_uint32(p, 0);
uint32_t len;
int j;
uint32_t j, len;
p += 4;
if (remaining < 4) {
......@@ -234,6 +233,7 @@ int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb,
unsigned int nelem = 0;
size_t len;
unsigned int found = 0;
struct ldb_val *ldb_val_single_array = NULL;
if (list == NULL) {
list_size = 0;
......@@ -314,6 +314,26 @@ int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb,
goto failed;
}
/*
* In typical use, most values are single-valued. This makes
* it quite expensive to allocate an array of ldb_val for each
* of these, just to then hold the pointer to the data buffer
* (in the LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC we don't
* allocate the data). So with
* LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC we allocate this ahead
* of time and use it for the single values where possible.
* (This is used the the normal search case, but not in the
* index case because of caller requirements).
*/
if (flags & LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC) {
ldb_val_single_array = talloc_array(message->elements, struct ldb_val,
message->num_elements);
if (ldb_val_single_array == NULL) {
errno = ENOMEM;
goto failed;
}
}
for (i=0;i<message->num_elements;i++) {
const char *attr = NULL;
size_t attr_len;
......@@ -348,7 +368,7 @@ int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb,
*/
if (list_size != 0) {
bool keep = false;
int h;
unsigned int h;
/*
* We know that p has a \0 terminator before the
......@@ -397,7 +417,9 @@ int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb,
p += attr_len + 1;
element->num_values = pull_uint32(p, 0);
element->values = NULL;
if (element->num_values != 0) {
if ((flags & LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC) && element->num_values == 1) {
element->values = &ldb_val_single_array[nelem];
} else if (element->num_values != 0) {
element->values = talloc_array(message->elements,
struct ldb_val,
element->num_values);
......
......@@ -427,6 +427,11 @@ const struct ldb_dn_extended_syntax *ldb_dn_extended_syntax_by_name(struct ldb_c
*/
#define LDB_ATTR_FLAG_FORCE_BASE64_LDIF (1<<5)
/*
* The attribute was loaded from a DB, rather than via the C API
*/
#define LDB_ATTR_FLAG_FROM_DB (1<<6)
/**
LDAP attribute syntax for a DN
......@@ -498,6 +503,13 @@ typedef int (*ldb_qsort_cmp_fn_t) (void *v1, void *v2, void *opaque);
#define LDB_CONTROL_BYPASS_OPERATIONAL_OID "1.3.6.1.4.1.7165.4.3.13"
#define LDB_CONTROL_BYPASS_OPERATIONAL_NAME "bypassoperational"
/**
OID for recalculate RDN (rdn attribute and 'name') control. This control forces
the rdn_name module to the recalculate the rdn and name attributes as if the
object was just created.
*/
#define LDB_CONTROL_RECALCULATE_RDN_OID "1.3.6.1.4.1.7165.4.3.30"
/**
OID for recalculate SD control. This control force the
dsdb code to recalculate the SD of the object as if the
......
......@@ -412,8 +412,15 @@ int ldb_unpack_data(struct ldb_context *ldb,
* Giving a NULL list (or a list_size of 0) unpacks all the attributes.
*
* Flags allow control of allocation, so that if
* LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC is specified, then values are
* not allocate, instead they point into the supplier constant buffer.
* LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC is specified, then data in values are
* not allocated, instead they point into the supplier constant buffer.
*
* If LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC is specified, then values
* array are not allocated individually (for single-valued
* attributes), instead they point into a single buffer per message.
*
* LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC is only valid when
* LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC is also specified.
*
* Likewise if LDB_UNPACK_DATA_FLAG_NO_DN is specified, the DN is omitted.
*/
......@@ -425,7 +432,8 @@ int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb,
unsigned int flags,
unsigned int *nb_elements_in_db);
#define LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC 0x0001
#define LDB_UNPACK_DATA_FLAG_NO_DN 0x0002
#define LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC 0x0001
#define LDB_UNPACK_DATA_FLAG_NO_DN 0x0002
#define LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC 0x0004
#endif
......@@ -163,6 +163,18 @@ extern const struct ldb_backend_ops ldb_ldapi_backend_ops;
extern const struct ldb_backend_ops ldb_ldaps_backend_ops;
int ldb_setup_wellknown_attributes(struct ldb_context *ldb);
/*
remove attributes with a specified flag (eg LDB_ATTR_FLAG_FROM_DB) for this ldb context
This is to permit correct reloads
*/
void ldb_schema_attribute_remove_flagged(struct ldb_context *ldb, unsigned int flag);
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);
const char **ldb_subclass_list(struct ldb_context *ldb, const char *classname);
void ldb_subclass_remove(struct ldb_context *ldb, const char *classname);
......
......@@ -190,7 +190,7 @@ static int map_attrs_partition(struct ldb_module *module, void *mem_ctx, const c
static int ldb_msg_replace(struct ldb_message *msg, const struct ldb_message_element *el)
{
struct ldb_message_element *old;
int j;
unsigned j;
old = ldb_msg_find_element(msg, el->name);
/* no local result, add as new element */
......
......@@ -56,26 +56,10 @@ static const struct {
*/
static void ltdb_attributes_unload(struct ldb_module *module)
{
struct ldb_context *ldb;
void *data = ldb_module_get_private(module);
struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
struct ldb_message *msg;
unsigned int i;
ldb = ldb_module_get_ctx(module);
if (ltdb->cache->attributes == NULL) {
/* no previously loaded attributes */
return;
}
struct ldb_context *ldb = ldb_module_get_ctx(module);
msg = ltdb->cache->attributes;
for (i=0;i<msg->num_elements;i++) {
ldb_schema_attribute_remove(ldb, msg->elements[i].name);
}
ldb_schema_attribute_remove_flagged(ldb, LDB_ATTR_FLAG_FROM_DB);
talloc_free(ltdb->cache->attributes);
ltdb->cache->attributes = NULL;
}
/*
......@@ -102,17 +86,24 @@ static int ltdb_attributes_flags(struct ldb_message_element *el, unsigned *v)
return 0;
}
static int ldb_schema_attribute_compare(const void *p1, const void *p2)
{
const struct ldb_schema_attribute *sa1 = (const struct ldb_schema_attribute *)p1;
const struct ldb_schema_attribute *sa2 = (const struct ldb_schema_attribute *)p2;
return ldb_attr_cmp(sa1->name, sa2->name);
}
/*
register any special handlers from @ATTRIBUTES
*/
static int ltdb_attributes_load(struct ldb_module *module)
{
struct ldb_schema_attribute *attrs;
struct ldb_context *ldb;
void *data = ldb_module_get_private(module);
struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
struct ldb_message *msg = ltdb->cache->attributes;
struct ldb_message *attrs_msg = NULL;
struct ldb_dn *dn;
unsigned int i;
unsigned int num_loaded_attrs = 0;
int r;
ldb = ldb_module_get_ctx(module);
......@@ -123,26 +114,57 @@ static int ltdb_attributes_load(struct ldb_module *module)
return 0;
}
attrs_msg = ldb_msg_new(module);
if (attrs_msg == NULL) {
goto failed;
}
dn = ldb_dn_new(module, ldb, LTDB_ATTRIBUTES);
if (dn == NULL) goto failed;
r = ltdb_search_dn1(module, dn, msg, 0);
r = ltdb_search_dn1(module, dn, attrs_msg,
LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC
|LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC
|LDB_UNPACK_DATA_FLAG_NO_DN);
talloc_free(dn);
if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) {
goto failed;
}
if (r == LDB_ERR_NO_SUCH_OBJECT) {
if (r == LDB_ERR_NO_SUCH_OBJECT || attrs_msg->num_elements == 0) {
TALLOC_FREE(attrs_msg);
return 0;
}
attrs = talloc_array(attrs_msg,
struct ldb_schema_attribute,
attrs_msg->num_elements
+ ldb->schema.num_attributes);
if (attrs == NULL) {
goto failed;
}
memcpy(attrs,
ldb->schema.attributes,
sizeof(ldb->schema.attributes[0]) * ldb->schema.num_attributes);
/* mapping these flags onto ldap 'syntaxes' isn't strictly correct,
but its close enough for now */
for (i=0;i<msg->num_elements;i++) {
for (i=0;i<attrs_msg->num_elements;i++) {
unsigned flags;
const char *syntax;
const struct ldb_schema_syntax *s;
const struct ldb_schema_attribute *a =
ldb_schema_attribute_by_name(ldb,
attrs_msg->elements[i].name);
if (a != NULL && a->flags & LDB_ATTR_FLAG_FIXED) {
/* Must already be set in the array, and kept */
continue;
}
if (ltdb_attributes_flags(&msg->elements[i], &flags) != 0) {
ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid @ATTRIBUTES element for '%s'", msg->elements[i].name);
if (ltdb_attributes_flags(&attrs_msg->elements[i], &flags) != 0) {
ldb_debug(ldb, LDB_DEBUG_ERROR,
"Invalid @ATTRIBUTES element for '%s'",
attrs_msg->elements[i].name);
goto failed;
}
switch (flags & ~LTDB_FLAG_HIDDEN) {
......@@ -157,27 +179,50 @@ static int ltdb_attributes_load(struct ldb_module *module)
break;
default:
ldb_debug(ldb, LDB_DEBUG_ERROR,
"Invalid flag combination 0x%x for '%s' in @ATTRIBUTES",
flags, msg->elements[i].name);
"Invalid flag combination 0x%x for '%s' "
"in @ATTRIBUTES",
flags, attrs_msg->elements[i].name);
goto failed;
}
s = ldb_standard_syntax_by_name(ldb, syntax);
if (s == NULL) {
ldb_debug(ldb, LDB_DEBUG_ERROR,
"Invalid attribute syntax '%s' for '%s' in @ATTRIBUTES",
syntax, msg->elements[i].name);
"Invalid attribute syntax '%s' for '%s' "
"in @ATTRIBUTES",
syntax, attrs_msg->elements[i].name);
goto failed;
}
flags |= LDB_ATTR_FLAG_ALLOCATED;
if (ldb_schema_attribute_add_with_syntax(ldb, msg->elements[i].name, flags, s) != 0) {
flags |= LDB_ATTR_FLAG_ALLOCATED | LDB_ATTR_FLAG_FROM_DB;
r = ldb_schema_attribute_fill_with_syntax(ldb,
attrs,
attrs_msg->elements[i].name,
flags, s,
&attrs[num_loaded_attrs + ldb->schema.num_attributes]);
if (r != 0) {
goto failed;
}
num_loaded_attrs++;
}
attrs = talloc_realloc(attrs_msg,
attrs, struct ldb_schema_attribute,
num_loaded_attrs + ldb->schema.num_attributes);
if (attrs == NULL) {
goto failed;
}
TYPESAFE_QSORT(attrs, num_loaded_attrs + ldb->schema.num_attributes,
ldb_schema_attribute_compare);
talloc_unlink(ldb, ldb->schema.attributes);
ldb->schema.attributes = talloc_steal(ldb, attrs);
ldb->schema.num_attributes = num_loaded_attrs + ldb->schema.num_attributes;
TALLOC_FREE(attrs_msg);
return 0;
failed:
TALLOC_FREE(attrs_msg);
return -1;
}
......@@ -288,9 +333,7 @@ int ltdb_cache_load(struct ldb_module *module)
ltdb->cache = talloc_zero(ltdb, struct ltdb_cache);
if (ltdb->cache == NULL) goto failed;
ltdb->cache->indexlist = ldb_msg_new(ltdb->cache);
ltdb->cache->attributes = ldb_msg_new(ltdb->cache);
if (ltdb->cache->indexlist == NULL ||
ltdb->cache->attributes == NULL) {
if (ltdb->cache->indexlist == NULL) {
goto failed;
}
}
......@@ -360,12 +403,17 @@ int ltdb_cache_load(struct ldb_module *module)
}
talloc_free(ltdb->cache->indexlist);
ltdb_attributes_unload(module); /* calls internally "talloc_free" */
/*
* ltdb_attributes_unload() calls internally talloc_free() on
* any non-fixed elemnts in ldb->schema.attributes.
*
* NOTE WELL: This is per-ldb, not per module, so overwrites
* the handlers across all databases when used under Samba's
* partition module.
*/
ltdb_attributes_unload(module);
ltdb->cache->indexlist = ldb_msg_new(ltdb->cache);
ltdb->cache->attributes = ldb_msg_new(ltdb->cache);
if (ltdb->cache->indexlist == NULL ||
ltdb->cache->attributes == NULL) {
if (ltdb->cache->indexlist == NULL) {
goto failed;
}
ltdb->cache->one_level_indexes = false;
......@@ -374,7 +422,10 @@ int ltdb_cache_load(struct ldb_module *module)
indexlist_dn = ldb_dn_new(module, ldb, LTDB_INDEXLIST);
if (indexlist_dn == NULL) goto failed;
r = ltdb_search_dn1(module, indexlist_dn, ltdb->cache->indexlist, 0);
r = ltdb_search_dn1(module, indexlist_dn, ltdb->cache->indexlist,
LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC
|LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC
|LDB_UNPACK_DATA_FLAG_NO_DN);
if (r != LDB_SUCCESS && r != LDB_ERR_NO_SUCH_OBJECT) {
goto failed;
}
......@@ -386,6 +437,11 @@ int ltdb_cache_load(struct ldb_module *module)
ltdb->cache->attribute_indexes = true;
}
/*
* NOTE WELL: This is per-ldb, not per module, so overwrites
* the handlers across all databases when used under Samba's
* partition module.
*/
if (ltdb_attributes_load(module) == -1) {
goto failed;
}
......
......@@ -931,6 +931,7 @@ static int ltdb_index_filter(const struct dn_list *dn_list,
{
struct ldb_context *ldb;
struct ldb_message *msg;
struct ldb_message *filtered_msg;
unsigned int i;
ldb = ldb_module_get_ctx(ac->module);
......@@ -951,7 +952,9 @@ static int ltdb_index_filter(const struct dn_list *dn_list,
return LDB_ERR_OPERATIONS_ERROR;
}
ret = ltdb_search_dn1(ac->module, dn, msg, 0);
ret = ltdb_search_dn1(ac->module, dn, msg,
LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC|
LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC);
talloc_free(dn);
if (ret == LDB_ERR_NO_SUCH_OBJECT) {
/* the record has disappeared? yes, this can happen */
......@@ -977,14 +980,15 @@ static int ltdb_index_filter(const struct dn_list *dn_list,
}
/* filter the attributes that the user wants */
ret = ltdb_filter_attrs(msg, ac->attrs);
ret = ltdb_filter_attrs(ac, msg, ac->attrs, &filtered_msg);
talloc_free(msg);
if (ret == -1) {
talloc_free(msg);
return LDB_ERR_OPERATIONS_ERROR;
}
ret = ldb_module_send_entry(ac->req, msg, NULL);
ret = ldb_module_send_entry(ac->req, filtered_msg, NULL);
if (ret != LDB_SUCCESS) {
/* Regardless of success or failure, the msg
* is the callbacks responsiblity, and should
......@@ -1206,7 +1210,8 @@ static int ltdb_index_add_el(struct ldb_module *module, const char *dn,
add index entries for all elements in a message
*/
static int ltdb_index_add_all(struct ldb_module *module, const char *dn,
struct ldb_message_element *elements, int num_el,
struct ldb_message_element *elements,
unsigned int num_el,
bool is_new)
{
struct ltdb_private *ltdb = talloc_get_type(ldb_module_get_private(module), struct ltdb_private);
......
......@@ -385,81 +385,144 @@ int ltdb_add_attr_results(struct ldb_module *module,
/*
filter the specified list of attributes from a message
removing not requested attrs.
removing not requested attrs from the new message constructed.
The reason this makes a new message is that the old one may not be
individually allocated, which is what our callers expect.
*/
int ltdb_filter_attrs(struct ldb_message *msg, const char * const *attrs)
int ltdb_filter_attrs(TALLOC_CTX *mem_ctx,
const struct ldb_message *msg, const char * const *attrs,
struct ldb_message **filtered_msg)
{
unsigned int i;
int keep_all = 0;
struct ldb_message_element *el2;
bool keep_all = false;
bool add_dn = false;
uint32_t num_elements;
uint32_t elements_size;
struct ldb_message *msg2;
msg2 = ldb_msg_new(mem_ctx);
if (msg2 == NULL) {
goto failed;
}
msg2->dn = ldb_dn_copy(msg2, msg->dn);
if (msg2->dn == NULL) {
goto failed;
}
if (attrs) {
/* check for special attrs */
for (i = 0; attrs[i]; i++) {
if (strcmp(attrs[i], "*") == 0) {
keep_all = 1;
int cmp = strcmp(attrs[i], "*");
if (cmp == 0) {
keep_all = true;
break;
}
if (ldb_attr_cmp(attrs[i], "distinguishedName") == 0) {
if (msg_add_distinguished_name(msg) != 0) {
return -1;
}
cmp = ldb_attr_cmp(attrs[i], "distinguishedName");
if (cmp == 0) {
add_dn = true;
}
}
} else {
keep_all = 1;
keep_all = true;
}
if (keep_all) {
if (msg_add_distinguished_name(msg) != 0) {
add_dn = true;
elements_size = msg->num_elements + 1;
/* Shortcuts for the simple cases */
} else if (add_dn && i == 1) {
if (msg_add_distinguished_name(msg2) != 0) {
return -1;
}
*filtered_msg = msg2;
return 0;
} else if (i == 0) {
*filtered_msg = msg2;
return 0;
}
el2 = talloc_array(msg, struct ldb_message_element, msg->num_elements);
if (el2 == NULL) {
return -1;
/* Otherwise we are copying at most as many element as we have attributes */
} else {
elements_size = i;
}
msg2->elements = talloc_array(msg2, struct ldb_message_element,
elements_size);
if (msg2->elements == NULL) goto failed;
num_elements = 0;
for (i = 0; i < msg->num_elements; i++) {
struct ldb_message_element *el = &msg->elements[i];
struct ldb_message_element *el2 = &msg2->elements[num_elements];
unsigned int j;
int found = 0;
for (j = 0; attrs[j]; j++) {
if (ldb_attr_cmp(msg->elements[i].name, attrs[j]) == 0) {
found = 1;
break;
if (keep_all == false) {
bool found = false;
for (j = 0; attrs[j]; j++) {
int cmp = ldb_attr_cmp(el->name, attrs[j]);
if (cmp == 0) {
found = true;
break;
}
}
if (found == false) {
continue;
}