[SCM] Samba Shared Repository - branch master updated

Andrew Bartlett abartlet at samba.org
Wed May 15 05:36:02 UTC 2019


The branch, master has been updated
       via  0daa0ff921b s4 dsdb/repl_meta_data: fix use after free in dsdb_audit_add_ldb_value
       via  4aa99243102 s4 dsdb/repl_meta_data: allocate new extended DNs during ADD on a better context
       via  5841b164b2c ldap: Add a database open after fork to speed-up prefork binds
       via  ac9333cb91d util/charset/torture: ensure each cp850 high bytes is 3 utf8 bytes
       via  103d248bee8 util/charset/convert: do not pretend to realloc
       via  a6f47b4f758 util/charset/convert: when retrying, retry from the start
       via  02507ebf10e util/charset/convert: do not overflow dest len in corner case
       via  265b3b0c6cc util/charset/convert: do not overflow dest len
       via  09355b78556 util/charset/convert_string: always set length
       via  d1447aa8b54 test_regfio.c: include stdint.h before cmoka.h
       via  85b6f71c65e ldb: Release ldb 2.0.1
       via  15f0c4969a7 ldb: remove unpack only attr list functionality
       via  9310d9088dc ldb: move ldb_kv's filter into pack code
       via  9f9bbb5aac1 ldb: removing msg and dn copying from filter attrs
       via  a36e20c40cf ldb: perf test for pack format
       via  ea7fd52a78d ldb: removing alloc from unpack_data
       via  73bf2949e85 ldb_kv: Use ldb_msg_add_steal_value() in msg_add_distinguished_name()
       via  94989e4e99c ldb_kv: Remove incorrect reference to LDB_UNPACK_DATA_FLAG_NO_DN
      from  28518c579d4 s3:libsmb: Add missing OOM check in fill_quota_buffer()

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 0daa0ff921b270df9b794f02acbaa391c95cd89b
Author: Gary Lockyer <gary at catalyst.net.nz>
Date:   Tue May 14 15:53:22 2019 +1200

    s4 dsdb/repl_meta_data: fix use after free in dsdb_audit_add_ldb_value
    
    Fix use after free detected by AddressSanitizer
    
    AddressSanitizer: heap-use-after-free on address 0x61400026a4a0
                      at pc 0x7fd555c52f12 bp 0x7ffed7231180 sp 0x7ffed7231170
                      READ of size 1 at 0x61400026a4a0 thread T0
        #0 0x7fd555c52f11 in ldb_should_b64_encode
           ../../lib/ldb/common/ldb_ldif.c:197
        #1 0x7fd539dc9417 in dsdb_audit_add_ldb_value
           ../../source4/dsdb/samdb/ldb_modules/audit_util.c:491
        #2 0x7fd539dc9417 in dsdb_audit_attributes_json
           ../../source4/dsdb/samdb/ldb_modules/audit_util.c:651
        #3 0x7fd539dc6a7e in operation_json
           ../../source4/dsdb/samdb/ldb_modules/audit_log.c:305
    
    The problem is that at the successful end of these functions
    el->values is overwritten with new_values.  However get_parsed_dns()
    points p->v at the supplied el and it effectively gets used
    as a working area by replmd_build_la_val().  So we must duplicate it
    because our caller only called ldb_msg_copy_shallow().
    
    The reason this matters is that the audit_log module is
    above repl_meta_data in the stack, and tries to log the
    ldb_message it saw after the reply (to include the error code).
    If that ldb_message is changed it is not only misleading,
    it can point to memory that has since gone away.
    
    In this case the memory for the full extended DN in the
    member attribute ended up on 'ac', a context lost by
    the time repl_meta_data has finished processing.
    
    BUG: https://bugzilla.samba.org/show_bug.cgi?id=13941
    
    Signed-off-by: Gary Lockyer <gary at catalyst.net.nz>
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    
    Autobuild-User(master): Andrew Bartlett <abartlet at samba.org>
    Autobuild-Date(master): Wed May 15 05:35:47 UTC 2019 on sn-devel-184

