From: Andrew Bartlett Date: Tue, 3 Jul 2018 03:16:56 +0000 (+1200) Subject: ldb: Add new function ldb_dn_add_child_val() X-Git-Tag: ldb-1.5.1~2 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=2dafbd32136b7d4253bcadde4c038272350f7bb2;p=thirdparty%2Fsamba.git ldb: Add new function ldb_dn_add_child_val() 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 Reviewed-by: Douglas Bagnall --- diff --git a/lib/ldb/common/ldb_dn.c b/lib/ldb/common/ldb_dn.c index dfeb600f56f..3bd655adbd5 100644 --- a/lib/ldb/common/ldb_dn.c +++ b/lib/ldb/common/ldb_dn.c @@ -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; diff --git a/lib/ldb/include/ldb.h b/lib/ldb/include/ldb.h index 9918b4e69d9..81bee934da5 100644 --- a/lib/ldb/include/ldb.h +++ b/lib/ldb/include/ldb.h @@ -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 index 00000000000..4965dcef575 --- /dev/null +++ b/lib/ldb/tests/test_ldb_dn.c @@ -0,0 +1,117 @@ +/* + * Unix SMB/CIFS implementation. + * + * Copyright (C) 2018 Andreas Schneider + * + * 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 . + */ + +#include +#include +#include +#include + +#include + +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); +} diff --git a/lib/ldb/wscript b/lib/ldb/wscript index ac6aa8bef2b..d324f48516a 100644 --- a/lib/ldb/wscript +++ b/lib/ldb/wscript @@ -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',