ldb: Add new function ldb_dn_add_child_val()
authorAndrew Bartlett <abartlet@samba.org>
Tue, 3 Jul 2018 03:16:56 +0000 (15:16 +1200)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 15 Aug 2018 05:08:24 +0000 (07:08 +0200)
This is safer for untrusted input than ldb_dn_add_child_fmt()

BUG: https://bugzilla.samba.org/show_bug.cgi?id=13466

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Reviewed-by: Douglas Bagnall <douglas.bagnall@catalyst.net.nz>
lib/ldb/common/ldb_dn.c
lib/ldb/include/ldb.h
lib/ldb/tests/test_ldb_dn.c [new file with mode: 0644]
lib/ldb/wscript

index dfeb600f56fe34622322c82119954c3bc85e3eef..3bd655adbd5154754ab5c1e5cbaa214acb53df7c 100644 (file)
@@ -1605,6 +1605,41 @@ bool ldb_dn_add_child_fmt(struct ldb_dn *dn, const char *child_fmt, ...)
        return ret;
 }
 
+/* modify the given dn by adding a single child element.
+ *
+ * return true if successful and false if not
+ * if false is returned the dn may be marked invalid
+ */
+bool ldb_dn_add_child_val(struct ldb_dn *dn,
+                         const char *rdn,
+                         struct ldb_val value)
+{
+       bool ret;
+       int ldb_ret;
+       struct ldb_dn *child = NULL;
+
+       if ( !dn || dn->invalid) {
+               return false;
+       }
+
+       child = ldb_dn_new(dn, dn->ldb, "X=Y");
+       ret = ldb_dn_add_child(dn, child);
+
+       if (ret == false) {
+               return false;
+       }
+
+       ldb_ret = ldb_dn_set_component(dn,
+                                      0,
+                                      rdn,
+                                      value);
+       if (ldb_ret != LDB_SUCCESS) {
+               return false;
+       }
+
+       return true;
+}
+
 bool ldb_dn_remove_base_components(struct ldb_dn *dn, unsigned int num)
 {
        unsigned int i;
index 9918b4e69d9820e2471ceccd424076de052ccbe7..81bee934da587bf6a02689cfbffa868f747478b4 100644 (file)
@@ -1882,6 +1882,9 @@ bool ldb_dn_add_child(struct ldb_dn *dn, struct ldb_dn *child);
 bool ldb_dn_add_child_fmt(struct ldb_dn *dn, const char *child_fmt, ...) PRINTF_ATTRIBUTE(2,3);
 bool ldb_dn_remove_base_components(struct ldb_dn *dn, unsigned int num);
 bool ldb_dn_remove_child_components(struct ldb_dn *dn, unsigned int num);
+bool ldb_dn_add_child_val(struct ldb_dn *dn,
+                         const char *rdn,
+                         struct ldb_val value);
 
 struct ldb_dn *ldb_dn_copy(TALLOC_CTX *mem_ctx, struct ldb_dn *dn);
 struct ldb_dn *ldb_dn_get_parent(TALLOC_CTX *mem_ctx, struct ldb_dn *dn);
diff --git a/lib/ldb/tests/test_ldb_dn.c b/lib/ldb/tests/test_ldb_dn.c
new file mode 100644 (file)
index 0000000..4965dce
--- /dev/null
@@ -0,0 +1,117 @@
+/*
+ * Unix SMB/CIFS implementation.
+ *
+ * Copyright (C) 2018      Andreas Schneider <asn@samba.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include <ldb.h>
+
+static void test_ldb_dn_add_child_fmt(void **state)
+{
+       struct ldb_context *ldb = ldb_init(NULL, NULL);
+
+       struct ldb_dn *dn = ldb_dn_new(ldb, ldb, "dc=samba,dc=org");
+
+       assert_true(ldb_dn_add_child_fmt(dn,
+                                        "DC=X"));
+
+       assert_string_equal("DC=X,dc=samba,dc=org",
+                           ldb_dn_get_linearized(dn));
+
+       assert_string_equal("DC=X,DC=SAMBA,DC=ORG",
+                           ldb_dn_get_casefold(dn));
+
+}
+
+static void test_ldb_dn_add_child_fmt2(void **state)
+{
+       struct ldb_context *ldb = ldb_init(NULL, NULL);
+
+       struct ldb_dn *dn = ldb_dn_new(ldb, ldb, "dc=samba,dc=org");
+
+       assert_true(ldb_dn_add_child_fmt(dn,
+                                        "DC=X,DC=Y"));
+
+       assert_string_equal("DC=X,DC=Y,dc=samba,dc=org",
+                           ldb_dn_get_linearized(dn));
+
+       assert_string_equal("DC=X,DC=Y,DC=SAMBA,DC=ORG",
+                           ldb_dn_get_casefold(dn));
+
+       assert_int_equal(4,
+                        ldb_dn_get_comp_num(dn));
+
+}
+
+static void test_ldb_dn_add_child_val(void **state)
+{
+       struct ldb_context *ldb = ldb_init(NULL, NULL);
+
+       struct ldb_dn *dn = ldb_dn_new(ldb, ldb, "dc=samba,dc=org");
+       struct ldb_val name = {.data = discard_const("X"),
+                              .length = 1
+       };
+
+       assert_true(ldb_dn_add_child_val(dn,
+                                        "DC", name));
+
+       assert_string_equal("DC=X,dc=samba,dc=org",
+                           ldb_dn_get_linearized(dn));
+
+       assert_string_equal("DC=X,DC=SAMBA,DC=ORG",
+                           ldb_dn_get_casefold(dn));
+
+}
+
+static void test_ldb_dn_add_child_val2(void **state)
+{
+       struct ldb_context *ldb = ldb_init(NULL, NULL);
+
+       struct ldb_dn *dn = ldb_dn_new(ldb, ldb, "dc=samba,dc=org");
+
+       struct ldb_val name = {.data = discard_const("X,DC=Y"),
+                              .length = 6
+       };
+
+       assert_true(ldb_dn_add_child_val(dn,
+                                        "DC", name));
+
+       assert_string_equal("DC=X\\,DC\\3DY,dc=samba,dc=org",
+                           ldb_dn_get_linearized(dn));
+
+       assert_string_equal("DC=X\\,DC\\3DY,DC=SAMBA,DC=ORG",
+                           ldb_dn_get_casefold(dn));
+
+       assert_int_equal(3,
+                        ldb_dn_get_comp_num(dn));
+
+}
+
+int main(void) {
+       const struct CMUnitTest tests[] = {
+               cmocka_unit_test(test_ldb_dn_add_child_fmt),
+               cmocka_unit_test(test_ldb_dn_add_child_fmt2),
+               cmocka_unit_test(test_ldb_dn_add_child_val),
+               cmocka_unit_test(test_ldb_dn_add_child_val2),
+       };
+
+       return cmocka_run_group_tests(tests, NULL, NULL);
+}
index ac6aa8bef2bac34620bf593a4d23e8823d95f7a9..d324f48516a3f75f95ddc7192b41d04d31a93527 100644 (file)
@@ -512,6 +512,11 @@ def build(bld):
                          deps='cmocka ldb',
                          install=False)
 
+        bld.SAMBA_BINARY('test_ldb_dn',
+                         source='tests/test_ldb_dn.c',
+                         deps='cmocka ldb',
+                         install=False)
+
         if bld.CONFIG_SET('HAVE_LMDB'):
             bld.SAMBA_BINARY('ldb_mdb_mod_op_test',
                              source='tests/ldb_mod_op_test.c',
@@ -568,6 +573,7 @@ def test(ctx):
 
     cmocka_ret = 0
     test_exes = ['test_ldb_qsort',
+                 'test_ldb_dn',
                  'ldb_msg_test',
                  'ldb_tdb_mod_op_test',
                  'ldb_tdb_guid_mod_op_test',