commit 4aa9924310287ff3b36618496fa6c707c615ad4c
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed May 15 14:47:53 2019 +1200

    s4 dsdb/repl_meta_data: allocate new extended DNs during ADD on a better context
    
    Lower down in this function new_values is assigned over el->values and is
    filled in with the values of all the parsed DNs.  Therefore it is the natural
    talloc parent.
    
    This will allow el->values to be allocated on tmp_ctx in the next commit for
    a working area during the function call.
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>

commit 5841b164b2c57e1389b5486be4ccef8eb47f6892
Author: Garming Sam <garming at catalyst.net.nz>
Date:   Wed May 8 12:40:48 2019 +1200

    ldap: Add a database open after fork to speed-up prefork binds
    
    Removing this (system) database open from the later auth stack results
    in a 15-30% improvement in different types of binds and on different
    hardware (presumably better with slower disk speeds).
    
    Signed-off-by: Garming Sam <garming at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit ac9333cb91dfdd80ba6b218861a5802c559cfec1
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Fri May 10 23:04:02 2019 +1200

    util/charset/torture: ensure each cp850 high bytes is 3 utf8 bytes
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 103d248bee8cfea7ba8d19450e4ac2c14fcbee9f
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Fri May 10 19:37:54 2019 +1200

    util/charset/convert: do not pretend to realloc
    
    It seems very likely that our clever attempts to dynamically realloc
    the output buffer were never triggered. Two lines of reasoning lead to
    this conclusion:
    
    1. We allocate 3 * srclen to start with, but no conversion we use will
       more than that. To be precise, from 8-bit charsets we will only deal
       with codepoints in the Unicode basic multilingual plane (up to 0xFFFF).
    
       These can all be expressed as 3 or fewer utf-8 bytes. In UTF16 they
       are naturally 2 bytes, while in the DOS codes they are 1 byte.
    
       We have checked the code tables, and can not find a plausible
       (e.g. not EBCDIC) DOS code page or unix charset that is outside
       this range.  Clients cannot chose the code page, the only code
       pages we will use come from 'unix charset' and 'dos charset'
       smb.conf parameters.
    
       Therefore the worst that can possibly happen is we expand 1 byte into 3
       (specifically, when converting some e.g. CP850 codepoints to UTF-8).
    
    2. If the reallocation was ever used, the results would have been
       catastrophically wrong, as the input pointer was not reset.
    
    Therefore we skip the complication of the goto loop and let E2BIG be
    just another impossible error to report.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit a6f47b4f7581e0a160fc844efc78e213c6546aee
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Fri May 10 19:32:39 2019 +1200

    util/charset/convert: when retrying, retry from the start
    
    iconv() advances the inbuf pointer; if we decide to realloc and re-iconv,
    we need to reset inbuf to the source string
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 02507ebf10eb6c038ef2ebc1e1aa6a4bd53eeecd
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Fri May 10 17:10:28 2019 +1200

    util/charset/convert: do not overflow dest len in corner case
    
    Now, if destlen were SIZE_MAX - 1, destlen * 2 would wrap to SIZE_MAX - 3,
    which makes (destlen * 2 + 2) == SIZE_MAX - 1, the same number again.
    So we need the <= comparison in this case.
    
    As things stand, it is not actually possible for destlen to be
    SIZE_MAX (because it is always an even number after the first round,
    and the first round is constrained to be < SIZE_MAX / 2, but *if*
    destlen was SIZE_MAX, destlen * 2 + 2 would be 0, so that case is OK.
    Similarly the SIZE_MAX - 2 and smaller cases were covered by the
    original formula.
    
    We add the comment for people who are wondering WTF is going on with
    all this destlen manipulation.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 265b3b0c6cc38fb9644f240ce31edf32d9362b1c
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Fri May 10 17:07:43 2019 +1200

    util/charset/convert: do not overflow dest len
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 09355b7855650cc52781796ad0a5fd28504ea3d0
Author: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
Date:   Fri May 10 15:35:32 2019 +1200

    util/charset/convert_string: always set length
    
    In failure cases the destination string pointer is set to NULL, but
    the size is not changed. Some callers have not been checking the
    return value and passing the destination pointer and uninitialised
    length onto other functions. We can curse and blame those callers, but
    let's also keep them safe.
    
    Signed-off-by: Douglas Bagnall <douglas.bagnall at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit d1447aa8b54ceae3875fdc4d03d0be447f8db59a
Author: Fabrice Fontaine <fontaine.fabrice at gmail.com>
Date:   Sat May 11 00:07:50 2019 +0200

    test_regfio.c: include stdint.h before cmoka.h
    
    This fix the following build failure on mips64el:
    /usr/lfs/v0/rc-buildroot-test/scripts/instance-2/output/host/mips64el-buildroot-linux-uclibc/sysroot/usr/include/stdint.h:122:27: error: conflicting types for 'uintptr_t'
     typedef unsigned long int uintptr_t;
                               ^
    In file included from ../source3/registry/tests/test_regfio.c:23:0:
    ../third_party/cmocka/cmocka.h:126:28: note: previous declaration of 'uintptr_t' was here
           typedef unsigned int uintptr_t;
    
    Fixes:
     - http://autobuild.buildroot.org/results/bae0508e84c905dc23ad7cf1153cd1e9d8e4d734
    
    Signed-off-by: Fabrice Fontaine <fontaine.fabrice at gmail.com>
    Reviewed-by: Gary Lockyer <gary at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>

commit 85b6f71c65e7bfb167064f574a080bc81f7af16d
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Tue May 14 13:14:50 2019 +1200

    ldb: Release ldb 2.0.1
    
    * Rework pack routines to remove unused features:
      - ldb_unpack_data_only_attr_list_flags() is removed
      - LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC is now always implied
    
      This improves the unpack performace significantly.
    
    * Improve search performance via new internal flag
      LDB_UNPACK_DATA_FLAG_READ_LOCKED which removes a memdup
    
    * Improve search performance during full scan by ignoring
      index records early.
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Gary Lockyer <gary at catalyst.net.nz>

commit 15f0c4969a70414ee138a1a524a60750efe590e5
Author: Aaron Haslett <aaronhaslett at catalyst.net.nz>
Date:   Thu May 2 10:46:29 2019 +1200

    ldb: remove unpack only attr list functionality
    
    Unpack functions currently take an attribute list to restrict the set of
    attributes to be returned in the constructed message. This
    functionality is never used and complicates implementation of
    forthcoming new pack format. This patch removes that functionality.
    Using the unpack function then filtering the result turns
    out not to be any slower.
    
    NOTE: Configure with --abi-check-disable to build this commit. This
    patch is part of a set of LDB ABI changes, and the version update is
    done on the last commit.
    
    Signed-off-by: Aaron Haslett <aaronhaslett at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Gary Lockyer <gary at catalyst.net.nz>

commit 9310d9088dc21f76b7e8e5f5378ea6d5262192a0
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Wed May 15 11:04:42 2019 +1200

    ldb: move ldb_kv's filter into pack code
    
    This patch moves ldb_kv's filter code into the pack code to replace
    'only attr list' functionality which will be removed in forthcoming
    commit. Unpacking data then filtering the result is not any slower
    than the removed 'only attr list' approach.
    'only attr list' test repurposed to test unpack -> filter flow.
    
    NOTE: Configure with --abi-check-disable to build this commit. This
    patch is part of a set of LDB ABI changes, and the version update is
    done on the last commit.
    
    Signed-off-by: Aaron Haslett <aaronhaslett at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Gary Lockyer <gary at catalyst.net.nz>

commit 9f9bbb5aac15e8b6f34496e10fac1e94f4736a19
Author: Aaron Haslett <aaronhaslett at catalyst.net.nz>
Date:   Tue May 14 16:59:13 2019 +1200

    ldb: removing msg and dn copying from filter attrs
    
    Optimising filter_attrs by removing msg and dn allocation/copying. The
    caller can construct the msg and possibly steal the dn.
    Also giving the function an ldb for future use.
    
    NOTE: Configure with --abi-check-disable to build this commit. This
    patch is part of a set of LDB ABI changes, and the version update is
    done on the last commit.
    
    Signed-off-by: Aaron Haslett <aaronhaslett at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Gary Lockyer <gary at catalyst.net.nz>

commit a36e20c40cfcbced07962fcc72b26edd33f2ad3a
Author: Aaron Haslett <aaronhaslett at catalyst.net.nz>
Date:   Tue Apr 30 16:10:26 2019 +1200

    ldb: perf test for pack format
    
    Performance test for pack function and unpack function run with flag
    LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC. Run this test before and after
    forthcoming pack format changes to test throughput improvement. On my
    machine, the unpack improvement is around 50%.
    The test doesn't really belong in LDB torture but it's the only place
    where all the required functions are available.
    
    Signed-off-by: Aaron Haslett <aaronhaslett at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Gary Lockyer <gary at catalyst.net.nz>

commit ea7fd52a78d90f54c8b0f2583c72827971ddea6a
Author: Aaron Haslett <aaronhaslett at catalyst.net.nz>
Date:   Thu May 9 12:12:14 2019 +1200

    ldb: removing alloc from unpack_data
    
    Making unpack flag LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC required
    behaviour, since allocating data during unpack is slow and unnecessary
    in all current usages. In any future unpack usage, if editing of
    returned memory is required, some function that duplicates the message
    should be used, such as one of the filter_attrs functions, or msg_copy.
    
    Signed-off-by: Aaron Haslett <aaronhaslett at catalyst.net.nz>
    Reviewed-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Gary Lockyer <gary at catalyst.net.nz>

commit 73bf2949e85d94103d85e54b7963f79ed4f4a961
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri Apr 5 14:42:09 2019 +1300

    ldb_kv: Use ldb_msg_add_steal_value() in msg_add_distinguished_name()
    
    This more modern routine allocates a nice talloc tree.
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Gary Lockyer <gary at catalyst.net.nz>

commit 94989e4e99c4403d90936f0d0a9c81050e5512b8
Author: Andrew Bartlett <abartlet at samba.org>
Date:   Fri Apr 5 11:12:13 2019 +1300

    ldb_kv: Remove incorrect reference to LDB_UNPACK_DATA_FLAG_NO_DN
    
    The DN is now exploded so as to improve other aspects of the search handling.
    
    Signed-off-by: Andrew Bartlett <abartlet at samba.org>
    Reviewed-by: Gary Lockyer <gary at catalyst.net.nz>

-----------------------------------------------------------------------

Summary of changes:
 lib/ldb/ABI/{ldb-1.5.1.sigs => ldb-2.0.1.sigs}     |   4 +-
 ...yldb-util-1.1.10.sigs => pyldb-util-2.0.1.sigs} |   0
 lib/ldb/common/ldb_pack.c                          | 295 ++++++++++--------
 lib/ldb/include/ldb_module.h                       |  44 +--
 lib/ldb/ldb_key_value/ldb_kv.c                     |  11 +-
 lib/ldb/ldb_key_value/ldb_kv.h                     |   4 +-
 lib/ldb/ldb_key_value/ldb_kv_cache.c               |   6 +-
 lib/ldb/ldb_key_value/ldb_kv_index.c               |  52 ++--
 lib/ldb/ldb_key_value/ldb_kv_search.c              | 343 +++++----------------
 lib/ldb/wscript                                    |   2 +-
 lib/util/charset/convert_string.c                  |  28 +-
 lib/util/charset/tests/convert_string.c            |  52 ++++
 source3/registry/tests/test_regfio.c               |   1 +
 source4/dsdb/samdb/ldb_modules/repl_meta_data.c    |  38 ++-
 source4/ldap_server/ldap_server.c                  |  26 +-
 source4/ldap_server/ldap_server.h                  |   2 +
 source4/torture/ldb/ldb.c                          | 143 ++++++---
 17 files changed, 517 insertions(+), 534 deletions(-)
 copy lib/ldb/ABI/{ldb-1.5.1.sigs => ldb-2.0.1.sigs} (98%)
 copy lib/ldb/ABI/{pyldb-util-1.1.10.sigs => pyldb-util-2.0.1.sigs} (100%)


