*/
#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"
struct drsut_prefixmap_data {
struct dsdb_schema_prefixmap *pfm_new;
struct dsdb_schema_prefixmap *pfm_full;
+
+ /* default schemaInfo value to test with */
+ const char *schi_default_str;
+ struct dsdb_schema_info *schi_default;
+
+ struct ldb_context *ldb_ctx;
};
/**
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)
+ 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;
+ }
- torture_assert_int_equal(tctx, pfm_left->length, pfm_right->length,
- "prefixMaps differ in size");
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];
- torture_assert(tctx, entry_left->id == entry_right->id,
- talloc_asprintf(tctx, "Different IDs for index=%d", i));
- torture_assert_data_blob_equal(tctx, entry_left->bin_oid, entry_right->bin_oid,
- talloc_asprintf(tctx, "Different bin_oid for index=%d", 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;
}
/*
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);
+ bret = _torture_drs_pfm_compare_same(tctx, priv->pfm_new, pfm, false);
talloc_free(mem_ctx);
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, 0x00000000, tctx, &oid);
+ torture_assert_werr_ok(tctx, werr, "Testing prefixMap type attid = 0x0000000");
+
+ /* 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.
{
WERROR werr;
const char *schema_info;
- const char *schema_info_default = "FF0000000000000000000000000000000123456789";
struct dsdb_schema_prefixmap *pfm;
struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;
TALLOC_CTX *mem_ctx;
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, schema_info_default, mem_ctx, &ctr);
+ werr = dsdb_drsuapi_pfm_from_schema_pfm(priv->pfm_full, priv->schi_default_str, 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,
ctr->mappings[ctr->num_mappings - 1].oid.length);
torture_assert_str_equal(tctx,
schema_info,
- schema_info_default,
+ priv->schi_default_str,
"schema_info not stored correctly or not last entry");
/* compare schema_prefixMap and drsuapi_prefixMap */
/* 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_str_equal(tctx, schema_info, schema_info_default, "Fetched schema_info is different");
+ torture_assert_str_equal(tctx, schema_info, priv->schi_default_str, "Fetched schema_info is different");
+
/* compare against the original */
- if (!_torture_drs_pfm_compare_same(tctx, priv->pfm_full, pfm)) {
+ if (!_torture_drs_pfm_compare_same(tctx, priv->pfm_full, pfm, true)) {
talloc_free(mem_ctx);
return false;
}
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)) {
+ if (!_torture_drs_pfm_compare_same(tctx, priv->pfm_full, pfm, false)) {
talloc_free(mem_ctx);
return false;
}
{
WERROR werr;
const char *schema_info;
- const char *schema_info_default = "FF0000000000000000000000000000000123456789";
struct dsdb_schema *schema;
struct ldb_val pfm_ldb_val;
struct ldb_val schema_info_ldb_val;
mem_ctx = talloc_new(tctx);
torture_assert(tctx, mem_ctx, "Unexpected: Have no memory!");
- schema = dsdb_new_schema(mem_ctx, lp_iconv_convenience(tctx->lp_ctx));
+ 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 = schema_info_default;
+ schema->schema_info = priv->schi_default_str;
/* convert schema_prefixMap to ldb_val blob */
werr = dsdb_get_oid_mappings_ldb(schema, mem_ctx, &pfm_ldb_val, &schema_info_ldb_val);
schema_info_ldb_val.length);
torture_assert_str_equal(tctx,
schema_info,
- schema_info_default,
+ priv->schi_default_str,
"schema_info not stored correctly or not last entry");
/* convert pfm_ldb_val back to schema_prefixMap */
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)) {
+ if (!_torture_drs_pfm_compare_same(tctx, schema->prefixmap, priv->pfm_full, false)) {
talloc_free(mem_ctx);
return false;
}
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_str;
+
+ /* 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 rdsdb_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;
+ const struct {
+ const char *oid;
+ uint32_t attid;
+ bool exists; /* if this prefix already exists or should be added */
+ } _test_data[] = {
+ {.oid="2.5.4.0", .attid=0x00000000, true},
+ {.oid="2.5.4.42", .attid=0x0000002a, true},
+ {.oid="1.2.840.113556.1.2.1", .attid=0x00020001, true},
+ {.oid="1.2.840.113556.1.2.13", .attid=0x0002000d, true},
+ {.oid="1.2.840.113556.1.2.281", .attid=0x00020119, true},
+ {.oid="1.2.840.113556.1.4.125", .attid=0x0009007d, true},
+ {.oid="1.2.840.113556.1.4.146", .attid=0x00090092, true},
+ {.oid="1.2.250.1", .attid=0x1b860001, false},
+ {.oid="1.2.250.16386", .attid=0x1c788002, false},
+ {.oid="1.2.250.2097154", .attid=0x1c7b8002, false},
+ };
+
+ 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_str;
+ 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");
+
+ for (i = 0; i < ARRAY_SIZE(_test_data); i++) {
+ struct dsdb_schema_prefixmap *pfm_ldb;
+ struct dsdb_schema_prefixmap *pfm_prev;
+
+ /* add ref to prefixMap so we can use it later */
+ pfm_prev = talloc_reference(schema, schema->prefixmap);
+
+ /* call dsdb_create_prefix_mapping() and check result accordingly */
+ werr = dsdb_create_prefix_mapping(priv->ldb_ctx, schema, _test_data[i].oid);
+ torture_assert_werr_ok(tctx, werr, "dsdb_create_prefix_mapping() failed");
+
+ /* verify pfm has been altered or not if needed */
+ if (_test_data[i].exists) {
+ 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");
+ }
+ } else {
+ torture_assert(tctx, pfm_prev != schema->prefixmap,
+ "schema->prefixmap should be reallocated!");
+ if (_torture_drs_pfm_compare_same(tctx, pfm_prev, schema->prefixmap, true)) {
+ torture_fail(tctx, "schema->prefixmap should be 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, schema->prefixmap, pfm_ldb, true)) {
+ torture_fail(tctx, "schema->prefixmap and pfm in LDB are different");
+ }
+ /* free mem for pfm read from LDB */
+ talloc_free(pfm_ldb);
+
+ /* release prefixMap pointer */
+ talloc_unlink(schema, pfm_prev);
+ }
+
+ 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_empty() 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)
+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 = talloc_zero(tctx, struct drsut_prefixmap_data);
- torture_assert(tctx, *priv != NULL, "Not enough memory");
+ 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);
+ 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);
+ 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");
+
+ priv->schi_default_str = data_blob_hex_string_upper(priv, &blob);
+
+ /* create temporary LDB and populate with data */
+ if (!torture_drs_unit_ldb_setup(tctx, priv)) {
+ return false;
+ }
+
return true;
}
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, "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;
}