Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 :
4 : DRSUAPI schemaInfo unit tests
5 :
6 : Copyright (C) Kamen Mazdrashki <kamenim@samba.org> 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 "dsdb/samdb/ldb_modules/util.h"
27 : #include "ldb_wrap.h"
28 : #include <ldb_module.h>
29 : #include "torture/rpc/drsuapi.h"
30 : #include "librpc/ndr/libndr.h"
31 : #include "param/param.h"
32 : #include "torture/drs/proto.h"
33 : #include "torture/drs/proto.h"
34 :
35 :
36 : /**
37 : * schemaInfo to init ldb context with
38 : * Rev: 0
39 : * GUID: 00000000-0000-0000-0000-000000000000
40 : */
41 : #define SCHEMA_INFO_INIT_STR "FF0000000000000000000000000000000000000000"
42 :
43 : /**
44 : * Default schema_info string to be used for testing
45 : * Rev: 01
46 : * GUID: 071c82fd-45c7-4351-a3db-51f75a630a7f
47 : */
48 : #define SCHEMA_INFO_DEFAULT_STR "FF00000001FD821C07C7455143A3DB51F75A630A7F"
49 :
50 : /**
51 : * Schema info data to test with
52 : */
53 : struct schemainfo_data {
54 : DATA_BLOB ndr_blob;
55 : struct dsdb_schema_info schi;
56 : WERROR werr_expected;
57 : bool test_both_ways;
58 : };
59 :
60 : /**
61 : * Schema info test data in human-readable format (... kind of)
62 : */
63 : static const struct {
64 : const char *schema_info_str;
65 : uint32_t revision;
66 : const char *guid_str;
67 : WERROR werr_expected;
68 : bool test_both_ways;
69 : } _schemainfo_test_data[] = {
70 : {
71 : .schema_info_str = "FF0000000000000000000000000000000000000000",
72 : .revision = 0,
73 : .guid_str = "00000000-0000-0000-0000-000000000000",
74 : .werr_expected = WERR_OK,
75 : .test_both_ways = true
76 : },
77 : {
78 : .schema_info_str = "FF00000001FD821C07C7455143A3DB51F75A630A7F",
79 : .revision = 1,
80 : .guid_str = "071c82fd-45c7-4351-a3db-51f75a630a7f",
81 : .werr_expected = WERR_OK,
82 : .test_both_ways = true
83 : },
84 : {
85 : .schema_info_str = "FFFFFFFFFFFD821C07C7455143A3DB51F75A630A7F",
86 : .revision = 0xFFFFFFFF,
87 : .guid_str = "071c82fd-45c7-4351-a3db-51f75a630a7f",
88 : .werr_expected = WERR_OK,
89 : .test_both_ways = true
90 : },
91 : { /* len == 21 */
92 : .schema_info_str = "FF00000001FD821C07C7455143A3DB51F75A630A7F00",
93 : .revision = 1,
94 : .guid_str = "071c82fd-45c7-4351-a3db-51f75a630a7f",
95 : .werr_expected = WERR_INVALID_PARAMETER,
96 : .test_both_ways = false
97 : },
98 : { /* marker == FF */
99 : .schema_info_str = "AA00000001FD821C07C7455143A3DB51F75A630A7F",
100 : .revision = 1,
101 : .guid_str = "071c82fd-45c7-4351-a3db-51f75a630a7f",
102 : .werr_expected = WERR_INVALID_PARAMETER,
103 : .test_both_ways = false
104 : }
105 : };
106 :
107 : /**
108 : * Private data to be shared among all test in Test case
109 : */
110 : struct drsut_schemainfo_data {
111 : struct ldb_context *ldb;
112 : struct ldb_module *ldb_module;
113 : struct dsdb_schema *schema;
114 :
115 : /* Initial schemaInfo set in ldb to test with */
116 : struct dsdb_schema_info *schema_info;
117 :
118 : uint32_t test_data_count;
119 : struct schemainfo_data *test_data;
120 : };
121 :
122 : /**
123 : * torture macro to assert for equal dsdb_schema_info's
124 : */
125 : #define torture_assert_schema_info_equal(torture_ctx,got,expected,cmt)\
126 : do { const struct dsdb_schema_info *__got = (got), *__expected = (expected); \
127 : if (__got->revision != __expected->revision) { \
128 : torture_result(torture_ctx, TORTURE_FAIL, \
129 : __location__": "#got".revision %d did not match "#expected".revision %d: %s", \
130 : (int)__got->revision, (int)__expected->revision, cmt); \
131 : return false; \
132 : } \
133 : if (!GUID_equal(&__got->invocation_id, &__expected->invocation_id)) { \
134 : torture_result(torture_ctx, TORTURE_FAIL, \
135 : __location__": "#got".invocation_id did not match "#expected".invocation_id: %s", cmt); \
136 : return false; \
137 : } \
138 : } while(0)
139 :
140 : /*
141 : * forward declaration for internal functions
142 : */
143 : static bool _drsut_ldb_schema_info_reset(struct torture_context *tctx,
144 : struct ldb_context *ldb,
145 : const char *schema_info_str,
146 : bool in_setup);
147 :
148 :
149 : /**
150 : * Creates dsdb_schema_info object based on NDR data
151 : * passed as hex string
152 : */
153 3 : static bool _drsut_schemainfo_new(struct torture_context *tctx,
154 : const char *schema_info_str, struct dsdb_schema_info **_si)
155 : {
156 3 : WERROR werr;
157 3 : DATA_BLOB blob;
158 :
159 3 : blob = strhex_to_data_blob(tctx, schema_info_str);
160 3 : if (!blob.data) {
161 0 : torture_comment(tctx, "Not enough memory!\n");
162 0 : return false;
163 : }
164 :
165 3 : werr = dsdb_schema_info_from_blob(&blob, tctx, _si);
166 3 : if (!W_ERROR_IS_OK(werr)) {
167 0 : torture_comment(tctx,
168 : "Failed to create dsdb_schema_info object for %s: %s",
169 : schema_info_str,
170 : win_errstr(werr));
171 0 : return false;
172 : }
173 :
174 3 : data_blob_free(&blob);
175 :
176 3 : return true;
177 : }
178 :
179 : /**
180 : * Creates dsdb_schema_info object based on predefined data
181 : * Function is public as it is intended to be used by other
182 : * tests (e.g. prefixMap tests)
183 : */
184 1 : bool drsut_schemainfo_new(struct torture_context *tctx, struct dsdb_schema_info **_si)
185 : {
186 1 : return _drsut_schemainfo_new(tctx, SCHEMA_INFO_DEFAULT_STR, _si);
187 : }
188 :
189 :
190 : /*
191 : * Tests dsdb_schema_info_new() and dsdb_schema_info_blob_new()
192 : */
193 1 : static bool test_dsdb_schema_info_new(struct torture_context *tctx,
194 : struct drsut_schemainfo_data *priv)
195 : {
196 1 : WERROR werr;
197 1 : DATA_BLOB ndr_blob;
198 1 : DATA_BLOB ndr_blob_expected;
199 1 : struct dsdb_schema_info *schi;
200 1 : TALLOC_CTX *mem_ctx;
201 :
202 1 : mem_ctx = talloc_new(priv);
203 1 : torture_assert(tctx, mem_ctx, "Not enough memory!");
204 1 : ndr_blob_expected = strhex_to_data_blob(mem_ctx, SCHEMA_INFO_INIT_STR);
205 1 : torture_assert(tctx, ndr_blob_expected.data, "Not enough memory!");
206 :
207 1 : werr = dsdb_schema_info_new(mem_ctx, &schi);
208 1 : torture_assert_werr_ok(tctx, werr, "dsdb_schema_info_new() failed");
209 1 : torture_assert_int_equal(tctx, schi->revision, 0,
210 : "dsdb_schema_info_new() creates schemaInfo with invalid revision");
211 1 : torture_assert(tctx, GUID_all_zero(&schi->invocation_id),
212 : "dsdb_schema_info_new() creates schemaInfo with not ZERO GUID");
213 :
214 1 : werr = dsdb_schema_info_blob_new(mem_ctx, &ndr_blob);
215 1 : torture_assert_werr_ok(tctx, werr, "dsdb_schema_info_blob_new() failed");
216 1 : torture_assert_data_blob_equal(tctx, ndr_blob, ndr_blob_expected,
217 : "dsdb_schema_info_blob_new() returned invalid blob");
218 :
219 1 : talloc_free(mem_ctx);
220 1 : return true;
221 : }
222 :
223 : /*
224 : * Tests dsdb_schema_info_from_blob()
225 : */
226 1 : static bool test_dsdb_schema_info_from_blob(struct torture_context *tctx,
227 : struct drsut_schemainfo_data *priv)
228 : {
229 1 : uint32_t i;
230 1 : WERROR werr;
231 1 : char *msg;
232 1 : struct dsdb_schema_info *schema_info;
233 1 : TALLOC_CTX *mem_ctx;
234 :
235 1 : mem_ctx = talloc_new(priv);
236 1 : torture_assert(tctx, mem_ctx, "Not enough memory!");
237 :
238 6 : for (i = 0; i < priv->test_data_count; i++) {
239 5 : struct schemainfo_data *data = &priv->test_data[i];
240 :
241 10 : msg = talloc_asprintf(tctx, "dsdb_schema_info_from_blob() [%d]-[%s]",
242 5 : i, _schemainfo_test_data[i].schema_info_str);
243 :
244 5 : werr = dsdb_schema_info_from_blob(&data->ndr_blob, mem_ctx, &schema_info);
245 5 : torture_assert_werr_equal(tctx, werr, data->werr_expected, msg);
246 :
247 : /* test returned data */
248 5 : if (W_ERROR_IS_OK(werr)) {
249 5 : torture_assert_schema_info_equal(tctx,
250 : schema_info, &data->schi,
251 : "after dsdb_schema_info_from_blob() call");
252 : }
253 : }
254 :
255 1 : talloc_free(mem_ctx);
256 :
257 1 : return true;
258 : }
259 :
260 : /*
261 : * Tests dsdb_blob_from_schema_info()
262 : */
263 1 : static bool test_dsdb_blob_from_schema_info(struct torture_context *tctx,
264 : struct drsut_schemainfo_data *priv)
265 : {
266 1 : uint32_t i;
267 1 : WERROR werr;
268 1 : char *msg;
269 1 : DATA_BLOB ndr_blob;
270 1 : TALLOC_CTX *mem_ctx;
271 :
272 1 : mem_ctx = talloc_new(priv);
273 1 : torture_assert(tctx, mem_ctx, "Not enough memory!");
274 :
275 6 : for (i = 0; i < priv->test_data_count; i++) {
276 5 : struct schemainfo_data *data = &priv->test_data[i];
277 :
278 : /* not all test are valid reverse type of conversion */
279 5 : if (!data->test_both_ways) {
280 2 : continue;
281 : }
282 :
283 6 : msg = talloc_asprintf(tctx, "dsdb_blob_from_schema_info() [%d]-[%s]",
284 3 : i, _schemainfo_test_data[i].schema_info_str);
285 :
286 3 : werr = dsdb_blob_from_schema_info(&data->schi, mem_ctx, &ndr_blob);
287 3 : torture_assert_werr_equal(tctx, werr, data->werr_expected, msg);
288 :
289 : /* test returned data */
290 3 : if (W_ERROR_IS_OK(werr)) {
291 5 : torture_assert_data_blob_equal(tctx,
292 : ndr_blob, data->ndr_blob,
293 : "dsdb_blob_from_schema_info()");
294 : }
295 : }
296 :
297 1 : talloc_free(mem_ctx);
298 :
299 1 : return true;
300 : }
301 :
302 1 : static bool test_dsdb_schema_info_cmp(struct torture_context *tctx,
303 : struct drsut_schemainfo_data *priv)
304 : {
305 1 : DATA_BLOB blob;
306 1 : struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;
307 1 : struct dsdb_schema_info schema_info;
308 :
309 1 : ctr = talloc_zero(priv, struct drsuapi_DsReplicaOIDMapping_Ctr);
310 1 : torture_assert(tctx, ctr, "Not enough memory!");
311 :
312 : /* not enough elements */
313 1 : torture_assert_werr_equal(tctx,
314 : dsdb_schema_info_cmp(priv->schema, ctr),
315 : WERR_INVALID_PARAMETER,
316 : "dsdb_schema_info_cmp(): unexpected result");
317 :
318 : /* an empty element for schemaInfo */
319 1 : ctr->num_mappings = 1;
320 1 : ctr->mappings = talloc_zero_array(ctr, struct drsuapi_DsReplicaOIDMapping, 1);
321 1 : torture_assert(tctx, ctr->mappings, "Not enough memory!");
322 1 : torture_assert_werr_equal(tctx,
323 : dsdb_schema_info_cmp(priv->schema, ctr),
324 : WERR_INVALID_PARAMETER,
325 : "dsdb_schema_info_cmp(): unexpected result");
326 :
327 : /* test with invalid schemaInfo - length != 21 */
328 1 : blob = strhex_to_data_blob(ctr, "FF00000001FD821C07C7455143A3DB51F75A630A7F00");
329 1 : torture_assert(tctx, blob.data, "Not enough memory!");
330 1 : ctr->mappings[0].oid.length = blob.length;
331 1 : ctr->mappings[0].oid.binary_oid = blob.data;
332 1 : torture_assert_werr_equal(tctx,
333 : dsdb_schema_info_cmp(priv->schema, ctr),
334 : WERR_INVALID_PARAMETER,
335 : "dsdb_schema_info_cmp(): unexpected result");
336 :
337 : /* test with invalid schemaInfo - marker != 0xFF */
338 1 : blob = strhex_to_data_blob(ctr, "AA00000001FD821C07C7455143A3DB51F75A630A7F");
339 1 : torture_assert(tctx, blob.data, "Not enough memory!");
340 1 : ctr->mappings[0].oid.length = blob.length;
341 1 : ctr->mappings[0].oid.binary_oid = blob.data;
342 1 : torture_assert_werr_equal(tctx,
343 : dsdb_schema_info_cmp(priv->schema, ctr),
344 : WERR_INVALID_PARAMETER,
345 : "dsdb_schema_info_cmp(): unexpected result");
346 :
347 : /* test with valid schemaInfo, but older one should be ok */
348 1 : blob = strhex_to_data_blob(ctr, "FF0000000000000000000000000000000000000000");
349 1 : torture_assert(tctx, blob.data, "Not enough memory!");
350 1 : ctr->mappings[0].oid.length = blob.length;
351 1 : ctr->mappings[0].oid.binary_oid = blob.data;
352 1 : torture_assert_werr_equal(tctx,
353 : dsdb_schema_info_cmp(priv->schema, ctr),
354 : WERR_OK,
355 : "dsdb_schema_info_cmp(): unexpected result");
356 :
357 : /* test with correct schemaInfo, but invalid ATTID */
358 1 : schema_info = *priv->schema->schema_info;
359 1 : torture_assert_werr_ok(tctx,
360 : dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
361 : "dsdb_blob_from_schema_info() failed");
362 1 : ctr->mappings[0].id_prefix = 1;
363 1 : ctr->mappings[0].oid.length = blob.length;
364 1 : ctr->mappings[0].oid.binary_oid = blob.data;
365 1 : torture_assert_werr_equal(tctx,
366 : dsdb_schema_info_cmp(priv->schema, ctr),
367 : WERR_INVALID_PARAMETER,
368 : "dsdb_schema_info_cmp(): unexpected result");
369 :
370 : /* test with valid schemaInfo */
371 1 : ctr->mappings[0].id_prefix = 0;
372 1 : torture_assert_werr_ok(tctx,
373 : dsdb_schema_info_cmp(priv->schema, ctr),
374 : "dsdb_schema_info_cmp(): unexpected result");
375 :
376 : /* test with valid schemaInfo, but older revision */
377 1 : schema_info = *priv->schema->schema_info;
378 1 : schema_info.revision -= 1;
379 1 : torture_assert_werr_ok(tctx,
380 : dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
381 : "dsdb_blob_from_schema_info() failed");
382 1 : ctr->mappings[0].oid.length = blob.length;
383 1 : ctr->mappings[0].oid.binary_oid = blob.data;
384 1 : torture_assert_werr_equal(tctx,
385 : dsdb_schema_info_cmp(priv->schema, ctr),
386 : WERR_OK,
387 : "dsdb_schema_info_cmp(): unexpected result");
388 :
389 : /* test with valid schemaInfo, but newer revision */
390 1 : schema_info = *priv->schema->schema_info;
391 1 : schema_info.revision += 1;
392 1 : torture_assert_werr_ok(tctx,
393 : dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
394 : "dsdb_blob_from_schema_info() failed");
395 1 : ctr->mappings[0].oid.length = blob.length;
396 1 : ctr->mappings[0].oid.binary_oid = blob.data;
397 1 : torture_assert_werr_equal(tctx,
398 : dsdb_schema_info_cmp(priv->schema, ctr),
399 : WERR_DS_DRA_SCHEMA_MISMATCH,
400 : "dsdb_schema_info_cmp(): unexpected result");
401 :
402 : /* test with valid schemaInfo, but newer revision and other invocationId */
403 1 : schema_info = *priv->schema->schema_info;
404 1 : schema_info.revision += 1;
405 1 : schema_info.invocation_id.time_mid += 1;
406 1 : torture_assert_werr_ok(tctx,
407 : dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
408 : "dsdb_blob_from_schema_info() failed");
409 1 : ctr->mappings[0].oid.length = blob.length;
410 1 : ctr->mappings[0].oid.binary_oid = blob.data;
411 1 : torture_assert_werr_equal(tctx,
412 : dsdb_schema_info_cmp(priv->schema, ctr),
413 : WERR_DS_DRA_SCHEMA_MISMATCH,
414 : "dsdb_schema_info_cmp(): unexpected result");
415 :
416 : /* test with valid schemaInfo, but older revision and other invocationId */
417 1 : schema_info = *priv->schema->schema_info;
418 1 : schema_info.revision -= 1;
419 1 : schema_info.invocation_id.time_mid += 1;
420 1 : torture_assert_werr_ok(tctx,
421 : dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
422 : "dsdb_blob_from_schema_info() failed");
423 1 : ctr->mappings[0].oid.length = blob.length;
424 1 : ctr->mappings[0].oid.binary_oid = blob.data;
425 1 : torture_assert_werr_equal(tctx,
426 : dsdb_schema_info_cmp(priv->schema, ctr),
427 : WERR_OK,
428 : "dsdb_schema_info_cmp(): unexpected result");
429 :
430 : /* test with valid schemaInfo, but same revision and other invocationId */
431 1 : schema_info = *priv->schema->schema_info;
432 1 : schema_info.invocation_id.time_mid += 1;
433 1 : torture_assert_werr_ok(tctx,
434 : dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
435 : "dsdb_blob_from_schema_info() failed");
436 1 : ctr->mappings[0].oid.length = blob.length;
437 1 : ctr->mappings[0].oid.binary_oid = blob.data;
438 1 : torture_assert_werr_equal(tctx,
439 : dsdb_schema_info_cmp(priv->schema, ctr),
440 : WERR_DS_DRA_SCHEMA_CONFLICT,
441 : "dsdb_schema_info_cmp(): unexpected result");
442 :
443 1 : talloc_free(ctr);
444 1 : return true;
445 : }
446 :
447 : /*
448 : * Tests dsdb_module_schema_info_blob_read()
449 : * and dsdb_module_schema_info_blob_write()
450 : */
451 1 : static bool test_dsdb_module_schema_info_blob_rw(struct torture_context *tctx,
452 : struct drsut_schemainfo_data *priv)
453 : {
454 1 : int ldb_err;
455 1 : DATA_BLOB blob_write;
456 1 : DATA_BLOB blob_read;
457 :
458 : /* reset schmeInfo to know value */
459 1 : torture_assert(tctx,
460 : _drsut_ldb_schema_info_reset(tctx, priv->ldb, SCHEMA_INFO_INIT_STR, false),
461 : "_drsut_ldb_schema_info_reset() failed");
462 :
463 : /* write tests' default schemaInfo */
464 1 : blob_write = strhex_to_data_blob(priv, SCHEMA_INFO_DEFAULT_STR);
465 1 : torture_assert(tctx, blob_write.data, "Not enough memory!");
466 :
467 1 : ldb_err = dsdb_module_schema_info_blob_write(priv->ldb_module,
468 : DSDB_FLAG_TOP_MODULE,
469 : &blob_write, NULL);
470 1 : torture_assert_int_equal(tctx, ldb_err, LDB_SUCCESS, "dsdb_module_schema_info_blob_write() failed");
471 :
472 1 : ldb_err = dsdb_module_schema_info_blob_read(priv->ldb_module, DSDB_FLAG_TOP_MODULE,
473 : priv, &blob_read, NULL);
474 1 : torture_assert_int_equal(tctx, ldb_err, LDB_SUCCESS, "dsdb_module_schema_info_blob_read() failed");
475 :
476 : /* check if we get what we wrote */
477 1 : torture_assert_data_blob_equal(tctx, blob_read, blob_write,
478 : "Write/Read of schemeInfo blob failed");
479 :
480 0 : return true;
481 : }
482 :
483 : /*
484 : * Tests dsdb_schema_update_schema_info()
485 : */
486 1 : static bool test_dsdb_module_schema_info_update(struct torture_context *tctx,
487 : struct drsut_schemainfo_data *priv)
488 : {
489 1 : int ldb_err;
490 1 : WERROR werr;
491 1 : DATA_BLOB blob;
492 1 : struct dsdb_schema_info *schema_info;
493 :
494 : /* reset schmeInfo to know value */
495 1 : torture_assert(tctx,
496 : _drsut_ldb_schema_info_reset(tctx, priv->ldb, SCHEMA_INFO_INIT_STR, false),
497 : "_drsut_ldb_schema_info_reset() failed");
498 :
499 1 : ldb_err = dsdb_module_schema_info_update(priv->ldb_module,
500 : priv->schema,
501 : DSDB_FLAG_TOP_MODULE | DSDB_FLAG_AS_SYSTEM, NULL);
502 1 : torture_assert_int_equal(tctx, ldb_err, LDB_SUCCESS, "dsdb_module_schema_info_update() failed");
503 :
504 : /* get updated schemaInfo */
505 1 : ldb_err = dsdb_module_schema_info_blob_read(priv->ldb_module, DSDB_FLAG_TOP_MODULE,
506 : priv, &blob, NULL);
507 1 : torture_assert_int_equal(tctx, ldb_err, LDB_SUCCESS, "dsdb_module_schema_info_blob_read() failed");
508 :
509 1 : werr = dsdb_schema_info_from_blob(&blob, priv, &schema_info);
510 1 : torture_assert_werr_ok(tctx, werr, "dsdb_schema_info_from_blob() failed");
511 :
512 : /* check against default schema_info */
513 1 : torture_assert_schema_info_equal(tctx, schema_info, priv->schema_info,
514 : "schemaInfo attribute no updated correctly");
515 :
516 0 : return true;
517 : }
518 :
519 :
520 : /**
521 : * Reset schemaInfo record to know value
522 : */
523 3 : static bool _drsut_ldb_schema_info_reset(struct torture_context *tctx,
524 : struct ldb_context *ldb,
525 : const char *schema_info_str,
526 : bool in_setup)
527 : {
528 3 : bool bret = true;
529 3 : int ldb_err;
530 3 : DATA_BLOB blob;
531 3 : struct ldb_message *msg;
532 3 : TALLOC_CTX *mem_ctx = talloc_new(tctx);
533 :
534 3 : blob = strhex_to_data_blob(mem_ctx, schema_info_str);
535 3 : torture_assert_goto(tctx, blob.data, bret, DONE, "Not enough memory!");
536 :
537 3 : msg = ldb_msg_new(mem_ctx);
538 3 : torture_assert_goto(tctx, msg, bret, DONE, "Not enough memory!");
539 :
540 3 : msg->dn = ldb_get_schema_basedn(ldb);
541 3 : ldb_err = ldb_msg_add_value(msg, "schemaInfo", &blob, NULL);
542 3 : torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE,
543 : "ldb_msg_add_value() failed");
544 :
545 3 : if (in_setup) {
546 1 : ldb_err = ldb_add(ldb, msg);
547 : } else {
548 2 : ldb_err = dsdb_replace(ldb, msg, DSDB_MODIFY_PERMISSIVE);
549 : }
550 3 : torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE,
551 : "dsdb_replace() failed");
552 :
553 3 : DONE:
554 3 : talloc_free(mem_ctx);
555 3 : return bret;
556 : }
557 :
558 : /**
559 : * Prepare temporary LDB and opens it
560 : */
561 1 : static bool _drsut_ldb_setup(struct torture_context *tctx, struct drsut_schemainfo_data *priv)
562 : {
563 1 : int ldb_err;
564 1 : char *ldb_url;
565 1 : bool bret = true;
566 1 : char *tempdir = NULL;
567 1 : NTSTATUS status;
568 1 : TALLOC_CTX* mem_ctx;
569 :
570 1 : mem_ctx = talloc_new(priv);
571 1 : torture_assert(tctx, mem_ctx, "Not enough memory!");
572 :
573 1 : status = torture_temp_dir(tctx, "drs_", &tempdir);
574 1 : torture_assert_ntstatus_ok_goto(tctx, status, bret, DONE, "creating temp dir");
575 :
576 1 : ldb_url = talloc_asprintf(priv, "%s/drs_schemainfo.ldb", tempdir);
577 1 : torture_assert_goto(tctx, ldb_url, bret, DONE, "Not enough memory!");
578 :
579 : /* create LDB */
580 1 : priv->ldb = ldb_wrap_connect(priv, tctx->ev, tctx->lp_ctx,
581 : ldb_url, NULL, NULL, 0);
582 1 : torture_assert_goto(tctx, priv->ldb, bret, DONE, "ldb_wrap_connect() failed");
583 :
584 : /* set some schemaNamingContext */
585 1 : ldb_err = ldb_set_opaque(priv->ldb,
586 : "schemaNamingContext",
587 1 : ldb_dn_new(priv->ldb, priv->ldb, "CN=Schema,CN=Config"));
588 1 : torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE,
589 : "ldb_set_opaque() failed");
590 :
591 : /* add schemaInfo attribute so tested layer could work properly */
592 1 : torture_assert_goto(tctx,
593 : _drsut_ldb_schema_info_reset(tctx, priv->ldb, SCHEMA_INFO_INIT_STR, true),
594 : bret, DONE,
595 : "_drsut_ldb_schema_info_reset() failed");
596 :
597 1 : DONE:
598 1 : talloc_free(tempdir);
599 1 : talloc_free(mem_ctx);
600 1 : return bret;
601 : }
602 :
603 : /*
604 : * Setup/Teardown for test case
605 : */
606 1 : static bool torture_drs_unit_schemainfo_setup(struct torture_context *tctx,
607 : struct drsut_schemainfo_data **_priv)
608 : {
609 1 : size_t i;
610 1 : int ldb_err;
611 1 : NTSTATUS status;
612 1 : DATA_BLOB ndr_blob;
613 1 : struct GUID guid;
614 1 : struct drsut_schemainfo_data *priv;
615 :
616 1 : priv = talloc_zero(tctx, struct drsut_schemainfo_data);
617 1 : torture_assert(tctx, priv, "Not enough memory!");
618 :
619 : /* returned allocated pointer here
620 : * teardown() will be called even in case of failure,
621 : * so we'll get a changes to clean up */
622 1 : *_priv = priv;
623 :
624 : /* create initial schemaInfo */
625 1 : torture_assert(tctx,
626 : _drsut_schemainfo_new(tctx, SCHEMA_INFO_DEFAULT_STR, &priv->schema_info),
627 : "Failed to create schema_info test object");
628 :
629 : /* create data to test with */
630 1 : priv->test_data_count = ARRAY_SIZE(_schemainfo_test_data);
631 1 : priv->test_data = talloc_array(tctx, struct schemainfo_data, priv->test_data_count);
632 :
633 6 : for (i = 0; i < ARRAY_SIZE(_schemainfo_test_data); i++) {
634 5 : struct schemainfo_data *data = &priv->test_data[i];
635 :
636 5 : ndr_blob = strhex_to_data_blob(priv,
637 5 : _schemainfo_test_data[i].schema_info_str);
638 5 : torture_assert(tctx, ndr_blob.data, "Not enough memory!");
639 :
640 5 : status = GUID_from_string(_schemainfo_test_data[i].guid_str, &guid);
641 5 : torture_assert_ntstatus_ok(tctx, status,
642 : talloc_asprintf(tctx,
643 : "GUID_from_string() failed for %s",
644 : _schemainfo_test_data[i].guid_str));
645 :
646 5 : data->ndr_blob = ndr_blob;
647 5 : data->schi.invocation_id = guid;
648 5 : data->schi.revision = _schemainfo_test_data[i].revision;
649 5 : data->werr_expected = _schemainfo_test_data[i].werr_expected;
650 5 : data->test_both_ways = _schemainfo_test_data[i].test_both_ways;
651 :
652 : }
653 :
654 : /* create temporary LDB and populate with data */
655 1 : if (!_drsut_ldb_setup(tctx, priv)) {
656 0 : return false;
657 : }
658 :
659 : /* create ldb_module mockup object */
660 1 : priv->ldb_module = ldb_module_new(priv, priv->ldb, "schemaInfo_test_module", NULL);
661 1 : torture_assert(tctx, priv->ldb_module, "Not enough memory!");
662 :
663 : /* create schema mockup object */
664 1 : priv->schema = dsdb_new_schema(priv);
665 :
666 : /* set schema_info in dsdb_schema for testing */
667 1 : torture_assert(tctx,
668 : _drsut_schemainfo_new(tctx, SCHEMA_INFO_DEFAULT_STR, &priv->schema->schema_info),
669 : "Failed to create schema_info test object");
670 :
671 : /* pre-cache invocationId for samdb_ntds_invocation_id()
672 : * to work with our mock ldb */
673 2 : ldb_err = ldb_set_opaque(priv->ldb, "cache.invocation_id",
674 1 : &priv->schema_info->invocation_id);
675 1 : torture_assert_int_equal(tctx, ldb_err, LDB_SUCCESS, "ldb_set_opaque() failed");
676 :
677 : /* Perform all tests in transactions so that
678 : * underlying modify calls not to fail */
679 1 : ldb_err = ldb_transaction_start(priv->ldb);
680 1 : torture_assert_int_equal(tctx,
681 : ldb_err,
682 : LDB_SUCCESS,
683 : "ldb_transaction_start() failed");
684 :
685 0 : return true;
686 : }
687 :
688 1 : static bool torture_drs_unit_schemainfo_teardown(struct torture_context *tctx,
689 : struct drsut_schemainfo_data *priv)
690 : {
691 1 : int ldb_err;
692 :
693 : /* commit pending transaction so we will
694 : * be able to check what LDB state is */
695 1 : ldb_err = ldb_transaction_commit(priv->ldb);
696 1 : if (ldb_err != LDB_SUCCESS) {
697 0 : torture_comment(tctx, "ldb_transaction_commit() - %s (%s)",
698 : ldb_strerror(ldb_err),
699 : ldb_errstring(priv->ldb));
700 : }
701 :
702 1 : talloc_free(priv);
703 :
704 1 : return true;
705 : }
706 :
707 : /**
708 : * Test case initialization for
709 : * drs.unit.schemaInfo
710 : */
711 2354 : struct torture_tcase * torture_drs_unit_schemainfo(struct torture_suite *suite)
712 : {
713 125 : typedef bool (*pfn_setup)(struct torture_context *, void **);
714 125 : typedef bool (*pfn_teardown)(struct torture_context *, void *);
715 125 : typedef bool (*pfn_run)(struct torture_context *, void *);
716 :
717 2354 : struct torture_tcase * tc = torture_suite_add_tcase(suite, "schemaInfo");
718 :
719 2354 : torture_tcase_set_fixture(tc,
720 : (pfn_setup)torture_drs_unit_schemainfo_setup,
721 : (pfn_teardown)torture_drs_unit_schemainfo_teardown);
722 :
723 2354 : tc->description = talloc_strdup(tc, "Unit tests for DRSUAPI::schemaInfo implementation");
724 :
725 2354 : torture_tcase_add_simple_test(tc, "dsdb_schema_info_new",
726 : (pfn_run)test_dsdb_schema_info_new);
727 2354 : torture_tcase_add_simple_test(tc, "dsdb_schema_info_from_blob",
728 : (pfn_run)test_dsdb_schema_info_from_blob);
729 2354 : torture_tcase_add_simple_test(tc, "dsdb_blob_from_schema_info",
730 : (pfn_run)test_dsdb_blob_from_schema_info);
731 2354 : torture_tcase_add_simple_test(tc, "dsdb_schema_info_cmp",
732 : (pfn_run)test_dsdb_schema_info_cmp);
733 2354 : torture_tcase_add_simple_test(tc, "dsdb_module_schema_info_blob read|write",
734 : (pfn_run)test_dsdb_module_schema_info_blob_rw);
735 2354 : torture_tcase_add_simple_test(tc, "dsdb_module_schema_info_update",
736 : (pfn_run)test_dsdb_module_schema_info_update);
737 :
738 :
739 2354 : return tc;
740 : }
|