Changeset truncated at 500 lines:

diff --git a/lib/ldb/ABI/ldb-1.5.1.sigs b/lib/ldb/ABI/ldb-2.0.1.sigs
similarity index 98%
copy from lib/ldb/ABI/ldb-1.5.1.sigs
copy to lib/ldb/ABI/ldb-2.0.1.sigs
index 0c1234f1c97..f782d73afb1 100644
--- a/lib/ldb/ABI/ldb-1.5.1.sigs
+++ b/lib/ldb/ABI/ldb-2.0.1.sigs
@@ -85,6 +85,7 @@ ldb_error_at: int (struct ldb_context *, int, const char *, const char *, int)
 ldb_errstring: const char *(struct ldb_context *)
 ldb_extended: int (struct ldb_context *, const char *, void *, struct ldb_result **)
 ldb_extended_default_callback: int (struct ldb_request *, struct ldb_reply *)
+ldb_filter_attrs: int (struct ldb_context *, const struct ldb_message *, const char * const *, struct ldb_message *)
 ldb_filter_from_tree: char *(TALLOC_CTX *, const struct ldb_parse_tree *)
 ldb_get_config_basedn: struct ldb_dn *(struct ldb_context *)
 ldb_get_create_perms: unsigned int (struct ldb_context *)
@@ -267,8 +268,7 @@ ldb_transaction_commit: int (struct ldb_context *)
 ldb_transaction_prepare_commit: int (struct ldb_context *)
 ldb_transaction_start: int (struct ldb_context *)
 ldb_unpack_data: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *)
