/* Unix SMB/CIFS implementation. DRSUAPI prefixMap unit tests Copyright (C) Kamen Mazdrashki 2009-2010 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 "includes.h" #include "system/filesys.h" #include "torture/smbtorture.h" #include "dsdb/samdb/samdb.h" #include "torture/rpc/drsuapi.h" #include "torture/drs/proto.h" #include "param/param.h" #include "librpc/ndr/libndr.h" /** * Private data to be shared among all test in Test case */ struct drsut_prefixmap_data { struct dsdb_schema_prefixmap *pfm_new; struct dsdb_schema_prefixmap *pfm_full; /* default schemaInfo value to test with */ struct dsdb_schema_info *schi_default; struct ldb_context *ldb_ctx; }; /** * Test-oid data structure */ struct drsut_pfm_oid_data { uint32_t id; const char *bin_oid; const char *oid_prefix; }; /** * Default prefixMap initialization data. * This prefixMap is what dsdb_schema_pfm_new() should return. * Based on: MS-DRSR, 5.16.4 ATTRTYP-to-OID Conversion * procedure NewPrefixTable( ) */ static const struct drsut_pfm_oid_data _prefixmap_test_new_data[] = { {.id=0x00000000, .bin_oid="5504", .oid_prefix="2.5.4"}, {.id=0x00000001, .bin_oid="5506", .oid_prefix="2.5.6"}, {.id=0x00000002, .bin_oid="2A864886F7140102", .oid_prefix="1.2.840.113556.1.2"}, {.id=0x00000003, .bin_oid="2A864886F7140103", .oid_prefix="1.2.840.113556.1.3"}, {.id=0x00000004, .bin_oid="6086480165020201", .oid_prefix="2.16.840.1.101.2.2.1"}, {.id=0x00000005, .bin_oid="6086480165020203", .oid_prefix="2.16.840.1.101.2.2.3"}, {.id=0x00000006, .bin_oid="6086480165020105", .oid_prefix="2.16.840.1.101.2.1.5"}, {.id=0x00000007, .bin_oid="6086480165020104", .oid_prefix="2.16.840.1.101.2.1.4"}, {.id=0x00000008, .bin_oid="5505", .oid_prefix="2.5.5"}, {.id=0x00000009, .bin_oid="2A864886F7140104", .oid_prefix="1.2.840.113556.1.4"}, {.id=0x0000000A, .bin_oid="2A864886F7140105", .oid_prefix="1.2.840.113556.1.5"}, {.id=0x00000013, .bin_oid="0992268993F22C64", .oid_prefix="0.9.2342.19200300.100"}, {.id=0x00000014, .bin_oid="6086480186F84203", .oid_prefix="2.16.840.1.113730.3"}, {.id=0x00000015, .bin_oid="0992268993F22C6401", .oid_prefix="0.9.2342.19200300.100.1"}, {.id=0x00000016, .bin_oid="6086480186F8420301", .oid_prefix="2.16.840.1.113730.3.1"}, {.id=0x00000017, .bin_oid="2A864886F7140105B658", .oid_prefix="1.2.840.113556.1.5.7000"}, {.id=0x00000018, .bin_oid="5515", .oid_prefix="2.5.21"}, {.id=0x00000019, .bin_oid="5512", .oid_prefix="2.5.18"}, {.id=0x0000001A, .bin_oid="5514", .oid_prefix="2.5.20"}, }; /** * Data to be used for creating full prefix map for testing. * 'full-prefixMap' is based on what w2k8 returns as a prefixMap * on clean installation - i.e. prefixMap for clean Schema */ static const struct drsut_pfm_oid_data _prefixmap_full_map_data[] = { {.id=0x00000000, .bin_oid="0x5504", .oid_prefix="2.5.4"}, {.id=0x00000001, .bin_oid="0x5506", .oid_prefix="2.5.6"}, {.id=0x00000002, .bin_oid="0x2A864886F7140102", .oid_prefix="1.2.840.113556.1.2"}, {.id=0x00000003, .bin_oid="0x2A864886F7140103", .oid_prefix="1.2.840.113556.1.3"}, {.id=0x00000004, .bin_oid="0x6086480165020201", .oid_prefix="2.16.840.1.101.2.2.1"}, {.id=0x00000005, .bin_oid="0x6086480165020203", .oid_prefix="2.16.840.1.101.2.2.3"}, {.id=0x00000006, .bin_oid="0x6086480165020105", .oid_prefix="2.16.840.1.101.2.1.5"}, {.id=0x00000007, .bin_oid="0x6086480165020104", .oid_prefix="2.16.840.1.101.2.1.4"}, {.id=0x00000008, .bin_oid="0x5505", .oid_prefix="2.5.5"}, {.id=0x00000009, .bin_oid="0x2A864886F7140104", .oid_prefix="1.2.840.113556.1.4"}, {.id=0x0000000a, .bin_oid="0x2A864886F7140105", .oid_prefix="1.2.840.113556.1.5"}, {.id=0x00000013, .bin_oid="0x0992268993F22C64", .oid_prefix="0.9.2342.19200300.100"}, {.id=0x00000014, .bin_oid="0x6086480186F84203", .oid_prefix="2.16.840.1.113730.3"}, {.id=0x00000015, .bin_oid="0x0992268993F22C6401", .oid_prefix="0.9.2342.19200300.100.1"}, {.id=0x00000016, .bin_oid="0x6086480186F8420301", .oid_prefix="2.16.840.1.113730.3.1"}, {.id=0x00000017, .bin_oid="0x2A864886F7140105B658", .oid_prefix="1.2.840.113556.1.5.7000"}, {.id=0x00000018, .bin_oid="0x5515", .oid_prefix="2.5.21"}, {.id=0x00000019, .bin_oid="0x5512", .oid_prefix="2.5.18"}, {.id=0x0000001a, .bin_oid="0x5514", .oid_prefix="2.5.20"}, {.id=0x0000000b, .bin_oid="0x2A864886F71401048204", .oid_prefix="1.2.840.113556.1.4.260"}, {.id=0x0000000c, .bin_oid="0x2A864886F714010538", .oid_prefix="1.2.840.113556.1.5.56"}, {.id=0x0000000d, .bin_oid="0x2A864886F71401048206", .oid_prefix="1.2.840.113556.1.4.262"}, {.id=0x0000000e, .bin_oid="0x2A864886F714010539", .oid_prefix="1.2.840.113556.1.5.57"}, {.id=0x0000000f, .bin_oid="0x2A864886F71401048207", .oid_prefix="1.2.840.113556.1.4.263"}, {.id=0x00000010, .bin_oid="0x2A864886F71401053A", .oid_prefix="1.2.840.113556.1.5.58"}, {.id=0x00000011, .bin_oid="0x2A864886F714010549", .oid_prefix="1.2.840.113556.1.5.73"}, {.id=0x00000012, .bin_oid="0x2A864886F71401048231", .oid_prefix="1.2.840.113556.1.4.305"}, {.id=0x0000001b, .bin_oid="0x2B060104018B3A6577", .oid_prefix="1.3.6.1.4.1.1466.101.119"}, {.id=0x0000001c, .bin_oid="0x6086480186F8420302", .oid_prefix="2.16.840.1.113730.3.2"}, {.id=0x0000001d, .bin_oid="0x2B06010401817A01", .oid_prefix="1.3.6.1.4.1.250.1"}, {.id=0x0000001e, .bin_oid="0x2A864886F70D0109", .oid_prefix="1.2.840.113549.1.9"}, {.id=0x0000001f, .bin_oid="0x0992268993F22C6404", .oid_prefix="0.9.2342.19200300.100.4"}, {.id=0x00000020, .bin_oid="0x2A864886F714010617", .oid_prefix="1.2.840.113556.1.6.23"}, {.id=0x00000021, .bin_oid="0x2A864886F71401061201", .oid_prefix="1.2.840.113556.1.6.18.1"}, {.id=0x00000022, .bin_oid="0x2A864886F71401061202", .oid_prefix="1.2.840.113556.1.6.18.2"}, {.id=0x00000023, .bin_oid="0x2A864886F71401060D03", .oid_prefix="1.2.840.113556.1.6.13.3"}, {.id=0x00000024, .bin_oid="0x2A864886F71401060D04", .oid_prefix="1.2.840.113556.1.6.13.4"}, {.id=0x00000025, .bin_oid="0x2B0601010101", .oid_prefix="1.3.6.1.1.1.1"}, {.id=0x00000026, .bin_oid="0x2B0601010102", .oid_prefix="1.3.6.1.1.1.2"}, {.id=0x000003ed, .bin_oid="0x2A864886F7140104B65866", .oid_prefix="1.2.840.113556.1.4.7000.102"}, {.id=0x00000428, .bin_oid="0x2A864886F7140105B6583E", .oid_prefix="1.2.840.113556.1.5.7000.62"}, {.id=0x0000044c, .bin_oid="0x2A864886F7140104B6586683", .oid_prefix="1.2.840.113556.1.4.7000.102:0x83"}, {.id=0x0000044f, .bin_oid="0x2A864886F7140104B6586681", .oid_prefix="1.2.840.113556.1.4.7000.102:0x81"}, {.id=0x0000047d, .bin_oid="0x2A864886F7140105B6583E81", .oid_prefix="1.2.840.113556.1.5.7000.62:0x81"}, {.id=0x00000561, .bin_oid="0x2A864886F7140105B6583E83", .oid_prefix="1.2.840.113556.1.5.7000.62:0x83"}, {.id=0x000007d1, .bin_oid="0x2A864886F71401061401", .oid_prefix="1.2.840.113556.1.6.20.1"}, {.id=0x000007e1, .bin_oid="0x2A864886F71401061402", .oid_prefix="1.2.840.113556.1.6.20.2"}, {.id=0x00001b86, .bin_oid="0x2A817A", .oid_prefix="1.2.250"}, {.id=0x00001c78, .bin_oid="0x2A817A81", .oid_prefix="1.2.250:0x81"}, {.id=0x00001c7b, .bin_oid="0x2A817A8180", .oid_prefix="1.2.250:0x8180"}, }; /** * OID-to-ATTID mappings to be used for testing. * An entry is marked as 'exists=true' if it exists in * base prefixMap (_prefixmap_test_new_data) */ static const struct { const char *oid; uint32_t id; uint32_t attid; bool exists; } _prefixmap_test_data[] = { {.oid="2.5.4.0", .id=0x00000000, .attid=0x000000, .exists=true}, {.oid="2.5.4.42", .id=0x00000000, .attid=0x00002a, .exists=true}, {.oid="1.2.840.113556.1.2.1", .id=0x00000002, .attid=0x020001, .exists=true}, {.oid="1.2.840.113556.1.2.13", .id=0x00000002, .attid=0x02000d, .exists=true}, {.oid="1.2.840.113556.1.2.281", .id=0x00000002, .attid=0x020119, .exists=true}, {.oid="1.2.840.113556.1.4.125", .id=0x00000009, .attid=0x09007d, .exists=true}, {.oid="1.2.840.113556.1.4.146", .id=0x00000009, .attid=0x090092, .exists=true}, {.oid="1.2.250.1", .id=0x00001b86, .attid=0x1b860001, .exists=false}, {.oid="1.2.250.16386", .id=0x00001c78, .attid=0x1c788002, .exists=false}, {.oid="1.2.250.2097154", .id=0x00001c7b, .attid=0x1c7b8002, .exists=false}, }; /** * Creates dsdb_schema_prefixmap based on predefined data */ static WERROR _drsut_prefixmap_new(const struct drsut_pfm_oid_data *_pfm_init_data, uint32_t count, TALLOC_CTX *mem_ctx, struct dsdb_schema_prefixmap **_pfm) { uint32_t i; struct dsdb_schema_prefixmap *pfm; pfm = talloc(mem_ctx, struct dsdb_schema_prefixmap); W_ERROR_HAVE_NO_MEMORY(pfm); pfm->length = count; pfm->prefixes = talloc_array(pfm, struct dsdb_schema_prefixmap_oid, pfm->length); if (!pfm->prefixes) { talloc_free(pfm); return WERR_NOT_ENOUGH_MEMORY; } for (i = 0; i < pfm->length; i++) { pfm->prefixes[i].id = _pfm_init_data[i].id; pfm->prefixes[i].bin_oid = strhex_to_data_blob(pfm, _pfm_init_data[i].bin_oid); if (!pfm->prefixes[i].bin_oid.data) { talloc_free(pfm); return WERR_NOT_ENOUGH_MEMORY; } } *_pfm = pfm; return WERR_OK; } /** * Compares two prefixMaps for being equal - same items on same indexes */ static bool _torture_drs_pfm_compare_same(struct torture_context *tctx, const struct dsdb_schema_prefixmap *pfm_left, const struct dsdb_schema_prefixmap *pfm_right, bool quiet) { uint32_t i; char *err_msg = NULL; if (pfm_left->length != pfm_right->length) { err_msg = talloc_asprintf(tctx, "prefixMaps differ in size; left = %d, right = %d", pfm_left->length, pfm_right->length); goto failed; } for (i = 0; i < pfm_left->length; i++) { struct dsdb_schema_prefixmap_oid *entry_left = &pfm_left->prefixes[i]; struct dsdb_schema_prefixmap_oid *entry_right = &pfm_right->prefixes[i]; if (entry_left->id != entry_right->id) { err_msg = talloc_asprintf(tctx, "Different IDs for index=%d", i); goto failed; } if (data_blob_cmp(&entry_left->bin_oid, &entry_right->bin_oid)) { err_msg = talloc_asprintf(tctx, "Different bin_oid for index=%d", i); goto failed; } } return true; failed: if (!quiet) { torture_comment(tctx, "_torture_drs_pfm_compare_same: %s", err_msg); } talloc_free(err_msg); return false; } /* * Tests dsdb_schema_pfm_new() */ static bool torture_drs_unit_pfm_new(struct torture_context *tctx, struct drsut_prefixmap_data *priv) { WERROR werr; bool bret; TALLOC_CTX *mem_ctx; struct dsdb_schema_prefixmap *pfm = NULL; mem_ctx = talloc_new(priv); /* create new prefix map */ werr = dsdb_schema_pfm_new(mem_ctx, &pfm); torture_assert_werr_ok(tctx, werr, "dsdb_schema_pfm_new() failed!"); torture_assert(tctx, pfm != NULL, "NULL prefixMap created!"); torture_assert(tctx, pfm->length > 0, "Empty prefixMap created!"); torture_assert(tctx, pfm->prefixes != NULL, "No prefixes for newly created prefixMap!"); /* compare newly created prefixMap with template one */ bret = _torture_drs_pfm_compare_same(tctx, priv->pfm_new, pfm, false); talloc_free(mem_ctx); return bret; } /** * Tests dsdb_schema_pfm_make_attid() using full prefixMap. * In this test we know exactly which ATTID and prefixMap->ID * should be returned, i.e. no prefixMap entries should be added. */ static bool torture_drs_unit_pfm_make_attid_full_map(struct torture_context *tctx, struct drsut_prefixmap_data *priv) { WERROR werr; uint32_t i, count; uint32_t attid; char *err_msg; count = ARRAY_SIZE(_prefixmap_test_data); for (i = 0; i < count; i++) { werr = dsdb_schema_pfm_make_attid(priv->pfm_full, _prefixmap_test_data[i].oid, &attid); /* prepare error message */ err_msg = talloc_asprintf(priv, "dsdb_schema_pfm_make_attid() failed with %s", _prefixmap_test_data[i].oid); torture_assert(tctx, err_msg, "Unexpected: Have no memory!"); /* verify result and returned ATTID */ torture_assert_werr_ok(tctx, werr, err_msg); torture_assert_int_equal(tctx, attid, _prefixmap_test_data[i].attid, err_msg); /* reclaim memory for prepared error message */ talloc_free(err_msg); } return true; } /** * Tests dsdb_schema_pfm_make_attid() using initially small prefixMap. * In this test we don't know exactly which ATTID and prefixMap->ID * should be returned, but we can verify lo-word of ATTID. * This test verifies implementation branch when a new * prefix should be added into prefixMap. */ static bool torture_drs_unit_pfm_make_attid_small_map(struct torture_context *tctx, struct drsut_prefixmap_data *priv) { WERROR werr; uint32_t i, j; uint32_t idx; uint32_t attid, attid_2; char *err_msg; struct dsdb_schema_prefixmap *pfm = NULL; TALLOC_CTX *mem_ctx; mem_ctx = talloc_new(priv); /* create new prefix map */ werr = dsdb_schema_pfm_new(mem_ctx, &pfm); torture_assert_werr_ok(tctx, werr, "dsdb_schema_pfm_new() failed!"); /* make some ATTIDs and check result */ for (i = 0; i < ARRAY_SIZE(_prefixmap_test_data); i++) { werr = dsdb_schema_pfm_make_attid(pfm, _prefixmap_test_data[i].oid, &attid); /* prepare error message */ err_msg = talloc_asprintf(mem_ctx, "dsdb_schema_pfm_make_attid() failed with %s", _prefixmap_test_data[i].oid); torture_assert(tctx, err_msg, "Unexpected: Have no memory!"); /* verify result and returned ATTID */ torture_assert_werr_ok(tctx, werr, err_msg); /* verify ATTID lo-word */ torture_assert_int_equal(tctx, attid & 0xFFFF, _prefixmap_test_data[i].attid & 0xFFFF, err_msg); /* try again, this time verify for whole ATTID */ werr = dsdb_schema_pfm_make_attid(pfm, _prefixmap_test_data[i].oid, &attid_2); torture_assert_werr_ok(tctx, werr, err_msg); torture_assert_int_equal(tctx, attid_2, attid, err_msg); /* reclaim memory for prepared error message */ talloc_free(err_msg); /* check there is such an index in modified prefixMap */ idx = (attid >> 16); for (j = 0; j < pfm->length; j++) { if (pfm->prefixes[j].id == idx) break; } if (j >= pfm->length) { torture_result(tctx, TORTURE_FAIL, __location__": No prefix for ATTID=0x%08X", attid); return false; } } talloc_free(mem_ctx); return true; } /** * Tests dsdb_schema_pfm_attid_from_oid() using full prefixMap. * In this test we know exactly which ATTID and prefixMap->ID * should be returned- dsdb_schema_pfm_attid_from_oid() should succeed. */ static bool torture_drs_unit_pfm_attid_from_oid_full_map(struct torture_context *tctx, struct drsut_prefixmap_data *priv) { WERROR werr; uint32_t i, count; uint32_t attid; char *err_msg; count = ARRAY_SIZE(_prefixmap_test_data); for (i = 0; i < count; i++) { werr = dsdb_schema_pfm_attid_from_oid(priv->pfm_full, _prefixmap_test_data[i].oid, &attid); /* prepare error message */ err_msg = talloc_asprintf(priv, "dsdb_schema_pfm_attid_from_oid() failed with %s", _prefixmap_test_data[i].oid); torture_assert(tctx, err_msg, "Unexpected: Have no memory!"); /* verify result and returned ATTID */ torture_assert_werr_ok(tctx, werr, err_msg); torture_assert_int_equal(tctx, attid, _prefixmap_test_data[i].attid, err_msg); /* reclaim memory for prepared error message */ talloc_free(err_msg); } return true; } /** * Tests dsdb_schema_pfm_attid_from_oid() using base (initial) prefixMap. * dsdb_schema_pfm_attid_from_oid() should fail when testing with OID * that are not already in the prefixMap. */ static bool torture_drs_unit_pfm_attid_from_oid_base_map(struct torture_context *tctx, struct drsut_prefixmap_data *priv) { WERROR werr; uint32_t i; uint32_t attid; char *err_msg; struct dsdb_schema_prefixmap *pfm = NULL; struct dsdb_schema_prefixmap pfm_prev; TALLOC_CTX *mem_ctx; mem_ctx = talloc_new(priv); torture_assert(tctx, mem_ctx, "Unexpected: Have no memory!"); /* create new prefix map */ werr = dsdb_schema_pfm_new(mem_ctx, &pfm); torture_assert_werr_ok(tctx, werr, "dsdb_schema_pfm_new() failed!"); /* keep initial pfm around for testing */ pfm_prev = *pfm; pfm_prev.prefixes = talloc_reference(mem_ctx, pfm->prefixes); /* get some ATTIDs and check result */ for (i = 0; i < ARRAY_SIZE(_prefixmap_test_data); i++) { werr = dsdb_schema_pfm_attid_from_oid(pfm, _prefixmap_test_data[i].oid, &attid); /* prepare error message */ err_msg = talloc_asprintf(mem_ctx, "dsdb_schema_pfm_attid_from_oid() failed for %s", _prefixmap_test_data[i].oid); torture_assert(tctx, err_msg, "Unexpected: Have no memory!"); /* verify pfm hasn't been altered */ if (_prefixmap_test_data[i].exists) { /* should succeed and return valid ATTID */ torture_assert_werr_ok(tctx, werr, err_msg); /* verify ATTID */ torture_assert_int_equal(tctx, attid, _prefixmap_test_data[i].attid, err_msg); } else { /* should fail */ torture_assert_werr_equal(tctx, werr, WERR_NOT_FOUND, err_msg); } /* prefixMap should never be changed */ if (!_torture_drs_pfm_compare_same(tctx, &pfm_prev, pfm, true)) { torture_fail(tctx, "schema->prefixmap has changed"); } /* reclaim memory for prepared error message */ talloc_free(err_msg); } talloc_free(mem_ctx); return true; } /** * Tests dsdb_schema_pfm_oid_from_attid() using full prefixMap. */ static bool torture_drs_unit_pfm_oid_from_attid(struct torture_context *tctx, struct drsut_prefixmap_data *priv) { WERROR werr; uint32_t i, count; char *err_msg; const char *oid; count = ARRAY_SIZE(_prefixmap_test_data); for (i = 0; i < count; i++) { oid = NULL; werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, _prefixmap_test_data[i].attid, priv, &oid); /* prepare error message */ err_msg = talloc_asprintf(priv, "dsdb_schema_pfm_oid_from_attid() failed with 0x%08X", _prefixmap_test_data[i].attid); torture_assert(tctx, err_msg, "Unexpected: Have no memory!"); /* verify result and returned ATTID */ torture_assert_werr_ok(tctx, werr, err_msg); torture_assert(tctx, oid, "dsdb_schema_pfm_oid_from_attid() returned NULL OID!!!"); torture_assert_str_equal(tctx, oid, _prefixmap_test_data[i].oid, err_msg); /* reclaim memory for prepared error message */ talloc_free(err_msg); /* free memory for OID */ talloc_free(discard_const(oid)); } return true; } /** * Tests dsdb_schema_pfm_oid_from_attid() for handling * correctly different type of attid values. * See: MS-ADTS, 3.1.1.2.6 ATTRTYP */ static bool torture_drs_unit_pfm_oid_from_attid_check_attid(struct torture_context *tctx, struct drsut_prefixmap_data *priv) { WERROR werr; const char *oid; /* Test with valid prefixMap attid */ werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0x00010001, tctx, &oid); torture_assert_werr_ok(tctx, werr, "Testing prefixMap type attid = 0x00010001"); /* Test with valid attid but invalid index */ werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0x01110001, tctx, &oid); torture_assert_werr_equal(tctx, werr, WERR_DS_NO_ATTRIBUTE_OR_VALUE, "Testing invalid-index attid = 0x01110001"); /* Test with attid in msDS-IntId range */ werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0x80000000, tctx, &oid); torture_assert_werr_equal(tctx, werr, WERR_INVALID_PARAMETER, "Testing msDS-IntId type attid = 0x80000000"); werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0xBFFFFFFF, tctx, &oid); torture_assert_werr_equal(tctx, werr, WERR_INVALID_PARAMETER, "Testing msDS-IntId type attid = 0xBFFFFFFF"); /* Test with attid in RESERVED range */ werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0xC0000000, tctx, &oid); torture_assert_werr_equal(tctx, werr, WERR_INVALID_PARAMETER, "Testing RESERVED type attid = 0xC0000000"); werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0xFFFEFFFF, tctx, &oid); torture_assert_werr_equal(tctx, werr, WERR_INVALID_PARAMETER, "Testing RESERVED type attid = 0xFFFEFFFF"); /* Test with attid in INTERNAL range */ werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0xFFFF0000, tctx, &oid); torture_assert_werr_equal(tctx, werr, WERR_INVALID_PARAMETER, "Testing INTERNAL type attid = 0xFFFF0000"); werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0xFFFFFFFF, tctx, &oid); torture_assert_werr_equal(tctx, werr, WERR_INVALID_PARAMETER, "Testing INTERNAL type attid = 0xFFFFFFFF"); return true; } /** * Test Schema prefixMap conversions to/from drsuapi prefixMap * representation. */ static bool torture_drs_unit_pfm_to_from_drsuapi(struct torture_context *tctx, struct drsut_prefixmap_data *priv) { WERROR werr; struct dsdb_schema_info *schema_info; DATA_BLOB schema_info_blob; struct dsdb_schema_prefixmap *pfm; struct drsuapi_DsReplicaOIDMapping_Ctr *ctr; TALLOC_CTX *mem_ctx; mem_ctx = talloc_new(tctx); torture_assert(tctx, mem_ctx, "Unexpected: Have no memory!"); /* convert Schema_prefixMap to drsuapi_prefixMap */ werr = dsdb_drsuapi_pfm_from_schema_pfm(priv->pfm_full, priv->schi_default, mem_ctx, &ctr); torture_assert_werr_ok(tctx, werr, "dsdb_drsuapi_pfm_from_schema_pfm() failed"); torture_assert(tctx, ctr && ctr->mappings, "drsuapi_prefixMap not constructed correctly"); torture_assert_int_equal(tctx, ctr->num_mappings, priv->pfm_full->length + 1, "drs_mappings count does not match"); /* look for schema_info entry - it should be the last one */ schema_info_blob = data_blob_const(ctr->mappings[ctr->num_mappings - 1].oid.binary_oid, ctr->mappings[ctr->num_mappings - 1].oid.length); werr = dsdb_schema_info_from_blob(&schema_info_blob, tctx, &schema_info); torture_assert_werr_ok(tctx, werr, "dsdb_schema_info_from_blob failed"); torture_assert_int_equal(tctx, schema_info->revision, priv->schi_default->revision, "schema_info (revision) not stored correctly or not last entry"); torture_assert(tctx, GUID_equal(&schema_info->invocation_id, &priv->schi_default->invocation_id), "schema_info (invocation_id) not stored correctly or not last entry"); /* compare schema_prefixMap and drsuapi_prefixMap */ werr = dsdb_schema_pfm_contains_drsuapi_pfm(priv->pfm_full, ctr); torture_assert_werr_ok(tctx, werr, "dsdb_schema_pfm_contains_drsuapi_pfm() failed"); /* convert back drsuapi_prefixMap to schema_prefixMap */ werr = dsdb_schema_pfm_from_drsuapi_pfm(ctr, true, mem_ctx, &pfm, &schema_info); torture_assert_werr_ok(tctx, werr, "dsdb_schema_pfm_from_drsuapi_pfm() failed"); torture_assert_int_equal(tctx, schema_info->revision, priv->schi_default->revision, "Fetched schema_info is different (revision)"); torture_assert(tctx, GUID_equal(&schema_info->invocation_id, &priv->schi_default->invocation_id), "Fetched schema_info is different (invocation_id)"); /* compare against the original */ if (!_torture_drs_pfm_compare_same(tctx, priv->pfm_full, pfm, true)) { talloc_free(mem_ctx); return false; } /* test conversion with partial drsuapi_prefixMap */ ctr->num_mappings--; werr = dsdb_schema_pfm_from_drsuapi_pfm(ctr, false, mem_ctx, &pfm, NULL); torture_assert_werr_ok(tctx, werr, "dsdb_schema_pfm_from_drsuapi_pfm() failed"); /* compare against the original */ if (!_torture_drs_pfm_compare_same(tctx, priv->pfm_full, pfm, false)) { talloc_free(mem_ctx); return false; } talloc_free(mem_ctx); return true; } /** * Test Schema prefixMap conversions to/from ldb_val * blob representation. */ static bool torture_drs_unit_pfm_to_from_ldb_val(struct torture_context *tctx, struct drsut_prefixmap_data *priv) { WERROR werr; struct dsdb_schema *schema; struct ldb_val pfm_ldb_val; struct ldb_val schema_info_ldb_val; TALLOC_CTX *mem_ctx; mem_ctx = talloc_new(tctx); torture_assert(tctx, mem_ctx, "Unexpected: Have no memory!"); schema = dsdb_new_schema(mem_ctx); torture_assert(tctx, schema, "Unexpected: failed to allocate schema object"); /* set priv->pfm_full as prefixMap for new schema object */ schema->prefixmap = priv->pfm_full; schema->schema_info = priv->schi_default; /* convert schema_prefixMap to ldb_val blob */ werr = dsdb_get_oid_mappings_ldb(schema, mem_ctx, &pfm_ldb_val, &schema_info_ldb_val); torture_assert_werr_ok(tctx, werr, "dsdb_get_oid_mappings_ldb() failed"); torture_assert(tctx, pfm_ldb_val.data && pfm_ldb_val.length, "pfm_ldb_val not constructed correctly"); torture_assert(tctx, schema_info_ldb_val.data && schema_info_ldb_val.length, "schema_info_ldb_val not constructed correctly"); /* convert pfm_ldb_val back to schema_prefixMap */ schema->prefixmap = NULL; schema->schema_info = NULL; werr = dsdb_load_oid_mappings_ldb(schema, &pfm_ldb_val, &schema_info_ldb_val); torture_assert_werr_ok(tctx, werr, "dsdb_load_oid_mappings_ldb() failed"); /* compare against the original */ if (!_torture_drs_pfm_compare_same(tctx, schema->prefixmap, priv->pfm_full, false)) { talloc_free(mem_ctx); return false; } torture_assert_int_equal(tctx, schema->schema_info->revision, priv->schi_default->revision, "Fetched schema_info is different (revision)"); torture_assert(tctx, GUID_equal(&schema->schema_info->invocation_id, &priv->schi_default->invocation_id), "Fetched schema_info is different (invocation_id)"); talloc_free(mem_ctx); return true; } /** * Test read/write in ldb implementation */ static bool torture_drs_unit_pfm_read_write_ldb(struct torture_context *tctx, struct drsut_prefixmap_data *priv) { WERROR werr; struct dsdb_schema *schema; struct dsdb_schema_prefixmap *pfm; TALLOC_CTX *mem_ctx; mem_ctx = talloc_new(tctx); torture_assert(tctx, mem_ctx, "Unexpected: Have no memory!"); /* makeup a dsdb_schema to test with */ schema = dsdb_new_schema(mem_ctx); torture_assert(tctx, schema, "Unexpected: failed to allocate schema object"); /* set priv->pfm_full as prefixMap for new schema object */ schema->prefixmap = priv->pfm_full; schema->schema_info = priv->schi_default; /* write prfixMap to ldb */ werr = dsdb_write_prefixes_from_schema_to_ldb(mem_ctx, priv->ldb_ctx, schema); torture_assert_werr_ok(tctx, werr, "dsdb_write_prefixes_from_schema_to_ldb() failed"); /* read from ldb what we have written */ werr = dsdb_read_prefixes_from_ldb(priv->ldb_ctx, mem_ctx, &pfm); torture_assert_werr_ok(tctx, werr, "dsdb_read_prefixes_from_ldb() failed"); /* compare data written/read */ if (!_torture_drs_pfm_compare_same(tctx, schema->prefixmap, priv->pfm_full, false)) { torture_fail(tctx, "prefixMap read/write in LDB is not consistent"); } talloc_free(mem_ctx); return true; } /** * Test dsdb_create_prefix_mapping */ static bool torture_drs_unit_dsdb_create_prefix_mapping(struct torture_context *tctx, struct drsut_prefixmap_data *priv) { WERROR werr; uint32_t i; struct dsdb_schema *schema; TALLOC_CTX *mem_ctx; struct dsdb_schema_prefixmap *pfm_ldb = NULL; mem_ctx = talloc_new(tctx); torture_assert(tctx, mem_ctx, "Unexpected: Have no memory!"); /* makeup a dsdb_schema to test with */ schema = dsdb_new_schema(mem_ctx); torture_assert(tctx, schema, "Unexpected: failed to allocate schema object"); /* set priv->pfm_full as prefixMap for new schema object */ schema->schema_info = priv->schi_default; werr = _drsut_prefixmap_new(_prefixmap_test_new_data, ARRAY_SIZE(_prefixmap_test_new_data), schema, &schema->prefixmap); torture_assert_werr_ok(tctx, werr, "_drsut_prefixmap_new() failed"); /* write prfixMap to ldb */ werr = dsdb_write_prefixes_from_schema_to_ldb(mem_ctx, priv->ldb_ctx, schema); torture_assert_werr_ok(tctx, werr, "dsdb_write_prefixes_from_schema_to_ldb() failed"); /* read from ldb what we have written */ werr = dsdb_read_prefixes_from_ldb(priv->ldb_ctx, mem_ctx, &pfm_ldb); torture_assert_werr_ok(tctx, werr, "dsdb_read_prefixes_from_ldb() failed"); /* compare data written/read */ if (!_torture_drs_pfm_compare_same(tctx, schema->prefixmap, pfm_ldb, true)) { torture_fail(tctx, "pfm in LDB is different"); } TALLOC_FREE(pfm_ldb); for (i = 0; i < ARRAY_SIZE(_prefixmap_test_data); i++) { struct dsdb_schema_prefixmap *pfm_prev; struct dsdb_schema_prefixmap *pfm_new; pfm_prev = schema->prefixmap; pfm_new = dsdb_schema_pfm_copy_shallow(schema, pfm_prev); torture_assert(tctx, pfm_new != NULL, "dsdb_schema_pfm_copy_shallow() failed"); if (!_prefixmap_test_data[i].exists) { uint32_t attid; werr = dsdb_schema_pfm_make_attid(pfm_new, _prefixmap_test_data[i].oid, &attid); torture_assert_werr_ok(tctx, werr, "dsdb_schema_pfm_make_attid() failed"); } /* call dsdb_create_prefix_mapping() and check result accordingly */ werr = dsdb_create_prefix_mapping(priv->ldb_ctx, schema, _prefixmap_test_data[i].oid); torture_assert_werr_ok(tctx, werr, "dsdb_create_prefix_mapping() failed"); /* * The prefix should not change, only on reload */ torture_assert(tctx, pfm_prev == schema->prefixmap, "schema->prefixmap has been reallocated!"); if (!_torture_drs_pfm_compare_same(tctx, pfm_prev, schema->prefixmap, true)) { torture_fail(tctx, "schema->prefixmap has changed"); } /* read from ldb what we have written */ werr = dsdb_read_prefixes_from_ldb(priv->ldb_ctx, mem_ctx, &pfm_ldb); torture_assert_werr_ok(tctx, werr, "dsdb_read_prefixes_from_ldb() failed"); /* compare data written/read */ if (!_torture_drs_pfm_compare_same(tctx, pfm_new, pfm_ldb, true)) { torture_fail(tctx, talloc_asprintf(tctx, "%u: pfm in LDB is different", i)); } /* free mem for pfm read from LDB */ TALLOC_FREE(pfm_ldb); /* prepare for the next round */ schema->prefixmap = pfm_new; } talloc_free(mem_ctx); return true; } /** * Prepare temporary LDB and opens it */ static bool torture_drs_unit_ldb_setup(struct torture_context *tctx, struct drsut_prefixmap_data *priv) { int ldb_err; char *ldb_url; bool bret = true; TALLOC_CTX* mem_ctx; char *tempdir; NTSTATUS status; mem_ctx = talloc_new(priv); status = torture_temp_dir(tctx, "drs_", &tempdir); torture_assert_ntstatus_ok(tctx, status, "creating temp dir"); ldb_url = talloc_asprintf(priv, "%s/drs_test.ldb", tempdir); /* create LDB */ priv->ldb_ctx = ldb_init(priv, tctx->ev); ldb_err = ldb_connect(priv->ldb_ctx, ldb_url, 0, NULL); torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE, "ldb_connect() failed"); /* set some schemaNamingContext */ ldb_err = ldb_set_opaque(priv->ldb_ctx, "schemaNamingContext", ldb_dn_new(priv->ldb_ctx, priv->ldb_ctx, "CN=Schema,CN=Config")); torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE, "ldb_set_opaque() failed"); /* add prefixMap attribute so tested layer could work properly */ { struct ldb_message *msg = ldb_msg_new(mem_ctx); msg->dn = ldb_get_schema_basedn(priv->ldb_ctx); ldb_err = ldb_msg_add_string(msg, "prefixMap", "prefixMap"); torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE, "ldb_msg_add_string() failed"); ldb_err = ldb_add(priv->ldb_ctx, msg); torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE, "ldb_add() failed"); } DONE: talloc_free(mem_ctx); return bret; } /* * Setup/Teardown for test case */ static bool torture_drs_unit_prefixmap_setup(struct torture_context *tctx, struct drsut_prefixmap_data **_priv) { WERROR werr; DATA_BLOB blob; struct drsut_prefixmap_data *priv; priv = *_priv = talloc_zero(tctx, struct drsut_prefixmap_data); torture_assert(tctx, priv != NULL, "Not enough memory"); werr = _drsut_prefixmap_new(_prefixmap_test_new_data, ARRAY_SIZE(_prefixmap_test_new_data), tctx, &priv->pfm_new); torture_assert_werr_ok(tctx, werr, "failed to create pfm_new"); werr = _drsut_prefixmap_new(_prefixmap_full_map_data, ARRAY_SIZE(_prefixmap_full_map_data), tctx, &priv->pfm_full); torture_assert_werr_ok(tctx, werr, "failed to create pfm_test"); torture_assert(tctx, drsut_schemainfo_new(tctx, &priv->schi_default), "drsut_schemainfo_new() failed"); werr = dsdb_blob_from_schema_info(priv->schi_default, priv, &blob); torture_assert_werr_ok(tctx, werr, "dsdb_blob_from_schema_info() failed"); /* create temporary LDB and populate with data */ if (!torture_drs_unit_ldb_setup(tctx, priv)) { return false; } return true; } static bool torture_drs_unit_prefixmap_teardown(struct torture_context *tctx, struct drsut_prefixmap_data *priv) { talloc_free(priv); return true; } /** * Test case initialization for * drs.unit.prefixMap */ struct torture_tcase * torture_drs_unit_prefixmap(struct torture_suite *suite) { typedef bool (*pfn_setup)(struct torture_context *, void **); typedef bool (*pfn_teardown)(struct torture_context *, void *); typedef bool (*pfn_run)(struct torture_context *, void *); struct torture_tcase * tc = torture_suite_add_tcase(suite, "prefixMap"); torture_tcase_set_fixture(tc, (pfn_setup)torture_drs_unit_prefixmap_setup, (pfn_teardown)torture_drs_unit_prefixmap_teardown); tc->description = talloc_strdup(tc, "Unit tests for DRSUAPI::prefixMap implementation"); torture_tcase_add_simple_test(tc, "new", (pfn_run)torture_drs_unit_pfm_new); torture_tcase_add_simple_test(tc, "make_attid_full_map", (pfn_run)torture_drs_unit_pfm_make_attid_full_map); torture_tcase_add_simple_test(tc, "make_attid_small_map", (pfn_run)torture_drs_unit_pfm_make_attid_small_map); torture_tcase_add_simple_test(tc, "attid_from_oid_full_map", (pfn_run)torture_drs_unit_pfm_attid_from_oid_full_map); torture_tcase_add_simple_test(tc, "attid_from_oid_empty_map", (pfn_run)torture_drs_unit_pfm_attid_from_oid_base_map); torture_tcase_add_simple_test(tc, "oid_from_attid_full_map", (pfn_run)torture_drs_unit_pfm_oid_from_attid); torture_tcase_add_simple_test(tc, "oid_from_attid_check_attid", (pfn_run)torture_drs_unit_pfm_oid_from_attid_check_attid); torture_tcase_add_simple_test(tc, "pfm_to_from_drsuapi", (pfn_run)torture_drs_unit_pfm_to_from_drsuapi); torture_tcase_add_simple_test(tc, "pfm_to_from_ldb_val", (pfn_run)torture_drs_unit_pfm_to_from_ldb_val); torture_tcase_add_simple_test(tc, "pfm_read_write_ldb", (pfn_run)torture_drs_unit_pfm_read_write_ldb); torture_tcase_add_simple_test(tc, "dsdb_create_prefix_mapping", (pfn_run)torture_drs_unit_dsdb_create_prefix_mapping); return tc; }