2 Unit tests for the unique objectSID code in unique_object_sids.c
4 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2017
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
26 int ldb_unique_object_sids_init(const char *version);
27 #include "../unique_object_sids.c"
29 #include "../libcli/security/dom_sid.h"
30 #include "librpc/gen_ndr/ndr_security.h"
34 #define DOMAIN_SID "S-1-5-21-2470180966-3899876309-2637894779"
35 #define LOCAL_SID "S-1-5-21-2470180966-3899876309-2637894779-1000"
36 #define FOREIGN_SID "S-1-5-21-2470180966-3899876309-2637894778-1000"
38 static struct ldb_request *last_request;
41 * ldb_next_request mock, records the request passed in last_request
42 * so it can be examined in the test cases.
45 struct ldb_module *module,
46 struct ldb_request *request)
48 last_request = request;
49 return ldb_module_done(request, NULL, NULL, LDB_SUCCESS);
56 struct tevent_context *ev;
57 struct ldb_context *ldb;
58 struct ldb_module *module;
61 const char *lockfile; /* lockfile is separate */
64 struct dom_sid *domain_sid;
68 * Remove any database files created by the tests
70 static void unlink_old_db(struct ldbtest_ctx *test_ctx)
75 ret = unlink(test_ctx->lockfile);
76 if (ret == -1 && errno != ENOENT) {
81 ret = unlink(test_ctx->dbfile);
82 if (ret == -1 && errno != ENOENT) {
88 * Empty module to signal the end of the module list
90 static const struct ldb_module_ops eol_ops = {
103 static int setup(void **state)
105 struct ldbtest_ctx *test_ctx = NULL;
106 struct ldb_module *eol = NULL;
109 test_ctx = talloc_zero(NULL, struct ldbtest_ctx);
110 assert_non_null(test_ctx);
112 test_ctx->ev = tevent_context_init(test_ctx);
113 assert_non_null(test_ctx->ev);
115 test_ctx->ldb = ldb_init(test_ctx, test_ctx->ev);
116 assert_non_null(test_ctx->ldb);
118 test_ctx->domain_sid = talloc_zero(test_ctx, struct dom_sid);
119 assert_non_null(test_ctx->domain_sid);
120 assert_true(string_to_sid(test_ctx->domain_sid, DOMAIN_SID));
121 ldb_set_opaque(test_ctx->ldb, "cache.domain_sid", test_ctx->domain_sid);
123 test_ctx->module = ldb_module_new(
126 "unique_object_sids",
127 &ldb_unique_object_sids_module_ops);
128 assert_non_null(test_ctx->module);
129 eol = ldb_module_new(test_ctx, test_ctx->ldb, "eol", &eol_ops);
130 assert_non_null(eol);
131 ldb_module_set_next(test_ctx->module, eol);
133 test_ctx->dbfile = talloc_strdup(test_ctx, "duptest.ldb");
134 assert_non_null(test_ctx->dbfile);
136 test_ctx->lockfile = talloc_asprintf(test_ctx, "%s-lock",
138 assert_non_null(test_ctx->lockfile);
140 test_ctx->dbpath = talloc_asprintf(test_ctx,
141 TEST_BE"://%s", test_ctx->dbfile);
142 assert_non_null(test_ctx->dbpath);
144 unlink_old_db(test_ctx);
146 rc = ldb_connect(test_ctx->ldb, test_ctx->dbpath, 0, NULL);
147 assert_int_equal(rc, LDB_SUCCESS);
149 rc = unique_object_sids_init(test_ctx->module);
150 assert_int_equal(rc, LDB_SUCCESS);
161 static int teardown(void **state)
163 struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
166 unlink_old_db(test_ctx);
167 talloc_free(test_ctx);
172 * Add an objectSID in string form to the supplied message
177 struct ldb_message *msg,
181 enum ndr_err_code ndr_err;
182 struct dom_sid *sid = NULL;
184 sid = talloc_zero(msg, struct dom_sid);
185 assert_non_null(sid);
186 assert_true(string_to_sid(sid, sid_str));
187 ndr_err = ndr_push_struct_blob(&v, msg, sid,
188 (ndr_push_flags_fn_t)ndr_push_dom_sid);
189 assert_true(NDR_ERR_CODE_IS_SUCCESS(ndr_err));
190 assert_int_equal(0, ldb_msg_add_value(msg, "objectSID", &v, NULL));
194 * The object is in the current local domain so it should have
195 * DB_FLAG_INTERNAL_UNIQUE_VALUE set
197 static void test_objectSID_in_domain(void **state)
199 struct ldbtest_ctx *test_ctx =
200 talloc_get_type_abort(*state, struct ldbtest_ctx);
201 struct ldb_context *ldb = test_ctx->ldb;
202 struct ldb_message *msg = ldb_msg_new(test_ctx);
203 struct ldb_message_element *el = NULL;
204 struct ldb_request *request = NULL;
205 struct ldb_request *original_request = NULL;
208 msg->dn = ldb_dn_new(msg, ldb, "dc=test");
209 add_sid(msg, LOCAL_SID);
211 rc = ldb_build_add_req(
218 ldb_op_default_callback,
221 assert_int_equal(rc, LDB_SUCCESS);
222 assert_non_null(request);
223 original_request = request;
225 rc = unique_object_sids_add(test_ctx->module, request);
226 assert_int_equal(rc, LDB_SUCCESS);
229 * Check that a copy of the request was passed to the next module
230 * and not the original request
232 assert_ptr_not_equal(last_request, original_request);
235 * Check the flag was set on the request passed to the next
238 el = ldb_msg_find_element(last_request->op.add.message, "objectSID");
240 assert_true(el->flags & LDB_FLAG_INTERNAL_FORCE_UNIQUE_INDEX);
243 * Check the flag was not set on the original request
245 el = ldb_msg_find_element(request->op.add.message, "objectSID");
247 assert_false(el->flags & LDB_FLAG_INTERNAL_FORCE_UNIQUE_INDEX);
252 * The object is not in the current local domain so it should NOT have
253 * DB_FLAG_INTERNAL_UNIQUE_VALUE set
255 static void test_objectSID_not_in_domain(void **state)
257 struct ldbtest_ctx *test_ctx =
258 talloc_get_type_abort(*state, struct ldbtest_ctx);
259 struct ldb_context *ldb = test_ctx->ldb;
260 struct ldb_message *msg = ldb_msg_new(test_ctx);
261 struct ldb_message_element *el = NULL;
262 struct ldb_request *request = NULL;
263 struct ldb_request *original_request = NULL;
266 msg->dn = ldb_dn_new(msg, ldb, "dc=test");
267 add_sid(msg, FOREIGN_SID);
269 rc = ldb_build_add_req(
276 ldb_op_default_callback,
279 assert_int_equal(rc, LDB_SUCCESS);
280 assert_non_null(request);
281 original_request = request;
283 rc = unique_object_sids_add(test_ctx->module, request);
284 assert_int_equal(rc, LDB_SUCCESS);
287 * Check that the original request was passed to the next module
290 assert_ptr_equal(last_request, original_request);
293 * Check that the flag was not set on the objectSID element
295 el = ldb_msg_find_element(msg, "objectSID");
297 assert_false(el->flags & LDB_FLAG_INTERNAL_FORCE_UNIQUE_INDEX);
301 * No objectSID on the record so it should pass through the module untouched
304 static void test_no_objectSID(void **state)
306 struct ldbtest_ctx *test_ctx =
307 talloc_get_type_abort(*state, struct ldbtest_ctx);
308 struct ldb_context *ldb = test_ctx->ldb;
309 struct ldb_message *msg = ldb_msg_new(test_ctx);
310 struct ldb_request *request = NULL;
311 struct ldb_request *original_request = NULL;
314 msg->dn = ldb_dn_new(msg, ldb, "dc=test");
315 assert_int_equal(LDB_SUCCESS, ldb_msg_add_string(msg, "cn", "test"));
317 rc = ldb_build_add_req(
324 ldb_op_default_callback,
327 assert_int_equal(rc, LDB_SUCCESS);
328 assert_non_null(request);
329 original_request = request;
331 rc = unique_object_sids_add(test_ctx->module, request);
332 assert_int_equal(rc, LDB_SUCCESS);
335 * Check that the original request was passed to the next module
338 assert_ptr_equal(last_request, original_request);
343 * Attempt to modify an objectSID DSDB_CONTROL_REPLICATED_UPDATE_OID not set
344 * this should fail with LDB_ERR_UNWILLING_TO_PERFORM
346 static void test_modify_of_objectSID_not_replicated(void **state)
348 struct ldbtest_ctx *test_ctx =
349 talloc_get_type_abort(*state, struct ldbtest_ctx);
350 struct ldb_context *ldb = test_ctx->ldb;
351 struct ldb_message *msg = ldb_msg_new(test_ctx);
352 struct ldb_request *request = NULL;
355 msg->dn = ldb_dn_new(msg, ldb, "dc=test");
356 add_sid(msg, LOCAL_SID);
358 rc = ldb_build_mod_req(
365 ldb_op_default_callback,
368 assert_int_equal(rc, LDB_SUCCESS);
369 assert_non_null(request);
371 rc = unique_object_sids_modify(test_ctx->module, request);
373 assert_int_equal(rc, LDB_ERR_UNWILLING_TO_PERFORM);
378 * Attempt to modify an objectSID DSDB_CONTROL_REPLICATED_UPDATE_OID set
379 * this should succeed
381 static void test_modify_of_objectSID_replicated(void **state)
383 struct ldbtest_ctx *test_ctx =
384 talloc_get_type_abort(*state, struct ldbtest_ctx);
385 struct ldb_context *ldb = test_ctx->ldb;
386 struct ldb_message *msg = ldb_msg_new(test_ctx);
387 struct ldb_message_element *el = NULL;
388 struct ldb_request *request = NULL;
389 struct ldb_request *original_request = NULL;
392 msg->dn = ldb_dn_new(msg, ldb, "dc=test");
393 add_sid(msg, LOCAL_SID);
395 rc = ldb_build_mod_req(
402 ldb_op_default_callback,
404 assert_int_equal(rc, LDB_SUCCESS);
405 assert_non_null(request);
406 original_request = request;
408 ldb_request_add_control(
410 DSDB_CONTROL_REPLICATED_UPDATE_OID,
414 rc = unique_object_sids_modify(test_ctx->module, request);
416 assert_int_equal(rc, LDB_SUCCESS);
419 * Check that a copy of the request was passed to the next module
420 * and not the original request
422 assert_ptr_not_equal(last_request, original_request);
425 * Check the flag was set on the request passed to the next
428 el = ldb_msg_find_element(last_request->op.add.message, "objectSID");
430 assert_true(el->flags & LDB_FLAG_INTERNAL_FORCE_UNIQUE_INDEX);
433 * Check the flag was not set on the original request
435 el = ldb_msg_find_element(request->op.add.message, "objectSID");
437 assert_false(el->flags & LDB_FLAG_INTERNAL_FORCE_UNIQUE_INDEX);
442 * Test the a modify with no object SID is passed through correctly
445 static void test_modify_no_objectSID(void **state)
447 struct ldbtest_ctx *test_ctx =
448 talloc_get_type_abort(*state, struct ldbtest_ctx);
449 struct ldb_context *ldb = test_ctx->ldb;
450 struct ldb_message *msg = ldb_msg_new(test_ctx);
451 struct ldb_request *request = NULL;
452 struct ldb_request *original_request = NULL;
455 msg->dn = ldb_dn_new(msg, ldb, "dc=test");
456 assert_int_equal(LDB_SUCCESS, ldb_msg_add_string(msg, "cn", "test"));
458 rc = ldb_build_mod_req(
465 ldb_op_default_callback,
468 assert_int_equal(rc, LDB_SUCCESS);
469 assert_non_null(request);
470 original_request = request;
472 rc = unique_object_sids_modify(test_ctx->module, request);
473 assert_int_equal(rc, LDB_SUCCESS);
476 * Check that the original request was passed to the next module
479 assert_ptr_equal(last_request, original_request);
484 const struct CMUnitTest tests[] = {
485 cmocka_unit_test_setup_teardown(
486 test_objectSID_in_domain,
489 cmocka_unit_test_setup_teardown(
490 test_objectSID_not_in_domain,
493 cmocka_unit_test_setup_teardown(
497 cmocka_unit_test_setup_teardown(
498 test_modify_no_objectSID,
501 cmocka_unit_test_setup_teardown(
502 test_modify_of_objectSID_not_replicated,
505 cmocka_unit_test_setup_teardown(
506 test_modify_of_objectSID_replicated,
511 cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
512 return cmocka_run_group_tests(tests, NULL, NULL);