-ldb_unpack_data_only_attr_list: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, const char * const *, unsigned int, unsigned int *)
-ldb_unpack_data_only_attr_list_flags: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, const char * const *, unsigned int, unsigned int, unsigned int *)
+ldb_unpack_data_flags: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, unsigned int)
 ldb_val_dup: struct ldb_val (TALLOC_CTX *, const struct ldb_val *)
 ldb_val_equal_exact: int (const struct ldb_val *, const struct ldb_val *)
 ldb_val_map_local: struct ldb_val (struct ldb_module *, void *, const struct ldb_map_attribute *, const struct ldb_val *)
diff --git a/lib/ldb/ABI/pyldb-util-1.1.10.sigs b/lib/ldb/ABI/pyldb-util-2.0.1.sigs
similarity index 100%
copy from lib/ldb/ABI/pyldb-util-1.1.10.sigs
copy to lib/ldb/ABI/pyldb-util-2.0.1.sigs
diff --git a/lib/ldb/common/ldb_pack.c b/lib/ldb/common/ldb_pack.c
index 448c577ae1b..5360a36cccc 100644
--- a/lib/ldb/common/ldb_pack.c
+++ b/lib/ldb/common/ldb_pack.c
@@ -180,50 +180,16 @@ int ldb_pack_data(struct ldb_context *ldb,
 	return 0;
 }
 
