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