s4-smbtorture: Make test names lowercase and dot-separated.
[samba.git] / source4 / torture / drs / unit / prefixmap_tests.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    DRSUAPI prefixMap unit tests
5
6    Copyright (C) Kamen Mazdrashki <kamenim@samba.org> 2009-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 "torture/rpc/drsuapi.h"
27 #include "torture/drs/proto.h"
28 #include "param/param.h"
29
30
31 /**
32  * Private data to be shared among all test in Test case
33  */
34 struct drsut_prefixmap_data {
35         struct dsdb_schema_prefixmap *pfm_new;
36         struct dsdb_schema_prefixmap *pfm_full;
37
38         /* default schemaInfo value to test with */
39         const char *schi_default_str;
40         struct dsdb_schema_info *schi_default;
41
42         struct ldb_context *ldb_ctx;
43 };
44
45 /**
46  * Test-oid data structure
47  */
48 struct drsut_pfm_oid_data {
49         uint32_t        id;
50         const char      *bin_oid;
51         const char      *oid_prefix;
52 };
53
54 /**
55  * Default prefixMap initialization data.
56  * This prefixMap is what dsdb_schema_pfm_new() should return.
57  * Based on: MS-DRSR, 5.16.4 ATTRTYP-to-OID Conversion
58  *           procedure NewPrefixTable( )
59  */
60 static const struct drsut_pfm_oid_data _prefixmap_test_new_data[] = {
61         {.id=0x00000000, .bin_oid="5504",                 .oid_prefix="2.5.4"},
62         {.id=0x00000001, .bin_oid="5506",                 .oid_prefix="2.5.6"},
63         {.id=0x00000002, .bin_oid="2A864886F7140102",     .oid_prefix="1.2.840.113556.1.2"},
64         {.id=0x00000003, .bin_oid="2A864886F7140103",     .oid_prefix="1.2.840.113556.1.3"},
65         {.id=0x00000004, .bin_oid="6086480165020201",     .oid_prefix="2.16.840.1.101.2.2.1"},
66         {.id=0x00000005, .bin_oid="6086480165020203",     .oid_prefix="2.16.840.1.101.2.2.3"},
67         {.id=0x00000006, .bin_oid="6086480165020105",     .oid_prefix="2.16.840.1.101.2.1.5"},
68         {.id=0x00000007, .bin_oid="6086480165020104",     .oid_prefix="2.16.840.1.101.2.1.4"},
69         {.id=0x00000008, .bin_oid="5505",                 .oid_prefix="2.5.5"},
70         {.id=0x00000009, .bin_oid="2A864886F7140104",     .oid_prefix="1.2.840.113556.1.4"},
71         {.id=0x0000000A, .bin_oid="2A864886F7140105",     .oid_prefix="1.2.840.113556.1.5"},
72         {.id=0x00000013, .bin_oid="0992268993F22C64",     .oid_prefix="0.9.2342.19200300.100"},
73         {.id=0x00000014, .bin_oid="6086480186F84203",     .oid_prefix="2.16.840.1.113730.3"},
74         {.id=0x00000015, .bin_oid="0992268993F22C6401",   .oid_prefix="0.9.2342.19200300.100.1"},
75         {.id=0x00000016, .bin_oid="6086480186F8420301",   .oid_prefix="2.16.840.1.113730.3.1"},
76         {.id=0x00000017, .bin_oid="2A864886F7140105B658", .oid_prefix="1.2.840.113556.1.5.7000"},
77         {.id=0x00000018, .bin_oid="5515",                 .oid_prefix="2.5.21"},
78         {.id=0x00000019, .bin_oid="5512",                 .oid_prefix="2.5.18"},
79         {.id=0x0000001A, .bin_oid="5514",                 .oid_prefix="2.5.20"},
80 };
81
82 /**
83  * Data to be used for creating full prefix map for testing.
84  * 'full-prefixMap' is based on what w2k8 returns as a prefixMap
85  * on clean installation - i.e. prefixMap for clean Schema
86  */
87 static const struct drsut_pfm_oid_data _prefixmap_full_map_data[] = {
88         {.id=0x00000000, .bin_oid="0x5504",                     .oid_prefix="2.5.4"},
89         {.id=0x00000001, .bin_oid="0x5506",                     .oid_prefix="2.5.6"},
90         {.id=0x00000002, .bin_oid="0x2A864886F7140102",         .oid_prefix="1.2.840.113556.1.2"},
91         {.id=0x00000003, .bin_oid="0x2A864886F7140103",         .oid_prefix="1.2.840.113556.1.3"},
92         {.id=0x00000004, .bin_oid="0x6086480165020201",         .oid_prefix="2.16.840.1.101.2.2.1"},
93         {.id=0x00000005, .bin_oid="0x6086480165020203",         .oid_prefix="2.16.840.1.101.2.2.3"},
94         {.id=0x00000006, .bin_oid="0x6086480165020105",         .oid_prefix="2.16.840.1.101.2.1.5"},
95         {.id=0x00000007, .bin_oid="0x6086480165020104",         .oid_prefix="2.16.840.1.101.2.1.4"},
96         {.id=0x00000008, .bin_oid="0x5505",                     .oid_prefix="2.5.5"},
97         {.id=0x00000009, .bin_oid="0x2A864886F7140104",         .oid_prefix="1.2.840.113556.1.4"},
98         {.id=0x0000000a, .bin_oid="0x2A864886F7140105",         .oid_prefix="1.2.840.113556.1.5"},
99         {.id=0x00000013, .bin_oid="0x0992268993F22C64",         .oid_prefix="0.9.2342.19200300.100"},
100         {.id=0x00000014, .bin_oid="0x6086480186F84203",         .oid_prefix="2.16.840.1.113730.3"},
101         {.id=0x00000015, .bin_oid="0x0992268993F22C6401",       .oid_prefix="0.9.2342.19200300.100.1"},
102         {.id=0x00000016, .bin_oid="0x6086480186F8420301",       .oid_prefix="2.16.840.1.113730.3.1"},
103         {.id=0x00000017, .bin_oid="0x2A864886F7140105B658",     .oid_prefix="1.2.840.113556.1.5.7000"},
104         {.id=0x00000018, .bin_oid="0x5515",                     .oid_prefix="2.5.21"},
105         {.id=0x00000019, .bin_oid="0x5512",                     .oid_prefix="2.5.18"},
106         {.id=0x0000001a, .bin_oid="0x5514",                     .oid_prefix="2.5.20"},
107         {.id=0x0000000b, .bin_oid="0x2A864886F71401048204",     .oid_prefix="1.2.840.113556.1.4.260"},
108         {.id=0x0000000c, .bin_oid="0x2A864886F714010538",       .oid_prefix="1.2.840.113556.1.5.56"},
109         {.id=0x0000000d, .bin_oid="0x2A864886F71401048206",     .oid_prefix="1.2.840.113556.1.4.262"},
110         {.id=0x0000000e, .bin_oid="0x2A864886F714010539",       .oid_prefix="1.2.840.113556.1.5.57"},
111         {.id=0x0000000f, .bin_oid="0x2A864886F71401048207",     .oid_prefix="1.2.840.113556.1.4.263"},
112         {.id=0x00000010, .bin_oid="0x2A864886F71401053A",       .oid_prefix="1.2.840.113556.1.5.58"},
113         {.id=0x00000011, .bin_oid="0x2A864886F714010549",       .oid_prefix="1.2.840.113556.1.5.73"},
114         {.id=0x00000012, .bin_oid="0x2A864886F71401048231",     .oid_prefix="1.2.840.113556.1.4.305"},
115         {.id=0x0000001b, .bin_oid="0x2B060104018B3A6577",       .oid_prefix="1.3.6.1.4.1.1466.101.119"},
116         {.id=0x0000001c, .bin_oid="0x6086480186F8420302",       .oid_prefix="2.16.840.1.113730.3.2"},
117         {.id=0x0000001d, .bin_oid="0x2B06010401817A01",         .oid_prefix="1.3.6.1.4.1.250.1"},
118         {.id=0x0000001e, .bin_oid="0x2A864886F70D0109",         .oid_prefix="1.2.840.113549.1.9"},
119         {.id=0x0000001f, .bin_oid="0x0992268993F22C6404",       .oid_prefix="0.9.2342.19200300.100.4"},
120         {.id=0x00000020, .bin_oid="0x2A864886F714010617",       .oid_prefix="1.2.840.113556.1.6.23"},
121         {.id=0x00000021, .bin_oid="0x2A864886F71401061201",     .oid_prefix="1.2.840.113556.1.6.18.1"},
122         {.id=0x00000022, .bin_oid="0x2A864886F71401061202",     .oid_prefix="1.2.840.113556.1.6.18.2"},
123         {.id=0x00000023, .bin_oid="0x2A864886F71401060D03",     .oid_prefix="1.2.840.113556.1.6.13.3"},
124         {.id=0x00000024, .bin_oid="0x2A864886F71401060D04",     .oid_prefix="1.2.840.113556.1.6.13.4"},
125         {.id=0x00000025, .bin_oid="0x2B0601010101",             .oid_prefix="1.3.6.1.1.1.1"},
126         {.id=0x00000026, .bin_oid="0x2B0601010102",             .oid_prefix="1.3.6.1.1.1.2"},
127         {.id=0x000003ed, .bin_oid="0x2A864886F7140104B65866",   .oid_prefix="1.2.840.113556.1.4.7000.102"},
128         {.id=0x00000428, .bin_oid="0x2A864886F7140105B6583E",   .oid_prefix="1.2.840.113556.1.5.7000.62"},
129         {.id=0x0000044c, .bin_oid="0x2A864886F7140104B6586683", .oid_prefix="1.2.840.113556.1.4.7000.102:0x83"},
130         {.id=0x0000044f, .bin_oid="0x2A864886F7140104B6586681", .oid_prefix="1.2.840.113556.1.4.7000.102:0x81"},
131         {.id=0x0000047d, .bin_oid="0x2A864886F7140105B6583E81", .oid_prefix="1.2.840.113556.1.5.7000.62:0x81"},
132         {.id=0x00000561, .bin_oid="0x2A864886F7140105B6583E83", .oid_prefix="1.2.840.113556.1.5.7000.62:0x83"},
133         {.id=0x000007d1, .bin_oid="0x2A864886F71401061401",     .oid_prefix="1.2.840.113556.1.6.20.1"},
134         {.id=0x000007e1, .bin_oid="0x2A864886F71401061402",     .oid_prefix="1.2.840.113556.1.6.20.2"},
135         {.id=0x00001b86, .bin_oid="0x2A817A",                   .oid_prefix="1.2.250"},
136         {.id=0x00001c78, .bin_oid="0x2A817A81",                 .oid_prefix="1.2.250:0x81"},
137         {.id=0x00001c7b, .bin_oid="0x2A817A8180",               .oid_prefix="1.2.250:0x8180"},
138 };
139
140
141 /**
142  * OID-to-ATTID mappings to be used for testing.
143  * An entry is marked as 'exists=true' if it exists in
144  * base prefixMap (_prefixmap_test_new_data)
145  */
146 static const struct {
147         const char      *oid;
148         uint32_t        id;
149         uint32_t        attid;
150         bool            exists;
151 } _prefixmap_test_data[] = {
152         {.oid="2.5.4.0",                .id=0x00000000, .attid=0x000000,   .exists=true},
153         {.oid="2.5.4.42",               .id=0x00000000, .attid=0x00002a,   .exists=true},
154         {.oid="1.2.840.113556.1.2.1",   .id=0x00000002, .attid=0x020001,   .exists=true},
155         {.oid="1.2.840.113556.1.2.13",  .id=0x00000002, .attid=0x02000d,   .exists=true},
156         {.oid="1.2.840.113556.1.2.281", .id=0x00000002, .attid=0x020119,   .exists=true},
157         {.oid="1.2.840.113556.1.4.125", .id=0x00000009, .attid=0x09007d,   .exists=true},
158         {.oid="1.2.840.113556.1.4.146", .id=0x00000009, .attid=0x090092,   .exists=true},
159         {.oid="1.2.250.1",              .id=0x00001b86, .attid=0x1b860001, .exists=false},
160         {.oid="1.2.250.16386",          .id=0x00001c78, .attid=0x1c788002, .exists=false},
161         {.oid="1.2.250.2097154",        .id=0x00001c7b, .attid=0x1c7b8002, .exists=false},
162 };
163
164
165 /**
166  * Creates dsdb_schema_prefixmap based on predefined data
167  */
168 static WERROR _drsut_prefixmap_new(const struct drsut_pfm_oid_data *_pfm_init_data, uint32_t count,
169                                    TALLOC_CTX *mem_ctx, struct dsdb_schema_prefixmap **_pfm)
170 {
171         uint32_t i;
172         struct dsdb_schema_prefixmap *pfm;
173
174         pfm = talloc(mem_ctx, struct dsdb_schema_prefixmap);
175         W_ERROR_HAVE_NO_MEMORY(pfm);
176
177         pfm->length = count;
178         pfm->prefixes = talloc_array(pfm, struct dsdb_schema_prefixmap_oid, pfm->length);
179         if (!pfm->prefixes) {
180                 talloc_free(pfm);
181                 return WERR_NOMEM;
182         }
183
184         for (i = 0; i < pfm->length; i++) {
185                 pfm->prefixes[i].id = _pfm_init_data[i].id;
186                 pfm->prefixes[i].bin_oid = strhex_to_data_blob(pfm, _pfm_init_data[i].bin_oid);
187                 if (!pfm->prefixes[i].bin_oid.data) {
188                         talloc_free(pfm);
189                         return WERR_NOMEM;
190                 }
191         }
192
193         *_pfm = pfm;
194
195         return WERR_OK;
196 }
197
198 /**
199  * Compares two prefixMaps for being equal - same items on same indexes
200  */
201 static bool _torture_drs_pfm_compare_same(struct torture_context *tctx,
202                                           const struct dsdb_schema_prefixmap *pfm_left,
203                                           const struct dsdb_schema_prefixmap *pfm_right,
204                                           bool quiet)
205 {
206         uint32_t i;
207         char *err_msg = NULL;
208
209         if (pfm_left->length != pfm_right->length) {
210                 err_msg = talloc_asprintf(tctx, "prefixMaps differ in size; left = %d, right = %d",
211                                           pfm_left->length, pfm_right->length);
212                 goto failed;
213         }
214
215         for (i = 0; i < pfm_left->length; i++) {
216                 struct dsdb_schema_prefixmap_oid *entry_left = &pfm_left->prefixes[i];
217                 struct dsdb_schema_prefixmap_oid *entry_right = &pfm_right->prefixes[i];
218
219                 if (entry_left->id != entry_right->id) {
220                         err_msg = talloc_asprintf(tctx, "Different IDs for index=%d", i);
221                         goto failed;
222                 }
223                 if (data_blob_cmp(&entry_left->bin_oid, &entry_right->bin_oid)) {
224                         err_msg = talloc_asprintf(tctx, "Different bin_oid for index=%d", i);
225                         goto failed;
226                 }
227         }
228
229         return true;
230
231 failed:
232         if (!quiet) {
233                 torture_comment(tctx, "_torture_drs_pfm_compare_same: %s", err_msg);
234         }
235         talloc_free(err_msg);
236
237         return false;
238 }
239
240 /*
241  * Tests dsdb_schema_pfm_new()
242  */
243 static bool torture_drs_unit_pfm_new(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
244 {
245         WERROR werr;
246         bool bret;
247         TALLOC_CTX *mem_ctx;
248         struct dsdb_schema_prefixmap *pfm = NULL;
249
250         mem_ctx = talloc_new(priv);
251
252         /* create new prefix map */
253         werr = dsdb_schema_pfm_new(mem_ctx, &pfm);
254         torture_assert_werr_ok(tctx, werr, "dsdb_schema_pfm_new() failed!");
255         torture_assert(tctx, pfm != NULL, "NULL prefixMap created!");
256         torture_assert(tctx, pfm->length > 0, "Empty prefixMap created!");
257         torture_assert(tctx, pfm->prefixes != NULL, "No prefixes for newly created prefixMap!");
258
259         /* compare newly created prefixMap with template one */
260         bret = _torture_drs_pfm_compare_same(tctx, priv->pfm_new, pfm, false);
261
262         talloc_free(mem_ctx);
263
264         return bret;
265 }
266
267 /**
268  * Tests dsdb_schema_pfm_make_attid() using full prefixMap.
269  * In this test we know exactly which ATTID and prefixMap->ID
270  * should be returned, i.e. no prefixMap entries should be added.
271  */
272 static bool torture_drs_unit_pfm_make_attid_full_map(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
273 {
274         WERROR werr;
275         uint32_t i, count;
276         uint32_t attid;
277         char *err_msg;
278
279         count = ARRAY_SIZE(_prefixmap_test_data);
280         for (i = 0; i < count; i++) {
281                 werr = dsdb_schema_pfm_make_attid(priv->pfm_full, _prefixmap_test_data[i].oid, &attid);
282                 /* prepare error message */
283                 err_msg = talloc_asprintf(priv, "dsdb_schema_pfm_make_attid() failed with %s",
284                                                 _prefixmap_test_data[i].oid);
285                 torture_assert(tctx, err_msg, "Unexpected: Have no memory!");
286                 /* verify result and returned ATTID */
287                 torture_assert_werr_ok(tctx, werr, err_msg);
288                 torture_assert_int_equal(tctx, attid, _prefixmap_test_data[i].attid, err_msg);
289                 /* reclaim memory for prepared error message */
290                 talloc_free(err_msg);
291         }
292
293         return true;
294 }
295
296 /**
297  * Tests dsdb_schema_pfm_make_attid() using initially small prefixMap.
298  * In this test we don't know exactly which ATTID and prefixMap->ID
299  * should be returned, but we can verify lo-word of ATTID.
300  * This test verifies implementation branch when a new
301  * prefix should be added into prefixMap.
302  */
303 static bool torture_drs_unit_pfm_make_attid_small_map(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
304 {
305         WERROR werr;
306         uint32_t i, j;
307         uint32_t idx;
308         uint32_t attid, attid_2;
309         char *err_msg;
310         struct dsdb_schema_prefixmap *pfm = NULL;
311         TALLOC_CTX *mem_ctx;
312
313         mem_ctx = talloc_new(priv);
314
315         /* create new prefix map */
316         werr = dsdb_schema_pfm_new(mem_ctx, &pfm);
317         torture_assert_werr_ok(tctx, werr, "dsdb_schema_pfm_new() failed!");
318
319         /* make some ATTIDs and check result */
320         for (i = 0; i < ARRAY_SIZE(_prefixmap_test_data); i++) {
321                 werr = dsdb_schema_pfm_make_attid(pfm, _prefixmap_test_data[i].oid, &attid);
322
323                 /* prepare error message */
324                 err_msg = talloc_asprintf(mem_ctx, "dsdb_schema_pfm_make_attid() failed with %s",
325                                                 _prefixmap_test_data[i].oid);
326                 torture_assert(tctx, err_msg, "Unexpected: Have no memory!");
327
328                 /* verify result and returned ATTID */
329                 torture_assert_werr_ok(tctx, werr, err_msg);
330                 /* verify ATTID lo-word */
331                 torture_assert_int_equal(tctx, attid & 0xFFFF, _prefixmap_test_data[i].attid & 0xFFFF, err_msg);
332
333                 /* try again, this time verify for whole ATTID */
334                 werr = dsdb_schema_pfm_make_attid(pfm, _prefixmap_test_data[i].oid, &attid_2);
335                 torture_assert_werr_ok(tctx, werr, err_msg);
336                 torture_assert_int_equal(tctx, attid_2, attid, err_msg);
337
338                 /* reclaim memory for prepared error message */
339                 talloc_free(err_msg);
340
341                 /* check there is such an index in modified prefixMap */
342                 idx = (attid >> 16);
343                 for (j = 0; j < pfm->length; j++) {
344                         if (pfm->prefixes[j].id == idx)
345                                 break;
346                 }
347                 if (j >= pfm->length) {
348                         torture_result(tctx, TORTURE_FAIL, __location__": No prefix for ATTID=0x%08X", attid);
349                         return false;
350                 }
351
352         }
353
354         talloc_free(mem_ctx);
355
356         return true;
357 }
358
359 /**
360  * Tests dsdb_schema_pfm_attid_from_oid() using full prefixMap.
361  * In this test we know exactly which ATTID and prefixMap->ID
362  * should be returned- dsdb_schema_pfm_attid_from_oid() should succeed.
363  */
364 static bool torture_drs_unit_pfm_attid_from_oid_full_map(struct torture_context *tctx,
365                                                          struct drsut_prefixmap_data *priv)
366 {
367         WERROR werr;
368         uint32_t i, count;
369         uint32_t attid;
370         char *err_msg;
371
372         count = ARRAY_SIZE(_prefixmap_test_data);
373         for (i = 0; i < count; i++) {
374                 werr = dsdb_schema_pfm_attid_from_oid(priv->pfm_full,
375                                                       _prefixmap_test_data[i].oid,
376                                                       &attid);
377                 /* prepare error message */
378                 err_msg = talloc_asprintf(priv, "dsdb_schema_pfm_attid_from_oid() failed with %s",
379                                                 _prefixmap_test_data[i].oid);
380                 torture_assert(tctx, err_msg, "Unexpected: Have no memory!");
381                 /* verify result and returned ATTID */
382                 torture_assert_werr_ok(tctx, werr, err_msg);
383                 torture_assert_int_equal(tctx, attid, _prefixmap_test_data[i].attid, err_msg);
384                 /* reclaim memory for prepared error message */
385                 talloc_free(err_msg);
386         }
387
388         return true;
389 }
390
391 /**
392  * Tests dsdb_schema_pfm_attid_from_oid() using base (initial) prefixMap.
393  * dsdb_schema_pfm_attid_from_oid() should fail when testing with OID
394  * that are not already in the prefixMap.
395  */
396 static bool torture_drs_unit_pfm_attid_from_oid_base_map(struct torture_context *tctx,
397                                                          struct drsut_prefixmap_data *priv)
398 {
399         WERROR werr;
400         uint32_t i;
401         uint32_t attid;
402         char *err_msg;
403         struct dsdb_schema_prefixmap *pfm = NULL;
404         struct dsdb_schema_prefixmap pfm_prev;
405         TALLOC_CTX *mem_ctx;
406
407         mem_ctx = talloc_new(priv);
408         torture_assert(tctx, mem_ctx, "Unexpected: Have no memory!");
409
410         /* create new prefix map */
411         werr = dsdb_schema_pfm_new(mem_ctx, &pfm);
412         torture_assert_werr_ok(tctx, werr, "dsdb_schema_pfm_new() failed!");
413
414         /* keep initial pfm around for testing */
415         pfm_prev = *pfm;
416         pfm_prev.prefixes = talloc_reference(mem_ctx, pfm->prefixes);
417
418         /* get some ATTIDs and check result */
419         for (i = 0; i < ARRAY_SIZE(_prefixmap_test_data); i++) {
420                 werr = dsdb_schema_pfm_attid_from_oid(pfm, _prefixmap_test_data[i].oid, &attid);
421
422                 /* prepare error message */
423                 err_msg = talloc_asprintf(mem_ctx,
424                                           "dsdb_schema_pfm_attid_from_oid() failed for %s",
425                                           _prefixmap_test_data[i].oid);
426                 torture_assert(tctx, err_msg, "Unexpected: Have no memory!");
427
428
429                 /* verify pfm hasn't been altered */
430                 if (_prefixmap_test_data[i].exists) {
431                         /* should succeed and return valid ATTID */
432                         torture_assert_werr_ok(tctx, werr, err_msg);
433                         /* verify ATTID */
434                         torture_assert_int_equal(tctx,
435                                                  attid, _prefixmap_test_data[i].attid,
436                                                  err_msg);
437                 } else {
438                         /* should fail */
439                         torture_assert_werr_equal(tctx, werr, WERR_NOT_FOUND, err_msg);
440                 }
441
442                 /* prefixMap should never be changed */
443                 if (!_torture_drs_pfm_compare_same(tctx, &pfm_prev, pfm, true)) {
444                         torture_fail(tctx, "schema->prefixmap has changed");
445                 }
446
447                 /* reclaim memory for prepared error message */
448                 talloc_free(err_msg);
449         }
450
451         talloc_free(mem_ctx);
452
453         return true;
454 }
455
456 /**
457  * Tests dsdb_schema_pfm_oid_from_attid() using full prefixMap.
458  */
459 static bool torture_drs_unit_pfm_oid_from_attid(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
460 {
461         WERROR werr;
462         uint32_t i, count;
463         char *err_msg;
464         const char *oid;
465
466         count = ARRAY_SIZE(_prefixmap_test_data);
467         for (i = 0; i < count; i++) {
468                 oid = NULL;
469                 werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, _prefixmap_test_data[i].attid,
470                                                       priv, &oid);
471                 /* prepare error message */
472                 err_msg = talloc_asprintf(priv, "dsdb_schema_pfm_oid_from_attid() failed with 0x%08X",
473                                                 _prefixmap_test_data[i].attid);
474                 torture_assert(tctx, err_msg, "Unexpected: Have no memory!");
475                 /* verify result and returned ATTID */
476                 torture_assert_werr_ok(tctx, werr, err_msg);
477                 torture_assert(tctx, oid, "dsdb_schema_pfm_oid_from_attid() returned NULL OID!!!");
478                 torture_assert_str_equal(tctx, oid, _prefixmap_test_data[i].oid, err_msg);
479                 /* reclaim memory for prepared error message */
480                 talloc_free(err_msg);
481                 /* free memory for OID */
482                 talloc_free(discard_const(oid));
483         }
484
485         return true;
486 }
487
488 /**
489  * Tests dsdb_schema_pfm_oid_from_attid() for handling
490  * correctly different type of attid values.
491  * See: MS-ADTS, 3.1.1.2.6 ATTRTYP
492  */
493 static bool torture_drs_unit_pfm_oid_from_attid_check_attid(struct torture_context *tctx,
494                                                             struct drsut_prefixmap_data *priv)
495 {
496         WERROR werr;
497         const char *oid;
498
499         /* Test with valid prefixMap attid */
500         werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0x00010001, tctx, &oid);
501         torture_assert_werr_ok(tctx, werr, "Testing prefixMap type attid = 0x00010001");
502
503         /* Test with valid attid but invalid index */
504         werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0x01110001, tctx, &oid);
505         torture_assert_werr_equal(tctx, werr, WERR_DS_NO_ATTRIBUTE_OR_VALUE,
506                                   "Testing invalid-index attid = 0x01110001");
507
508         /* Test with attid in msDS-IntId range */
509         werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0x80000000, tctx, &oid);
510         torture_assert_werr_equal(tctx, werr, WERR_INVALID_PARAMETER,
511                                   "Testing msDS-IntId type attid = 0x80000000");
512         werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0xBFFFFFFF, tctx, &oid);
513         torture_assert_werr_equal(tctx, werr, WERR_INVALID_PARAMETER,
514                                   "Testing msDS-IntId type attid = 0xBFFFFFFF");
515
516         /* Test with attid in RESERVED range */
517         werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0xC0000000, tctx, &oid);
518         torture_assert_werr_equal(tctx, werr, WERR_INVALID_PARAMETER,
519                                   "Testing RESERVED type attid = 0xC0000000");
520         werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0xFFFEFFFF, tctx, &oid);
521         torture_assert_werr_equal(tctx, werr, WERR_INVALID_PARAMETER,
522                                   "Testing RESERVED type attid = 0xFFFEFFFF");
523
524         /* Test with attid in INTERNAL range */
525         werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0xFFFF0000, tctx, &oid);
526         torture_assert_werr_equal(tctx, werr, WERR_INVALID_PARAMETER,
527                                   "Testing INTERNAL type attid = 0xFFFF0000");
528         werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0xFFFFFFFF, tctx, &oid);
529         torture_assert_werr_equal(tctx, werr, WERR_INVALID_PARAMETER,
530                                   "Testing INTERNAL type attid = 0xFFFFFFFF");
531
532         return true;
533 }
534
535 /**
536  * Test Schema prefixMap conversions to/from drsuapi prefixMap
537  * representation.
538  */
539 static bool torture_drs_unit_pfm_to_from_drsuapi(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
540 {
541         WERROR werr;
542         const char *schema_info;
543         struct dsdb_schema_prefixmap *pfm;
544         struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;
545         TALLOC_CTX *mem_ctx;
546
547         mem_ctx = talloc_new(tctx);
548         torture_assert(tctx, mem_ctx, "Unexpected: Have no memory!");
549
550         /* convert Schema_prefixMap to drsuapi_prefixMap */
551         werr = dsdb_drsuapi_pfm_from_schema_pfm(priv->pfm_full, priv->schi_default_str, mem_ctx, &ctr);
552         torture_assert_werr_ok(tctx, werr, "dsdb_drsuapi_pfm_from_schema_pfm() failed");
553         torture_assert(tctx, ctr && ctr->mappings, "drsuapi_prefixMap not constructed correctly");
554         torture_assert_int_equal(tctx, ctr->num_mappings, priv->pfm_full->length + 1,
555                                  "drs_mappings count does not match");
556         /* look for schema_info entry - it should be the last one */
557         schema_info = hex_encode_talloc(mem_ctx,
558                                         ctr->mappings[ctr->num_mappings - 1].oid.binary_oid,
559                                         ctr->mappings[ctr->num_mappings - 1].oid.length);
560         torture_assert_str_equal(tctx,
561                                  schema_info,
562                                  priv->schi_default_str,
563                                  "schema_info not stored correctly or not last entry");
564
565         /* compare schema_prefixMap and drsuapi_prefixMap */
566         werr = dsdb_schema_pfm_contains_drsuapi_pfm(priv->pfm_full, ctr);
567         torture_assert_werr_ok(tctx, werr, "dsdb_schema_pfm_contains_drsuapi_pfm() failed");
568
569         /* convert back drsuapi_prefixMap to schema_prefixMap */
570         werr = dsdb_schema_pfm_from_drsuapi_pfm(ctr, true, mem_ctx, &pfm, &schema_info);
571         torture_assert_werr_ok(tctx, werr, "dsdb_schema_pfm_from_drsuapi_pfm() failed");
572         torture_assert_str_equal(tctx, schema_info, priv->schi_default_str, "Fetched schema_info is different");
573
574         /* compare against the original */
575         if (!_torture_drs_pfm_compare_same(tctx, priv->pfm_full, pfm, true)) {
576                 talloc_free(mem_ctx);
577                 return false;
578         }
579
580         /* test conversion with partial drsuapi_prefixMap */
581         ctr->num_mappings--;
582         werr = dsdb_schema_pfm_from_drsuapi_pfm(ctr, false, mem_ctx, &pfm, NULL);
583         torture_assert_werr_ok(tctx, werr, "dsdb_schema_pfm_from_drsuapi_pfm() failed");
584         /* compare against the original */
585         if (!_torture_drs_pfm_compare_same(tctx, priv->pfm_full, pfm, false)) {
586                 talloc_free(mem_ctx);
587                 return false;
588         }
589
590         talloc_free(mem_ctx);
591         return true;
592 }
593
594
595 /**
596  * Test Schema prefixMap conversions to/from ldb_val
597  * blob representation.
598  */
599 static bool torture_drs_unit_pfm_to_from_ldb_val(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
600 {
601         WERROR werr;
602         const char *schema_info;
603         struct dsdb_schema *schema;
604         struct ldb_val pfm_ldb_val;
605         struct ldb_val schema_info_ldb_val;
606         TALLOC_CTX *mem_ctx;
607
608         mem_ctx = talloc_new(tctx);
609         torture_assert(tctx, mem_ctx, "Unexpected: Have no memory!");
610
611         schema = dsdb_new_schema(mem_ctx);
612         torture_assert(tctx, schema, "Unexpected: failed to allocate schema object");
613
614         /* set priv->pfm_full as prefixMap for new schema object */
615         schema->prefixmap = priv->pfm_full;
616         schema->schema_info = priv->schi_default_str;
617
618         /* convert schema_prefixMap to ldb_val blob */
619         werr = dsdb_get_oid_mappings_ldb(schema, mem_ctx, &pfm_ldb_val, &schema_info_ldb_val);
620         torture_assert_werr_ok(tctx, werr, "dsdb_get_oid_mappings_ldb() failed");
621         torture_assert(tctx, pfm_ldb_val.data && pfm_ldb_val.length,
622                        "pfm_ldb_val not constructed correctly");
623         torture_assert(tctx, schema_info_ldb_val.data && schema_info_ldb_val.length,
624                        "schema_info_ldb_val not constructed correctly");
625         /* look for schema_info entry - it should be the last one */
626         schema_info = hex_encode_talloc(mem_ctx,
627                                         schema_info_ldb_val.data,
628                                         schema_info_ldb_val.length);
629         torture_assert_str_equal(tctx,
630                                  schema_info,
631                                  priv->schi_default_str,
632                                  "schema_info not stored correctly or not last entry");
633
634         /* convert pfm_ldb_val back to schema_prefixMap */
635         schema->prefixmap = NULL;
636         schema->schema_info = NULL;
637         werr = dsdb_load_oid_mappings_ldb(schema, &pfm_ldb_val, &schema_info_ldb_val);
638         torture_assert_werr_ok(tctx, werr, "dsdb_load_oid_mappings_ldb() failed");
639         /* compare against the original */
640         if (!_torture_drs_pfm_compare_same(tctx, schema->prefixmap, priv->pfm_full, false)) {
641                 talloc_free(mem_ctx);
642                 return false;
643         }
644
645         talloc_free(mem_ctx);
646         return true;
647 }
648
649 /**
650  * Test read/write in ldb implementation
651  */
652 static bool torture_drs_unit_pfm_read_write_ldb(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
653 {
654         WERROR werr;
655         struct dsdb_schema *schema;
656         struct dsdb_schema_prefixmap *pfm;
657         TALLOC_CTX *mem_ctx;
658
659         mem_ctx = talloc_new(tctx);
660         torture_assert(tctx, mem_ctx, "Unexpected: Have no memory!");
661
662         /* makeup a dsdb_schema to test with */
663         schema = dsdb_new_schema(mem_ctx);
664         torture_assert(tctx, schema, "Unexpected: failed to allocate schema object");
665         /* set priv->pfm_full as prefixMap for new schema object */
666         schema->prefixmap = priv->pfm_full;
667         schema->schema_info = priv->schi_default_str;
668
669         /* write prfixMap to ldb */
670         werr = dsdb_write_prefixes_from_schema_to_ldb(mem_ctx, priv->ldb_ctx, schema);
671         torture_assert_werr_ok(tctx, werr, "dsdb_write_prefixes_from_schema_to_ldb() failed");
672
673         /* read from ldb what we have written */
674         werr = dsdb_read_prefixes_from_ldb(priv->ldb_ctx, mem_ctx, &pfm);
675         torture_assert_werr_ok(tctx, werr, "dsdb_read_prefixes_from_ldb() failed");
676
677         /* compare data written/read */
678         if (!_torture_drs_pfm_compare_same(tctx, schema->prefixmap, priv->pfm_full, false)) {
679                 torture_fail(tctx, "prefixMap read/write in LDB is not consistent");
680         }
681
682         talloc_free(mem_ctx);
683
684         return true;
685 }
686
687 /**
688  * Test dsdb_create_prefix_mapping
689  */
690 static bool torture_drs_unit_dsdb_create_prefix_mapping(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
691 {
692         WERROR werr;
693         uint32_t i;
694         struct dsdb_schema *schema;
695         TALLOC_CTX *mem_ctx;
696
697         mem_ctx = talloc_new(tctx);
698         torture_assert(tctx, mem_ctx, "Unexpected: Have no memory!");
699
700         /* makeup a dsdb_schema to test with */
701         schema = dsdb_new_schema(mem_ctx);
702         torture_assert(tctx, schema, "Unexpected: failed to allocate schema object");
703         /* set priv->pfm_full as prefixMap for new schema object */
704         schema->schema_info = priv->schi_default_str;
705         werr = _drsut_prefixmap_new(_prefixmap_test_new_data, ARRAY_SIZE(_prefixmap_test_new_data),
706                                     schema, &schema->prefixmap);
707         torture_assert_werr_ok(tctx, werr, "_drsut_prefixmap_new() failed");
708         /* write prfixMap to ldb */
709         werr = dsdb_write_prefixes_from_schema_to_ldb(mem_ctx, priv->ldb_ctx, schema);
710         torture_assert_werr_ok(tctx, werr, "dsdb_write_prefixes_from_schema_to_ldb() failed");
711
712         for (i = 0; i < ARRAY_SIZE(_prefixmap_test_data); i++) {
713                 struct dsdb_schema_prefixmap *pfm_ldb;
714                 struct dsdb_schema_prefixmap *pfm_prev;
715
716                 /* add ref to prefixMap so we can use it later */
717                 pfm_prev = talloc_reference(schema, schema->prefixmap);
718
719                 /* call dsdb_create_prefix_mapping() and check result accordingly */
720                 werr = dsdb_create_prefix_mapping(priv->ldb_ctx, schema, _prefixmap_test_data[i].oid);
721                 torture_assert_werr_ok(tctx, werr, "dsdb_create_prefix_mapping() failed");
722
723                 /* verify pfm has been altered or not if needed */
724                 if (_prefixmap_test_data[i].exists) {
725                         torture_assert(tctx, pfm_prev == schema->prefixmap,
726                                        "schema->prefixmap has been reallocated!");
727                         if (!_torture_drs_pfm_compare_same(tctx, pfm_prev, schema->prefixmap, true)) {
728                                 torture_fail(tctx, "schema->prefixmap has changed");
729                         }
730                 } else {
731                         torture_assert(tctx, pfm_prev != schema->prefixmap,
732                                        "schema->prefixmap should be reallocated!");
733                         if (_torture_drs_pfm_compare_same(tctx, pfm_prev, schema->prefixmap, true)) {
734                                 torture_fail(tctx, "schema->prefixmap should be changed");
735                         }
736                 }
737
738                 /* read from ldb what we have written */
739                 werr = dsdb_read_prefixes_from_ldb(priv->ldb_ctx, mem_ctx, &pfm_ldb);
740                 torture_assert_werr_ok(tctx, werr, "dsdb_read_prefixes_from_ldb() failed");
741                 /* compare data written/read */
742                 if (!_torture_drs_pfm_compare_same(tctx, schema->prefixmap, pfm_ldb, true)) {
743                         torture_fail(tctx, "schema->prefixmap and pfm in LDB are different");
744                 }
745                 /* free mem for pfm read from LDB */
746                 talloc_free(pfm_ldb);
747
748                 /* release prefixMap pointer */
749                 talloc_unlink(schema, pfm_prev);
750         }
751
752         talloc_free(mem_ctx);
753
754         return true;
755 }
756
757 /**
758  * Prepare temporary LDB and opens it
759  */
760 static bool torture_drs_unit_ldb_setup(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
761 {
762         int ldb_err;
763         char *ldb_url;
764         bool bret = true;
765         TALLOC_CTX* mem_ctx;
766         char *tempdir;
767         NTSTATUS status;
768
769         mem_ctx = talloc_new(priv);
770
771         status = torture_temp_dir(tctx, "drs_", &tempdir);
772         torture_assert_ntstatus_ok(tctx, status, "creating temp dir");
773
774         ldb_url = talloc_asprintf(priv, "%s/drs_test.ldb", tempdir);
775
776         /* create LDB */
777         priv->ldb_ctx = ldb_init(priv, tctx->ev);
778         ldb_err = ldb_connect(priv->ldb_ctx, ldb_url, 0, NULL);
779         torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE, "ldb_connect() failed");
780
781         /* set some schemaNamingContext */
782         ldb_err = ldb_set_opaque(priv->ldb_ctx,
783                                  "schemaNamingContext",
784                                  ldb_dn_new(priv->ldb_ctx, priv->ldb_ctx, "CN=Schema,CN=Config"));
785         torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE, "ldb_set_opaque() failed");
786
787         /* add prefixMap attribute so tested layer could work properly */
788         {
789                 struct ldb_message *msg = ldb_msg_new(mem_ctx);
790                 msg->dn = ldb_get_schema_basedn(priv->ldb_ctx);
791                 ldb_err = ldb_msg_add_string(msg, "prefixMap", "prefixMap");
792                 torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE,
793                                               "ldb_msg_add_empty() failed");
794
795                 ldb_err = ldb_add(priv->ldb_ctx, msg);
796                 torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE, "ldb_add() failed");
797         }
798
799 DONE:
800         talloc_free(mem_ctx);
801         return bret;
802 }
803
804 /*
805  * Setup/Teardown for test case
806  */
807 static bool torture_drs_unit_prefixmap_setup(struct torture_context *tctx, struct drsut_prefixmap_data **_priv)
808 {
809         WERROR werr;
810         DATA_BLOB blob;
811         struct drsut_prefixmap_data *priv;
812
813         priv = *_priv = talloc_zero(tctx, struct drsut_prefixmap_data);
814         torture_assert(tctx, priv != NULL, "Not enough memory");
815
816         werr = _drsut_prefixmap_new(_prefixmap_test_new_data, ARRAY_SIZE(_prefixmap_test_new_data),
817                                     tctx, &priv->pfm_new);
818         torture_assert_werr_ok(tctx, werr, "failed to create pfm_new");
819
820         werr = _drsut_prefixmap_new(_prefixmap_full_map_data, ARRAY_SIZE(_prefixmap_full_map_data),
821                                     tctx, &priv->pfm_full);
822         torture_assert_werr_ok(tctx, werr, "failed to create pfm_test");
823
824         torture_assert(tctx, drsut_schemainfo_new(tctx, &priv->schi_default),
825                        "drsut_schemainfo_new() failed");
826
827         werr = dsdb_blob_from_schema_info(priv->schi_default, priv, &blob);
828         torture_assert_werr_ok(tctx, werr, "dsdb_blob_from_schema_info() failed");
829
830         priv->schi_default_str = data_blob_hex_string_upper(priv, &blob);
831
832         /* create temporary LDB and populate with data */
833         if (!torture_drs_unit_ldb_setup(tctx, priv)) {
834                 return false;
835         }
836
837         return true;
838 }
839
840 static bool torture_drs_unit_prefixmap_teardown(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
841 {
842         talloc_free(priv);
843
844         return true;
845 }
846
847 /**
848  * Test case initialization for
849  * drs.unit.prefixMap
850  */
851 struct torture_tcase * torture_drs_unit_prefixmap(struct torture_suite *suite)
852 {
853         typedef bool (*pfn_setup)(struct torture_context *, void **);
854         typedef bool (*pfn_teardown)(struct torture_context *, void *);
855         typedef bool (*pfn_run)(struct torture_context *, void *);
856
857         struct torture_tcase * tc = torture_suite_add_tcase(suite, "prefixMap");
858
859         torture_tcase_set_fixture(tc,
860                                   (pfn_setup)torture_drs_unit_prefixmap_setup,
861                                   (pfn_teardown)torture_drs_unit_prefixmap_teardown);
862
863         tc->description = talloc_strdup(tc, "Unit tests for DRSUAPI::prefixMap implementation");
864
865         torture_tcase_add_simple_test(tc, "new", (pfn_run)torture_drs_unit_pfm_new);
866
867         torture_tcase_add_simple_test(tc, "make_attid_full_map", (pfn_run)torture_drs_unit_pfm_make_attid_full_map);
868         torture_tcase_add_simple_test(tc, "make_attid_small_map", (pfn_run)torture_drs_unit_pfm_make_attid_small_map);
869
870         torture_tcase_add_simple_test(tc, "attid_from_oid_full_map",
871                                       (pfn_run)torture_drs_unit_pfm_attid_from_oid_full_map);
872         torture_tcase_add_simple_test(tc, "attid_from_oid_empty_map",
873                                       (pfn_run)torture_drs_unit_pfm_attid_from_oid_base_map);
874
875         torture_tcase_add_simple_test(tc, "oid_from_attid_full_map", (pfn_run)torture_drs_unit_pfm_oid_from_attid);
876         torture_tcase_add_simple_test(tc, "oid_from_attid_check_attid",
877                                       (pfn_run)torture_drs_unit_pfm_oid_from_attid_check_attid);
878
879         torture_tcase_add_simple_test(tc, "pfm_to_from_drsuapi", (pfn_run)torture_drs_unit_pfm_to_from_drsuapi);
880
881         torture_tcase_add_simple_test(tc, "pfm_to_from_ldb_val", (pfn_run)torture_drs_unit_pfm_to_from_ldb_val);
882
883         torture_tcase_add_simple_test(tc, "pfm_read_write_ldb", (pfn_run)torture_drs_unit_pfm_read_write_ldb);
884
885         torture_tcase_add_simple_test(tc, "dsdb_create_prefix_mapping", (pfn_run)torture_drs_unit_dsdb_create_prefix_mapping);
886
887         return tc;
888 }