-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 j, len;
-
-	p += 4;
-	if (remaining < 4) {
-		return false;
-	}
-	remaining -= 4;
-	for (j = 0; j < num_values; j++) {
-		len = pull_uint32(p, 0);
-		if (remaining < 5) {
-			return false;
-		}
-		remaining -= 5;
-		if (len > remaining) {
-			return false;
-		}
-		remaining -= len;
-		p += len + 4 + 1;
-	}
-
-	*premaining = remaining;
-	*pp = p;
-	return true;
-}
-
-
 /*
  * Unpack a ldb message from a linear buffer in ldb_val
  *
  * Providing a list of attributes to this function allows selective unpacking.
  * Giving a NULL list (or a list_size of 0) unpacks all the attributes.
  */
-int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb,
-					 const struct ldb_val *data,
-					 struct ldb_message *message,
-					 const char * const *list,
-					 unsigned int list_size,
-					 unsigned int flags,
-					 unsigned int *nb_elements_in_db)
+int ldb_unpack_data_flags(struct ldb_context *ldb,
+			  const struct ldb_val *data,
+			  struct ldb_message *message,
+			  unsigned int flags)
 {
 	uint8_t *p;
 	size_t remaining;
@@ -232,13 +198,8 @@ int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb,
 	unsigned format;
 	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;
-	}
-
 	message->elements = NULL;
 
 	p = data->data;
