s4-pfm-test: Enrich and fix comment primary for testing data
[kai/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  */
144 static const struct {
145         const char      *oid;
146         uint32_t        id;
147         uint32_t        attid;
148 } _prefixmap_test_data[] = {
149         {.oid="2.5.4.0",                .id=0x00000000, .attid=0x000000},
150         {.oid="2.5.4.42",               .id=0x00000000, .attid=0x00002a},
151         {.oid="1.2.840.113556.1.2.1",   .id=0x00000002, .attid=0x020001},
152         {.oid="1.2.840.113556.1.2.13",  .id=0x00000002, .attid=0x02000d},
153         {.oid="1.2.840.113556.1.2.281", .id=0x00000002, .attid=0x020119},
154         {.oid="1.2.840.113556.1.4.125", .id=0x00000009, .attid=0x09007d},
155         {.oid="1.2.840.113556.1.4.146", .id=0x00000009, .attid=0x090092},
156         {.oid="1.2.250.1",              .id=0x00001b86, .attid=0x1b860001},
157         {.oid="1.2.250.130",            .id=0x00001b86, .attid=0x1b860082},
158         {.oid="1.2.250.16386",          .id=0x00001c78, .attid=0x1c788002},
159         {.oid="1.2.250.2097154",        .id=0x00001c7b, .attid=0x1c7b8002},
160 };
161
162
163 /**
164  * Creates dsdb_schema_prefixmap based on predefined data
165  */
166 static WERROR _drsut_prefixmap_new(const struct drsut_pfm_oid_data *_pfm_init_data, uint32_t count,
167                                    TALLOC_CTX *mem_ctx, struct dsdb_schema_prefixmap **_pfm)
168 {
169         uint32_t i;
170         struct dsdb_schema_prefixmap *pfm;
171
172         pfm = talloc(mem_ctx, struct dsdb_schema_prefixmap);
173         W_ERROR_HAVE_NO_MEMORY(pfm);
174
175         pfm->length = count;
176         pfm->prefixes = talloc_array(pfm, struct dsdb_schema_prefixmap_oid, pfm->length);
177         if (!pfm->prefixes) {
178                 talloc_free(pfm);
179                 return WERR_NOMEM;
180         }
181
182         for (i = 0; i < pfm->length; i++) {
183                 pfm->prefixes[i].id = _pfm_init_data[i].id;
184                 pfm->prefixes[i].bin_oid = strhex_to_data_blob(pfm, _pfm_init_data[i].bin_oid);
185                 if (!pfm->prefixes[i].bin_oid.data) {
186                         talloc_free(pfm);
187                         return WERR_NOMEM;
188                 }
189         }
190
191         *_pfm = pfm;
192
193         return WERR_OK;
194 }
195
196 /**
197  * Compares two prefixMaps for being equal - same items on same indexes
198  */
199 static bool _torture_drs_pfm_compare_same(struct torture_context *tctx,
200                                           const struct dsdb_schema_prefixmap *pfm_left,
201                                           const struct dsdb_schema_prefixmap *pfm_right,
202                                           bool quiet)
203 {
204         uint32_t i;
205         char *err_msg = NULL;
206
207         if (pfm_left->length != pfm_right->length) {
208                 err_msg = talloc_asprintf(tctx, "prefixMaps differ in size; left = %d, right = %d",
209                                           pfm_left->length, pfm_right->length);
210                 goto failed;
211         }
212
213         for (i = 0; i < pfm_left->length; i++) {
214                 struct dsdb_schema_prefixmap_oid *entry_left = &pfm_left->prefixes[i];
215                 struct dsdb_schema_prefixmap_oid *entry_right = &pfm_right->prefixes[i];
216
217                 if (entry_left->id != entry_right->id) {
218                         err_msg = talloc_asprintf(tctx, "Different IDs for index=%d", i);
219                         goto failed;
220                 }
221                 if (data_blob_cmp(&entry_left->bin_oid, &entry_right->bin_oid)) {
222                         err_msg = talloc_asprintf(tctx, "Different bin_oid for index=%d", i);
223                         goto failed;
224                 }
225         }
226
227         return true;
228
229 failed:
230         if (!quiet) {
231                 torture_comment(tctx, "_torture_drs_pfm_compare_same: %s", err_msg);
232         }
233         talloc_free(err_msg);
234
235         return false;
236 }
237
238 /*
239  * Tests dsdb_schema_pfm_new()
240  */
241 static bool torture_drs_unit_pfm_new(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
242 {
243         WERROR werr;
244         bool bret;
245         TALLOC_CTX *mem_ctx;
246         struct dsdb_schema_prefixmap *pfm = NULL;
247
248         mem_ctx = talloc_new(priv);
249
250         /* create new prefix map */
251         werr = dsdb_schema_pfm_new(mem_ctx, &pfm);
252         torture_assert_werr_ok(tctx, werr, "dsdb_schema_pfm_new() failed!");
253         torture_assert(tctx, pfm != NULL, "NULL prefixMap created!");
254         torture_assert(tctx, pfm->length > 0, "Empty prefixMap created!");
255         torture_assert(tctx, pfm->prefixes != NULL, "No prefixes for newly created prefixMap!");
256
257         /* compare newly created prefixMap with template one */
258         bret = _torture_drs_pfm_compare_same(tctx, priv->pfm_new, pfm, false);
259
260         talloc_free(mem_ctx);
261
262         return bret;
263 }
264
265 /**
266  * Tests dsdb_schema_pfm_make_attid() using full prefixMap.
267  * In this test we know exactly which ATTID and prefixMap->ID
268  * should be returned, i.e. no prefixMap entries should be added.
269  */
270 static bool torture_drs_unit_pfm_make_attid_full_map(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
271 {
272         WERROR werr;
273         uint32_t i, count;
274         uint32_t attid;
275         char *err_msg;
276
277         count = ARRAY_SIZE(_prefixmap_test_data);
278         for (i = 0; i < count; i++) {
279                 werr = dsdb_schema_pfm_make_attid(priv->pfm_full, _prefixmap_test_data[i].oid, &attid);
280                 /* prepare error message */
281                 err_msg = talloc_asprintf(priv, "dsdb_schema_pfm_make_attid() failed with %s",
282                                                 _prefixmap_test_data[i].oid);
283                 torture_assert(tctx, err_msg, "Unexpected: Have no memory!");
284                 /* verify result and returned ATTID */
285                 torture_assert_werr_ok(tctx, werr, err_msg);
286                 torture_assert_int_equal(tctx, attid, _prefixmap_test_data[i].attid, err_msg);
287                 /* reclaim memory for prepared error message */
288                 talloc_free(err_msg);
289         }
290
291         return true;
292 }
293
294 /**
295  * Tests dsdb_schema_pfm_make_attid() using initially small prefixMap.
296  * In this test we don't know exactly which ATTID and prefixMap->ID
297  * should be returned, but we can verify lo-word of ATTID.
298  * This test verifies implementation branch when a new
299  * prefix should be added into prefixMap.
300  */
301 static bool torture_drs_unit_pfm_make_attid_small_map(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
302 {
303         WERROR werr;
304         uint32_t i, j;
305         uint32_t idx;
306         uint32_t attid, attid_2;
307         char *err_msg;
308         struct dsdb_schema_prefixmap *pfm = NULL;
309         TALLOC_CTX *mem_ctx;
310
311         mem_ctx = talloc_new(priv);
312
313         /* create new prefix map */
314         werr = dsdb_schema_pfm_new(mem_ctx, &pfm);
315         torture_assert_werr_ok(tctx, werr, "dsdb_schema_pfm_new() failed!");
316
317         /* make some ATTIDs and check result */
318         for (i = 0; i < ARRAY_SIZE(_prefixmap_test_data); i++) {
319                 werr = dsdb_schema_pfm_make_attid(pfm, _prefixmap_test_data[i].oid, &attid);
320
321                 /* prepare error message */
322                 err_msg = talloc_asprintf(mem_ctx, "dsdb_schema_pfm_make_attid() failed with %s",
323                                                 _prefixmap_test_data[i].oid);
324                 torture_assert(tctx, err_msg, "Unexpected: Have no memory!");
325
326                 /* verify result and returned ATTID */
327                 torture_assert_werr_ok(tctx, werr, err_msg);
328                 /* verify ATTID lo-word */
329                 torture_assert_int_equal(tctx, attid & 0xFFFF, _prefixmap_test_data[i].attid & 0xFFFF, err_msg);
330
331                 /* try again, this time verify for whole ATTID */
332                 werr = dsdb_schema_pfm_make_attid(pfm, _prefixmap_test_data[i].oid, &attid_2);
333                 torture_assert_werr_ok(tctx, werr, err_msg);
334                 torture_assert_int_equal(tctx, attid_2, attid, err_msg);
335
336                 /* reclaim memory for prepared error message */
337                 talloc_free(err_msg);
338
339                 /* check there is such an index in modified prefixMap */
340                 idx = (attid >> 16);
341                 for (j = 0; j < pfm->length; j++) {
342                         if (pfm->prefixes[j].id == idx)
343                                 break;
344                 }
345                 if (j >= pfm->length) {
346                         torture_result(tctx, TORTURE_FAIL, __location__": No prefix for ATTID=0x%08X", attid);
347                         return false;
348                 }
349
350         }
351
352         talloc_free(mem_ctx);
353
354         return true;
355 }
356
357 /**
358  * Tests dsdb_schema_pfm_attid_from_oid() using full prefixMap.
359  * In this test we know exactly which ATTID and prefixMap->ID
360  * should be returned- dsdb_schema_pfm_attid_from_oid() should succeed.
361  */
362 static bool torture_drs_unit_pfm_attid_from_oid_full_map(struct torture_context *tctx,
363                                                          struct drsut_prefixmap_data *priv)
364 {
365         WERROR werr;
366         uint32_t i, count;
367         uint32_t attid;
368         char *err_msg;
369
370         count = ARRAY_SIZE(_prefixmap_test_data);
371         for (i = 0; i < count; i++) {
372                 werr = dsdb_schema_pfm_attid_from_oid(priv->pfm_full,
373                                                       _prefixmap_test_data[i].oid,
374                                                       &attid);
375                 /* prepare error message */
376                 err_msg = talloc_asprintf(priv, "dsdb_schema_pfm_attid_from_oid() failed with %s",
377                                                 _prefixmap_test_data[i].oid);
378                 torture_assert(tctx, err_msg, "Unexpected: Have no memory!");
379                 /* verify result and returned ATTID */
380                 torture_assert_werr_ok(tctx, werr, err_msg);
381                 torture_assert_int_equal(tctx, attid, _prefixmap_test_data[i].attid, err_msg);
382                 /* reclaim memory for prepared error message */
383                 talloc_free(err_msg);
384         }
385
386         return true;
387 }
388
389 /**
390  * Tests dsdb_schema_pfm_attid_from_oid() using base (initial) prefixMap.
391  * dsdb_schema_pfm_attid_from_oid() should fail when testing with OID
392  * that are not already in the prefixMap.
393  */
394 static bool torture_drs_unit_pfm_attid_from_oid_base_map(struct torture_context *tctx,
395                                                          struct drsut_prefixmap_data *priv)
396 {
397         WERROR werr;
398         uint32_t i;
399         uint32_t attid;
400         char *err_msg;
401         struct dsdb_schema_prefixmap *pfm = NULL;
402         struct dsdb_schema_prefixmap pfm_prev;
403         TALLOC_CTX *mem_ctx;
404         const struct {
405                 const char      *oid;
406                 uint32_t        attid;
407                 bool            exists; /* if this prefix already exists or should be added */
408         } _test_data[] = {
409                 {.oid="2.5.4.0",                .attid=0x00000000, true},
410                 {.oid="2.5.4.42",               .attid=0x0000002a, true},
411                 {.oid="1.2.840.113556.1.2.1",   .attid=0x00020001, true},
412                 {.oid="1.2.840.113556.1.2.13",  .attid=0x0002000d, true},
413                 {.oid="1.2.840.113556.1.2.281", .attid=0x00020119, true},
414                 {.oid="1.2.840.113556.1.4.125", .attid=0x0009007d, true},
415                 {.oid="1.2.840.113556.1.4.146", .attid=0x00090092, true},
416                 {.oid="1.2.250.1",              .attid=0x1b860001, false},
417                 {.oid="1.2.250.16386",          .attid=0x1c788002, false},
418                 {.oid="1.2.250.2097154",        .attid=0x1c7b8002, false},
419         };
420
421         mem_ctx = talloc_new(priv);
422         torture_assert(tctx, mem_ctx, "Unexpected: Have no memory!");
423
424         /* create new prefix map */
425         werr = dsdb_schema_pfm_new(mem_ctx, &pfm);
426         torture_assert_werr_ok(tctx, werr, "dsdb_schema_pfm_new() failed!");
427
428         /* keep initial pfm around for testing */
429         pfm_prev = *pfm;
430         pfm_prev.prefixes = talloc_reference(mem_ctx, pfm->prefixes);
431
432         /* get some ATTIDs and check result */
433         for (i = 0; i < ARRAY_SIZE(_test_data); i++) {
434                 werr = dsdb_schema_pfm_attid_from_oid(pfm, _test_data[i].oid, &attid);
435
436                 /* prepare error message */
437                 err_msg = talloc_asprintf(mem_ctx,
438                                           "dsdb_schema_pfm_attid_from_oid() failed for %s",
439                                           _test_data[i].oid);
440                 torture_assert(tctx, err_msg, "Unexpected: Have no memory!");
441
442
443                 /* verify pfm hasn't been altered */
444                 if (_test_data[i].exists) {
445                         /* should succeed and return valid ATTID */
446                         torture_assert_werr_ok(tctx, werr, err_msg);
447                         /* verify ATTID */
448                         torture_assert_int_equal(tctx, attid, _test_data[i].attid, err_msg);
449                 } else {
450                         /* should fail */
451                         torture_assert_werr_equal(tctx, werr, WERR_NOT_FOUND, err_msg);
452                 }
453
454                 /* prefixMap should never be changed */
455                 if (!_torture_drs_pfm_compare_same(tctx, &pfm_prev, pfm, true)) {
456                         torture_fail(tctx, "schema->prefixmap has changed");
457                 }
458
459                 /* reclaim memory for prepared error message */
460                 talloc_free(err_msg);
461         }
462
463         talloc_free(mem_ctx);
464
465         return true;
466 }
467
468 /**
469  * Tests dsdb_schema_pfm_oid_from_attid() using full prefixMap.
470  */
471 static bool torture_drs_unit_pfm_oid_from_attid(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
472 {
473         WERROR werr;
474         uint32_t i, count;
475         char *err_msg;
476         const char *oid;
477
478         count = ARRAY_SIZE(_prefixmap_test_data);
479         for (i = 0; i < count; i++) {
480                 oid = NULL;
481                 werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, _prefixmap_test_data[i].attid,
482                                                       priv, &oid);
483                 /* prepare error message */
484                 err_msg = talloc_asprintf(priv, "dsdb_schema_pfm_oid_from_attid() failed with 0x%08X",
485                                                 _prefixmap_test_data[i].attid);
486                 torture_assert(tctx, err_msg, "Unexpected: Have no memory!");
487                 /* verify result and returned ATTID */
488                 torture_assert_werr_ok(tctx, werr, err_msg);
489                 torture_assert(tctx, oid, "dsdb_schema_pfm_oid_from_attid() returned NULL OID!!!");
490                 torture_assert_str_equal(tctx, oid, _prefixmap_test_data[i].oid, err_msg);
491                 /* reclaim memory for prepared error message */
492                 talloc_free(err_msg);
493                 /* free memory for OID */
494                 talloc_free(discard_const(oid));
495         }
496
497         return true;
498 }
499
500 /**
501  * Tests dsdb_schema_pfm_oid_from_attid() for handling
502  * correctly different type of attid values.
503  * See: MS-ADTS, 3.1.1.2.6 ATTRTYP
504  */
505 static bool torture_drs_unit_pfm_oid_from_attid_check_attid(struct torture_context *tctx,
506                                                             struct drsut_prefixmap_data *priv)
507 {
508         WERROR werr;
509         const char *oid;
510
511         /* Test with valid prefixMap attid */
512         werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0x00010001, tctx, &oid);
513         torture_assert_werr_ok(tctx, werr, "Testing prefixMap type attid = 0x00010001");
514
515         /* Test with valid attid but invalid index */
516         werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0x01110001, tctx, &oid);
517         torture_assert_werr_equal(tctx, werr, WERR_DS_NO_ATTRIBUTE_OR_VALUE,
518                                   "Testing invalid-index attid = 0x01110001");
519
520         /* Test with attid in msDS-IntId range */
521         werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0x80000000, tctx, &oid);
522         torture_assert_werr_equal(tctx, werr, WERR_INVALID_PARAMETER,
523                                   "Testing msDS-IntId type attid = 0x80000000");
524         werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0xBFFFFFFF, tctx, &oid);
525         torture_assert_werr_equal(tctx, werr, WERR_INVALID_PARAMETER,
526                                   "Testing msDS-IntId type attid = 0xBFFFFFFF");
527
528         /* Test with attid in RESERVED range */
529         werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0xC0000000, tctx, &oid);
530         torture_assert_werr_equal(tctx, werr, WERR_INVALID_PARAMETER,
531                                   "Testing RESERVED type attid = 0xC0000000");
532         werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0xFFFEFFFF, tctx, &oid);
533         torture_assert_werr_equal(tctx, werr, WERR_INVALID_PARAMETER,
534                                   "Testing RESERVED type attid = 0xFFFEFFFF");
535
536         /* Test with attid in INTERNAL range */
537         werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0xFFFF0000, tctx, &oid);
538         torture_assert_werr_equal(tctx, werr, WERR_INVALID_PARAMETER,
539                                   "Testing INTERNAL type attid = 0xFFFF0000");
540         werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0xFFFFFFFF, tctx, &oid);
541         torture_assert_werr_equal(tctx, werr, WERR_INVALID_PARAMETER,
542                                   "Testing INTERNAL type attid = 0xFFFFFFFF");
543
544         return true;
545 }
546
547 /**
548  * Test Schema prefixMap conversions to/from drsuapi prefixMap
549  * representation.
550  */
551 static bool torture_drs_unit_pfm_to_from_drsuapi(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
552 {
553         WERROR werr;
554         const char *schema_info;
555         struct dsdb_schema_prefixmap *pfm;
556         struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;
557         TALLOC_CTX *mem_ctx;
558
559         mem_ctx = talloc_new(tctx);
560         torture_assert(tctx, mem_ctx, "Unexpected: Have no memory!");
561
562         /* convert Schema_prefixMap to drsuapi_prefixMap */
563         werr = dsdb_drsuapi_pfm_from_schema_pfm(priv->pfm_full, priv->schi_default_str, mem_ctx, &ctr);
564         torture_assert_werr_ok(tctx, werr, "dsdb_drsuapi_pfm_from_schema_pfm() failed");
565         torture_assert(tctx, ctr && ctr->mappings, "drsuapi_prefixMap not constructed correctly");
566         torture_assert_int_equal(tctx, ctr->num_mappings, priv->pfm_full->length + 1,
567                                  "drs_mappings count does not match");
568         /* look for schema_info entry - it should be the last one */
569         schema_info = hex_encode_talloc(mem_ctx,
570                                         ctr->mappings[ctr->num_mappings - 1].oid.binary_oid,
571                                         ctr->mappings[ctr->num_mappings - 1].oid.length);
572         torture_assert_str_equal(tctx,
573                                  schema_info,
574                                  priv->schi_default_str,
575                                  "schema_info not stored correctly or not last entry");
576
577         /* compare schema_prefixMap and drsuapi_prefixMap */
578         werr = dsdb_schema_pfm_contains_drsuapi_pfm(priv->pfm_full, ctr);
579         torture_assert_werr_ok(tctx, werr, "dsdb_schema_pfm_contains_drsuapi_pfm() failed");
580
581         /* convert back drsuapi_prefixMap to schema_prefixMap */
582         werr = dsdb_schema_pfm_from_drsuapi_pfm(ctr, true, mem_ctx, &pfm, &schema_info);
583         torture_assert_werr_ok(tctx, werr, "dsdb_schema_pfm_from_drsuapi_pfm() failed");
584         torture_assert_str_equal(tctx, schema_info, priv->schi_default_str, "Fetched schema_info is different");
585
586         /* compare against the original */
587         if (!_torture_drs_pfm_compare_same(tctx, priv->pfm_full, pfm, true)) {
588                 talloc_free(mem_ctx);
589                 return false;
590         }
591
592         /* test conversion with partial drsuapi_prefixMap */
593         ctr->num_mappings--;
594         werr = dsdb_schema_pfm_from_drsuapi_pfm(ctr, false, mem_ctx, &pfm, NULL);
595         torture_assert_werr_ok(tctx, werr, "dsdb_schema_pfm_from_drsuapi_pfm() failed");
596         /* compare against the original */
597         if (!_torture_drs_pfm_compare_same(tctx, priv->pfm_full, pfm, false)) {
598                 talloc_free(mem_ctx);
599                 return false;
600         }
601
602         talloc_free(mem_ctx);
603         return true;
604 }
605
606
607 /**
608  * Test Schema prefixMap conversions to/from ldb_val
609  * blob representation.
610  */
611 static bool torture_drs_unit_pfm_to_from_ldb_val(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
612 {
613         WERROR werr;
614         const char *schema_info;
615         struct dsdb_schema *schema;
616         struct ldb_val pfm_ldb_val;
617         struct ldb_val schema_info_ldb_val;
618         TALLOC_CTX *mem_ctx;
619
620         mem_ctx = talloc_new(tctx);
621         torture_assert(tctx, mem_ctx, "Unexpected: Have no memory!");
622
623         schema = dsdb_new_schema(mem_ctx);
624         torture_assert(tctx, schema, "Unexpected: failed to allocate schema object");
625
626         /* set priv->pfm_full as prefixMap for new schema object */
627         schema->prefixmap = priv->pfm_full;
628         schema->schema_info = priv->schi_default_str;
629
630         /* convert schema_prefixMap to ldb_val blob */
631         werr = dsdb_get_oid_mappings_ldb(schema, mem_ctx, &pfm_ldb_val, &schema_info_ldb_val);
632         torture_assert_werr_ok(tctx, werr, "dsdb_get_oid_mappings_ldb() failed");
633         torture_assert(tctx, pfm_ldb_val.data && pfm_ldb_val.length,
634                        "pfm_ldb_val not constructed correctly");
635         torture_assert(tctx, schema_info_ldb_val.data && schema_info_ldb_val.length,
636                        "schema_info_ldb_val not constructed correctly");
637         /* look for schema_info entry - it should be the last one */
638         schema_info = hex_encode_talloc(mem_ctx,
639                                         schema_info_ldb_val.data,
640                                         schema_info_ldb_val.length);
641         torture_assert_str_equal(tctx,
642                                  schema_info,
643                                  priv->schi_default_str,
644                                  "schema_info not stored correctly or not last entry");
645
646         /* convert pfm_ldb_val back to schema_prefixMap */
647         schema->prefixmap = NULL;
648         schema->schema_info = NULL;
649         werr = dsdb_load_oid_mappings_ldb(schema, &pfm_ldb_val, &schema_info_ldb_val);
650         torture_assert_werr_ok(tctx, werr, "dsdb_load_oid_mappings_ldb() failed");
651         /* compare against the original */
652         if (!_torture_drs_pfm_compare_same(tctx, schema->prefixmap, priv->pfm_full, false)) {
653                 talloc_free(mem_ctx);
654                 return false;
655         }
656
657         talloc_free(mem_ctx);
658         return true;
659 }
660
661 /**
662  * Test read/write in ldb implementation
663  */
664 static bool torture_drs_unit_pfm_read_write_ldb(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
665 {
666         WERROR werr;
667         struct dsdb_schema *schema;
668         struct dsdb_schema_prefixmap *pfm;
669         TALLOC_CTX *mem_ctx;
670
671         mem_ctx = talloc_new(tctx);
672         torture_assert(tctx, mem_ctx, "Unexpected: Have no memory!");
673
674         /* makeup a dsdb_schema to test with */
675         schema = dsdb_new_schema(mem_ctx);
676         torture_assert(tctx, schema, "Unexpected: failed to allocate schema object");
677         /* set priv->pfm_full as prefixMap for new schema object */
678         schema->prefixmap = priv->pfm_full;
679         schema->schema_info = priv->schi_default_str;
680
681         /* write prfixMap to ldb */
682         werr = dsdb_write_prefixes_from_schema_to_ldb(mem_ctx, priv->ldb_ctx, schema);
683         torture_assert_werr_ok(tctx, werr, "dsdb_write_prefixes_from_schema_to_ldb() failed");
684
685         /* read from ldb what we have written */
686         werr = dsdb_read_prefixes_from_ldb(priv->ldb_ctx, mem_ctx, &pfm);
687         torture_assert_werr_ok(tctx, werr, "dsdb_read_prefixes_from_ldb() failed");
688
689         /* compare data written/read */
690         if (!_torture_drs_pfm_compare_same(tctx, schema->prefixmap, priv->pfm_full, false)) {
691                 torture_fail(tctx, "prefixMap read/write in LDB is not consistent");
692         }
693
694         talloc_free(mem_ctx);
695
696         return true;
697 }
698
699 /**
700  * Test dsdb_create_prefix_mapping
701  */
702 static bool torture_drs_unit_dsdb_create_prefix_mapping(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
703 {
704         WERROR werr;
705         uint32_t i;
706         struct dsdb_schema *schema;
707         TALLOC_CTX *mem_ctx;
708         const struct {
709                 const char      *oid;
710                 uint32_t        attid;
711                 bool            exists; /* if this prefix already exists or should be added */
712         } _test_data[] = {
713                 {.oid="2.5.4.0",                .attid=0x00000000, true},
714                 {.oid="2.5.4.42",               .attid=0x0000002a, true},
715                 {.oid="1.2.840.113556.1.2.1",   .attid=0x00020001, true},
716                 {.oid="1.2.840.113556.1.2.13",  .attid=0x0002000d, true},
717                 {.oid="1.2.840.113556.1.2.281", .attid=0x00020119, true},
718                 {.oid="1.2.840.113556.1.4.125", .attid=0x0009007d, true},
719                 {.oid="1.2.840.113556.1.4.146", .attid=0x00090092, true},
720                 {.oid="1.2.250.1",              .attid=0x1b860001, false},
721                 {.oid="1.2.250.16386",          .attid=0x1c788002, false},
722                 {.oid="1.2.250.2097154",        .attid=0x1c7b8002, false},
723         };
724
725         mem_ctx = talloc_new(tctx);
726         torture_assert(tctx, mem_ctx, "Unexpected: Have no memory!");
727
728         /* makeup a dsdb_schema to test with */
729         schema = dsdb_new_schema(mem_ctx);
730         torture_assert(tctx, schema, "Unexpected: failed to allocate schema object");
731         /* set priv->pfm_full as prefixMap for new schema object */
732         schema->schema_info = priv->schi_default_str;
733         werr = _drsut_prefixmap_new(_prefixmap_test_new_data, ARRAY_SIZE(_prefixmap_test_new_data),
734                                     schema, &schema->prefixmap);
735         torture_assert_werr_ok(tctx, werr, "_drsut_prefixmap_new() failed");
736         /* write prfixMap to ldb */
737         werr = dsdb_write_prefixes_from_schema_to_ldb(mem_ctx, priv->ldb_ctx, schema);
738         torture_assert_werr_ok(tctx, werr, "dsdb_write_prefixes_from_schema_to_ldb() failed");
739
740         for (i = 0; i < ARRAY_SIZE(_test_data); i++) {
741                 struct dsdb_schema_prefixmap *pfm_ldb;
742                 struct dsdb_schema_prefixmap *pfm_prev;
743
744                 /* add ref to prefixMap so we can use it later */
745                 pfm_prev = talloc_reference(schema, schema->prefixmap);
746
747                 /* call dsdb_create_prefix_mapping() and check result accordingly */
748                 werr = dsdb_create_prefix_mapping(priv->ldb_ctx, schema, _test_data[i].oid);
749                 torture_assert_werr_ok(tctx, werr, "dsdb_create_prefix_mapping() failed");
750
751                 /* verify pfm has been altered or not if needed */
752                 if (_test_data[i].exists) {
753                         torture_assert(tctx, pfm_prev == schema->prefixmap,
754                                        "schema->prefixmap has been reallocated!");
755                         if (!_torture_drs_pfm_compare_same(tctx, pfm_prev, schema->prefixmap, true)) {
756                                 torture_fail(tctx, "schema->prefixmap has changed");
757                         }
758                 } else {
759                         torture_assert(tctx, pfm_prev != schema->prefixmap,
760                                        "schema->prefixmap should be reallocated!");
761                         if (_torture_drs_pfm_compare_same(tctx, pfm_prev, schema->prefixmap, true)) {
762                                 torture_fail(tctx, "schema->prefixmap should be changed");
763                         }
764                 }
765
766                 /* read from ldb what we have written */
767                 werr = dsdb_read_prefixes_from_ldb(priv->ldb_ctx, mem_ctx, &pfm_ldb);
768                 torture_assert_werr_ok(tctx, werr, "dsdb_read_prefixes_from_ldb() failed");
769                 /* compare data written/read */
770                 if (!_torture_drs_pfm_compare_same(tctx, schema->prefixmap, pfm_ldb, true)) {
771                         torture_fail(tctx, "schema->prefixmap and pfm in LDB are different");
772                 }
773                 /* free mem for pfm read from LDB */
774                 talloc_free(pfm_ldb);
775
776                 /* release prefixMap pointer */
777                 talloc_unlink(schema, pfm_prev);
778         }
779
780         talloc_free(mem_ctx);
781
782         return true;
783 }
784
785 /**
786  * Prepare temporary LDB and opens it
787  */
788 static bool torture_drs_unit_ldb_setup(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
789 {
790         int ldb_err;
791         char *ldb_url;
792         bool bret = true;
793         TALLOC_CTX* mem_ctx;
794         char *tempdir;
795         NTSTATUS status;
796
797         mem_ctx = talloc_new(priv);
798
799         status = torture_temp_dir(tctx, "drs_", &tempdir);
800         torture_assert_ntstatus_ok(tctx, status, "creating temp dir");
801
802         ldb_url = talloc_asprintf(priv, "%s/drs_test.ldb", tempdir);
803
804         /* create LDB */
805         priv->ldb_ctx = ldb_init(priv, tctx->ev);
806         ldb_err = ldb_connect(priv->ldb_ctx, ldb_url, 0, NULL);
807         torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE, "ldb_connect() failed");
808
809         /* set some schemaNamingContext */
810         ldb_err = ldb_set_opaque(priv->ldb_ctx,
811                                  "schemaNamingContext",
812                                  ldb_dn_new(priv->ldb_ctx, priv->ldb_ctx, "CN=Schema,CN=Config"));
813         torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE, "ldb_set_opaque() failed");
814
815         /* add prefixMap attribute so tested layer could work properly */
816         {
817                 struct ldb_message *msg = ldb_msg_new(mem_ctx);
818                 msg->dn = ldb_get_schema_basedn(priv->ldb_ctx);
819                 ldb_err = ldb_msg_add_string(msg, "prefixMap", "prefixMap");
820                 torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE,
821                                               "ldb_msg_add_empty() failed");
822
823                 ldb_err = ldb_add(priv->ldb_ctx, msg);
824                 torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE, "ldb_add() failed");
825         }
826
827 DONE:
828         talloc_free(mem_ctx);
829         return bret;
830 }
831
832 /*
833  * Setup/Teardown for test case
834  */
835 static bool torture_drs_unit_prefixmap_setup(struct torture_context *tctx, struct drsut_prefixmap_data **_priv)
836 {
837         WERROR werr;
838         DATA_BLOB blob;
839         struct drsut_prefixmap_data *priv;
840
841         priv = *_priv = talloc_zero(tctx, struct drsut_prefixmap_data);
842         torture_assert(tctx, priv != NULL, "Not enough memory");
843
844         werr = _drsut_prefixmap_new(_prefixmap_test_new_data, ARRAY_SIZE(_prefixmap_test_new_data),
845                                     tctx, &priv->pfm_new);
846         torture_assert_werr_ok(tctx, werr, "failed to create pfm_new");
847
848         werr = _drsut_prefixmap_new(_prefixmap_full_map_data, ARRAY_SIZE(_prefixmap_full_map_data),
849                                     tctx, &priv->pfm_full);
850         torture_assert_werr_ok(tctx, werr, "failed to create pfm_test");
851
852         torture_assert(tctx, drsut_schemainfo_new(tctx, &priv->schi_default),
853                        "drsut_schemainfo_new() failed");
854
855         werr = dsdb_blob_from_schema_info(priv->schi_default, priv, &blob);
856         torture_assert_werr_ok(tctx, werr, "dsdb_blob_from_schema_info() failed");
857
858         priv->schi_default_str = data_blob_hex_string_upper(priv, &blob);
859
860         /* create temporary LDB and populate with data */
861         if (!torture_drs_unit_ldb_setup(tctx, priv)) {
862                 return false;
863         }
864
865         return true;
866 }
867
868 static bool torture_drs_unit_prefixmap_teardown(struct torture_context *tctx, struct drsut_prefixmap_data *priv)
869 {
870         talloc_free(priv);
871
872         return true;
873 }
874
875 /**
876  * Test case initialization for
877  * DRS-UNIT.prefixMap
878  */
879 struct torture_tcase * torture_drs_unit_prefixmap(struct torture_suite *suite)
880 {
881         typedef bool (*pfn_setup)(struct torture_context *, void **);
882         typedef bool (*pfn_teardown)(struct torture_context *, void *);
883         typedef bool (*pfn_run)(struct torture_context *, void *);
884
885         struct torture_tcase * tc = torture_suite_add_tcase(suite, "prefixMap");
886
887         torture_tcase_set_fixture(tc,
888                                   (pfn_setup)torture_drs_unit_prefixmap_setup,
889                                   (pfn_teardown)torture_drs_unit_prefixmap_teardown);
890
891         tc->description = talloc_strdup(tc, "Unit tests for DRSUAPI::prefixMap implementation");
892
893         torture_tcase_add_simple_test(tc, "new", (pfn_run)torture_drs_unit_pfm_new);
894
895         torture_tcase_add_simple_test(tc, "make_attid_full_map", (pfn_run)torture_drs_unit_pfm_make_attid_full_map);
896         torture_tcase_add_simple_test(tc, "make_attid_small_map", (pfn_run)torture_drs_unit_pfm_make_attid_small_map);
897
898         torture_tcase_add_simple_test(tc, "attid_from_oid_full_map",
899                                       (pfn_run)torture_drs_unit_pfm_attid_from_oid_full_map);
900         torture_tcase_add_simple_test(tc, "attid_from_oid_empty_map",
901                                       (pfn_run)torture_drs_unit_pfm_attid_from_oid_base_map);
902
903         torture_tcase_add_simple_test(tc, "oid_from_attid_full_map", (pfn_run)torture_drs_unit_pfm_oid_from_attid);
904         torture_tcase_add_simple_test(tc, "oid_from_attid_check_attid",
905                                       (pfn_run)torture_drs_unit_pfm_oid_from_attid_check_attid);
906
907         torture_tcase_add_simple_test(tc, "pfm_to_from_drsuapi", (pfn_run)torture_drs_unit_pfm_to_from_drsuapi);
908
909         torture_tcase_add_simple_test(tc, "pfm_to_from_ldb_val", (pfn_run)torture_drs_unit_pfm_to_from_ldb_val);
910
911         torture_tcase_add_simple_test(tc, "pfm_read_write_ldb", (pfn_run)torture_drs_unit_pfm_read_write_ldb);
912
913         torture_tcase_add_simple_test(tc, "dsdb_create_prefix_mapping", (pfn_run)torture_drs_unit_dsdb_create_prefix_mapping);
914
915         return tc;
916 }