LCOV - code coverage report
Current view: top level - source4/dsdb/samdb/ldb_modules/tests - test_unique_object_sids.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 190 192 99.0 %
Date: 2024-04-21 15:09:00 Functions: 12 12 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unit tests for the unique objectSID code in unique_object_sids.c
       3             : 
       4             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2017
       5             : 
       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.
      10             : 
      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.
      15             : 
      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/>.
      18             : */
      19             : 
      20             : #include <stdarg.h>
      21             : #include <stddef.h>
      22             : #include <setjmp.h>
      23             : #include <unistd.h>
      24             : #include <cmocka.h>
      25             : 
      26             : int ldb_unique_object_sids_init(const char *version);
      27             : #include "../unique_object_sids.c"
      28             : 
      29             : #include "../libcli/security/dom_sid.h"
      30             : #include "librpc/gen_ndr/ndr_security.h"
      31             : 
      32             : #define TEST_BE "tdb"
      33             : 
      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"
      37             : 
      38             : static struct ldb_request *last_request;
      39             : 
      40             : /*
      41             :  * ldb_next_request mock, records the request passed in last_request
      42             :  * so it can be examined in the test cases.
      43             :  */
      44          17 : int ldb_next_request(
      45             :         struct ldb_module *module,
      46             :         struct ldb_request *request)
      47             : {
      48          17 :         last_request = request;
      49          17 :         return ldb_module_done(request, NULL, NULL, LDB_SUCCESS);
      50             : }
      51             : 
      52             : /*
      53             :  * Test context
      54             :  */
      55             : struct ldbtest_ctx {
      56             :         struct tevent_context *ev;
      57             :         struct ldb_context *ldb;
      58             :         struct ldb_module *module;
      59             : 
      60             :         const char *dbfile;
      61             :         const char *lockfile;   /* lockfile is separate */
      62             : 
      63             :         const char *dbpath;
      64             :         struct dom_sid *domain_sid;
      65             : };
      66             : 
      67             : /*
      68             :  * Remove any database files created by the tests
      69             :  */
      70          12 : static void unlink_old_db(struct ldbtest_ctx *test_ctx)
      71             : {
      72          12 :         int ret;
      73             : 
      74          12 :         errno = 0;
      75          12 :         ret = unlink(test_ctx->lockfile);
      76          12 :         if (ret == -1 && errno != ENOENT) {
      77           0 :                 fail();
      78             :         }
      79             : 
      80          12 :         errno = 0;
      81          12 :         ret = unlink(test_ctx->dbfile);
      82          12 :         if (ret == -1 && errno != ENOENT) {
      83           0 :                 fail();
      84             :         }
      85          12 : }
      86             : 
      87             : /*
      88             :  * Empty module to signal the end of the module list
      89             :  */
      90             : static const struct ldb_module_ops eol_ops = {
      91             :         .name              = "eol",
      92             :         .search            = NULL,
      93             :         .add               = NULL,
      94             :         .modify            = NULL,
      95             :         .del               = NULL,
      96             :         .rename            = NULL,
      97             :         .init_context      = NULL
      98             : };
      99             : 
     100             : /*
     101             :  * Test set up
     102             :  */
     103           6 : static int setup(void **state)
     104             : {
     105           6 :         struct ldbtest_ctx *test_ctx    = NULL;
     106           6 :         struct ldb_module *eol          = NULL;
     107           6 :         int rc;
     108             : 
     109           6 :         test_ctx = talloc_zero(NULL, struct ldbtest_ctx);
     110           6 :         assert_non_null(test_ctx);
     111             : 
     112           6 :         test_ctx->ev = tevent_context_init(test_ctx);
     113           6 :         assert_non_null(test_ctx->ev);
     114             : 
     115           6 :         test_ctx->ldb = ldb_init(test_ctx, test_ctx->ev);
     116           6 :         assert_non_null(test_ctx->ldb);
     117             : 
     118           6 :         test_ctx->domain_sid = talloc_zero(test_ctx, struct dom_sid);
     119           6 :         assert_non_null(test_ctx->domain_sid);
     120           6 :         assert_true(string_to_sid(test_ctx->domain_sid, DOMAIN_SID));
     121           6 :         ldb_set_opaque(test_ctx->ldb, "cache.domain_sid", test_ctx->domain_sid);
     122             : 
     123           6 :         test_ctx->module = ldb_module_new(
     124             :                 test_ctx,
     125             :                 test_ctx->ldb,
     126             :                 "unique_object_sids",
     127             :                 &ldb_unique_object_sids_module_ops);
     128           6 :         assert_non_null(test_ctx->module);
     129           6 :         eol = ldb_module_new(test_ctx, test_ctx->ldb, "eol", &eol_ops);
     130           6 :         assert_non_null(eol);
     131           6 :         ldb_module_set_next(test_ctx->module, eol);
     132             : 
     133           6 :         test_ctx->dbfile = talloc_strdup(test_ctx, "duptest.ldb");
     134           6 :         assert_non_null(test_ctx->dbfile);
     135             : 
     136           6 :         test_ctx->lockfile = talloc_asprintf(test_ctx, "%s-lock",
     137             :                                              test_ctx->dbfile);
     138           6 :         assert_non_null(test_ctx->lockfile);
     139             : 
     140           6 :         test_ctx->dbpath = talloc_asprintf(test_ctx,
     141             :                         TEST_BE"://%s", test_ctx->dbfile);
     142           6 :         assert_non_null(test_ctx->dbpath);
     143             : 
     144           6 :         unlink_old_db(test_ctx);
     145             : 
     146           6 :         rc = ldb_connect(test_ctx->ldb, test_ctx->dbpath, 0, NULL);
     147           6 :         assert_int_equal(rc, LDB_SUCCESS);
     148             : 
     149           6 :         rc = unique_object_sids_init(test_ctx->module);
     150           6 :         assert_int_equal(rc, LDB_SUCCESS);
     151             : 
     152           6 :         *state = test_ctx;
     153             : 
     154           6 :         last_request = NULL;
     155           6 :         return 0;
     156             : }
     157             : 
     158             : /*
     159             :  * Test clean up
     160             :  */
     161           6 : static int teardown(void **state)
     162             : {
     163           6 :         struct ldbtest_ctx *test_ctx = talloc_get_type_abort(*state,
     164             :                                                         struct ldbtest_ctx);
     165             : 
     166           6 :         unlink_old_db(test_ctx);
     167           6 :         talloc_free(test_ctx);
     168           6 :         return 0;
     169             : }
     170             : 
     171             : /*
     172             :  * Add an objectSID in string form to the supplied message
     173             :  *
     174             :  *
     175             :  */
     176           4 : static void add_sid(
     177             :         struct ldb_message *msg,
     178             :         const char *sid_str)
     179             : {
     180           4 :         struct ldb_val v;
     181           4 :         enum ndr_err_code ndr_err;
     182           4 :         struct dom_sid *sid = NULL;
     183             : 
     184           4 :         sid = talloc_zero(msg, struct dom_sid);
     185           4 :         assert_non_null(sid);
     186           4 :         assert_true(string_to_sid(sid, sid_str));
     187           4 :         ndr_err = ndr_push_struct_blob(&v, msg, sid,
     188             :                                        (ndr_push_flags_fn_t)ndr_push_dom_sid);
     189           4 :         assert_true(NDR_ERR_CODE_IS_SUCCESS(ndr_err));
     190           4 :         assert_int_equal(0, ldb_msg_add_value(msg, "objectSID", &v, NULL));
     191           4 : }
     192             : 
     193             : /*
     194             :  * The object is in the current local domain so it should have
     195             :  * DB_FLAG_INTERNAL_UNIQUE_VALUE set
     196             :  */
     197           1 : static void test_objectSID_in_domain(void **state)
     198             : {
     199           1 :         struct ldbtest_ctx *test_ctx =
     200           1 :                 talloc_get_type_abort(*state, struct ldbtest_ctx);
     201           1 :         struct ldb_context *ldb                 = test_ctx->ldb;
     202           1 :         struct ldb_message *msg                 = ldb_msg_new(test_ctx);
     203           1 :         struct ldb_message_element *el          = NULL;
     204           1 :         struct ldb_request *request             = NULL;
     205           1 :         struct ldb_request *original_request    = NULL;
     206           1 :         int rc;
     207             : 
     208           1 :         msg->dn = ldb_dn_new(msg, ldb, "dc=test");
     209           1 :         add_sid(msg, LOCAL_SID);
     210             : 
     211           1 :         rc = ldb_build_add_req(
     212             :                 &request,
     213             :                 test_ctx->ldb,
     214             :                 test_ctx,
     215             :                 msg,
     216             :                 NULL,
     217             :                 NULL,
     218             :                 ldb_op_default_callback,
     219             :                 NULL);
     220             : 
     221           1 :         assert_int_equal(rc, LDB_SUCCESS);
     222           1 :         assert_non_null(request);
     223           1 :         original_request = request;
     224             : 
     225           1 :         rc = unique_object_sids_add(test_ctx->module, request);
     226           1 :         assert_int_equal(rc, LDB_SUCCESS);
     227             : 
     228             :         /*
     229             :          * Check that a copy of the request was passed to the next module
     230             :          * and not the original request
     231             :          */
     232           1 :         assert_ptr_not_equal(last_request, original_request);
     233             : 
     234             :         /*
     235             :          * Check the flag was set on the request passed to the next
     236             :          * module
     237             :          */
     238           1 :         el = ldb_msg_find_element(last_request->op.add.message, "objectSID");
     239           1 :         assert_non_null(el);
     240           1 :         assert_true(el->flags & LDB_FLAG_INTERNAL_FORCE_UNIQUE_INDEX);
     241             : 
     242             :         /*
     243             :          * Check the flag was not  set on the original request
     244             :          */
     245           1 :         el = ldb_msg_find_element(request->op.add.message, "objectSID");
     246           1 :         assert_non_null(el);
     247           1 :         assert_false(el->flags & LDB_FLAG_INTERNAL_FORCE_UNIQUE_INDEX);
     248             : 
     249           1 : }
     250             : 
     251             : /*
     252             :  * The object is not in the current local domain so it should NOT have
     253             :  * DB_FLAG_INTERNAL_UNIQUE_VALUE set
     254             :  */
     255           1 : static void test_objectSID_not_in_domain(void **state)
     256             : {
     257           1 :         struct ldbtest_ctx *test_ctx =
     258           1 :                 talloc_get_type_abort(*state, struct ldbtest_ctx);
     259           1 :         struct ldb_context *ldb                 = test_ctx->ldb;
     260           1 :         struct ldb_message *msg                 = ldb_msg_new(test_ctx);
     261           1 :         struct ldb_message_element *el          = NULL;
     262           1 :         struct ldb_request *request             = NULL;
     263           1 :         struct ldb_request *original_request    = NULL;
     264           1 :         int rc;
     265             : 
     266           1 :         msg->dn = ldb_dn_new(msg, ldb, "dc=test");
     267           1 :         add_sid(msg, FOREIGN_SID);
     268             : 
     269           1 :         rc = ldb_build_add_req(
     270             :                 &request,
     271             :                 test_ctx->ldb,
     272             :                 test_ctx,
     273             :                 msg,
     274             :                 NULL,
     275             :                 NULL,
     276             :                 ldb_op_default_callback,
     277             :                 NULL);
     278             : 
     279           1 :         assert_int_equal(rc, LDB_SUCCESS);
     280           1 :         assert_non_null(request);
     281           1 :         original_request = request;
     282             : 
     283           1 :         rc = unique_object_sids_add(test_ctx->module, request);
     284           1 :         assert_int_equal(rc, LDB_SUCCESS);
     285             : 
     286             :         /*
     287             :          * Check that the original request was passed to the next module
     288             :          * and not a copy
     289             :          */
     290           1 :         assert_ptr_equal(last_request, original_request);
     291             : 
     292             :         /*
     293             :          * Check that the flag was not set on the objectSID element
     294             :          */
     295           1 :         el = ldb_msg_find_element(msg, "objectSID");
     296           1 :         assert_non_null(el);
     297           1 :         assert_false(el->flags & LDB_FLAG_INTERNAL_FORCE_UNIQUE_INDEX);
     298           1 : }
     299             : 
     300             : /*
     301             :  * No objectSID on the record so it should pass through the module untouched
     302             :  *
     303             :  */
     304           1 : static void test_no_objectSID(void **state)
     305             : {
     306           1 :         struct ldbtest_ctx *test_ctx =
     307           1 :                 talloc_get_type_abort(*state, struct ldbtest_ctx);
     308           1 :         struct ldb_context *ldb                 = test_ctx->ldb;
     309           1 :         struct ldb_message *msg                 = ldb_msg_new(test_ctx);
     310           1 :         struct ldb_request *request             = NULL;
     311           1 :         struct ldb_request *original_request    = NULL;
     312           1 :         int rc;
     313             : 
     314           1 :         msg->dn = ldb_dn_new(msg, ldb, "dc=test");
     315           1 :         assert_int_equal(LDB_SUCCESS, ldb_msg_add_string(msg, "cn", "test"));
     316             : 
     317           1 :         rc = ldb_build_add_req(
     318             :                 &request,
     319             :                 test_ctx->ldb,
     320             :                 test_ctx,
     321             :                 msg,
     322             :                 NULL,
     323             :                 NULL,
     324             :                 ldb_op_default_callback,
     325             :                 NULL);
     326             : 
     327           1 :         assert_int_equal(rc, LDB_SUCCESS);
     328           1 :         assert_non_null(request);
     329           1 :         original_request = request;
     330             : 
     331           1 :         rc = unique_object_sids_add(test_ctx->module, request);
     332           1 :         assert_int_equal(rc, LDB_SUCCESS);
     333             : 
     334             :         /*
     335             :          * Check that the original request was passed to the next module
     336             :          * and not a copy
     337             :          */
     338           1 :         assert_ptr_equal(last_request, original_request);
     339             : 
     340           1 : }
     341             : 
     342             : /*
     343             :  * Attempt to modify an objectSID DSDB_CONTROL_REPLICATED_UPDATE_OID not set
     344             :  * this should fail with LDB_ERR_UNWILLING_TO_PERFORM
     345             :  */
     346           1 : static void test_modify_of_objectSID_not_replicated(void **state)
     347             : {
     348           1 :         struct ldbtest_ctx *test_ctx =
     349           1 :                 talloc_get_type_abort(*state, struct ldbtest_ctx);
     350           1 :         struct ldb_context *ldb                 = test_ctx->ldb;
     351           1 :         struct ldb_message *msg                 = ldb_msg_new(test_ctx);
     352           1 :         struct ldb_request *request             = NULL;
     353           1 :         int rc;
     354             : 
     355           1 :         msg->dn = ldb_dn_new(msg, ldb, "dc=test");
     356           1 :         add_sid(msg, LOCAL_SID);
     357             : 
     358           1 :         rc = ldb_build_mod_req(
     359             :                 &request,
     360             :                 test_ctx->ldb,
     361             :                 test_ctx,
     362             :                 msg,
     363             :                 NULL,
     364             :                 NULL,
     365             :                 ldb_op_default_callback,
     366             :                 NULL);
     367             : 
     368           1 :         assert_int_equal(rc, LDB_SUCCESS);
     369           1 :         assert_non_null(request);
     370             : 
     371           1 :         rc = unique_object_sids_modify(test_ctx->module, request);
     372             : 
     373           1 :         assert_int_equal(rc, LDB_ERR_UNWILLING_TO_PERFORM);
     374           1 : }
     375             : 
     376             : 
     377             : /*
     378             :  * Attempt to modify an objectSID DSDB_CONTROL_REPLICATED_UPDATE_OID set
     379             :  * this should succeed
     380             :  */
     381           1 : static void test_modify_of_objectSID_replicated(void **state)
     382             : {
     383           1 :         struct ldbtest_ctx *test_ctx =
     384           1 :                 talloc_get_type_abort(*state, struct ldbtest_ctx);
     385           1 :         struct ldb_context *ldb                 = test_ctx->ldb;
     386           1 :         struct ldb_message *msg                 = ldb_msg_new(test_ctx);
     387           1 :         struct ldb_message_element *el          = NULL;
     388           1 :         struct ldb_request *request             = NULL;
     389           1 :         struct ldb_request *original_request    = NULL;
     390           1 :         int rc;
     391             : 
     392           1 :         msg->dn = ldb_dn_new(msg, ldb, "dc=test");
     393           1 :         add_sid(msg, LOCAL_SID);
     394             : 
     395           1 :         rc = ldb_build_mod_req(
     396             :                 &request,
     397             :                 test_ctx->ldb,
     398             :                 test_ctx,
     399             :                 msg,
     400             :                 NULL,
     401             :                 NULL,
     402             :                 ldb_op_default_callback,
     403             :                 NULL);
     404           1 :         assert_int_equal(rc, LDB_SUCCESS);
     405           1 :         assert_non_null(request);
     406           1 :         original_request = request;
     407             : 
     408           1 :         rc = ldb_request_add_control(
     409             :                 request,
     410             :                 DSDB_CONTROL_REPLICATED_UPDATE_OID,
     411             :                 false,
     412             :                 NULL);
     413           1 :         assert_int_equal(rc, LDB_SUCCESS);
     414             : 
     415           1 :         rc = unique_object_sids_modify(test_ctx->module, request);
     416             : 
     417           1 :         assert_int_equal(rc, LDB_SUCCESS);
     418             : 
     419             :         /*
     420             :          * Check that a copy of the request was passed to the next module
     421             :          * and not the original request
     422             :          */
     423           1 :         assert_ptr_not_equal(last_request, original_request);
     424             : 
     425             :         /*
     426             :          * Check the flag was set on the request passed to the next
     427             :          * module
     428             :          */
     429           1 :         el = ldb_msg_find_element(last_request->op.add.message, "objectSID");
     430           1 :         assert_non_null(el);
     431           1 :         assert_true(el->flags & LDB_FLAG_INTERNAL_FORCE_UNIQUE_INDEX);
     432             : 
     433             :         /*
     434             :          * Check the flag was not  set on the original request
     435             :          */
     436           1 :         el = ldb_msg_find_element(request->op.add.message, "objectSID");
     437           1 :         assert_non_null(el);
     438           1 :         assert_false(el->flags & LDB_FLAG_INTERNAL_FORCE_UNIQUE_INDEX);
     439             : 
     440           1 : }
     441             : 
     442             : /*
     443             :  * Test that a modify with no object SID is passed through correctly
     444             :  *
     445             :  */
     446           1 : static void test_modify_no_objectSID(void **state)
     447             : {
     448           1 :         struct ldbtest_ctx *test_ctx =
     449           1 :                 talloc_get_type_abort(*state, struct ldbtest_ctx);
     450           1 :         struct ldb_context *ldb                 = test_ctx->ldb;
     451           1 :         struct ldb_message *msg                 = ldb_msg_new(test_ctx);
     452           1 :         struct ldb_request *request             = NULL;
     453           1 :         struct ldb_request *original_request    = NULL;
     454           1 :         int rc;
     455             : 
     456           1 :         msg->dn = ldb_dn_new(msg, ldb, "dc=test");
     457           1 :         assert_int_equal(LDB_SUCCESS, ldb_msg_add_string(msg, "cn", "test"));
     458             : 
     459           1 :         rc = ldb_build_mod_req(
     460             :                 &request,
     461             :                 test_ctx->ldb,
     462             :                 test_ctx,
     463             :                 msg,
     464             :                 NULL,
     465             :                 NULL,
     466             :                 ldb_op_default_callback,
     467             :                 NULL);
     468             : 
     469           1 :         assert_int_equal(rc, LDB_SUCCESS);
     470           1 :         assert_non_null(request);
     471           1 :         original_request = request;
     472             : 
     473           1 :         rc = unique_object_sids_modify(test_ctx->module, request);
     474           1 :         assert_int_equal(rc, LDB_SUCCESS);
     475             : 
     476             :         /*
     477             :          * Check that the original request was passed to the next module
     478             :          * and not a copy
     479             :          */
     480           1 :         assert_ptr_equal(last_request, original_request);
     481             : 
     482           1 : }
     483             : 
     484           1 : int main(void) {
     485           1 :         const struct CMUnitTest tests[] = {
     486             :                 cmocka_unit_test_setup_teardown(
     487             :                         test_objectSID_in_domain,
     488             :                         setup,
     489             :                         teardown),
     490             :                 cmocka_unit_test_setup_teardown(
     491             :                         test_objectSID_not_in_domain,
     492             :                         setup,
     493             :                         teardown),
     494             :                 cmocka_unit_test_setup_teardown(
     495             :                         test_no_objectSID,
     496             :                         setup,
     497             :                         teardown),
     498             :                 cmocka_unit_test_setup_teardown(
     499             :                         test_modify_no_objectSID,
     500             :                         setup,
     501             :                         teardown),
     502             :                 cmocka_unit_test_setup_teardown(
     503             :                         test_modify_of_objectSID_not_replicated,
     504             :                         setup,
     505             :                         teardown),
     506             :                 cmocka_unit_test_setup_teardown(
     507             :                         test_modify_of_objectSID_replicated,
     508             :                         setup,
     509             :                         teardown),
     510             :         };
     511             : 
     512           1 :         cmocka_set_message_output(CM_OUTPUT_SUBUNIT);
     513           1 :         return cmocka_run_group_tests(tests, NULL, NULL);
     514             : }

Generated by: LCOV version 1.14