@@ -250,9 +211,6 @@ int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb,
 	format = pull_uint32(p, 0);
 	message->num_elements = pull_uint32(p, 4);
 	p += 8;
-	if (nb_elements_in_db) {
-		*nb_elements_in_db = message->num_elements;
-	}
 
 	remaining = data->length - 8;
 
@@ -326,10 +284,8 @@ int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb,
 	 * 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.
+	 * 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).
 	 */
@@ -366,55 +322,8 @@ int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb,
 		}
 		attr = (char *)p;
 
-		/*
-		 * The general idea is to reduce allocations by skipping over
-		 * attributes that we do not actually care about.
-		 *
-		 * This is a bit expensive but normally the list is pretty small
-		 * also the cost of freeing unused attributes is quite important
-		 * and can dwarf the cost of looping.
-		 */
-		if (list_size != 0) {
-			bool keep = false;
-			unsigned int h;
-
-			/*
-			 * We know that p has a \0 terminator before the
-			 * end of the buffer due to the check above.
-			 */
-			for (h = 0; h < list_size && found < list_size; h++) {
-				if (ldb_attr_cmp(attr, list[h]) == 0) {
-					keep = true;
-					found++;
-					break;
-				}
-			}
-
-			if (!keep) {
-				if (remaining < (attr_len + 1)) {
-					errno = EIO;
-					goto failed;
-				}
-				remaining -= attr_len + 1;
-				p += attr_len + 1;
-				if (!ldb_consume_element_data(&p, &remaining)) {
-					errno = EIO;
-					goto failed;
-				}
-				continue;
-			}
-		}
 		element = &message->elements[nelem];
-		if (flags & LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC) {
-			element->name = attr;
-		} else {
-			element->name = talloc_memdup(message->elements, attr, attr_len+1);
-
-			if (element->name == NULL) {
-				errno = ENOMEM;
-				goto failed;
-			}
-		}
+		element->name = attr;
 		element->flags = 0;
 
 		if (remaining < (attr_len + 1)) {
@@ -460,18 +369,7 @@ int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb,
 			}
 
 			element->values[j].length = len;
-			if (flags & LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC) {
-				element->values[j].data = p + 4;
-			} else {
-				element->values[j].data = talloc_size(element->values, len+1);
-				if (element->values[j].data == NULL) {
-					errno = ENOMEM;
-					goto failed;
-				}
-				memcpy(element->values[j].data, p + 4,
-				       len);
-				element->values[j].data[len] = 0;
-			}
+			element->values[j].data = p + 4;
 			remaining -= len;
 			p += len+4+1;
 		}
@@ -493,7 +391,7 @@ int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb,
 
 	if (remaining != 0) {
 		ldb_debug(ldb, LDB_DEBUG_ERROR,
-			  "Error: %zu bytes unread in ldb_unpack_data_only_attr_list",
+			  "Error: %zu bytes unread in ldb_unpack_data_flags",
 			  remaining);
 	}
 
@@ -507,30 +405,165 @@ failed:
 /*
  * Unpack a ldb message from a linear buffer in ldb_val
  *
- * Providing a list of attributes to this function allows selective unpacking.
- * Giving a NULL list (or a list_size of 0) unpacks all the attributes.
- *
  * Free with ldb_unpack_data_free()
  */
