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 */
_drsut_schemainfo_new(struct torture_context * tctx,const char * schema_info_str,struct dsdb_schema_info ** _si)153 static bool _drsut_schemainfo_new(struct torture_context *tctx,
154 const char *schema_info_str, struct dsdb_schema_info **_si)
155 {
156 WERROR werr;
157 DATA_BLOB blob;
158
159 blob = strhex_to_data_blob(tctx, schema_info_str);
160 if (!blob.data) {
161 torture_comment(tctx, "Not enough memory!\n");
162 return false;
163 }
164
165 werr = dsdb_schema_info_from_blob(&blob, tctx, _si);
166 if (!W_ERROR_IS_OK(werr)) {
167 torture_comment(tctx,
168 "Failed to create dsdb_schema_info object for %s: %s",
169 schema_info_str,
170 win_errstr(werr));
171 return false;
172 }
173
174 data_blob_free(&blob);
175
176 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 */
drsut_schemainfo_new(struct torture_context * tctx,struct dsdb_schema_info ** _si)184 bool drsut_schemainfo_new(struct torture_context *tctx, struct dsdb_schema_info **_si)
185 {
186 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 */
test_dsdb_schema_info_new(struct torture_context * tctx,struct drsut_schemainfo_data * priv)193 static bool test_dsdb_schema_info_new(struct torture_context *tctx,
194 struct drsut_schemainfo_data *priv)
195 {
196 WERROR werr;
197 DATA_BLOB ndr_blob;
198 DATA_BLOB ndr_blob_expected;
199 struct dsdb_schema_info *schi;
200 TALLOC_CTX *mem_ctx;
201
202 mem_ctx = talloc_new(priv);
203 torture_assert(tctx, mem_ctx, "Not enough memory!");
204 ndr_blob_expected = strhex_to_data_blob(mem_ctx, SCHEMA_INFO_INIT_STR);
205 torture_assert(tctx, ndr_blob_expected.data, "Not enough memory!");
206
207 werr = dsdb_schema_info_new(mem_ctx, &schi);
208 torture_assert_werr_ok(tctx, werr, "dsdb_schema_info_new() failed");
209 torture_assert_int_equal(tctx, schi->revision, 0,
210 "dsdb_schema_info_new() creates schemaInfo with invalid revision");
211 torture_assert(tctx, GUID_all_zero(&schi->invocation_id),
212 "dsdb_schema_info_new() creates schemaInfo with not ZERO GUID");
213
214 werr = dsdb_schema_info_blob_new(mem_ctx, &ndr_blob);
215 torture_assert_werr_ok(tctx, werr, "dsdb_schema_info_blob_new() failed");
216 torture_assert_data_blob_equal(tctx, ndr_blob, ndr_blob_expected,
217 "dsdb_schema_info_blob_new() returned invalid blob");
218
219 talloc_free(mem_ctx);
220 return true;
221 }
222
223 /*
224 * Tests dsdb_schema_info_from_blob()
225 */
test_dsdb_schema_info_from_blob(struct torture_context * tctx,struct drsut_schemainfo_data * priv)226 static bool test_dsdb_schema_info_from_blob(struct torture_context *tctx,
227 struct drsut_schemainfo_data *priv)
228 {
229 int i;
230 WERROR werr;
231 char *msg;
232 struct dsdb_schema_info *schema_info;
233 TALLOC_CTX *mem_ctx;
234
235 mem_ctx = talloc_new(priv);
236 torture_assert(tctx, mem_ctx, "Not enough memory!");
237
238 for (i = 0; i < priv->test_data_count; i++) {
239 struct schemainfo_data *data = &priv->test_data[i];
240
241 msg = talloc_asprintf(tctx, "dsdb_schema_info_from_blob() [%d]-[%s]",
242 i, _schemainfo_test_data[i].schema_info_str);
243
244 werr = dsdb_schema_info_from_blob(&data->ndr_blob, mem_ctx, &schema_info);
245 torture_assert_werr_equal(tctx, werr, data->werr_expected, msg);
246
247 /* test returned data */
248 if (W_ERROR_IS_OK(werr)) {
249 torture_assert_schema_info_equal(tctx,
250 schema_info, &data->schi,
251 "after dsdb_schema_info_from_blob() call");
252 }
253 }
254
255 talloc_free(mem_ctx);
256
257 return true;
258 }
259
260 /*
261 * Tests dsdb_blob_from_schema_info()
262 */
test_dsdb_blob_from_schema_info(struct torture_context * tctx,struct drsut_schemainfo_data * priv)263 static bool test_dsdb_blob_from_schema_info(struct torture_context *tctx,
264 struct drsut_schemainfo_data *priv)
265 {
266 int i;
267 WERROR werr;
268 char *msg;
269 DATA_BLOB ndr_blob;
270 TALLOC_CTX *mem_ctx;
271
272 mem_ctx = talloc_new(priv);
273 torture_assert(tctx, mem_ctx, "Not enough memory!");
274
275 for (i = 0; i < priv->test_data_count; i++) {
276 struct schemainfo_data *data = &priv->test_data[i];
277
278 /* not all test are valid reverse type of conversion */
279 if (!data->test_both_ways) {
280 continue;
281 }
282
283 msg = talloc_asprintf(tctx, "dsdb_blob_from_schema_info() [%d]-[%s]",
284 i, _schemainfo_test_data[i].schema_info_str);
285
286 werr = dsdb_blob_from_schema_info(&data->schi, mem_ctx, &ndr_blob);
287 torture_assert_werr_equal(tctx, werr, data->werr_expected, msg);
288
289 /* test returned data */
290 if (W_ERROR_IS_OK(werr)) {
291 torture_assert_data_blob_equal(tctx,
292 ndr_blob, data->ndr_blob,
293 "dsdb_blob_from_schema_info()");
294 }
295 }
296
297 talloc_free(mem_ctx);
298
299 return true;
300 }
301
test_dsdb_schema_info_cmp(struct torture_context * tctx,struct drsut_schemainfo_data * priv)302 static bool test_dsdb_schema_info_cmp(struct torture_context *tctx,
303 struct drsut_schemainfo_data *priv)
304 {
305 DATA_BLOB blob;
306 struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;
307 struct dsdb_schema_info schema_info;
308
309 ctr = talloc_zero(priv, struct drsuapi_DsReplicaOIDMapping_Ctr);
310 torture_assert(tctx, ctr, "Not enough memory!");
311
312 /* not enough elements */
313 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 ctr->num_mappings = 1;
320 ctr->mappings = talloc_zero_array(ctr, struct drsuapi_DsReplicaOIDMapping, 1);
321 torture_assert(tctx, ctr->mappings, "Not enough memory!");
322 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 blob = strhex_to_data_blob(ctr, "FF00000001FD821C07C7455143A3DB51F75A630A7F00");
329 torture_assert(tctx, blob.data, "Not enough memory!");
330 ctr->mappings[0].oid.length = blob.length;
331 ctr->mappings[0].oid.binary_oid = blob.data;
332 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 blob = strhex_to_data_blob(ctr, "AA00000001FD821C07C7455143A3DB51F75A630A7F");
339 torture_assert(tctx, blob.data, "Not enough memory!");
340 ctr->mappings[0].oid.length = blob.length;
341 ctr->mappings[0].oid.binary_oid = blob.data;
342 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 blob = strhex_to_data_blob(ctr, "FF0000000000000000000000000000000000000000");
349 torture_assert(tctx, blob.data, "Not enough memory!");
350 ctr->mappings[0].oid.length = blob.length;
351 ctr->mappings[0].oid.binary_oid = blob.data;
352 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 schema_info = *priv->schema->schema_info;
359 torture_assert_werr_ok(tctx,
360 dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
361 "dsdb_blob_from_schema_info() failed");
362 ctr->mappings[0].id_prefix = 1;
363 ctr->mappings[0].oid.length = blob.length;
364 ctr->mappings[0].oid.binary_oid = blob.data;
365 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 ctr->mappings[0].id_prefix = 0;
372 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 schema_info = *priv->schema->schema_info;
378 schema_info.revision -= 1;
379 torture_assert_werr_ok(tctx,
380 dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
381 "dsdb_blob_from_schema_info() failed");
382 ctr->mappings[0].oid.length = blob.length;
383 ctr->mappings[0].oid.binary_oid = blob.data;
384 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 schema_info = *priv->schema->schema_info;
391 schema_info.revision += 1;
392 torture_assert_werr_ok(tctx,
393 dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
394 "dsdb_blob_from_schema_info() failed");
395 ctr->mappings[0].oid.length = blob.length;
396 ctr->mappings[0].oid.binary_oid = blob.data;
397 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 schema_info = *priv->schema->schema_info;
404 schema_info.revision += 1;
405 schema_info.invocation_id.time_mid += 1;
406 torture_assert_werr_ok(tctx,
407 dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
408 "dsdb_blob_from_schema_info() failed");
409 ctr->mappings[0].oid.length = blob.length;
410 ctr->mappings[0].oid.binary_oid = blob.data;
411 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 schema_info = *priv->schema->schema_info;
418 schema_info.revision -= 1;
419 schema_info.invocation_id.time_mid += 1;
420 torture_assert_werr_ok(tctx,
421 dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
422 "dsdb_blob_from_schema_info() failed");
423 ctr->mappings[0].oid.length = blob.length;
424 ctr->mappings[0].oid.binary_oid = blob.data;
425 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 schema_info = *priv->schema->schema_info;
432 schema_info.invocation_id.time_mid += 1;
433 torture_assert_werr_ok(tctx,
434 dsdb_blob_from_schema_info(&schema_info, tctx, &blob),
435 "dsdb_blob_from_schema_info() failed");
436 ctr->mappings[0].oid.length = blob.length;
437 ctr->mappings[0].oid.binary_oid = blob.data;
438 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 talloc_free(ctr);
444 return true;
445 }
446
447 /*
448 * Tests dsdb_module_schema_info_blob_read()
449 * and dsdb_module_schema_info_blob_write()
450 */
test_dsdb_module_schema_info_blob_rw(struct torture_context * tctx,struct drsut_schemainfo_data * priv)451 static bool test_dsdb_module_schema_info_blob_rw(struct torture_context *tctx,
452 struct drsut_schemainfo_data *priv)
453 {
454 int ldb_err;
455 DATA_BLOB blob_write;
456 DATA_BLOB blob_read;
457
458 /* reset schmeInfo to know value */
459 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 blob_write = strhex_to_data_blob(priv, SCHEMA_INFO_DEFAULT_STR);
465 torture_assert(tctx, blob_write.data, "Not enough memory!");
466
467 ldb_err = dsdb_module_schema_info_blob_write(priv->ldb_module,
468 DSDB_FLAG_TOP_MODULE,
469 &blob_write, NULL);
470 torture_assert_int_equal(tctx, ldb_err, LDB_SUCCESS, "dsdb_module_schema_info_blob_write() failed");
471
472 ldb_err = dsdb_module_schema_info_blob_read(priv->ldb_module, DSDB_FLAG_TOP_MODULE,
473 priv, &blob_read, NULL);
474 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 torture_assert_data_blob_equal(tctx, blob_read, blob_write,
478 "Write/Read of schemeInfo blob failed");
479
480 return true;
481 }
482
483 /*
484 * Tests dsdb_schema_update_schema_info()
485 */
test_dsdb_module_schema_info_update(struct torture_context * tctx,struct drsut_schemainfo_data * priv)486 static bool test_dsdb_module_schema_info_update(struct torture_context *tctx,
487 struct drsut_schemainfo_data *priv)
488 {
489 int ldb_err;
490 WERROR werr;
491 DATA_BLOB blob;
492 struct dsdb_schema_info *schema_info;
493
494 /* reset schmeInfo to know value */
495 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 ldb_err = dsdb_module_schema_info_update(priv->ldb_module,
500 priv->schema,
501 DSDB_FLAG_TOP_MODULE | DSDB_FLAG_AS_SYSTEM, NULL);
502 torture_assert_int_equal(tctx, ldb_err, LDB_SUCCESS, "dsdb_module_schema_info_update() failed");
503
504 /* get updated schemaInfo */
505 ldb_err = dsdb_module_schema_info_blob_read(priv->ldb_module, DSDB_FLAG_TOP_MODULE,
506 priv, &blob, NULL);
507 torture_assert_int_equal(tctx, ldb_err, LDB_SUCCESS, "dsdb_module_schema_info_blob_read() failed");
508
509 werr = dsdb_schema_info_from_blob(&blob, priv, &schema_info);
510 torture_assert_werr_ok(tctx, werr, "dsdb_schema_info_from_blob() failed");
511
512 /* check against default schema_info */
513 torture_assert_schema_info_equal(tctx, schema_info, priv->schema_info,
514 "schemaInfo attribute no updated correctly");
515
516 return true;
517 }
518
519
520 /**
521 * Reset schemaInfo record to know value
522 */
_drsut_ldb_schema_info_reset(struct torture_context * tctx,struct ldb_context * ldb,const char * schema_info_str,bool in_setup)523 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 bool bret = true;
529 int ldb_err;
530 DATA_BLOB blob;
531 struct ldb_message *msg;
532 TALLOC_CTX *mem_ctx = talloc_new(tctx);
533
534 blob = strhex_to_data_blob(mem_ctx, schema_info_str);
535 torture_assert_goto(tctx, blob.data, bret, DONE, "Not enough memory!");
536
537 msg = ldb_msg_new(mem_ctx);
538 torture_assert_goto(tctx, msg, bret, DONE, "Not enough memory!");
539
540 msg->dn = ldb_get_schema_basedn(ldb);
541 ldb_err = ldb_msg_add_value(msg, "schemaInfo", &blob, NULL);
542 torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE,
543 "ldb_msg_add_value() failed");
544
545 if (in_setup) {
546 ldb_err = ldb_add(ldb, msg);
547 } else {
548 ldb_err = dsdb_replace(ldb, msg, DSDB_MODIFY_PERMISSIVE);
549 }
550 torture_assert_int_equal_goto(tctx, ldb_err, LDB_SUCCESS, bret, DONE,
551 "dsdb_replace() failed");
552
553 DONE:
554 talloc_free(mem_ctx);
555 return bret;
556 }
557
558 /**
559 * Prepare temporary LDB and opens it
560 */
_drsut_ldb_setup(struct torture_context * tctx,struct drsut_schemainfo_data * priv)561 static bool _drsut_ldb_setup(struct torture_context *tctx, struct drsut_schemainfo_data *priv)
562 {
563 int ldb_err;
564 char *ldb_url;
565 bool bret = true;
566 char *tempdir = NULL;
567 NTSTATUS status;
568 TALLOC_CTX* mem_ctx;
569
570 mem_ctx = talloc_new(priv);
571 torture_assert(tctx, mem_ctx, "Not enough memory!");
572
573 status = torture_temp_dir(tctx, "drs_", &tempdir);
574 torture_assert_ntstatus_ok_goto(tctx, status, bret, DONE, "creating temp dir");
575
576 ldb_url = talloc_asprintf(priv, "%s/drs_schemainfo.ldb", tempdir);
577 torture_assert_goto(tctx, ldb_url, bret, DONE, "Not enough memory!");
578
579 /* create LDB */
580 priv->ldb = ldb_wrap_connect(priv, tctx->ev, tctx->lp_ctx,
581 ldb_url, NULL, NULL, 0);
582 torture_assert_goto(tctx, priv->ldb, bret, DONE, "ldb_wrap_connect() failed");
583
584 /* set some schemaNamingContext */
585 ldb_err = ldb_set_opaque(priv->ldb,
586 "schemaNamingContext",
587 ldb_dn_new(priv->ldb, priv->ldb, "CN=Schema,CN=Config"));
588 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 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 DONE:
598 talloc_free(tempdir);
599 talloc_free(mem_ctx);
600 return bret;
601 }
602
603 /*
604 * Setup/Teardown for test case
605 */
torture_drs_unit_schemainfo_setup(struct torture_context * tctx,struct drsut_schemainfo_data ** _priv)606 static bool torture_drs_unit_schemainfo_setup(struct torture_context *tctx,
607 struct drsut_schemainfo_data **_priv)
608 {
609 int i;
610 int ldb_err;
611 NTSTATUS status;
612 DATA_BLOB ndr_blob;
613 struct GUID guid;
614 struct drsut_schemainfo_data *priv;
615
616 priv = talloc_zero(tctx, struct drsut_schemainfo_data);
617 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 *_priv = priv;
623
624 /* create initial schemaInfo */
625 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 priv->test_data_count = ARRAY_SIZE(_schemainfo_test_data);
631 priv->test_data = talloc_array(tctx, struct schemainfo_data, priv->test_data_count);
632
633 for (i = 0; i < ARRAY_SIZE(_schemainfo_test_data); i++) {
634 struct schemainfo_data *data = &priv->test_data[i];
635
636 ndr_blob = strhex_to_data_blob(priv,
637 _schemainfo_test_data[i].schema_info_str);
638 torture_assert(tctx, ndr_blob.data, "Not enough memory!");
639
640 status = GUID_from_string(_schemainfo_test_data[i].guid_str, &guid);
641 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 data->ndr_blob = ndr_blob;
647 data->schi.invocation_id = guid;
648 data->schi.revision = _schemainfo_test_data[i].revision;
649 data->werr_expected = _schemainfo_test_data[i].werr_expected;
650 data->test_both_ways = _schemainfo_test_data[i].test_both_ways;
651
652 }
653
654 /* create temporary LDB and populate with data */
655 if (!_drsut_ldb_setup(tctx, priv)) {
656 return false;
657 }
658
659 /* create ldb_module mockup object */
660 priv->ldb_module = ldb_module_new(priv, priv->ldb, "schemaInfo_test_module", NULL);
661 torture_assert(tctx, priv->ldb_module, "Not enough memory!");
662
663 /* create schema mockup object */
664 priv->schema = dsdb_new_schema(priv);
665
666 /* set schema_info in dsdb_schema for testing */
667 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 ldb_err = ldb_set_opaque(priv->ldb, "cache.invocation_id",
674 &priv->schema_info->invocation_id);
675 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 ldb_err = ldb_transaction_start(priv->ldb);
680 torture_assert_int_equal(tctx,
681 ldb_err,
682 LDB_SUCCESS,
683 "ldb_transaction_start() failed");
684
685 return true;
686 }
687
torture_drs_unit_schemainfo_teardown(struct torture_context * tctx,struct drsut_schemainfo_data * priv)688 static bool torture_drs_unit_schemainfo_teardown(struct torture_context *tctx,
689 struct drsut_schemainfo_data *priv)
690 {
691 int ldb_err;
692
693 /* commit pending transaction so we will
694 * be able to check what LDB state is */
695 ldb_err = ldb_transaction_commit(priv->ldb);
696 if (ldb_err != LDB_SUCCESS) {
697 torture_comment(tctx, "ldb_transaction_commit() - %s (%s)",
698 ldb_strerror(ldb_err),
699 ldb_errstring(priv->ldb));
700 }
701
702 talloc_free(priv);
703
704 return true;
705 }
706
707 /**
708 * Test case initialization for
709 * drs.unit.schemaInfo
710 */
torture_drs_unit_schemainfo(struct torture_suite * suite)711 struct torture_tcase * torture_drs_unit_schemainfo(struct torture_suite *suite)
712 {
713 typedef bool (*pfn_setup)(struct torture_context *, void **);
714 typedef bool (*pfn_teardown)(struct torture_context *, void *);
715 typedef bool (*pfn_run)(struct torture_context *, void *);
716
717 struct torture_tcase * tc = torture_suite_add_tcase(suite, "schemaInfo");
718
719 torture_tcase_set_fixture(tc,
720 (pfn_setup)torture_drs_unit_schemainfo_setup,
721 (pfn_teardown)torture_drs_unit_schemainfo_teardown);
722
723 tc->description = talloc_strdup(tc, "Unit tests for DRSUAPI::schemaInfo implementation");
724
725 torture_tcase_add_simple_test(tc, "dsdb_schema_info_new",
726 (pfn_run)test_dsdb_schema_info_new);
727 torture_tcase_add_simple_test(tc, "dsdb_schema_info_from_blob",
728 (pfn_run)test_dsdb_schema_info_from_blob);
729 torture_tcase_add_simple_test(tc, "dsdb_blob_from_schema_info",
730 (pfn_run)test_dsdb_blob_from_schema_info);
731 torture_tcase_add_simple_test(tc, "dsdb_schema_info_cmp",
732 (pfn_run)test_dsdb_schema_info_cmp);
733 torture_tcase_add_simple_test(tc, "dsdb_module_schema_info_blob read|write",
734 (pfn_run)test_dsdb_module_schema_info_blob_rw);
735 torture_tcase_add_simple_test(tc, "dsdb_module_schema_info_update",
736 (pfn_run)test_dsdb_module_schema_info_update);
737
738
739 return tc;
740 }
741