LCOV - code coverage report
Current view: top level - source4/torture/drs/unit - schemainfo_tests.c (source / functions) Hit Total Coverage
Test: coverage report for master 98b443d9 Lines: 259 268 96.6 %
Date: 2024-05-31 13:13:24 Functions: 13 13 100.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    DRSUAPI schemaInfo unit tests
       5             : 
       6             :    Copyright (C) Kamen Mazdrashki <kamenim@samba.org> 2010
       7             : 
       8             :    This program is free software; you can redistribute it and/or modify
       9             :    it under the terms of the GNU General Public License as published by
      10             :    the Free Software Foundation; either version 3 of the License, or
      11             :    (at your option) any later version.
      12             : 
      13             :    This program is distributed in the hope that it will be useful,
      14             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      15             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      16             :    GNU General Public License for more details.
      17             : 
      18             :    You should have received a copy of the GNU General Public License
      19             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      20             : */
      21             : 
      22             : #include "includes.h"
      23             : #include "system/filesys.h"
      24             : #include "torture/smbtorture.h"
      25             : #include "dsdb/samdb/samdb.h"
      26             : #include "dsdb/samdb/ldb_modules/util.h"
      27             : #include "ldb_wrap.h"
      28             : #include <ldb_module.h>
      29             : #include "torture/rpc/drsuapi.h"
      30             : #include "librpc/ndr/libndr.h"
      31             : #include "param/param.h"
      32             : #include "torture/drs/proto.h"
      33             : #include "torture/drs/proto.h"
      34             : 
      35             : 
      36             : /**
      37             :  * schemaInfo to init ldb context with
      38             :  *   Rev:  0
      39             :  *   GUID: 00000000-0000-0000-0000-000000000000
      40             :  */
      41             : #define SCHEMA_INFO_INIT_STR            "FF0000000000000000000000000000000000000000"
      42             : 
      43             : /**
      44             :  * Default schema_info string to be used for testing
      45             :  *   Rev:  01
      46             :  *   GUID: 071c82fd-45c7-4351-a3db-51f75a630a7f
      47             :  */
      48             : #define SCHEMA_INFO_DEFAULT_STR         "FF00000001FD821C07C7455143A3DB51F75A630A7F"
      49             : 
      50             : /**
      51             :  * Schema info data to test with
      52             :  */
      53             : struct schemainfo_data {
      54             :         DATA_BLOB       ndr_blob;
      55             :         struct dsdb_schema_info schi;
      56             :         WERROR          werr_expected;
      57             :         bool            test_both_ways;
      58             : };
      59             : 
      60             : /**
      61             :  * Schema info test data in human-readable format (... kind of)
      62             :  */
      63             : static const struct {
      64             :         const char      *schema_info_str;
      65             :         uint32_t        revision;
      66             :         const char      *guid_str;
      67             :         WERROR          werr_expected;
      68             :         bool            test_both_ways;
      69             : } _schemainfo_test_data[] = {
      70             :         {
      71             :                 .schema_info_str = "FF0000000000000000000000000000000000000000",
      72             :                 .revision = 0,
      73             :                 .guid_str = "00000000-0000-0000-0000-000000000000",
      74             :                 .werr_expected = WERR_OK,
      75             :                 .test_both_ways = true
      76             :         },
      77             :         {
      78             :                 .schema_info_str = "FF00000001FD821C07C7455143A3DB51F75A630A7F",
      79             :                 .revision = 1,
      80             :                 .guid_str = "071c82fd-45c7-4351-a3db-51f75a630a7f",
      81             :                 .werr_expected = WERR_OK,
      82             :                 .test_both_ways = true
      83             :         },
      84             :         {
      85             :                 .schema_info_str = "FFFFFFFFFFFD821C07C7455143A3DB51F75A630A7F",
      86             :                 .revision = 0xFFFFFFFF,
      87             :                 .guid_str = "071c82fd-45c7-4351-a3db-51f75a630a7f",
      88             :                 .werr_expected = WERR_OK,
      89             :                 .test_both_ways = true
      90             :         },
      91             :         { /* len == 21 */
      92             :                 .schema_info_str = "FF00000001FD821C07C7455143A3DB51F75A630A7F00",
      93             :                 .revision = 1,
      94             :                 .guid_str = "071c82fd-45c7-4351-a3db-51f75a630a7f",
      95             :                 .werr_expected = WERR_INVALID_PARAMETER,
      96             :                 .test_both_ways = false
      97             :         },
      98             :         { /* marker == FF */
      99             :                 .schema_info_str = "AA00000001FD821C07C7455143A3DB51F75A630A7F",
     100             :                 .revision = 1,
     101             :                 .guid_str = "071c82fd-45c7-4351-a3db-51f75a630a7f",
     102             :                 .werr_expected = WERR_INVALID_PARAMETER,
     103             :                 .test_both_ways = false
     104             :         }
     105             : };
     106             : 
     107             : /**
     108             :  * Private data to be shared among all test in Test case
     109             :  */
     110             : struct drsut_schemainfo_data {
     111             :         struct ldb_context *ldb;
     112             :         struct ldb_module  *ldb_module;
     113             :         struct dsdb_schema *schema;
     114             : 
     115             :         /* Initial schemaInfo set in ldb to test with */
     116             :         struct dsdb_schema_info *schema_info;
     117             : 
     118             :         uint32_t test_data_count;
     119             :         struct schemainfo_data *test_data;
     120             : };
     121             : 
     122             : /**
     123             :  * torture macro to assert for equal dsdb_schema_info's
     124             :  */
     125             : #define torture_assert_schema_info_equal(torture_ctx,got,expected,cmt)\
     126             :         do { const struct dsdb_schema_info *__got = (got), *__expected = (expected); \
     127             :         if (__got->revision != __expected->revision) { \
     128             :                 torture_result(torture_ctx, TORTURE_FAIL, \
     129             :                                __location__": "#got".revision %d did not match "#expected".revision %d: %s", \
     130             :                                (int)__got->revision, (int)__expected->revision, cmt); \
     131             :                 return false; \
     132             :         } \
     133             :         if (!GUID_equal(&__got->invocation_id, &__expected->invocation_id)) { \
     134             :                 torture_result(torture_ctx, TORTURE_FAIL, \
     135             :                                __location__": "#got".invocation_id did not match "#expected".invocation_id: %s", cmt); \
     136             :                 return false; \
     137             :         } \
     138             :         } while(0)
     139             : 
     140             : /*
     141             :  * forward declaration for internal functions
     142             :  */
     143             : static bool _drsut_ldb_schema_info_reset(struct torture_context *tctx,
     144             :                                          struct ldb_context *ldb,
     145             :                                          const char *schema_info_str,
     146             :                                          bool in_setup);
     147             : 
     148             : 
     149             : /**
     150             :  * Creates dsdb_schema_info object based on NDR data
     151             :  * passed as hex string
     152             :  */
     153           3 : static bool _drsut_schemainfo_new(struct torture_context *tctx,
     154             :                                   const char *schema_info_str, struct dsdb_schema_info **_si)
     155             : {
     156           3 :         WERROR werr;
     157           3 :         DATA_BLOB blob;
     158             : 
     159           3 :         blob = strhex_to_data_blob(tctx, schema_info_str);
     160           3 :         if (!blob.data) {
     161           0 :                 torture_comment(tctx, "Not enough memory!\n");
     162           0 :                 return false;
     163             :         }
     164             : 
     165           3 :         werr = dsdb_schema_info_from_blob(&blob, tctx, _si);
     166           3 :         if (!W_ERROR_IS_OK(werr)) {
     167           0 :                 torture_comment(tctx,
     168             :                                 "Failed to create dsdb_schema_info object for %s: %s",
     169             :                                 schema_info_str,
     170             :                                 win_errstr(werr));
     171           0 :                 return false;
     172             :         }
     173             : 
     174           3 :         data_blob_free(&blob);
     175             : 
     176           3 :         return true;
     177             : }
     178             : 
     179             : /**
     180             :  * Creates dsdb_schema_info object based on predefined data
     181             :  * Function is public as it is intended to be used by other
     182             :  * tests (e.g. prefixMap tests)
     183             :  */
     184           1 : bool drsut_schemainfo_new(struct torture_context *tctx, struct dsdb_schema_info **_si)
     185             : {
     186           1 :         return _drsut_schemainfo_new(tctx, SCHEMA_INFO_DEFAULT_STR, _si);
     187             : }
     188             : 
     189             : 
     190             : /*
     191             :  * Tests dsdb_schema_info_new() and dsdb_schema_info_blob_new()
     192             :  */
     193           1 : static bool test_dsdb_schema_info_new(struct torture_context *tctx,
     194             :                                       struct drsut_schemainfo_data *priv)
     195             : {
     196           1 :         WERROR werr;
     197           1 :         DATA_BLOB ndr_blob;
     198           1 :         DATA_BLOB ndr_blob_expected;
     199           1 :         struct dsdb_schema_info *schi;
     200           1 :         TALLOC_CTX *mem_ctx;
     201             : 
     202           1 :         mem_ctx = talloc_new(priv);
     203           1 :         torture_assert(tctx, mem_ctx, "Not enough memory!");
     204           1 :         ndr_blob_expected = strhex_to_data_blob(mem_ctx, SCHEMA_INFO_INIT_STR);
     205           1 :         torture_assert(tctx, ndr_blob_expected.data, "Not enough memory!");
     206             : 
     207           1 :         werr = dsdb_schema_info_new(mem_ctx, &schi);
     208           1 :         torture_assert_werr_ok(tctx, werr, "dsdb_schema_info_new() failed");
     209           1 :         torture_assert_int_equal(tctx, schi->revision, 0,
     210             :                                  "dsdb_schema_info_new() creates schemaInfo with invalid revision");
     211           1 :         torture_assert(tctx, GUID_all_zero(&schi->invocation_id),
     212             :                         "dsdb_schema_info_new() creates schemaInfo with not ZERO GUID");
     213             : 
     214           1 :         werr = dsdb_schema_info_blob_new(mem_ctx, &ndr_blob);
     215           1 :         torture_assert_werr_ok(tctx, werr, "dsdb_schema_info_blob_new() failed");
     216           1 :         torture_assert_data_blob_equal(tctx, ndr_blob, ndr_blob_expected,
     217             :                                        "dsdb_schema_info_blob_new() returned invalid blob");
     218             : 
     219           1 :         talloc_free(mem_ctx);
     220           1 :         return true;
     221             : }
     222             : 
     223             : /*
     224             :  * Tests dsdb_schema_info_from_blob()
     225             :  */
     226           1 : static bool test_dsdb_schema_info_from_blob(struct torture_context *tctx,
     227             :                                             struct drsut_schemainfo_data *priv)
     228             : {
     229           1 :         uint32_t i;
     230           1 :         WERROR werr;
     231           1 :         char *msg;
     232           1 :         struct dsdb_schema_info *schema_info;
     233           1 :         TALLOC_CTX *mem_ctx;
     234             : 
     235           1 :         mem_ctx = talloc_new(priv);
     236           1 :         torture_assert(tctx, mem_ctx, "Not enough memory!");
     237             : 
     238           6 :         for (i = 0; i < priv->test_data_count; i++) {
     239           5 :                 struct schemainfo_data *data = &priv->test_data[i];
     240             : 
     241          10 :                 msg = talloc_asprintf(tctx, "dsdb_schema_info_from_blob() [%d]-[%s]",
     242           5 :                                       i, _schemainfo_test_data[i].schema_info_str);
     243             : 
     244           5 :                 werr = dsdb_schema_info_from_blob(&data->ndr_blob, mem_ctx, &schema_info);
     245           5 :                 torture_assert_werr_equal(tctx, werr, data->werr_expected, msg);
     246             : 
     247             :                 /* test returned data */
     248           5 :                 if (W_ERROR_IS_OK(werr)) {
     249           5 :                         torture_assert_schema_info_equal(tctx,
     250             :                                                          schema_info, &data->schi,
     251             :                                                          "after dsdb_schema_info_from_blob() call");
     252             :                 }
     253             :         }
     254             : 
     255           1 :         talloc_free(mem_ctx);
     256             : 
     257           1 :         return true;
     258             : }
     259             : 
     260             : /*
     261             :  * Tests dsdb_blob_from_schema_info()
     262             :  */
     263           1 : static bool test_dsdb_blob_from_schema_info(struct torture_context *tctx,
     264             :                                             struct drsut_schemainfo_data *priv)
     265             : {
     266           1 :         uint32_t i;
     267           1 :         WERROR werr;
     268           1 :         char *msg;
     269           1 :         DATA_BLOB ndr_blob;
     270           1 :         TALLOC_CTX *mem_ctx;
     271             : 
     272           1 :         mem_ctx = talloc_new(priv);
     273           1 :         torture_assert(tctx, mem_ctx, "Not enough memory!");
     274             : 
     275           6 :         for (i = 0; i < priv->test_data_count; i++) {
     276           5 :                 struct schemainfo_data *data = &priv->test_data[i];
     277             : 
     278             :                 /* not all test are valid reverse type of conversion */
     279           5 :                 if (!data->test_both_ways) {
     280           2 :                         continue;
     281             :                 }
     282             : 
     283           6 :                 msg = talloc_asprintf(tctx, "dsdb_blob_from_schema_info() [%d]-[%s]",
     284           3 :                                       i, _schemainfo_test_data[i].schema_info_str);
     285             : 
     286           3 :                 werr = dsdb_blob_from_schema_info(&data->schi, mem_ctx, &ndr_blob);
     287           3 :                 torture_assert_werr_equal(tctx, werr, data->werr_expected, msg);
     288             : 
     289             :                 /* test returned data */
     290           3 :                 if (W_ERROR_IS_OK(werr)) {
     291           5 :                         torture_assert_data_blob_equal(tctx,
     292             :                                                        ndr_blob, data->ndr_blob,
     293             :                                                        "dsdb_blob_from_schema_info()");
     294             :                 }
     295             :         }
     296             : 
     297           1 :         talloc_free(mem_ctx);
     298             : 
     299           1 :         return true;
     300             : }
     301             : 
     302           1 : static bool test_dsdb_schema_info_cmp(struct torture_context *tctx,
     303             :                                       struct drsut_schemainfo_data *priv)
     304             : {
     305           1 :         DATA_BLOB blob;
     306           1 :         struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;
     307           1 :         struct dsdb_schema_info schema_info;
     308             : 
     309           1 :         ctr = talloc_zero(priv, struct drsuapi_DsReplicaOIDMapping_Ctr);
     310           1 :         torture_assert(tctx, ctr, "Not enough memory!");
     311             : 
     312             :         /* not enough elements */
     313           1 :         torture_assert_werr_equal(tctx,
     314             :                                   dsdb_schema_info_cmp(priv->schema, ctr),
     315             :                                   WERR_INVALID_PARAMETER,
     316             :                                   "dsdb_schema_info_cmp(): unexpected result");
     317             : 
     318             :         /* an empty element for schemaInfo */
     319           1 :         ctr->num_mappings = 1;
     320           1 :         ctr->mappings = talloc_zero_array(ctr, struct drsuapi_DsReplicaOIDMapping, 1);
     321           1 :         torture_assert(tctx, ctr->mappings, "Not enough memory!");
     322           1 :         torture_assert_werr_equal(tctx,
     323             :                                   dsdb_schema_info_cmp(priv->schema, ctr),
     324             :                                   WERR_INVALID_PARAMETER,
     325             :                                   "dsdb_schema_info_cmp(): unexpected result");
     326             : 
     327             :         /* test with invalid schemaInfo - length != 21 */
     328           1 :         blob = strhex_to_data_blob(ctr, "FF00000001FD821C07C7455143A3DB51F75A630A7F00");
     329           1 :         torture_assert(tctx, blob.data, "Not enough memory!");
     330           1 :         ctr->mappings[0].oid.length     = blob.length;
     331           1 :         ctr->mappings[0].oid.binary_oid = blob.data;
     332           1 :         torture_assert_werr_equal(tctx,
     333             :                                   dsdb_schema_info_cmp(priv->schema, ctr),
     334             :                                   WERR_INVALID_PARAMETER,
     335             :                                   "dsdb_schema_info_cmp(): unexpected result");
     336             : 
     337             :         /* test with invalid schemaInfo - marker != 0xFF */
     338           1 :         blob = strhex_to_data_blob(ctr, "AA00000001FD821C07C7455143A3DB51F75A630A7F");
     339           1 :         torture_assert(tctx, blob.data, "Not enough memory!");
     340           1 :         ctr->mappings[0].oid.length     = blob.length;
     341           1 :         ctr->mappings[0].oid.binary_oid = blob.data;
     342           1 :         torture_assert_werr_equal(tctx,
     343             :                                   dsdb_schema_info_cmp(priv->schema, ctr),
     344             :                                   WERR_INVALID_PARAMETER,
     345             :                                   "dsdb_schema_info_cmp(): unexpected result");
     346             : 
     347             :         /* test with valid schemaInfo, but older one should be ok */
     348           1 :         blob = strhex_to_data_blob(ctr, "FF0000000000000000000000000000000000000000");
     349           1 :         torture_assert(tctx, blob.data, "Not enough memory!");
     350           1 :         ctr->mappings[0].oid.length     = blob.length;
     351           1 :         ctr->mappings[0].oid.binary_oid = blob.data;
     352           1 :         torture_assert_werr_equal(tctx,
     353             :                                   dsdb_schema_info_cmp(priv->schema, ctr),
     354             :                                   WERR_OK,
     355             :                                   "dsdb_schema_info_cmp(): unexpected result");
     356             : 
     357             :         /* test with correct schemaInfo, but invalid ATTID */
     358           1 :         schema_info = *priv->schema->schema_info;
     359           1 :         torture_assert_werr_ok(tctx,
     360             :                 dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
     361             :                 "dsdb_blob_from_schema_info() failed");
     362           1 :         ctr->mappings[0].id_prefix   = 1;
     363           1 :         ctr->mappings[0].oid.length     = blob.length;
     364           1 :         ctr->mappings[0].oid.binary_oid = blob.data;
     365           1 :         torture_assert_werr_equal(tctx,
     366             :                                   dsdb_schema_info_cmp(priv->schema, ctr),
     367             :                                   WERR_INVALID_PARAMETER,
     368             :                                   "dsdb_schema_info_cmp(): unexpected result");
     369             : 
     370             :         /* test with valid schemaInfo */
     371           1 :         ctr->mappings[0].id_prefix   = 0;
     372           1 :         torture_assert_werr_ok(tctx,
     373             :                                dsdb_schema_info_cmp(priv->schema, ctr),
     374             :                                "dsdb_schema_info_cmp(): unexpected result");
     375             : 
     376             :         /* test with valid schemaInfo, but older revision */
     377           1 :         schema_info = *priv->schema->schema_info;
     378           1 :         schema_info.revision -= 1;
     379           1 :         torture_assert_werr_ok(tctx,
     380             :                 dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
     381             :                 "dsdb_blob_from_schema_info() failed");
     382           1 :         ctr->mappings[0].oid.length     = blob.length;
     383           1 :         ctr->mappings[0].oid.binary_oid = blob.data;
     384           1 :         torture_assert_werr_equal(tctx,
     385             :                                   dsdb_schema_info_cmp(priv->schema, ctr),
     386             :                                   WERR_OK,
     387             :                                   "dsdb_schema_info_cmp(): unexpected result");
     388             : 
     389             :         /* test with valid schemaInfo, but newer revision */
     390           1 :         schema_info = *priv->schema->schema_info;
     391           1 :         schema_info.revision += 1;
     392           1 :         torture_assert_werr_ok(tctx,
     393             :                 dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
     394             :                 "dsdb_blob_from_schema_info() failed");
     395           1 :         ctr->mappings[0].oid.length     = blob.length;
     396           1 :         ctr->mappings[0].oid.binary_oid = blob.data;
     397           1 :         torture_assert_werr_equal(tctx,
     398             :                                   dsdb_schema_info_cmp(priv->schema, ctr),
     399             :                                   WERR_DS_DRA_SCHEMA_MISMATCH,
     400             :                                   "dsdb_schema_info_cmp(): unexpected result");
     401             : 
     402             :         /* test with valid schemaInfo, but newer revision and other invocationId */
     403           1 :         schema_info = *priv->schema->schema_info;
     404           1 :         schema_info.revision += 1;
     405           1 :         schema_info.invocation_id.time_mid += 1;
     406           1 :         torture_assert_werr_ok(tctx,
     407             :                 dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
     408             :                 "dsdb_blob_from_schema_info() failed");
     409           1 :         ctr->mappings[0].oid.length     = blob.length;
     410           1 :         ctr->mappings[0].oid.binary_oid = blob.data;
     411           1 :         torture_assert_werr_equal(tctx,
     412             :                                   dsdb_schema_info_cmp(priv->schema, ctr),
     413             :                                   WERR_DS_DRA_SCHEMA_MISMATCH,
     414             :                                   "dsdb_schema_info_cmp(): unexpected result");
     415             : 
     416             :         /* test with valid schemaInfo, but older revision and other invocationId */
     417           1 :         schema_info = *priv->schema->schema_info;
     418           1 :         schema_info.revision -= 1;
     419           1 :         schema_info.invocation_id.time_mid += 1;
     420           1 :         torture_assert_werr_ok(tctx,
     421             :                 dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
     422             :                 "dsdb_blob_from_schema_info() failed");
     423           1 :         ctr->mappings[0].oid.length     = blob.length;
     424           1 :         ctr->mappings[0].oid.binary_oid = blob.data;
     425           1 :         torture_assert_werr_equal(tctx,
     426             :                                   dsdb_schema_info_cmp(priv->schema, ctr),
     427             :                                   WERR_OK,
     428             :                                   "dsdb_schema_info_cmp(): unexpected result");
     429             : 
     430             :         /* test with valid schemaInfo, but same revision and other invocationId */
     431           1 :         schema_info = *priv->schema->schema_info;
     432           1 :         schema_info.invocation_id.time_mid += 1;
     433           1 :         torture_assert_werr_ok(tctx,
     434             :                 dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
     435             :                 "dsdb_blob_from_schema_info() failed");
     436           1 :         ctr->mappings[0].oid.length     = blob.length;
     437           1 :         ctr->mappings[0].oid.binary_oid = blob.data;
     438           1 :         torture_assert_werr_equal(tctx,
     439             :                                   dsdb_schema_info_cmp(priv->schema, ctr),
     440             :                                   WERR_DS_DRA_SCHEMA_CONFLICT,
     441             :                                   "dsdb_schema_info_cmp(): unexpected result");
     442             : 
     443           1 :         talloc_free(ctr);
     444           1 :         return true;
     445             : }
     446             : 
     447             : /*
     448             :  * Tests dsdb_module_schema_info_blob_read()
     449             :  *   and dsdb_module_schema_info_blob_write()
     450             :  */
     451           1 : static bool test_dsdb_module_schema_info_blob_rw(struct torture_context *tctx,
     452             :                                                 struct drsut_schemainfo_data *priv)
     453             : {
     454           1 :         int ldb_err;
     455           1 :         DATA_BLOB blob_write;
     456           1 :         DATA_BLOB blob_read;
     457             : 
     458             :         /* reset schmeInfo to know value */
     459           1 :         torture_assert(tctx,
     460             :                        _drsut_ldb_schema_info_reset(tctx, priv->ldb, SCHEMA_INFO_INIT_STR, false),
     461             :                        "_drsut_ldb_schema_info_reset() failed");
     462             : 
     463             :         /* write tests' default schemaInfo */
     464           1 :         blob_write = strhex_to_data_blob(priv, SCHEMA_INFO_DEFAULT_STR);
     465           1 :         torture_assert(tctx, blob_write.data, "Not enough memory!");
     466             : 
     467           1 :         ldb_err = dsdb_module_schema_info_blob_write(priv->ldb_module,
     468             :                                                      DSDB_FLAG_TOP_MODULE,
     469             :                                                      &blob_write, NULL);
     470           1 :         torture_assert_int_equal(tctx, ldb_err, LDB_SUCCESS, "dsdb_module_schema_info_blob_write() failed");
     471             : 
     472           1 :         ldb_err = dsdb_module_schema_info_blob_read(priv->ldb_module, DSDB_FLAG_TOP_MODULE,
     473             :                                                     priv, &blob_read, NULL);
     474           1 :         torture_assert_int_equal(tctx, ldb_err, LDB_SUCCESS, "dsdb_module_schema_info_blob_read() failed");
     475             : 
     476             :         /* check if we get what we wrote */
     477           1 :         torture_assert_data_blob_equal(tctx, blob_read, blob_write,
     478             :                                        "Write/Read of schemeInfo blob failed");
     479             : 
     480           0 :         return true;
     481             : }
     482             : 
     483             : /*
     484             :  * Tests dsdb_schema_update_schema_info()
     485             :  */
     486           1 : static bool test_dsdb_module_schema_info_update(struct torture_context *tctx,
     487             :                                                 struct drsut_schemainfo_data *priv)
     488             : {
     489           1 :         int ldb_err;
     490           1 :         WERROR werr;
     491           1 :         DATA_BLOB blob;
     492           1 :         struct dsdb_schema_info *schema_info;
     493             : 
     494             :         /* reset schmeInfo to know value */
     495           1 :         torture_assert(tctx,
     496             :                        _drsut_ldb_schema_info_reset(tctx, priv->ldb, SCHEMA_INFO_INIT_STR, false),
     497             :                        "_drsut_ldb_schema_info_reset() failed");
     498             : 
     499           1 :         ldb_err = dsdb_module_schema_info_update(priv->ldb_module,
     500             :                                                  priv->schema,
     501             :                                                  DSDB_FLAG_TOP_MODULE | DSDB_FLAG_AS_SYSTEM, NULL);
     502           1 :         torture_assert_int_equal(tctx, ldb_err, LDB_SUCCESS, "dsdb_module_schema_info_update() failed");
     503             : 
     504             :         /* get updated schemaInfo */
     505           1 :         ldb_err = dsdb_module_schema_info_blob_read(priv->ldb_module, DSDB_FLAG_TOP_MODULE,
     506             :                                                     priv, &blob, NULL);
     507           1 :         torture_assert_int_equal(tctx, ldb_err, LDB_SUCCESS, "dsdb_module_schema_info_blob_read() failed");
     508             : 
     509           1 :         werr = dsdb_schema_info_from_blob(&blob, priv, &schema_info);
     510           1 :         torture_assert_werr_ok(tctx, werr, "dsdb_schema_info_from_blob() failed");
     511             : 
     512             :         /* check against default schema_info */
     513           1 :         torture_assert_schema_info_equal(tctx, schema_info, priv->schema_info,
     514             :                                           "schemaInfo attribute no updated correctly");
     515             : 
     516           0 :         return true;
     517             : }
     518             : 
     519             : 
     520             : /**
     521             :  * Reset schemaInfo record to know value
     522             :  */
     523           3 : static bool _drsut_ldb_schema_info_reset(struct torture_context *tctx,
     524             :                                          struct ldb_context *ldb,
     525             :                                          const char *schema_info_str,
     526             :                                          bool in_setup)
     527             : {
     528           3 :         bool bret = true;
     529           3 :         int ldb_err;
     530           3 :         DATA_BLOB blob;
     531           3 :         struct ldb_message *msg;
     532           3 :         TALLOC_CTX *mem_ctx = talloc_new(tctx);
     533             : 
     534           3 :         blob = strhex_to_data_blob(mem_ctx, schema_info_str);
     535           3 :         torture_assert_goto(tctx, blob.data, bret, DONE, "Not enough memory!");
     536             : 
     537           3 :         msg = ldb_msg_new(mem_ctx);
     538           3 :         torture_assert_goto(tctx, msg, bret, DONE, "Not enough memory!");
     539             : 
     540           3 :         msg->dn = ldb_get_schema_basedn(ldb);
     541           3 :         ldb_err = ldb_msg_add_value(msg, "schemaInfo", &blob, NULL);
     542           3 :         torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE,
     543             :                                       "ldb_msg_add_value() failed");
     544             : 
     545           3 :         if (in_setup) {
     546           1 :                 ldb_err = ldb_add(ldb, msg);
     547             :         } else {
     548           2 :                 ldb_err = dsdb_replace(ldb, msg, DSDB_MODIFY_PERMISSIVE);
     549             :         }
     550           3 :         torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE,
     551             :                                       "dsdb_replace() failed");
     552             : 
     553           3 : DONE:
     554           3 :         talloc_free(mem_ctx);
     555           3 :         return bret;
     556             : }
     557             : 
     558             : /**
     559             :  * Prepare temporary LDB and opens it
     560             :  */
     561           1 : static bool _drsut_ldb_setup(struct torture_context *tctx, struct drsut_schemainfo_data *priv)
     562             : {
     563           1 :         int ldb_err;
     564           1 :         char *ldb_url;
     565           1 :         bool bret = true;
     566           1 :         char *tempdir = NULL;
     567           1 :         NTSTATUS status;
     568           1 :         TALLOC_CTX* mem_ctx;
     569             : 
     570           1 :         mem_ctx = talloc_new(priv);
     571           1 :         torture_assert(tctx, mem_ctx, "Not enough memory!");
     572             : 
     573           1 :         status = torture_temp_dir(tctx, "drs_", &tempdir);
     574           1 :         torture_assert_ntstatus_ok_goto(tctx, status, bret, DONE, "creating temp dir");
     575             : 
     576           1 :         ldb_url = talloc_asprintf(priv, "%s/drs_schemainfo.ldb", tempdir);
     577           1 :         torture_assert_goto(tctx, ldb_url, bret, DONE, "Not enough memory!");
     578             : 
     579             :         /* create LDB */
     580           1 :         priv->ldb = ldb_wrap_connect(priv, tctx->ev, tctx->lp_ctx,
     581             :                                      ldb_url, NULL, NULL, 0);
     582           1 :         torture_assert_goto(tctx, priv->ldb, bret, DONE,  "ldb_wrap_connect() failed");
     583             : 
     584             :         /* set some schemaNamingContext */
     585           1 :         ldb_err = ldb_set_opaque(priv->ldb,
     586             :                                  "schemaNamingContext",
     587           1 :                                  ldb_dn_new(priv->ldb, priv->ldb, "CN=Schema,CN=Config"));
     588           1 :         torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE,
     589             :                                       "ldb_set_opaque() failed");
     590             : 
     591             :         /* add schemaInfo attribute so tested layer could work properly */
     592           1 :         torture_assert_goto(tctx,
     593             :                             _drsut_ldb_schema_info_reset(tctx, priv->ldb, SCHEMA_INFO_INIT_STR, true),
     594             :                             bret, DONE,
     595             :                             "_drsut_ldb_schema_info_reset() failed");
     596             : 
     597           1 : DONE:
     598           1 :         talloc_free(tempdir);
     599           1 :         talloc_free(mem_ctx);
     600           1 :         return bret;
     601             : }
     602             : 
     603             : /*
     604             :  * Setup/Teardown for test case
     605             :  */
     606           1 : static bool torture_drs_unit_schemainfo_setup(struct torture_context *tctx,
     607             :                                               struct drsut_schemainfo_data **_priv)
     608             : {
     609           1 :         size_t i;
     610           1 :         int ldb_err;
     611           1 :         NTSTATUS status;
     612           1 :         DATA_BLOB ndr_blob;
     613           1 :         struct GUID guid;
     614           1 :         struct drsut_schemainfo_data *priv;
     615             : 
     616           1 :         priv = talloc_zero(tctx, struct drsut_schemainfo_data);
     617           1 :         torture_assert(tctx, priv, "Not enough memory!");
     618             : 
     619             :         /* returned allocated pointer here
     620             :          * teardown() will be called even in case of failure,
     621             :          * so we'll get a changes to clean up  */
     622           1 :         *_priv = priv;
     623             : 
     624             :         /* create initial schemaInfo */
     625           1 :         torture_assert(tctx,
     626             :                        _drsut_schemainfo_new(tctx, SCHEMA_INFO_DEFAULT_STR, &priv->schema_info),
     627             :                        "Failed to create schema_info test object");
     628             : 
     629             :         /* create data to test with */
     630           1 :         priv->test_data_count = ARRAY_SIZE(_schemainfo_test_data);
     631           1 :         priv->test_data = talloc_array(tctx, struct schemainfo_data, priv->test_data_count);
     632             : 
     633           6 :         for (i = 0; i < ARRAY_SIZE(_schemainfo_test_data); i++) {
     634           5 :                 struct schemainfo_data *data = &priv->test_data[i];
     635             : 
     636           5 :                 ndr_blob = strhex_to_data_blob(priv,
     637           5 :                                                _schemainfo_test_data[i].schema_info_str);
     638           5 :                 torture_assert(tctx, ndr_blob.data, "Not enough memory!");
     639             : 
     640           5 :                 status = GUID_from_string(_schemainfo_test_data[i].guid_str, &guid);
     641           5 :                 torture_assert_ntstatus_ok(tctx, status,
     642             :                                            talloc_asprintf(tctx,
     643             :                                                            "GUID_from_string() failed for %s",
     644             :                                                            _schemainfo_test_data[i].guid_str));
     645             : 
     646           5 :                 data->ndr_blob           = ndr_blob;
     647           5 :                 data->schi.invocation_id = guid;
     648           5 :                 data->schi.revision      = _schemainfo_test_data[i].revision;
     649           5 :                 data->werr_expected      = _schemainfo_test_data[i].werr_expected;
     650           5 :                 data->test_both_ways     = _schemainfo_test_data[i].test_both_ways;
     651             : 
     652             :         }
     653             : 
     654             :         /* create temporary LDB and populate with data */
     655           1 :         if (!_drsut_ldb_setup(tctx, priv)) {
     656           0 :                 return false;
     657             :         }
     658             : 
     659             :         /* create ldb_module mockup object */
     660           1 :         priv->ldb_module = ldb_module_new(priv, priv->ldb, "schemaInfo_test_module", NULL);
     661           1 :         torture_assert(tctx, priv->ldb_module, "Not enough memory!");
     662             : 
     663             :         /* create schema mockup object */
     664           1 :         priv->schema = dsdb_new_schema(priv);
     665             : 
     666             :         /* set schema_info in dsdb_schema for testing */
     667           1 :         torture_assert(tctx,
     668             :                        _drsut_schemainfo_new(tctx, SCHEMA_INFO_DEFAULT_STR, &priv->schema->schema_info),
     669             :                        "Failed to create schema_info test object");
     670             : 
     671             :         /* pre-cache invocationId for samdb_ntds_invocation_id()
     672             :          * to work with our mock ldb */
     673           2 :         ldb_err = ldb_set_opaque(priv->ldb, "cache.invocation_id",
     674           1 :                                  &priv->schema_info->invocation_id);
     675           1 :         torture_assert_int_equal(tctx, ldb_err, LDB_SUCCESS, "ldb_set_opaque() failed");
     676             : 
     677             :         /* Perform all tests in transactions so that
     678             :          * underlying modify calls not to fail */
     679           1 :         ldb_err = ldb_transaction_start(priv->ldb);
     680           1 :         torture_assert_int_equal(tctx,
     681             :                                  ldb_err,
     682             :                                  LDB_SUCCESS,
     683             :                                  "ldb_transaction_start() failed");
     684             : 
     685           0 :         return true;
     686             : }
     687             : 
     688           1 : static bool torture_drs_unit_schemainfo_teardown(struct torture_context *tctx,
     689             :                                                  struct drsut_schemainfo_data *priv)
     690             : {
     691           1 :         int ldb_err;
     692             : 
     693             :         /* commit pending transaction so we will
     694             :          * be able to check what LDB state is */
     695           1 :         ldb_err = ldb_transaction_commit(priv->ldb);
     696           1 :         if (ldb_err != LDB_SUCCESS) {
     697           0 :                 torture_comment(tctx, "ldb_transaction_commit() - %s (%s)",
     698             :                                 ldb_strerror(ldb_err),
     699             :                                 ldb_errstring(priv->ldb));
     700             :         }
     701             : 
     702           1 :         talloc_free(priv);
     703             : 
     704           1 :         return true;
     705             : }
     706             : 
     707             : /**
     708             :  * Test case initialization for
     709             :  * drs.unit.schemaInfo
     710             :  */
     711        2338 : struct torture_tcase * torture_drs_unit_schemainfo(struct torture_suite *suite)
     712             : {
     713         125 :         typedef bool (*pfn_setup)(struct torture_context *, void **);
     714         125 :         typedef bool (*pfn_teardown)(struct torture_context *, void *);
     715         125 :         typedef bool (*pfn_run)(struct torture_context *, void *);
     716             : 
     717        2338 :         struct torture_tcase * tc = torture_suite_add_tcase(suite, "schemaInfo");
     718             : 
     719        2338 :         torture_tcase_set_fixture(tc,
     720             :                                   (pfn_setup)torture_drs_unit_schemainfo_setup,
     721             :                                   (pfn_teardown)torture_drs_unit_schemainfo_teardown);
     722             : 
     723        2338 :         tc->description = talloc_strdup(tc, "Unit tests for DRSUAPI::schemaInfo implementation");
     724             : 
     725        2338 :         torture_tcase_add_simple_test(tc, "dsdb_schema_info_new",
     726             :                                       (pfn_run)test_dsdb_schema_info_new);
     727        2338 :         torture_tcase_add_simple_test(tc, "dsdb_schema_info_from_blob",
     728             :                                       (pfn_run)test_dsdb_schema_info_from_blob);
     729        2338 :         torture_tcase_add_simple_test(tc, "dsdb_blob_from_schema_info",
     730             :                                       (pfn_run)test_dsdb_blob_from_schema_info);
     731        2338 :         torture_tcase_add_simple_test(tc, "dsdb_schema_info_cmp",
     732             :                                       (pfn_run)test_dsdb_schema_info_cmp);
     733        2338 :         torture_tcase_add_simple_test(tc, "dsdb_module_schema_info_blob read|write",
     734             :                                       (pfn_run)test_dsdb_module_schema_info_blob_rw);
     735        2338 :         torture_tcase_add_simple_test(tc, "dsdb_module_schema_info_update",
     736             :                                       (pfn_run)test_dsdb_module_schema_info_update);
     737             : 
     738             : 
     739        2338 :         return tc;
     740             : }

Generated by: LCOV version 1.14