-int ldb_unpack_data_only_attr_list(struct ldb_context *ldb,
-				   const struct ldb_val *data,
-				   struct ldb_message *message,
-				   const char * const *list,
-				   unsigned int list_size,
-				   unsigned int *nb_elements_in_db)
-{
-	return ldb_unpack_data_only_attr_list_flags(ldb,
-						    data,
-						    message,
-						    list,
-						    list_size,
-						    0,
-						    nb_elements_in_db);
-}
-
 int ldb_unpack_data(struct ldb_context *ldb,
 		    const struct ldb_val *data,
 		    struct ldb_message *message)
 {
-	return ldb_unpack_data_only_attr_list(ldb, data, message, NULL, 0, NULL);
+	return ldb_unpack_data_flags(ldb, data, message, 0);
+}
+
+/*
+  add the special distinguishedName element
+*/
+static int msg_add_distinguished_name(struct ldb_message *msg)
+{
+	const char *dn_attr = "distinguishedName";
+	char *dn = NULL;
+
+	if (ldb_msg_find_element(msg, dn_attr)) {
+		/*
+		 * This should not happen, but this is
+		 * existing behaviour...
+		 */
+		return LDB_SUCCESS;
+	}
+
+	dn = ldb_dn_alloc_linearized(msg, msg->dn);
+	if (dn == NULL) {
+		return LDB_ERR_OPERATIONS_ERROR;
+	}
+
+	return ldb_msg_add_steal_string(msg, dn_attr, dn);
+}
+
+/*
+ * filter the specified list of attributes from msg,
+ * adding requested attributes, and perhaps all for *,
+ * but not the DN to filtered_msg.
+ */
+int ldb_filter_attrs(struct ldb_context *ldb,
+		     const struct ldb_message *msg,
+		     const char *const *attrs,
+		     struct ldb_message *filtered_msg)
+{
+	unsigned int i;
+	bool keep_all = false;
+	bool add_dn = false;
+	uint32_t num_elements;
+	uint32_t elements_size;
+
+	if (attrs) {
+		/* check for special attrs */
+		for (i = 0; attrs[i]; i++) {
+			int cmp = strcmp(attrs[i], "*");
+			if (cmp == 0) {
+				keep_all = true;
+				break;
+			}
+			cmp = ldb_attr_cmp(attrs[i], "distinguishedName");
+			if (cmp == 0) {
+				add_dn = true;
+			}
+		}
+	} else {
+		keep_all = true;
+	}
+
+	if (keep_all) {
+		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(filtered_msg) != 0) {
+			goto failed;
+		}
+		return 0;
+	} else if (i == 0) {
+		return 0;
+
+	/* Otherwise we are copying at most as many element as we have attributes */
+	} else {
+		elements_size = i;
+	}
+
+	filtered_msg->elements = talloc_array(filtered_msg,
+					      struct ldb_message_element,
+					      elements_size);
+	if (filtered_msg->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 = &filtered_msg->elements[num_elements];
+		unsigned int j;
+
+		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;
+			}
+		}
+		*el2 = *el;
+		el2->name = talloc_strdup(filtered_msg->elements,
+					  el->name);
+		if (el2->name == NULL) {
+			goto failed;
+		}
+		el2->values = talloc_array(filtered_msg->elements,
+					   struct ldb_val, el->num_values);
+		if (el2->values == NULL) {
+			goto failed;
+		}
+		for (j=0;j<el->num_values;j++) {
+			el2->values[j] = ldb_val_dup(el2->values, &el->values[j]);
+			if (el2->values[j].data == NULL && el->values[j].length != 0) {
+				goto failed;
+			}
+		}
+		num_elements++;
+
+		/* Pidginhole principle: we can't have more elements
+		 * than the number of attributes if they are unique in
+		 * the DB */
+		if (num_elements > elements_size) {
+			goto failed;
+		}
+	}
+
+	filtered_msg->num_elements = num_elements;
+
+	if (add_dn) {
+		if (msg_add_distinguished_name(filtered_msg) != 0) {
+			goto failed;
+		}
+	}
+
+	if (filtered_msg->num_elements > 0) {
+		filtered_msg->elements
+			= talloc_realloc(filtered_msg,
+					 filtered_msg->elements,
+					 struct ldb_message_element,
+					 filtered_msg->num_elements);
+		if (filtered_msg->elements == NULL) {
+			goto failed;
+		}
+	} else {
+		talloc_free(filtered_msg->elements);
+		filtered_msg->elements = NULL;
+	}
+
+	return 0;
+failed:
+	return -1;
 }
diff --git a/lib/ldb/include/ldb_module.h b/lib/ldb/include/ldb_module.h
index b45142abe5c..759a54a3169 100644
--- a/lib/ldb/include/ldb_module.h
+++ b/lib/ldb/include/ldb_module.h
@@ -512,51 +512,39 @@ int ldb_pack_data(struct ldb_context *ldb,
 		  struct ldb_val *data);
 /*
  * Unpack a ldb message from a linear buffer in ldb_val
- *
- * Providing a list of attributes to this function allows selective unpacking.
- * Giving a NULL list (or a list_size of 0) unpacks all the attributes.
  */
-int ldb_unpack_data_only_attr_list(struct ldb_context *ldb,
-				   const struct ldb_val *data,
-				   struct ldb_message *message,
-				   const char* const * list,
-				   unsigned int list_size,
-				   unsigned int *nb_attributes_indb);
 int ldb_unpack_data(struct ldb_context *ldb,
 		    const struct ldb_val *data,
 		    struct ldb_message *message);
+
+/*
+ * filter the specified list of attributes from msg,
+ * adding requested attributes, and perhaps all for *,
+ * but not the DN to filtered_msg.
+ */
+int ldb_filter_attrs(struct ldb_context *ldb,
+		     const struct ldb_message *msg,
+		     const char *const *attrs,
+		     struct ldb_message *filtered_msg);
 /*
  * Unpack a ldb message from a linear buffer in ldb_val
  *
- * Providing a list of attributes to this function allows selective unpacking.
- * 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 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.
  *
  * If LDB_UNPACK_DATA_FLAG_NO_ATTRS is specified, then no attributes
  * are unpacked or returned.
  *
  */
-int ldb_unpack_data_only_attr_list_flags(struct ldb_context *ldb,
-					 const struct ldb_val *data,
-					 struct ldb_message *message,
-					 const char * const *list,
-					 unsigned int list_size,
-					 unsigned int flags,
-					 unsigned int *nb_elements_in_db);
-
-#define LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC   0x0001
+int ldb_unpack_data_flags(struct ldb_context *ldb,
+			  const struct ldb_val *data,
+			  struct ldb_message *message,
+			  unsigned int flags);
+
+/* currently unused (was NO_DATA_ALLOC)      0x0001 */
 #define LDB_UNPACK_DATA_FLAG_NO_DN           0x0002
 #define LDB_UNPACK_DATA_FLAG_NO_VALUES_ALLOC 0x0004
 #define LDB_UNPACK_DATA_FLAG_NO_ATTRS        0x0008
diff --git a/lib/ldb/ldb_key_value/ldb_kv.c b/lib/ldb/ldb_key_value/ldb_kv.c
index c0846ba1b6a..53c326d36b2 100644
--- a/lib/ldb/ldb_key_value/ldb_kv.c
+++ b/lib/ldb/ldb_key_value/ldb_kv.c
@@ -644,8 +644,7 @@ static int ldb_kv_delete_internal(struct ldb_module *module, struct ldb_dn *dn)
 
 	/* in case any attribute of the message was indexed, we need
 	   to fetch the old record */
-	ret = ldb_kv_search_dn1(
-	    module, dn, msg, LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC);
+	ret = ldb_kv_search_dn1(module, dn, msg, 0);
 	if (ret != LDB_SUCCESS) {
 		/* not finding the old record is an error */
 		goto done;
@@ -902,8 +901,7 @@ int ldb_kv_modify_internal(struct ldb_module *module,
 		goto done;
 	}
 
-	ret = ldb_kv_search_dn1(
-	    module, msg->dn, msg2, LDB_UNPACK_DATA_FLAG_NO_DATA_ALLOC);
+	ret = ldb_kv_search_dn1(module, msg->dn, msg2, 0);
 	if (ret != LDB_SUCCESS) {
 		goto done;
 	}
@@ -1267,10 +1265,7 @@ static int ldb_kv_rename(struct ldb_kv_context *ctx)
 	}
 
 	/* we need to fetch the old record to re-add under the new name */
-	ret = ldb_kv_search_dn1(module,
-				req->op.rename.olddn,
-				msg,


-- 
Samba Shared Repository



More information about the samba-cvs mailing list