Line data Source code
1 : /*
2 : Unix SMB/CIFS implementation.
3 : SMB torture tester
4 : Copyright (C) Andrew Bartlett 2012
5 :
6 : This program is free software; you can redistribute it and/or modify
7 : it under the terms of the GNU General Public License as published by
8 : the Free Software Foundation; either version 3 of the License, or
9 : (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : GNU General Public License for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with this program. If not, see <http://www.gnu.org/licenses/>.
18 : */
19 :
20 : #include "includes.h"
21 : #include "torture/smbtorture.h"
22 : #include "system/network.h"
23 : #include "dns_server/dlz_minimal.h"
24 : #include <talloc.h>
25 : #include <ldb.h>
26 : #include "lib/param/param.h"
27 : #include "dsdb/samdb/samdb.h"
28 : #include "dsdb/common/util.h"
29 : #include "auth/session.h"
30 : #include "auth/gensec/gensec.h"
31 : #include "auth/credentials/credentials.h"
32 : #include "lib/cmdline/cmdline.h"
33 : #include "system/network.h"
34 : #include "dns_server/dnsserver_common.h"
35 : #include "librpc/gen_ndr/ndr_dnsserver.h"
36 : #include "librpc/gen_ndr/ndr_dnsserver_c.h"
37 : #include "torture/rpc/torture_rpc.h"
38 : #include "librpc/gen_ndr/ndr_dnsp.h"
39 :
40 : #include "librpc/rpc/dcerpc.h"
41 : #include "librpc/rpc/dcerpc_proto.h"
42 :
43 : /* Tests that configure multiple DLZs will use this. Increase to add stress. */
44 : #define NUM_DLZS_TO_CONFIGURE 4
45 :
46 : struct torture_context *tctx_static;
47 :
48 : static void dlz_bind9_log_wrapper(int level, const char *fmt, ...)
49 : PRINTF_ATTRIBUTE(2,3);
50 :
51 254 : static void dlz_bind9_log_wrapper(int level, const char *fmt, ...)
52 : {
53 0 : va_list ap;
54 0 : char *msg;
55 254 : va_start(ap, fmt);
56 254 : msg = talloc_vasprintf(NULL, fmt, ap);
57 254 : torture_comment(tctx_static, "%s\n", msg);
58 254 : TALLOC_FREE(msg);
59 254 : va_end(ap);
60 254 : }
61 :
62 1 : static bool test_dlz_bind9_version(struct torture_context *tctx)
63 : {
64 1 : unsigned int flags = 0;
65 1 : torture_assert_int_equal(tctx, dlz_version(&flags),
66 : DLZ_DLOPEN_VERSION, "got wrong DLZ version");
67 1 : return true;
68 : }
69 :
70 44 : static char *dlz_bind9_binddns_dir(struct torture_context *tctx,
71 : const char *file)
72 : {
73 44 : return talloc_asprintf(tctx,
74 : "ldb://%s/%s",
75 : lpcfg_binddns_dir(tctx->lp_ctx),
76 : file);
77 : }
78 :
79 1 : static bool test_dlz_bind9_create(struct torture_context *tctx)
80 : {
81 0 : void *dbdata;
82 2 : const char *argv[] = {
83 : "samba_dlz",
84 : "-H",
85 1 : dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
86 : NULL
87 : };
88 1 : tctx_static = tctx;
89 1 : torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, argv, &dbdata,
90 : "log", dlz_bind9_log_wrapper, NULL), ISC_R_SUCCESS,
91 : "Failed to create samba_dlz");
92 :
93 1 : dlz_destroy(dbdata);
94 :
95 1 : return true;
96 : }
97 :
98 : static bool calls_zone_hook = false;
99 :
100 28 : static isc_result_t dlz_bind9_writeable_zone_hook(dns_view_t *view,
101 : dns_dlzdb_t *dlzdb,
102 : const char *zone_name)
103 : {
104 28 : struct torture_context *tctx = talloc_get_type((void *)view, struct torture_context);
105 28 : struct ldb_context *samdb = NULL;
106 28 : char *errstring = NULL;
107 28 : int ret = samdb_connect_url(
108 : tctx,
109 : NULL,
110 : tctx->lp_ctx,
111 : system_session(tctx->lp_ctx),
112 : 0,
113 28 : dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
114 : NULL,
115 : &samdb,
116 : &errstring);
117 0 : struct ldb_message *msg;
118 28 : const char *attrs[] = {
119 : NULL
120 : };
121 28 : if (ret != LDB_SUCCESS) {
122 0 : torture_comment(tctx, "Failed to connect to samdb");
123 0 : return ISC_R_FAILURE;
124 : }
125 :
126 28 : ret = dsdb_search_one(samdb, tctx, &msg, NULL,
127 : LDB_SCOPE_SUBTREE, attrs, DSDB_SEARCH_SEARCH_ALL_PARTITIONS,
128 : "(&(objectClass=dnsZone)(name=%s))", zone_name);
129 28 : if (ret != LDB_SUCCESS) {
130 0 : torture_comment(tctx,
131 : "Failed to search for %s: %s",
132 : zone_name,
133 : ldb_errstring(samdb));
134 0 : return ISC_R_FAILURE;
135 : }
136 28 : talloc_free(msg);
137 :
138 28 : calls_zone_hook = true;
139 :
140 28 : return ISC_R_SUCCESS;
141 : }
142 :
143 5 : static bool test_dlz_bind9_configure(struct torture_context *tctx)
144 : {
145 5 : void *dbdata = NULL;
146 5 : dns_dlzdb_t *dlzdb = NULL;
147 0 : int ret;
148 10 : const char *argv[] = {
149 : "samba_dlz",
150 : "-H",
151 5 : dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
152 : NULL
153 : };
154 5 : tctx_static = tctx;
155 5 : ret = dlz_create("samba_dlz", 3, argv, &dbdata,
156 : "log", dlz_bind9_log_wrapper,
157 : "writeable_zone", dlz_bind9_writeable_zone_hook,
158 : NULL);
159 5 : torture_assert_int_equal(tctx,
160 : ret,
161 : ISC_R_SUCCESS,
162 : "Failed to create samba_dlz");
163 :
164 5 : calls_zone_hook = false;
165 5 : torture_assert_int_equal(tctx, dlz_configure((void*)tctx,
166 : dlzdb,
167 : dbdata),
168 : ISC_R_SUCCESS,
169 : "Failed to configure samba_dlz");
170 :
171 5 : dlz_destroy(dbdata);
172 :
173 5 : torture_assert_int_equal(tctx, calls_zone_hook, 1, "Hasn't called zone hook");
174 :
175 5 : return true;
176 : }
177 :
178 1 : static bool test_dlz_bind9_multiple_configure(struct torture_context *tctx)
179 : {
180 0 : int i;
181 5 : for(i = 0; i < NUM_DLZS_TO_CONFIGURE; i++){
182 4 : test_dlz_bind9_configure(tctx);
183 : }
184 1 : return true;
185 : }
186 :
187 2 : static bool configure_multiple_dlzs(struct torture_context *tctx,
188 : void **dbdata, int count)
189 : {
190 0 : int i, res;
191 2 : dns_dlzdb_t *dlzdb = NULL;
192 4 : const char *argv[] = {
193 : "samba_dlz",
194 : "-H",
195 2 : dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
196 : NULL
197 : };
198 :
199 2 : tctx_static = tctx;
200 10 : for(i = 0; i < count; i++){
201 8 : res = dlz_create("samba_dlz", 3, argv, &(dbdata[i]),
202 : "log", dlz_bind9_log_wrapper,
203 : "writeable_zone",
204 : dlz_bind9_writeable_zone_hook, NULL);
205 8 : torture_assert_int_equal(tctx, res, ISC_R_SUCCESS,
206 : "Failed to create samba_dlz");
207 :
208 8 : res = dlz_configure((void*)tctx, dlzdb, dbdata[i]);
209 8 : torture_assert_int_equal(tctx, res, ISC_R_SUCCESS,
210 : "Failed to configure samba_dlz");
211 : }
212 :
213 2 : return true;
214 : }
215 :
216 1 : static bool test_dlz_bind9_destroy_oldest_first(struct torture_context *tctx)
217 : {
218 0 : void *dbdata[NUM_DLZS_TO_CONFIGURE];
219 0 : int i;
220 1 : bool ret = configure_multiple_dlzs(tctx,
221 : dbdata,
222 : NUM_DLZS_TO_CONFIGURE);
223 1 : if (ret == false) {
224 : /* failure: has already been printed */
225 0 : return false;
226 : }
227 :
228 : /* Reload faults are reported to happen on the first destroy */
229 1 : dlz_destroy(dbdata[0]);
230 :
231 4 : for(i = 1; i < NUM_DLZS_TO_CONFIGURE; i++){
232 3 : dlz_destroy(dbdata[i]);
233 : }
234 :
235 1 : return true;
236 : }
237 :
238 1 : static bool test_dlz_bind9_destroy_newest_first(struct torture_context *tctx)
239 : {
240 0 : void *dbdata[NUM_DLZS_TO_CONFIGURE];
241 0 : int i;
242 1 : bool ret = configure_multiple_dlzs(tctx,
243 : dbdata,
244 : NUM_DLZS_TO_CONFIGURE);
245 1 : if (ret == false) {
246 : /* failure: has already been printed */
247 0 : return false;
248 : }
249 :
250 5 : for(i = NUM_DLZS_TO_CONFIGURE - 1; i >= 0; i--) {
251 4 : dlz_destroy(dbdata[i]);
252 : }
253 :
254 1 : return true;
255 : }
256 :
257 : /*
258 : * Test that a ticket obtained for the DNS service will be accepted on the Samba DLZ side
259 : *
260 : */
261 2 : static bool test_dlz_bind9_gensec(struct torture_context *tctx, const char *mech)
262 : {
263 0 : NTSTATUS status;
264 2 : dns_dlzdb_t *dlzdb = NULL;
265 :
266 0 : struct gensec_security *gensec_client_context;
267 :
268 0 : DATA_BLOB client_to_server, server_to_client;
269 :
270 0 : void *dbdata;
271 4 : const char *argv[] = {
272 : "samba_dlz",
273 : "-H",
274 2 : dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
275 : NULL
276 : };
277 2 : tctx_static = tctx;
278 2 : torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, argv, &dbdata,
279 : "log", dlz_bind9_log_wrapper,
280 : "writeable_zone", dlz_bind9_writeable_zone_hook, NULL),
281 : ISC_R_SUCCESS,
282 : "Failed to create samba_dlz");
283 :
284 2 : torture_assert_int_equal(tctx, dlz_configure((void*)tctx,
285 : dlzdb, dbdata),
286 : ISC_R_SUCCESS,
287 : "Failed to configure samba_dlz");
288 :
289 2 : status = gensec_client_start(tctx, &gensec_client_context,
290 : lpcfg_gensec_settings(tctx, tctx->lp_ctx));
291 2 : torture_assert_ntstatus_ok(tctx, status, "gensec_client_start (client) failed");
292 :
293 : /*
294 : * dlz_bind9 use the special dns/host.domain account
295 : */
296 2 : status = gensec_set_target_hostname(gensec_client_context,
297 2 : talloc_asprintf(tctx,
298 : "%s.%s",
299 : torture_setting_string(tctx, "host", NULL),
300 : lpcfg_dnsdomain(tctx->lp_ctx)));
301 2 : torture_assert_ntstatus_ok(tctx, status, "gensec_set_target_hostname (client) failed");
302 :
303 2 : status = gensec_set_target_service(gensec_client_context, "dns");
304 2 : torture_assert_ntstatus_ok(tctx, status, "gensec_set_target_service failed");
305 :
306 2 : status = gensec_set_credentials(gensec_client_context,
307 : samba_cmdline_get_creds());
308 2 : torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (client) failed");
309 :
310 2 : status = gensec_start_mech_by_sasl_name(gensec_client_context, mech);
311 2 : torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (client) failed");
312 :
313 2 : server_to_client = data_blob(NULL, 0);
314 :
315 : /* Do one step of the client-server update dance */
316 2 : status = gensec_update(gensec_client_context, tctx, server_to_client, &client_to_server);
317 2 : if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {;
318 0 : torture_assert_ntstatus_ok(tctx, status, "gensec_update (client) failed");
319 : }
320 :
321 2 : torture_assert_int_equal(tctx, dlz_ssumatch(
322 : cli_credentials_get_username(
323 : samba_cmdline_get_creds()),
324 : lpcfg_dnsdomain(tctx->lp_ctx),
325 : "127.0.0.1", "type", "key",
326 : client_to_server.length,
327 : client_to_server.data,
328 : dbdata),
329 : ISC_TRUE,
330 : "Failed to check key for update rights samba_dlz");
331 :
332 2 : dlz_destroy(dbdata);
333 :
334 2 : return true;
335 : }
336 :
337 1 : static bool test_dlz_bind9_gssapi(struct torture_context *tctx)
338 : {
339 1 : return test_dlz_bind9_gensec(tctx, "GSSAPI");
340 : }
341 :
342 1 : static bool test_dlz_bind9_spnego(struct torture_context *tctx)
343 : {
344 1 : return test_dlz_bind9_gensec(tctx, "GSS-SPNEGO");
345 : }
346 :
347 : struct test_expected_record {
348 : const char *name;
349 : const char *type;
350 : const char *data;
351 : int ttl;
352 : bool printed;
353 : const char *rdata;
354 : };
355 :
356 : struct test_expected_rr {
357 : struct torture_context *tctx;
358 : const char *query_name;
359 : size_t num_records;
360 : struct test_expected_record *records;
361 : size_t num_rr;
362 : };
363 :
364 93 : static bool dlz_bind9_putnamedrr_torture_hook(struct test_expected_rr *expected,
365 : const char *name,
366 : const char *type,
367 : dns_ttl_t ttl,
368 : const char *data)
369 : {
370 0 : size_t i;
371 :
372 93 : torture_assert(expected->tctx, name != NULL,
373 : talloc_asprintf(expected->tctx,
374 : "Got unnamed record type[%s] data[%s]\n",
375 : type, data));
376 :
377 93 : expected->num_rr++;
378 93 : torture_comment(expected->tctx, "%u: name[%s] type[%s] ttl[%u] data[%s]\n",
379 93 : (unsigned)expected->num_rr, name, type, (unsigned)ttl, data);
380 :
381 557 : for (i = 0; i < expected->num_records; i++) {
382 464 : if (expected->records[i].name != NULL) {
383 440 : if (strcmp(name, expected->records[i].name) != 0) {
384 124 : continue;
385 : }
386 : }
387 :
388 340 : if (strcmp(type, expected->records[i].type) != 0) {
389 219 : continue;
390 : }
391 :
392 121 : if (expected->records[i].data != NULL) {
393 : /*
394 : * For most types the data will have been reformatted
395 : * or normalised, so we need to do approximately the
396 : * same to compare.
397 : */
398 100 : const char *data2 = expected->records[i].data;
399 100 : if (strcmp(type, "aaaa") == 0) {
400 0 : struct in6_addr adr1;
401 0 : struct in6_addr adr2;
402 0 : int ret;
403 10 : ret = inet_pton(AF_INET6, data, &adr1);
404 10 : if (ret != 1) {
405 0 : continue;
406 : }
407 10 : ret = inet_pton(AF_INET6, data2, &adr2);
408 10 : if (ret != 1) {
409 0 : continue;
410 : }
411 10 : if (memcmp(&adr1, &adr2, sizeof(adr1)) != 0) {
412 0 : continue;
413 : }
414 90 : } else if (strcmp(type, "cname") == 0 ||
415 90 : strcmp(type, "ptr") == 0 ||
416 80 : strcmp(type, "ns") == 0) {
417 12 : if (!samba_dns_name_equal(data, data2)) {
418 0 : continue;
419 : }
420 78 : } else if (strcmp(type, "mx") == 0) {
421 : /*
422 : * samba_dns_name_equal works for MX records
423 : * because the space in "10 example.com." is
424 : * theoretically OK as a DNS character. And we
425 : * need it because dlz will add the trailing
426 : * dot.
427 : */
428 10 : if (!samba_dns_name_equal(data, data2)) {
429 0 : continue;
430 : }
431 68 : } else if (strcmp(data, data2) != 0) {
432 : /* default, works for A records */
433 33 : continue;
434 : }
435 : }
436 :
437 88 : torture_assert_int_equal(expected->tctx, ttl,
438 : expected->records[i].ttl,
439 : talloc_asprintf(expected->tctx,
440 : "TTL did not match expectations for type %s",
441 : type));
442 :
443 88 : expected->records[i].printed = true;
444 : }
445 :
446 93 : return true;
447 : }
448 :
449 : /*
450 : * Lookups in these tests end up coming round to run this function.
451 : */
452 69 : static isc_result_t dlz_bind9_putrr_hook(dns_sdlzlookup_t *lookup,
453 : const char *type,
454 : dns_ttl_t ttl,
455 : const char *data)
456 : {
457 0 : struct test_expected_rr *expected =
458 69 : talloc_get_type_abort(lookup, struct test_expected_rr);
459 0 : bool ok;
460 :
461 69 : ok = dlz_bind9_putnamedrr_torture_hook(expected, expected->query_name,
462 : type, ttl, data);
463 69 : if (!ok) {
464 0 : return ISC_R_FAILURE;
465 : }
466 :
467 69 : return ISC_R_SUCCESS;
468 : }
469 :
470 24 : static isc_result_t dlz_bind9_putnamedrr_hook(dns_sdlzallnodes_t *allnodes,
471 : const char *name,
472 : const char *type,
473 : dns_ttl_t ttl,
474 : const char *data)
475 : {
476 0 : struct test_expected_rr *expected =
477 24 : talloc_get_type_abort(allnodes, struct test_expected_rr);
478 0 : bool ok;
479 :
480 24 : ok = dlz_bind9_putnamedrr_torture_hook(expected, name, type, ttl, data);
481 24 : if (!ok) {
482 0 : return ISC_R_FAILURE;
483 : }
484 :
485 24 : return ISC_R_SUCCESS;
486 : }
487 :
488 : /*
489 : * Tests some lookups
490 : */
491 1 : static bool test_dlz_bind9_lookup(struct torture_context *tctx)
492 : {
493 0 : size_t i;
494 1 : void *dbdata = NULL;
495 1 : dns_clientinfomethods_t *methods = NULL;
496 1 : dns_clientinfo_t *clientinfo = NULL;
497 1 : dns_dlzdb_t *dlzdb = NULL;
498 2 : const char *argv[] = {
499 : "samba_dlz",
500 : "-H",
501 1 : dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
502 : NULL
503 : };
504 1 : struct test_expected_rr *expected1 = NULL;
505 1 : struct test_expected_rr *expected2 = NULL;
506 :
507 1 : tctx_static = tctx;
508 1 : torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, argv, &dbdata,
509 : "log", dlz_bind9_log_wrapper,
510 : "writeable_zone", dlz_bind9_writeable_zone_hook,
511 : "putrr", dlz_bind9_putrr_hook,
512 : "putnamedrr", dlz_bind9_putnamedrr_hook,
513 : NULL),
514 : ISC_R_SUCCESS,
515 : "Failed to create samba_dlz");
516 :
517 1 : torture_assert_int_equal(tctx,
518 : dlz_configure((void*)tctx, dlzdb, dbdata),
519 : ISC_R_SUCCESS,
520 : "Failed to configure samba_dlz");
521 :
522 1 : expected1 = talloc_zero(tctx, struct test_expected_rr);
523 1 : torture_assert(tctx, expected1 != NULL, "talloc failed");
524 1 : expected1->tctx = tctx;
525 :
526 1 : expected1->query_name = "@";
527 :
528 1 : expected1->num_records = 4;
529 1 : expected1->records = talloc_zero_array(expected1,
530 : struct test_expected_record,
531 : expected1->num_records);
532 1 : torture_assert(tctx, expected1->records != NULL, "talloc failed");
533 :
534 1 : expected1->records[0].name = expected1->query_name;
535 1 : expected1->records[0].type = "soa";
536 1 : expected1->records[0].ttl = 3600;
537 1 : expected1->records[0].data = talloc_asprintf(expected1->records,
538 : "%s.%s. hostmaster.%s. 1 900 600 86400 3600",
539 : torture_setting_string(tctx, "host", NULL),
540 : lpcfg_dnsdomain(tctx->lp_ctx),
541 : lpcfg_dnsdomain(tctx->lp_ctx));
542 1 : torture_assert(tctx, expected1->records[0].data != NULL, "talloc failed");
543 :
544 1 : expected1->records[1].name = expected1->query_name;
545 1 : expected1->records[1].type = "ns";
546 1 : expected1->records[1].ttl = 900;
547 1 : expected1->records[1].data = talloc_asprintf(expected1->records, "%s.%s.",
548 : torture_setting_string(tctx, "host", NULL),
549 : lpcfg_dnsdomain(tctx->lp_ctx));
550 1 : torture_assert(tctx, expected1->records[1].data != NULL, "talloc failed");
551 :
552 1 : expected1->records[2].name = expected1->query_name;
553 1 : expected1->records[2].type = "aaaa";
554 1 : expected1->records[2].ttl = 900;
555 :
556 1 : expected1->records[3].name = expected1->query_name;
557 1 : expected1->records[3].type = "a";
558 1 : expected1->records[3].ttl = 900;
559 :
560 1 : torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx),
561 : expected1->query_name, dbdata,
562 : (dns_sdlzlookup_t *)expected1,
563 : methods, clientinfo),
564 : ISC_R_SUCCESS,
565 : "Failed to lookup @");
566 5 : for (i = 0; i < expected1->num_records; i++) {
567 4 : torture_assert(tctx, expected1->records[i].printed,
568 : talloc_asprintf(tctx,
569 : "Failed to have putrr callback run for type %s",
570 : expected1->records[i].type));
571 : }
572 1 : torture_assert_int_equal(tctx, expected1->num_rr,
573 : expected1->num_records,
574 : "Got too much data");
575 :
576 1 : expected2 = talloc_zero(tctx, struct test_expected_rr);
577 1 : torture_assert(tctx, expected2 != NULL, "talloc failed");
578 1 : expected2->tctx = tctx;
579 :
580 1 : expected2->query_name = torture_setting_string(tctx, "host", NULL);
581 1 : torture_assert(tctx, expected2->query_name != NULL, "unknown host");
582 :
583 1 : expected2->num_records = 2;
584 1 : expected2->records = talloc_zero_array(expected2,
585 : struct test_expected_record,
586 : expected2->num_records);
587 1 : torture_assert(tctx, expected2->records != NULL, "talloc failed");
588 :
589 1 : expected2->records[0].name = expected2->query_name;
590 1 : expected2->records[0].type = "aaaa";
591 1 : expected2->records[0].ttl = 900;
592 :
593 1 : expected2->records[1].name = expected2->query_name;
594 1 : expected2->records[1].type = "a";
595 1 : expected2->records[1].ttl = 900;
596 :
597 1 : torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx),
598 : expected2->query_name, dbdata,
599 : (dns_sdlzlookup_t *)expected2,
600 : methods, clientinfo),
601 : ISC_R_SUCCESS,
602 : "Failed to lookup hostname");
603 3 : for (i = 0; i < expected2->num_records; i++) {
604 2 : torture_assert(tctx, expected2->records[i].printed,
605 : talloc_asprintf(tctx,
606 : "Failed to have putrr callback run name[%s] for type %s",
607 : expected2->records[i].name,
608 : expected2->records[i].type));
609 : }
610 1 : torture_assert_int_equal(tctx, expected2->num_rr,
611 : expected2->num_records,
612 : "Got too much data");
613 :
614 1 : dlz_destroy(dbdata);
615 :
616 1 : return true;
617 : }
618 :
619 : /*
620 : * Test some zone dumps
621 : */
622 1 : static bool test_dlz_bind9_zonedump(struct torture_context *tctx)
623 : {
624 0 : size_t i;
625 1 : void *dbdata = NULL;
626 1 : dns_dlzdb_t *dlzdb = NULL;
627 2 : const char *argv[] = {
628 : "samba_dlz",
629 : "-H",
630 1 : dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
631 : NULL
632 : };
633 1 : struct test_expected_rr *expected1 = NULL;
634 :
635 1 : tctx_static = tctx;
636 1 : torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, argv, &dbdata,
637 : "log", dlz_bind9_log_wrapper,
638 : "writeable_zone", dlz_bind9_writeable_zone_hook,
639 : "putrr", dlz_bind9_putrr_hook,
640 : "putnamedrr", dlz_bind9_putnamedrr_hook,
641 : NULL),
642 : ISC_R_SUCCESS,
643 : "Failed to create samba_dlz");
644 :
645 1 : torture_assert_int_equal(tctx, dlz_configure((void*)tctx, dlzdb, dbdata),
646 : ISC_R_SUCCESS,
647 : "Failed to configure samba_dlz");
648 :
649 1 : expected1 = talloc_zero(tctx, struct test_expected_rr);
650 1 : torture_assert(tctx, expected1 != NULL, "talloc failed");
651 1 : expected1->tctx = tctx;
652 :
653 1 : expected1->num_records = 7;
654 1 : expected1->records = talloc_zero_array(expected1,
655 : struct test_expected_record,
656 : expected1->num_records);
657 1 : torture_assert(tctx, expected1->records != NULL, "talloc failed");
658 :
659 1 : expected1->records[0].name = talloc_asprintf(expected1->records,
660 : "%s.", lpcfg_dnsdomain(tctx->lp_ctx));
661 1 : expected1->records[0].type = "soa";
662 1 : expected1->records[0].ttl = 3600;
663 1 : expected1->records[0].data = talloc_asprintf(expected1->records,
664 : "%s.%s. hostmaster.%s. 1 900 600 86400 3600",
665 : torture_setting_string(tctx, "host", NULL),
666 : lpcfg_dnsdomain(tctx->lp_ctx),
667 : lpcfg_dnsdomain(tctx->lp_ctx));
668 1 : torture_assert(tctx, expected1->records[0].data != NULL, "talloc failed");
669 :
670 1 : expected1->records[1].name = talloc_asprintf(expected1->records,
671 : "%s.", lpcfg_dnsdomain(tctx->lp_ctx));
672 1 : expected1->records[1].type = "ns";
673 1 : expected1->records[1].ttl = 900;
674 1 : expected1->records[1].data = talloc_asprintf(expected1->records, "%s.%s.",
675 : torture_setting_string(tctx, "host", NULL),
676 : lpcfg_dnsdomain(tctx->lp_ctx));
677 1 : torture_assert(tctx, expected1->records[1].data != NULL, "talloc failed");
678 :
679 1 : expected1->records[2].name = talloc_asprintf(expected1->records,
680 : "%s.", lpcfg_dnsdomain(tctx->lp_ctx));
681 1 : expected1->records[2].type = "aaaa";
682 1 : expected1->records[2].ttl = 900;
683 :
684 1 : expected1->records[3].name = talloc_asprintf(expected1->records,
685 : "%s.", lpcfg_dnsdomain(tctx->lp_ctx));
686 1 : expected1->records[3].type = "a";
687 1 : expected1->records[3].ttl = 900;
688 :
689 1 : expected1->records[4].name = talloc_asprintf(expected1->records, "%s.%s.",
690 : torture_setting_string(tctx, "host", NULL),
691 : lpcfg_dnsdomain(tctx->lp_ctx));
692 1 : torture_assert(tctx, expected1->records[4].name != NULL, "unknown host");
693 1 : expected1->records[4].type = "aaaa";
694 1 : expected1->records[4].ttl = 900;
695 :
696 1 : expected1->records[5].name = talloc_asprintf(expected1->records, "%s.%s.",
697 : torture_setting_string(tctx, "host", NULL),
698 : lpcfg_dnsdomain(tctx->lp_ctx));
699 1 : torture_assert(tctx, expected1->records[5].name != NULL, "unknown host");
700 1 : expected1->records[5].type = "a";
701 1 : expected1->records[5].ttl = 900;
702 :
703 : /*
704 : * We expect multiple srv records
705 : */
706 1 : expected1->records[6].name = NULL;
707 1 : expected1->records[6].type = "srv";
708 1 : expected1->records[6].ttl = 900;
709 :
710 1 : torture_assert_int_equal(tctx, dlz_allnodes(lpcfg_dnsdomain(tctx->lp_ctx),
711 : dbdata, (dns_sdlzallnodes_t *)expected1),
712 : ISC_R_SUCCESS,
713 : "Failed to configure samba_dlz");
714 8 : for (i = 0; i < expected1->num_records; i++) {
715 7 : torture_assert(tctx, expected1->records[i].printed,
716 : talloc_asprintf(tctx,
717 : "Failed to have putrr callback run name[%s] for type %s",
718 : expected1->records[i].name,
719 : expected1->records[i].type));
720 : }
721 1 : torture_assert_int_equal(tctx, expected1->num_rr, 24,
722 : "Got wrong record count");
723 :
724 1 : dlz_destroy(dbdata);
725 :
726 1 : return true;
727 : }
728 :
729 : /*
730 : * Test some updates
731 : */
732 1 : static bool test_dlz_bind9_update01(struct torture_context *tctx)
733 : {
734 0 : NTSTATUS status;
735 0 : struct gensec_security *gensec_client_context;
736 0 : DATA_BLOB client_to_server, server_to_client;
737 1 : void *dbdata = NULL;
738 1 : dns_dlzdb_t *dlzdb = NULL;
739 1 : void *version = NULL;
740 2 : const char *argv[] = {
741 : "samba_dlz",
742 : "-H",
743 1 : dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
744 : NULL
745 : };
746 1 : struct test_expected_rr *expected1 = NULL;
747 1 : char *name = NULL;
748 1 : char *data0 = NULL;
749 1 : char *data1 = NULL;
750 1 : char *data2 = NULL;
751 1 : bool ret = false;
752 1 : dns_clientinfomethods_t *methods = NULL;
753 1 : dns_clientinfo_t *clientinfo = NULL;
754 :
755 1 : tctx_static = tctx;
756 1 : torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, argv, &dbdata,
757 : "log", dlz_bind9_log_wrapper,
758 : "writeable_zone", dlz_bind9_writeable_zone_hook,
759 : "putrr", dlz_bind9_putrr_hook,
760 : "putnamedrr", dlz_bind9_putnamedrr_hook,
761 : NULL),
762 : ISC_R_SUCCESS,
763 : "Failed to create samba_dlz");
764 :
765 1 : torture_assert_int_equal(tctx, dlz_configure((void*)tctx, dlzdb, dbdata),
766 : ISC_R_SUCCESS,
767 : "Failed to configure samba_dlz");
768 :
769 1 : expected1 = talloc_zero(tctx, struct test_expected_rr);
770 1 : torture_assert(tctx, expected1 != NULL, "talloc failed");
771 1 : expected1->tctx = tctx;
772 :
773 1 : expected1->query_name = __func__;
774 :
775 1 : name = talloc_asprintf(expected1, "%s.%s",
776 : expected1->query_name,
777 : lpcfg_dnsdomain(tctx->lp_ctx));
778 1 : torture_assert(tctx, name != NULL, "talloc failed");
779 :
780 1 : expected1->num_records = 2;
781 1 : expected1->records = talloc_zero_array(expected1,
782 : struct test_expected_record,
783 : expected1->num_records);
784 1 : torture_assert(tctx, expected1->records != NULL, "talloc failed");
785 :
786 1 : expected1->records[0].name = expected1->query_name;
787 1 : expected1->records[0].type = "a";
788 1 : expected1->records[0].ttl = 3600;
789 1 : expected1->records[0].data = "127.1.2.3";
790 1 : expected1->records[0].printed = false;
791 :
792 1 : data0 = talloc_asprintf(expected1,
793 : "%s.\t" "%u\t" "%s\t" "%s\t" "%s",
794 : name,
795 1 : (unsigned)expected1->records[0].ttl,
796 : "in",
797 1 : expected1->records[0].type,
798 1 : expected1->records[0].data);
799 1 : torture_assert(tctx, data0 != NULL, "talloc failed");
800 :
801 1 : expected1->records[1].name = expected1->query_name;
802 1 : expected1->records[1].type = "a";
803 1 : expected1->records[1].ttl = 3600;
804 1 : expected1->records[1].data = "127.3.2.1";
805 1 : expected1->records[1].printed = false;
806 :
807 1 : data1 = talloc_asprintf(expected1,
808 : "%s.\t" "%u\t" "%s\t" "%s\t" "%s",
809 : name,
810 1 : (unsigned)expected1->records[1].ttl,
811 : "in",
812 1 : expected1->records[1].type,
813 1 : expected1->records[1].data);
814 1 : torture_assert(tctx, data1 != NULL, "talloc failed");
815 :
816 1 : data2 = talloc_asprintf(expected1,
817 : "%s.\t" "0\t" "in\t" "a\t" "127.3.3.3",
818 : name);
819 1 : torture_assert(tctx, data2 != NULL, "talloc failed");
820 :
821 : /*
822 : * Prepare session info
823 : */
824 1 : status = gensec_client_start(tctx, &gensec_client_context,
825 : lpcfg_gensec_settings(tctx, tctx->lp_ctx));
826 1 : torture_assert_ntstatus_ok(tctx, status, "gensec_client_start (client) failed");
827 :
828 : /*
829 : * dlz_bind9 use the special dns/host.domain account
830 : */
831 1 : status = gensec_set_target_hostname(gensec_client_context,
832 1 : talloc_asprintf(tctx,
833 : "%s.%s",
834 : torture_setting_string(tctx, "host", NULL),
835 : lpcfg_dnsdomain(tctx->lp_ctx)));
836 1 : torture_assert_ntstatus_ok(tctx, status, "gensec_set_target_hostname (client) failed");
837 :
838 1 : status = gensec_set_target_service(gensec_client_context, "dns");
839 1 : torture_assert_ntstatus_ok(tctx, status, "gensec_set_target_service failed");
840 :
841 1 : status = gensec_set_credentials(gensec_client_context,
842 : samba_cmdline_get_creds());
843 1 : torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (client) failed");
844 :
845 1 : status = gensec_start_mech_by_sasl_name(gensec_client_context, "GSS-SPNEGO");
846 1 : torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (client) failed");
847 :
848 1 : server_to_client = data_blob(NULL, 0);
849 :
850 : /* Do one step of the client-server update dance */
851 1 : status = gensec_update(gensec_client_context, tctx, server_to_client, &client_to_server);
852 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {;
853 0 : torture_assert_ntstatus_ok(tctx, status, "gensec_update (client) failed");
854 : }
855 :
856 1 : torture_assert_int_equal(tctx, dlz_ssumatch(
857 : cli_credentials_get_username(
858 : samba_cmdline_get_creds()),
859 : name,
860 : "127.0.0.1",
861 : expected1->records[0].type,
862 : "key",
863 : client_to_server.length,
864 : client_to_server.data,
865 : dbdata),
866 : ISC_TRUE,
867 : "Failed to check key for update rights samba_dlz");
868 :
869 : /*
870 : * We test the following:
871 : *
872 : * 1. lookup the records => NOT_FOUND
873 : * 2. delete all records => NOT_FOUND
874 : * 3. delete 1st record => NOT_FOUND
875 : * 4. create 1st record => SUCCESS
876 : * 5. lookup the records => found 1st
877 : * 6. create 2nd record => SUCCESS
878 : * 7. lookup the records => found 1st and 2nd
879 : * 8. delete unknown record => NOT_FOUND
880 : * 9. lookup the records => found 1st and 2nd
881 : * 10. delete 1st record => SUCCESS
882 : * 11. lookup the records => found 2nd
883 : * 12. delete 2nd record => SUCCESS
884 : * 13. lookup the records => NOT_FOUND
885 : * 14. create 1st record => SUCCESS
886 : * 15. lookup the records => found 1st
887 : * 16. create 2nd record => SUCCESS
888 : * 17. lookup the records => found 1st and 2nd
889 : * 18. update 1st record => SUCCESS
890 : * 19. lookup the records => found 1st and 2nd
891 : * 20. delete all unknown type records => NOT_FOUND
892 : * 21. lookup the records => found 1st and 2nd
893 : * 22. delete all records => SUCCESS
894 : * 23. lookup the records => NOT_FOUND
895 : */
896 :
897 : /* Step 1. */
898 1 : expected1->num_rr = 0;
899 1 : expected1->records[0].printed = false;
900 1 : expected1->records[1].printed = false;
901 1 : torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx),
902 : expected1->query_name, dbdata,
903 : (dns_sdlzlookup_t *)expected1,
904 : methods, clientinfo),
905 : ISC_R_NOTFOUND,
906 : "Found hostname");
907 1 : torture_assert_int_equal(tctx, expected1->num_rr, 0,
908 : "Got wrong record count");
909 :
910 : /* Step 2. */
911 1 : torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx),
912 : dbdata, &version),
913 : ISC_R_SUCCESS,
914 : "Failed to start transaction");
915 1 : torture_assert_int_equal_goto(tctx,
916 : dlz_delrdataset(name,
917 : expected1->records[0].type,
918 : dbdata, version),
919 : ISC_R_NOTFOUND, ret, cancel_version,
920 : talloc_asprintf(tctx, "Deleted name[%s] type[%s]\n",
921 : name, expected1->records[0].type));
922 1 : dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), false, dbdata, &version);
923 :
924 : /* Step 3. */
925 1 : torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx),
926 : dbdata, &version),
927 : ISC_R_SUCCESS,
928 : "Failed to start transaction");
929 1 : torture_assert_int_equal_goto(tctx,
930 : dlz_subrdataset(name, data0, dbdata, version),
931 : ISC_R_NOTFOUND, ret, cancel_version,
932 : talloc_asprintf(tctx, "Deleted name[%s] data[%s]\n",
933 : name, data0));
934 1 : dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), false, dbdata, &version);
935 :
936 : /* Step 4. */
937 1 : torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx),
938 : dbdata, &version),
939 : ISC_R_SUCCESS,
940 : "Failed to start transaction");
941 1 : torture_assert_int_equal_goto(tctx,
942 : dlz_addrdataset(name, data0, dbdata, version),
943 : ISC_R_SUCCESS, ret, cancel_version,
944 : talloc_asprintf(tctx, "Failed to add name[%s] data[%s]\n",
945 : name, data0));
946 1 : dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version);
947 :
948 : /* Step 5. */
949 1 : expected1->num_rr = 0;
950 1 : expected1->records[0].printed = false;
951 1 : expected1->records[1].printed = false;
952 1 : torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx),
953 : expected1->query_name, dbdata,
954 : (dns_sdlzlookup_t *)expected1,
955 : methods, clientinfo),
956 : ISC_R_SUCCESS,
957 : "Not found hostname");
958 1 : torture_assert(tctx, expected1->records[0].printed,
959 : talloc_asprintf(tctx,
960 : "Failed to have putrr callback run name[%s] for type %s",
961 : expected1->records[0].name,
962 : expected1->records[0].type));
963 1 : torture_assert_int_equal(tctx, expected1->num_rr, 1,
964 : "Got wrong record count");
965 :
966 : /* Step 6. */
967 1 : torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx),
968 : dbdata, &version),
969 : ISC_R_SUCCESS,
970 : "Failed to start transaction");
971 1 : torture_assert_int_equal_goto(tctx,
972 : dlz_addrdataset(name, data1, dbdata, version),
973 : ISC_R_SUCCESS, ret, cancel_version,
974 : talloc_asprintf(tctx, "Failed to add name[%s] data[%s]\n",
975 : name, data1));
976 1 : dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version);
977 :
978 : /* Step 7. */
979 1 : expected1->num_rr = 0;
980 1 : expected1->records[0].printed = false;
981 1 : expected1->records[1].printed = false;
982 1 : torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx),
983 : expected1->query_name, dbdata,
984 : (dns_sdlzlookup_t *)expected1,
985 : methods, clientinfo),
986 : ISC_R_SUCCESS,
987 : "Not found hostname");
988 1 : torture_assert(tctx, expected1->records[0].printed,
989 : talloc_asprintf(tctx,
990 : "Failed to have putrr callback run name[%s] for type %s",
991 : expected1->records[0].name,
992 : expected1->records[0].type));
993 1 : torture_assert(tctx, expected1->records[1].printed,
994 : talloc_asprintf(tctx,
995 : "Failed to have putrr callback run name[%s] for type %s",
996 : expected1->records[1].name,
997 : expected1->records[1].type));
998 1 : torture_assert_int_equal(tctx, expected1->num_rr, 2,
999 : "Got wrong record count");
1000 :
1001 : /* Step 8. */
1002 1 : torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx),
1003 : dbdata, &version),
1004 : ISC_R_SUCCESS,
1005 : "Failed to start transaction");
1006 1 : torture_assert_int_equal_goto(tctx,
1007 : dlz_subrdataset(name, data2, dbdata, version),
1008 : ISC_R_NOTFOUND, ret, cancel_version,
1009 : talloc_asprintf(tctx, "Deleted name[%s] data[%s]\n",
1010 : name, data2));
1011 1 : dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version);
1012 :
1013 : /* Step 9. */
1014 1 : expected1->num_rr = 0;
1015 1 : expected1->records[0].printed = false;
1016 1 : expected1->records[1].printed = false;
1017 1 : torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx),
1018 : expected1->query_name, dbdata,
1019 : (dns_sdlzlookup_t *)expected1,
1020 : methods, clientinfo),
1021 : ISC_R_SUCCESS,
1022 : "Not found hostname");
1023 1 : torture_assert(tctx, expected1->records[0].printed,
1024 : talloc_asprintf(tctx,
1025 : "Failed to have putrr callback run name[%s] for type %s",
1026 : expected1->records[0].name,
1027 : expected1->records[0].type));
1028 1 : torture_assert(tctx, expected1->records[1].printed,
1029 : talloc_asprintf(tctx,
1030 : "Failed to have putrr callback run name[%s] for type %s",
1031 : expected1->records[1].name,
1032 : expected1->records[1].type));
1033 1 : torture_assert_int_equal(tctx, expected1->num_rr, 2,
1034 : "Got wrong record count");
1035 :
1036 : /* Step 10. */
1037 1 : torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx),
1038 : dbdata, &version),
1039 : ISC_R_SUCCESS,
1040 : "Failed to start transaction");
1041 1 : torture_assert_int_equal_goto(tctx,
1042 : dlz_subrdataset(name, data0, dbdata, version),
1043 : ISC_R_SUCCESS, ret, cancel_version,
1044 : talloc_asprintf(tctx, "Failed to delete name[%s] data[%s]\n",
1045 : name, data0));
1046 1 : dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version);
1047 :
1048 : /* Step 11. */
1049 1 : expected1->num_rr = 0;
1050 1 : expected1->records[0].printed = false;
1051 1 : expected1->records[1].printed = false;
1052 1 : torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx),
1053 : expected1->query_name, dbdata,
1054 : (dns_sdlzlookup_t *)expected1,
1055 : methods, clientinfo),
1056 : ISC_R_SUCCESS,
1057 : "Not found hostname");
1058 1 : torture_assert(tctx, expected1->records[1].printed,
1059 : talloc_asprintf(tctx,
1060 : "Failed to have putrr callback run name[%s] for type %s",
1061 : expected1->records[1].name,
1062 : expected1->records[1].type));
1063 1 : torture_assert_int_equal(tctx, expected1->num_rr, 1,
1064 : "Got wrong record count");
1065 :
1066 : /* Step 12. */
1067 1 : torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx),
1068 : dbdata, &version),
1069 : ISC_R_SUCCESS,
1070 : "Failed to start transaction");
1071 1 : torture_assert_int_equal_goto(tctx,
1072 : dlz_subrdataset(name, data1, dbdata, version),
1073 : ISC_R_SUCCESS, ret, cancel_version,
1074 : talloc_asprintf(tctx, "Failed to delete name[%s] data[%s]\n",
1075 : name, data1));
1076 1 : dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version);
1077 :
1078 : /* Step 13. */
1079 1 : expected1->num_rr = 0;
1080 1 : expected1->records[0].printed = false;
1081 1 : expected1->records[1].printed = false;
1082 1 : torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx),
1083 : expected1->query_name, dbdata,
1084 : (dns_sdlzlookup_t *)expected1,
1085 : methods, clientinfo),
1086 : ISC_R_NOTFOUND,
1087 : "Found hostname");
1088 1 : torture_assert_int_equal(tctx, expected1->num_rr, 0,
1089 : "Got wrong record count");
1090 :
1091 : /* Step 14. */
1092 1 : torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx),
1093 : dbdata, &version),
1094 : ISC_R_SUCCESS,
1095 : "Failed to start transaction");
1096 1 : torture_assert_int_equal_goto(tctx,
1097 : dlz_addrdataset(name, data0, dbdata, version),
1098 : ISC_R_SUCCESS, ret, cancel_version,
1099 : talloc_asprintf(tctx, "Failed to add name[%s] data[%s]\n",
1100 : name, data0));
1101 1 : dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version);
1102 :
1103 : /* Step 15. */
1104 1 : expected1->num_rr = 0;
1105 1 : expected1->records[0].printed = false;
1106 1 : expected1->records[1].printed = false;
1107 1 : torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx),
1108 : expected1->query_name, dbdata,
1109 : (dns_sdlzlookup_t *)expected1,
1110 : methods, clientinfo),
1111 : ISC_R_SUCCESS,
1112 : "Not found hostname");
1113 1 : torture_assert(tctx, expected1->records[0].printed,
1114 : talloc_asprintf(tctx,
1115 : "Failed to have putrr callback run name[%s] for type %s",
1116 : expected1->records[0].name,
1117 : expected1->records[0].type));
1118 1 : torture_assert_int_equal(tctx, expected1->num_rr, 1,
1119 : "Got wrong record count");
1120 :
1121 : /* Step 16. */
1122 1 : torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx),
1123 : dbdata, &version),
1124 : ISC_R_SUCCESS,
1125 : "Failed to start transaction");
1126 1 : torture_assert_int_equal_goto(tctx,
1127 : dlz_addrdataset(name, data1, dbdata, version),
1128 : ISC_R_SUCCESS, ret, cancel_version,
1129 : talloc_asprintf(tctx, "Failed to add name[%s] data[%s]\n",
1130 : name, data1));
1131 1 : dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version);
1132 :
1133 : /* Step 17. */
1134 1 : expected1->num_rr = 0;
1135 1 : expected1->records[0].printed = false;
1136 1 : expected1->records[1].printed = false;
1137 1 : torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx),
1138 : expected1->query_name, dbdata,
1139 : (dns_sdlzlookup_t *)expected1,
1140 : methods, clientinfo),
1141 : ISC_R_SUCCESS,
1142 : "Not found hostname");
1143 1 : torture_assert(tctx, expected1->records[0].printed,
1144 : talloc_asprintf(tctx,
1145 : "Failed to have putrr callback run name[%s] for type %s",
1146 : expected1->records[0].name,
1147 : expected1->records[0].type));
1148 1 : torture_assert(tctx, expected1->records[1].printed,
1149 : talloc_asprintf(tctx,
1150 : "Failed to have putrr callback run name[%s] for type %s",
1151 : expected1->records[1].name,
1152 : expected1->records[1].type));
1153 1 : torture_assert_int_equal(tctx, expected1->num_rr, 2,
1154 : "Got wrong record count");
1155 :
1156 : /* Step 18. */
1157 1 : torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx),
1158 : dbdata, &version),
1159 : ISC_R_SUCCESS,
1160 : "Failed to start transaction");
1161 1 : torture_assert_int_equal_goto(tctx,
1162 : dlz_addrdataset(name, data0, dbdata, version),
1163 : ISC_R_SUCCESS, ret, cancel_version,
1164 : talloc_asprintf(tctx, "Failed to update name[%s] data[%s]\n",
1165 : name, data0));
1166 1 : dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version);
1167 :
1168 : /* Step 19. */
1169 1 : expected1->num_rr = 0;
1170 1 : expected1->records[0].printed = false;
1171 1 : expected1->records[1].printed = false;
1172 1 : torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx),
1173 : expected1->query_name, dbdata,
1174 : (dns_sdlzlookup_t *)expected1,
1175 : methods, clientinfo),
1176 : ISC_R_SUCCESS,
1177 : "Not found hostname");
1178 1 : torture_assert(tctx, expected1->records[0].printed,
1179 : talloc_asprintf(tctx,
1180 : "Failed to have putrr callback run name[%s] for type %s",
1181 : expected1->records[0].name,
1182 : expected1->records[0].type));
1183 1 : torture_assert(tctx, expected1->records[1].printed,
1184 : talloc_asprintf(tctx,
1185 : "Failed to have putrr callback run name[%s] for type %s",
1186 : expected1->records[1].name,
1187 : expected1->records[1].type));
1188 1 : torture_assert_int_equal(tctx, expected1->num_rr, 2,
1189 : "Got wrong record count");
1190 :
1191 : /* Step 20. */
1192 1 : torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx),
1193 : dbdata, &version),
1194 : ISC_R_SUCCESS,
1195 : "Failed to start transaction");
1196 1 : torture_assert_int_equal_goto(tctx,
1197 : dlz_delrdataset(name, "txt", dbdata, version),
1198 : ISC_R_FAILURE, ret, cancel_version,
1199 : talloc_asprintf(tctx, "Deleted name[%s] type[%s]\n",
1200 : name, "txt"));
1201 1 : dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), false, dbdata, &version);
1202 :
1203 : /* Step 21. */
1204 1 : expected1->num_rr = 0;
1205 1 : expected1->records[0].printed = false;
1206 1 : expected1->records[1].printed = false;
1207 1 : torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx),
1208 : expected1->query_name, dbdata,
1209 : (dns_sdlzlookup_t *)expected1,
1210 : methods, clientinfo),
1211 : ISC_R_SUCCESS,
1212 : "Not found hostname");
1213 1 : torture_assert(tctx, expected1->records[0].printed,
1214 : talloc_asprintf(tctx,
1215 : "Failed to have putrr callback run name[%s] for type %s",
1216 : expected1->records[0].name,
1217 : expected1->records[0].type));
1218 1 : torture_assert(tctx, expected1->records[1].printed,
1219 : talloc_asprintf(tctx,
1220 : "Failed to have putrr callback run name[%s] for type %s",
1221 : expected1->records[1].name,
1222 : expected1->records[1].type));
1223 1 : torture_assert_int_equal(tctx, expected1->num_rr, 2,
1224 : "Got wrong record count");
1225 :
1226 : /* Step 22. */
1227 1 : torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx),
1228 : dbdata, &version),
1229 : ISC_R_SUCCESS,
1230 : "Failed to start transaction");
1231 1 : torture_assert_int_equal_goto(tctx,
1232 : dlz_delrdataset(name,
1233 : expected1->records[0].type,
1234 : dbdata, version),
1235 : ISC_R_SUCCESS, ret, cancel_version,
1236 : talloc_asprintf(tctx, "Failed to delete name[%s] type[%s]\n",
1237 : name, expected1->records[0].type));
1238 1 : dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version);
1239 :
1240 : /* Step 23. */
1241 1 : expected1->num_rr = 0;
1242 1 : expected1->records[0].printed = false;
1243 1 : expected1->records[1].printed = false;
1244 1 : torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx),
1245 : expected1->query_name, dbdata,
1246 : (dns_sdlzlookup_t *)expected1,
1247 : methods, clientinfo),
1248 : ISC_R_NOTFOUND,
1249 : "Found hostname");
1250 1 : torture_assert_int_equal(tctx, expected1->num_rr, 0,
1251 : "Got wrong record count");
1252 :
1253 1 : dlz_destroy(dbdata);
1254 :
1255 1 : return true;
1256 :
1257 0 : cancel_version:
1258 0 : dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), false, dbdata, &version);
1259 0 : return ret;
1260 : }
1261 :
1262 : /*
1263 : * Test zone transfer requests restrictions
1264 : *
1265 : * 1: test that zone transfer is denied by default
1266 : * 2: with an authorized list of IPs set in smb.conf, test that zone transfer
1267 : * is accepted only for selected IPs.
1268 : */
1269 1 : static bool test_dlz_bind9_allowzonexfr(struct torture_context *tctx)
1270 : {
1271 0 : void *dbdata;
1272 2 : const char *argv[] = {
1273 : "samba_dlz",
1274 : "-H",
1275 1 : dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
1276 : NULL
1277 : };
1278 0 : isc_result_t ret;
1279 1 : dns_dlzdb_t *dlzdb = NULL;
1280 0 : bool ok;
1281 :
1282 1 : tctx_static = tctx;
1283 1 : torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, argv, &dbdata,
1284 : "log", dlz_bind9_log_wrapper,
1285 : "writeable_zone", dlz_bind9_writeable_zone_hook,
1286 : "putrr", dlz_bind9_putrr_hook,
1287 : "putnamedrr", dlz_bind9_putnamedrr_hook,
1288 : NULL),
1289 : ISC_R_SUCCESS,
1290 : "Failed to create samba_dlz");
1291 :
1292 1 : torture_assert_int_equal(tctx, dlz_configure((void*)tctx, dlzdb, dbdata),
1293 : ISC_R_SUCCESS,
1294 : "Failed to configure samba_dlz");
1295 :
1296 : /* Ask for zone transfer with no specific config => expect denied */
1297 1 : ret = dlz_allowzonexfr(dbdata, lpcfg_dnsdomain(tctx->lp_ctx), "127.0.0.1");
1298 1 : torture_assert_int_equal(tctx, ret, ISC_R_NOPERM,
1299 : "Zone transfer accepted with default settings");
1300 :
1301 : /* Ask for zone transfer with authorizations set */
1302 1 : ok = lpcfg_set_option(tctx->lp_ctx, "dns zone transfer clients allow=127.0.0.1,1234:5678::1,192.168.0.");
1303 1 : torture_assert(tctx, ok, "Failed to set dns zone transfer clients allow option.");
1304 :
1305 1 : ok = lpcfg_set_option(tctx->lp_ctx, "dns zone transfer clients deny=192.168.0.2");
1306 1 : torture_assert(tctx, ok, "Failed to set dns zone transfer clients deny option.");
1307 :
1308 1 : ret = dlz_allowzonexfr(dbdata, lpcfg_dnsdomain(tctx->lp_ctx), "127.0.0.1");
1309 1 : torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
1310 : "Zone transfer refused for authorized IPv4 address");
1311 :
1312 1 : ret = dlz_allowzonexfr(dbdata, lpcfg_dnsdomain(tctx->lp_ctx), "1234:5678::1");
1313 1 : torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
1314 : "Zone transfer refused for authorized IPv6 address.");
1315 :
1316 1 : ret = dlz_allowzonexfr(dbdata, lpcfg_dnsdomain(tctx->lp_ctx), "10.0.0.1");
1317 1 : torture_assert_int_equal(tctx, ret, ISC_R_NOPERM,
1318 : "Zone transfer accepted for unauthorized IP");
1319 :
1320 1 : ret = dlz_allowzonexfr(dbdata, lpcfg_dnsdomain(tctx->lp_ctx), "192.168.0.1");
1321 1 : torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
1322 : "Zone transfer refused for address in authorized IPv4 subnet.");
1323 :
1324 1 : ret = dlz_allowzonexfr(dbdata, lpcfg_dnsdomain(tctx->lp_ctx), "192.168.0.2");
1325 1 : torture_assert_int_equal(tctx, ret, ISC_R_NOPERM,
1326 : "Zone transfer allowed for denied client.");
1327 :
1328 1 : dlz_destroy(dbdata);
1329 1 : return true;
1330 : }
1331 :
1332 :
1333 1 : static int init_dlz(struct torture_context *tctx,
1334 : void **dbdata)
1335 : {
1336 0 : isc_result_t ret;
1337 2 : const char *argv[] = {
1338 : "samba_dlz",
1339 : "-H",
1340 1 : dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
1341 : NULL
1342 : };
1343 :
1344 1 : ret = dlz_create("samba_dlz", 3, argv, dbdata,
1345 : "log", dlz_bind9_log_wrapper,
1346 : "writeable_zone", dlz_bind9_writeable_zone_hook,
1347 : "putrr", dlz_bind9_putrr_hook,
1348 : "putnamedrr", dlz_bind9_putnamedrr_hook,
1349 : NULL);
1350 :
1351 1 : torture_assert_int_equal(tctx,
1352 : ret,
1353 : ISC_R_SUCCESS,
1354 : "Failed to create samba_dlz");
1355 :
1356 1 : ret = dlz_configure((void*)tctx, NULL, *dbdata);
1357 1 : torture_assert_int_equal(tctx,
1358 : ret,
1359 : ISC_R_SUCCESS,
1360 : "Failed to configure samba_dlz");
1361 :
1362 1 : return true;
1363 : }
1364 :
1365 :
1366 1 : static int init_gensec(struct torture_context *tctx,
1367 : struct gensec_security **gensec_client_context)
1368 : {
1369 0 : NTSTATUS status;
1370 : /*
1371 : * Prepare session info
1372 : */
1373 1 : status = gensec_client_start(tctx, gensec_client_context,
1374 : lpcfg_gensec_settings(tctx, tctx->lp_ctx));
1375 1 : torture_assert_ntstatus_ok(tctx, status,
1376 : "gensec_client_start (client) failed");
1377 :
1378 : /*
1379 : * dlz_bind9 use the special dns/host.domain account
1380 : */
1381 1 : status = gensec_set_target_hostname(*gensec_client_context,
1382 1 : talloc_asprintf(tctx,
1383 : "%s.%s",
1384 : torture_setting_string(tctx, "host", NULL),
1385 : lpcfg_dnsdomain(tctx->lp_ctx)));
1386 1 : torture_assert_ntstatus_ok(tctx, status,
1387 : "gensec_set_target_hostname (client) failed");
1388 :
1389 1 : status = gensec_set_target_service(*gensec_client_context, "dns");
1390 1 : torture_assert_ntstatus_ok(tctx, status,
1391 : "gensec_set_target_service failed");
1392 :
1393 1 : status = gensec_set_credentials(*gensec_client_context,
1394 : samba_cmdline_get_creds());
1395 1 : torture_assert_ntstatus_ok(tctx, status,
1396 : "gensec_set_credentials (client) failed");
1397 :
1398 1 : status = gensec_start_mech_by_sasl_name(*gensec_client_context,
1399 : "GSS-SPNEGO");
1400 1 : torture_assert_ntstatus_ok(tctx, status,
1401 : "gensec_start_mech_by_sasl_name (client) failed");
1402 :
1403 :
1404 1 : return true;
1405 : }
1406 :
1407 :
1408 :
1409 6 : static bool expected_record(TALLOC_CTX *mem_ctx,
1410 : struct test_expected_record *r,
1411 : const char *name,
1412 : const char *type,
1413 : const char *data)
1414 : {
1415 6 : unsigned int ttl = 3600;
1416 6 : const char *rdata = talloc_asprintf(
1417 : mem_ctx,
1418 : "%s.\t" "%u\t" "in\t" "%s\t" "%s",
1419 : name, ttl, type, data);
1420 6 : if (rdata == NULL) {
1421 0 : return false;
1422 : }
1423 :
1424 6 : *r = (struct test_expected_record){
1425 : .name = name,
1426 : .type = type,
1427 : .data = data,
1428 : .ttl = ttl,
1429 : .printed = false,
1430 : .rdata = rdata
1431 : };
1432 6 : return true;
1433 : }
1434 :
1435 :
1436 : struct dlz_test_handle {
1437 : struct dcerpc_pipe *p;
1438 : };
1439 :
1440 :
1441 2 : static bool set_zone_aging(struct torture_context *tctx,
1442 : const char *zone,
1443 : int value)
1444 : {
1445 0 : int ret;
1446 2 : char *cmd = talloc_asprintf(tctx,
1447 : "bin/samba-tool dns zoneoptions "
1448 : "$SERVER %s -U$USERNAME%%$PASSWORD "
1449 : "--aging %d", zone, value);
1450 :
1451 2 : if (cmd == NULL) {
1452 0 : return false;
1453 : }
1454 :
1455 2 : ret = system(cmd);
1456 2 : if (ret != 0) {
1457 0 : TALLOC_FREE(cmd);
1458 0 : return false;
1459 : }
1460 2 : TALLOC_FREE(cmd);
1461 2 : return true;
1462 : }
1463 :
1464 :
1465 1 : static struct ldb_context* get_samdb(struct torture_context *tctx)
1466 : {
1467 1 : struct ldb_context *samdb = NULL;
1468 0 : char *errstring;
1469 1 : int ret = samdb_connect_url(
1470 : tctx,
1471 : NULL,
1472 : tctx->lp_ctx,
1473 : system_session(tctx->lp_ctx),
1474 : 0,
1475 1 : dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
1476 : NULL,
1477 : &samdb,
1478 : &errstring);
1479 1 : if (ret != LDB_SUCCESS) {
1480 0 : return NULL;
1481 : }
1482 1 : return samdb;
1483 : }
1484 :
1485 :
1486 11 : static void print_node_records(struct torture_context *tctx,
1487 : struct ldb_context *samdb,
1488 : struct ldb_dn *node_dn,
1489 : const char *msg)
1490 : {
1491 0 : int ret;
1492 11 : struct ldb_result *result = NULL;
1493 0 : struct dnsp_DnssrvRpcRecord rec;
1494 11 : struct ldb_message_element *el = NULL;
1495 0 : size_t i;
1496 :
1497 11 : if (msg != NULL) {
1498 11 : torture_comment(tctx,
1499 : "\033[1;32m%s\033[0m\n",
1500 : msg);
1501 : }
1502 :
1503 11 : ret = dsdb_search(samdb, tctx, &result, node_dn,
1504 : LDB_SCOPE_SUBTREE, NULL,
1505 : 0, NULL);
1506 11 : if (ret != LDB_SUCCESS) {
1507 0 : torture_comment(tctx,
1508 : "Failed to find node: %s",
1509 : ldb_errstring(samdb));
1510 : }
1511 :
1512 11 : el = ldb_msg_find_element(result->msgs[0], "dnsRecord");
1513 :
1514 66 : for (i = 0; i < el->num_values; i++) {
1515 110 : ret = ndr_pull_struct_blob(
1516 55 : &(el->values[i]),
1517 : result,
1518 : &rec,
1519 : (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
1520 55 : if (!NDR_ERR_CODE_IS_SUCCESS(ret)) {
1521 0 : DBG_ERR("Failed to pull dns rec blob [%zu].\n",
1522 : i);
1523 0 : TALLOC_FREE(result);
1524 : }
1525 55 : torture_comment(tctx, "record[%zu]:\n", i);
1526 55 : torture_comment(tctx, "type: %d\n", rec.wType);
1527 55 : torture_comment(tctx, "timestamp: %u\n", rec.dwTimeStamp);
1528 55 : torture_comment(tctx, "%s\n",
1529 : NDR_PRINT_STRUCT_STRING(result,
1530 : dnsp_DnssrvRpcRecord,
1531 : &rec));
1532 : }
1533 11 : }
1534 :
1535 :
1536 :
1537 : /*
1538 : * Test some MORE updates, this time focussing on more record types and aging.
1539 : */
1540 1 : static bool test_dlz_bind9_aging(struct torture_context *tctx)
1541 : {
1542 1 : struct gensec_security *gensec_client_context = NULL;
1543 0 : DATA_BLOB client_to_server, server_to_client;
1544 0 : NTSTATUS status;
1545 1 : void *dbdata = NULL;
1546 1 : void *version = NULL;
1547 1 : struct test_expected_rr *testdata = NULL;
1548 1 : bool ok = false;
1549 1 : struct ldb_context *samdb = NULL;
1550 0 : isc_result_t ret;
1551 0 : size_t i, j;
1552 1 : const char *domain = lpcfg_dnsdomain(tctx->lp_ctx);
1553 1 : struct ldb_dn *domain_dn = NULL;
1554 1 : struct ldb_dn *node_dn = NULL;
1555 1 : struct ldb_result *result = NULL;
1556 0 : uint32_t dns_timestamp_before;
1557 0 : uint32_t dns_timestamp_after;
1558 1 : const char *name = NULL;
1559 1 : const char *attrs[] = {"dnsrecord", NULL};
1560 1 : const char *node_dn_str = NULL;
1561 1 : struct ldb_message_element *el = NULL;
1562 1 : struct ldb_message *msg = NULL;
1563 :
1564 1 : tctx_static = tctx;
1565 :
1566 : /* Step 0. set things up */
1567 :
1568 1 : ok = init_dlz(tctx, &dbdata);
1569 1 : if (! ok) {
1570 0 : torture_fail(tctx, "Failed to init_dlz");
1571 : }
1572 1 : ok = init_gensec(tctx, &gensec_client_context);
1573 1 : if (! ok) {
1574 0 : torture_fail(tctx, "Failed to init_gensec");
1575 : }
1576 :
1577 1 : samdb = get_samdb(tctx);
1578 1 : if (samdb == NULL) {
1579 0 : torture_fail(tctx, "Failed to connect to samdb");
1580 : }
1581 :
1582 1 : domain_dn = ldb_get_default_basedn(samdb);
1583 1 : testdata = talloc_zero(tctx, struct test_expected_rr);
1584 1 : torture_assert(tctx, testdata != NULL, "talloc failed");
1585 1 : testdata->tctx = tctx;
1586 :
1587 1 : testdata->query_name = __func__;
1588 :
1589 1 : name = talloc_asprintf(testdata, "%s.%s",
1590 : testdata->query_name,
1591 : domain);
1592 1 : torture_assert(tctx, name != NULL, "talloc failed");
1593 :
1594 1 : testdata->num_records = 6;
1595 1 : testdata->records = talloc_zero_array(testdata,
1596 : struct test_expected_record,
1597 : testdata->num_records);
1598 1 : torture_assert(tctx, testdata->records != NULL, "talloc failed");
1599 :
1600 1 : torture_assert(tctx,
1601 : expected_record(testdata->records,
1602 : &testdata->records[0],
1603 : testdata->query_name,
1604 : "aaaa",
1605 : "::1"),
1606 : "failed to add record");
1607 :
1608 1 : torture_assert(tctx,
1609 : expected_record(testdata->records,
1610 : &testdata->records[1],
1611 : testdata->query_name,
1612 : "a",
1613 : "127.11.12.13"),
1614 : "failed to add record");
1615 1 : torture_assert(tctx,
1616 : expected_record(testdata->records,
1617 : &testdata->records[2],
1618 : testdata->query_name,
1619 : "a",
1620 : "127.11.12.14"),
1621 : "failed to add record");
1622 :
1623 1 : torture_assert(tctx,
1624 : expected_record(testdata->records,
1625 : &testdata->records[3],
1626 : testdata->query_name,
1627 : "ptr",
1628 : "samba.example.com"),
1629 : "failed to add record");
1630 :
1631 : /*
1632 : * NOTE: Here we add the MX record with the priority before the name,
1633 : * rather than the other way around which you are more likely to see
1634 : * ("samba.example.com 11" e.g. in samba-tool dns), because this is
1635 : * how it goes in BIND9 configuration.
1636 : */
1637 1 : torture_assert(tctx,
1638 : expected_record(testdata->records,
1639 : &testdata->records[4],
1640 : testdata->query_name,
1641 : "mx",
1642 : "11 samba.example.com."),
1643 : "failed to add record");
1644 :
1645 1 : torture_assert(tctx,
1646 : expected_record(testdata->records,
1647 : &testdata->records[5],
1648 : testdata->query_name,
1649 : "cname",
1650 : "samba.example.com"),
1651 : "failed to add record");
1652 :
1653 :
1654 1 : server_to_client = data_blob(NULL, 0);
1655 :
1656 : /* Do one step of the client-server update dance */
1657 1 : status = gensec_update(gensec_client_context, tctx, server_to_client,
1658 : &client_to_server);
1659 1 : if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {;
1660 0 : torture_assert_ntstatus_ok(tctx, status,
1661 : "gensec_update (client) failed");
1662 : }
1663 :
1664 1 : torture_assert_int_equal(tctx, dlz_ssumatch(
1665 : cli_credentials_get_username(
1666 : samba_cmdline_get_creds()),
1667 : domain,
1668 : "127.0.0.1",
1669 : testdata->records[0].type,
1670 : "key",
1671 : client_to_server.length,
1672 : client_to_server.data,
1673 : dbdata),
1674 : ISC_TRUE,
1675 : "Failed to check key for update rights samba_dlz");
1676 :
1677 : /* remember the DN for use below */
1678 1 : node_dn = ldb_dn_copy(testdata, domain_dn);
1679 1 : if (node_dn == NULL) {
1680 0 : torture_fail(tctx, "Failed to make node dn");
1681 : }
1682 :
1683 1 : ok = ldb_dn_add_child_fmt(
1684 : node_dn,
1685 : "DC=%s,DC=%s,CN=MicrosoftDNS,DC=DomainDnsZones",
1686 : testdata->query_name,
1687 : domain);
1688 1 : if (! ok) {
1689 0 : torture_fail(tctx, "Failed to make node dn");
1690 : }
1691 1 : node_dn_str = ldb_dn_get_linearized(node_dn);
1692 1 : if (node_dn_str == NULL) {
1693 0 : torture_fail(tctx, "Failed to linearise node dn");
1694 : }
1695 :
1696 : /* LOOK: we are chopping off the last one (the CNAME) for now */
1697 1 : testdata->num_records = 5;
1698 :
1699 : /*
1700 : * We test the following:
1701 : *
1702 : * Step 1. Ensure we are starting with an empty node.
1703 : * Step 2. Add all the records (with aging off).
1704 : * Step 3. Check the timestamps are now-ish.
1705 : * Step 4. Add all the records AGAIN.
1706 : * Step 5: Turn aging on.
1707 : * Step 6. Add all the records again.
1708 : * Step 7. Check the timestamps are still now-ish.
1709 : * Step 8. Wind back the timestamps in the database.
1710 : * Step 9. Do another update, changing some timestamps
1711 : * Step 10. Check that the timestamps are right.
1712 : * Step 11. Set one record to be static.
1713 : * Step 12. Do updates on some records, zeroing their timestamps
1714 : * Step 13. Check that the record timeouts are *mostly* zero.
1715 : * Step 14. Turn aging off
1716 : * Step 15. Update, setting timestamps to zero
1717 : * Step 16. Check that the timestamps are all zero.
1718 : * Step 17. Reset to non-zero via ldb, with aging still off.
1719 : * Step 18. Update with aging off. Nothing should change.
1720 : * Step 19. Check that the timestamps didn't change.
1721 : * Step 20. Delete all the records, 1 by 1.
1722 : */
1723 :
1724 :
1725 : /*
1726 : * Step 1. Ensure we are starting with an empty node.
1727 : */
1728 1 : torture_comment(tctx, "step 1: %s records are not there\n",
1729 : testdata->query_name);
1730 1 : testdata->num_rr = 0;
1731 1 : torture_assert_int_equal(tctx, dlz_lookup(domain,
1732 : testdata->query_name,
1733 : dbdata,
1734 : (dns_sdlzlookup_t *)testdata,
1735 : NULL, NULL),
1736 : ISC_R_NOTFOUND,
1737 : "Found hostname");
1738 1 : torture_assert_int_equal(tctx, testdata->num_rr, 0,
1739 : "Got records when there should be none");
1740 :
1741 :
1742 1 : dns_timestamp_before = unix_to_dns_timestamp(time(NULL));
1743 :
1744 : /*
1745 : * Step 2. Add all the records (with aging off).
1746 : * After adding each one, expect to find it and earlier ones.
1747 : */
1748 1 : torture_comment(tctx,
1749 : "step 2: add %zu records\n",
1750 : testdata->num_records);
1751 :
1752 6 : for (i = 0; i < testdata->num_records; i++) {
1753 5 : struct test_expected_record r = testdata->records[i];
1754 5 : ret = dlz_newversion(domain, dbdata, &version);
1755 5 : torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
1756 : "Failed to start transaction");
1757 :
1758 5 : ret = dlz_addrdataset(name, r.rdata, dbdata, version);
1759 5 : torture_assert_int_equal_goto(
1760 : tctx, ret, ISC_R_SUCCESS, ok,
1761 : cancel_version,
1762 : talloc_asprintf(tctx,
1763 : "Failed to add record %zu «%s»\n",
1764 : i, r.rdata));
1765 :
1766 5 : dlz_closeversion(domain, true, dbdata, &version);
1767 :
1768 5 : testdata->num_rr = 0;
1769 :
1770 5 : ret = dlz_lookup(domain, testdata->query_name, dbdata,
1771 : (dns_sdlzlookup_t *)testdata, NULL, NULL);
1772 :
1773 5 : torture_assert_int_equal(tctx, ret,
1774 : ISC_R_SUCCESS,
1775 : "Not found hostname");
1776 5 : torture_assert_int_equal(tctx, testdata->num_rr, i + 1,
1777 : "Got wrong record count");
1778 :
1779 30 : for (j = 0; j < testdata->num_records; j++) {
1780 25 : struct test_expected_record *r2 = &testdata->records[j];
1781 25 : if (j <= i) {
1782 15 : torture_assertf(
1783 : tctx,
1784 : r2->printed,
1785 : "putrr callback not run on %s «%s»",
1786 : r2->type, r2->name);
1787 : } else {
1788 10 : torture_assertf(
1789 : tctx,
1790 : ! r2->printed,
1791 : "putrr callback should not see %s «%s»",
1792 : r2->type, r2->name);
1793 : }
1794 25 : r2->printed = false;
1795 : }
1796 : }
1797 :
1798 1 : dns_timestamp_after = unix_to_dns_timestamp(time(NULL));
1799 : /*
1800 : * Step 3. Check the timestamps are now-ish.
1801 : *
1802 : * Those records should have DNS timestamps between
1803 : * dns_timestamp_before and dns_timestamp_after (the resolution is
1804 : * hourly, so probably both are equal).
1805 : */
1806 1 : ret = dsdb_search(samdb, tctx, &result, node_dn,
1807 : LDB_SCOPE_SUBTREE, NULL,
1808 : 0, NULL);
1809 1 : if (ret != LDB_SUCCESS) {
1810 0 : torture_fail(tctx,
1811 : talloc_asprintf(
1812 : tctx,
1813 : "Failed to find %s node: %s",
1814 : name, ldb_errstring(samdb)));
1815 : }
1816 1 : torture_assert_int_equal(tctx, result->count, 1,
1817 : "Should be one node");
1818 :
1819 1 : el = ldb_msg_find_element(result->msgs[0], "dnsRecord");
1820 1 : torture_assert_not_null(tctx, el, "el");
1821 1 : torture_assert(tctx, dns_timestamp_before <= dns_timestamp_after, "<");
1822 1 : torture_assert_int_equal(tctx, el->num_values, testdata->num_records,
1823 : "num_values != num_records");
1824 :
1825 6 : for (i = 0; i < el->num_values; i++) {
1826 0 : struct dnsp_DnssrvRpcRecord rec;
1827 5 : ret = ndr_pull_struct_blob(
1828 5 : &(el->values[i]),
1829 : result,
1830 : &rec,
1831 : (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
1832 5 : if (!NDR_ERR_CODE_IS_SUCCESS(ret)) {
1833 0 : DBG_ERR("Failed to pull dns rec blob [%zu].\n",
1834 : i);
1835 0 : TALLOC_FREE(result);
1836 0 : torture_fail(tctx, "Failed to pull dns rec blob");
1837 : }
1838 5 : torture_comment(tctx, "record[%zu]:\n", i);
1839 5 : torture_comment(tctx, "type: %d\n", rec.wType);
1840 5 : torture_comment(tctx, "timestamp: %u\n", rec.dwTimeStamp);
1841 5 : torture_comment(tctx, "%s\n",
1842 : NDR_PRINT_STRUCT_STRING(result,
1843 : dnsp_DnssrvRpcRecord,
1844 : &rec));
1845 :
1846 5 : torture_assert(tctx, rec.dwTimeStamp >= dns_timestamp_before,
1847 : "timestamp < dns_timestamp_before");
1848 5 : torture_assert(tctx, rec.dwTimeStamp <= dns_timestamp_after,
1849 : "timestamp > dns_timestamp_after");
1850 : }
1851 :
1852 1 : talloc_free(result);
1853 :
1854 : /*
1855 : * Step 4. Add all the records AGAIN.
1856 : *
1857 : * After adding each one, we expect no change in the number or nature
1858 : * of records.
1859 : */
1860 1 : torture_comment(tctx, "step 4: add the records again\n");
1861 6 : for (i = 0; i < testdata->num_records; i++) {
1862 5 : struct test_expected_record r = testdata->records[i];
1863 :
1864 5 : ret = dlz_newversion(domain, dbdata, &version);
1865 5 : torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
1866 : "Failed to start transaction");
1867 :
1868 5 : ret = dlz_addrdataset(name, r.rdata, dbdata, version);
1869 5 : torture_assert_int_equal_goto(
1870 : tctx, ret, ISC_R_SUCCESS, ok,
1871 : cancel_version,
1872 : talloc_asprintf(tctx,
1873 : "Failed to add record %zu «%s»\n",
1874 : i, r.rdata));
1875 :
1876 5 : dlz_closeversion(domain, true, dbdata, &version);
1877 :
1878 5 : testdata->num_rr = 0;
1879 :
1880 5 : ret = dlz_lookup(domain, testdata->query_name, dbdata,
1881 : (dns_sdlzlookup_t *)testdata, NULL, NULL);
1882 :
1883 5 : torture_assert_int_equal(tctx, ret,
1884 : ISC_R_SUCCESS,
1885 : "Not found hostname");
1886 5 : torture_assert_int_equal(tctx,
1887 : testdata->num_rr,
1888 : testdata->num_records,
1889 : "Got wrong record count");
1890 :
1891 20 : for (j = 0; j <= i; j++) {
1892 : /* these ones are printed again. */
1893 15 : struct test_expected_record *r2 = &testdata->records[j];
1894 15 : torture_assert(
1895 : tctx,
1896 : r2->printed,
1897 : talloc_asprintf(
1898 : tctx,
1899 : "putrr callback not run on %s «%s»",
1900 : r2->type, r2->name));
1901 15 : r2->printed = false;
1902 : }
1903 : }
1904 :
1905 1 : print_node_records(tctx, samdb, node_dn, "after adding again");
1906 :
1907 :
1908 : /*
1909 : * Step 5: Turn aging on.
1910 : */
1911 1 : torture_comment(tctx, "step 5: turn aging on\n");
1912 1 : ok = set_zone_aging(tctx, domain, 1);
1913 1 : torture_assert(tctx, ok, "failed to enable aging");
1914 :
1915 1 : print_node_records(tctx, samdb, node_dn, "aging on");
1916 :
1917 : /*
1918 : * Step 6. Add all the records again.
1919 : *
1920 : * We expect no change in the number or nature of records, even with
1921 : * aging on, because the default noRefreshInterval is 7 days (also,
1922 : * there should be no change because almost no time has passed).
1923 : */
1924 1 : torture_comment(tctx, "step 6: add records again\n");
1925 :
1926 6 : for (i = 0; i < testdata->num_records; i++) {
1927 5 : struct test_expected_record r = testdata->records[i];
1928 :
1929 5 : ret = dlz_newversion(domain, dbdata, &version);
1930 5 : torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
1931 : "Failed to start transaction");
1932 :
1933 5 : ret = dlz_addrdataset(domain, r.rdata, dbdata, version);
1934 5 : torture_assert_int_equal_goto(
1935 : tctx, ret, ISC_R_SUCCESS, ok,
1936 : cancel_version,
1937 : talloc_asprintf(tctx,
1938 : "Failed to add record %zu «%s»\n",
1939 : i, r.rdata));
1940 :
1941 5 : dlz_closeversion(domain, true, dbdata, &version);
1942 : }
1943 :
1944 1 : print_node_records(tctx, samdb, node_dn, "add again");
1945 :
1946 :
1947 : /*
1948 : * Step 7. Check the timestamps are still now-ish.
1949 : *
1950 : */
1951 1 : ret = dsdb_search(samdb, tctx, &result, node_dn,
1952 : LDB_SCOPE_SUBTREE, NULL,
1953 : 0, NULL);
1954 1 : if (ret != LDB_SUCCESS) {
1955 0 : torture_fail(tctx,
1956 : talloc_asprintf(
1957 : tctx,
1958 : "Failed to find %s node: %s",
1959 : name, ldb_errstring(samdb)));
1960 : }
1961 1 : torture_assert_int_equal(tctx, result->count, 1,
1962 : "Should be one node");
1963 :
1964 1 : el = ldb_msg_find_element(result->msgs[0], "dnsRecord");
1965 1 : torture_assert_not_null(tctx, el, "el");
1966 1 : torture_assert(tctx, dns_timestamp_before <= dns_timestamp_after, "<");
1967 1 : torture_assert_int_equal(tctx, el->num_values, testdata->num_records,
1968 : "num_values != num_records");
1969 :
1970 6 : for (i = 0; i < el->num_values; i++) {
1971 0 : struct dnsp_DnssrvRpcRecord rec;
1972 5 : ret = ndr_pull_struct_blob(
1973 5 : &(el->values[i]),
1974 : result,
1975 : &rec,
1976 : (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
1977 5 : if (!NDR_ERR_CODE_IS_SUCCESS(ret)) {
1978 0 : DBG_ERR("Failed to pull dns rec blob [%zu].\n",
1979 : i);
1980 0 : TALLOC_FREE(result);
1981 0 : torture_fail(tctx, "Failed to pull dns rec blob");
1982 : }
1983 5 : torture_comment(tctx, "record[%zu]:\n", i);
1984 5 : torture_comment(tctx, "type: %d\n", rec.wType);
1985 5 : torture_comment(tctx, "timestamp: %u\n", rec.dwTimeStamp);
1986 5 : torture_comment(tctx, "%s\n",
1987 : NDR_PRINT_STRUCT_STRING(result,
1988 : dnsp_DnssrvRpcRecord,
1989 : &rec));
1990 :
1991 5 : torture_assert(tctx, rec.dwTimeStamp >= dns_timestamp_before,
1992 : "timestamp < dns_timestamp_before");
1993 5 : torture_assert(tctx, rec.dwTimeStamp <= dns_timestamp_after,
1994 : "timestamp > dns_timestamp_after");
1995 : }
1996 :
1997 1 : talloc_free(result);
1998 :
1999 : /*
2000 : * Step 8. Wind back the timestamps in the database.
2001 : *
2002 : * We use a different number of days for each record, so that some
2003 : * should be refreshed, and some shouldn't.
2004 : */
2005 1 : torture_comment(tctx, "step 8: alter timestamps\n");
2006 1 : ret = dsdb_search_one(samdb, tctx, &msg, node_dn,
2007 : LDB_SCOPE_BASE, attrs,
2008 : 0, NULL);
2009 1 : if (ret != LDB_SUCCESS) {
2010 0 : torture_fail(tctx,
2011 : talloc_asprintf(
2012 : tctx,
2013 : "Failed to find %s node: %s",
2014 : name, ldb_errstring(samdb)));
2015 : }
2016 :
2017 1 : el = ldb_msg_find_element(msg, "dnsRecord");
2018 1 : torture_assert_not_null(tctx, el, "el");
2019 1 : torture_assert_int_equal(tctx, el->num_values,
2020 : testdata->num_records,
2021 : "num_values != num_records");
2022 :
2023 6 : for (i = 0; i < el->num_values; i++) {
2024 0 : struct dnsp_DnssrvRpcRecord rec;
2025 5 : ret = ndr_pull_struct_blob(
2026 5 : &(el->values[i]),
2027 : msg,
2028 : &rec,
2029 : (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
2030 5 : torture_assert_ndr_success(tctx, ret, "failed to pull record");
2031 :
2032 5 : rec.dwTimeStamp = dns_timestamp_after + 3 - 24 * (i + 5);
2033 :
2034 5 : ret = ndr_push_struct_blob(
2035 5 : &el->values[i],
2036 : msg,
2037 : &rec,
2038 : (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord);
2039 5 : torture_assert_ndr_success(tctx, ret, "failed to PUSH record");
2040 : }
2041 1 : el->flags = LDB_FLAG_MOD_REPLACE;
2042 :
2043 1 : ret = ldb_modify(samdb, msg);
2044 1 : torture_assert_int_equal(tctx, ret, 0, "failed to ldb_modify");
2045 1 : print_node_records(tctx, samdb, node_dn, "after ldb_modify");
2046 :
2047 :
2048 : /*
2049 : * Step 9. Do another update, changing some timestamps
2050 : */
2051 :
2052 6 : for (i = 0; i < testdata->num_records; i++) {
2053 5 : struct test_expected_record r = testdata->records[i];
2054 :
2055 5 : ret = dlz_newversion(domain, dbdata, &version);
2056 5 : torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
2057 : "Failed to start transaction");
2058 :
2059 5 : ret = dlz_addrdataset(name, r.rdata, dbdata, version);
2060 5 : dlz_closeversion(domain, ret == ISC_R_SUCCESS, dbdata,
2061 : &version);
2062 5 : torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
2063 : "Failed to update record\n");
2064 : }
2065 1 : print_node_records(tctx, samdb, node_dn, "after update");
2066 :
2067 : /*
2068 : * Step 10. Check that the timestamps are right.
2069 : *
2070 : * The formula was
2071 : * (i + 5) days + 3 hours
2072 : * so 1 is 6 days + 3 hours, and should not be renewed.
2073 : * 2 is 7 days + 3 hours, and should be renewed
2074 : *
2075 : * NOTE: the ldb record order is different from the insertion order,
2076 : * but it should stay the same between searches.
2077 : */
2078 1 : ret = dsdb_search_one(samdb, tctx, &msg, node_dn,
2079 : LDB_SCOPE_BASE, attrs,
2080 : 0, NULL);
2081 1 : if (ret != LDB_SUCCESS) {
2082 0 : torture_fail(tctx,
2083 : talloc_asprintf(
2084 : tctx,
2085 : "Failed to find %s node: %s",
2086 : name, ldb_errstring(samdb)));
2087 : }
2088 :
2089 1 : el = ldb_msg_find_element(msg, "dnsRecord");
2090 1 : torture_assert_not_null(tctx, el, "el");
2091 1 : torture_assert_int_equal(tctx, el->num_values,
2092 : testdata->num_records,
2093 : "num_values != num_records");
2094 :
2095 6 : for (i = 0; i < el->num_values; i++) {
2096 0 : struct dnsp_DnssrvRpcRecord rec;
2097 5 : ret = ndr_pull_struct_blob(
2098 5 : &(el->values[i]),
2099 : msg,
2100 : &rec,
2101 : (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
2102 5 : torture_assert_ndr_success(tctx, ret, "failed to pull record");
2103 5 : if (i < 3) {
2104 : /* records 0 and 1 should not have been renewed */
2105 3 : int old_ts = dns_timestamp_after + 3 - 24 * (i + 5);
2106 3 : torture_assertf(
2107 : tctx,
2108 : rec.dwTimeStamp == old_ts,
2109 : "record[%zu] timestamp should not be altered."
2110 : " diff is %d\n",
2111 : i, rec.dwTimeStamp - old_ts);
2112 : } else {
2113 : /* records 3+ should have a now-ish timestamp */
2114 2 : int old_ts = dns_timestamp_after + 3 - 24 * (i + 5);
2115 2 : torture_assertf(
2116 : tctx,
2117 : rec.dwTimeStamp >= dns_timestamp_before,
2118 : "record[%zu] should have altered timestamp "
2119 : "now ~= %d, then ~= %d, has %d, diff %d\n", i,
2120 : dns_timestamp_before, old_ts, rec.dwTimeStamp,
2121 : dns_timestamp_before - rec.dwTimeStamp
2122 : );
2123 : }
2124 : }
2125 :
2126 : /*
2127 : * Step 11. Set one record to be static.
2128 : *
2129 : * This should make the node static, but it won't "know" that until we
2130 : * force it with an update.
2131 : */
2132 1 : torture_comment(tctx, "step 11: alter one timestamp to be 0\n");
2133 1 : ret = dsdb_search_one(samdb, tctx, &msg, node_dn,
2134 : LDB_SCOPE_BASE, attrs,
2135 : 0, NULL);
2136 1 : if (ret != LDB_SUCCESS) {
2137 0 : torture_fail(tctx,
2138 : talloc_asprintf(
2139 : tctx,
2140 : "Failed to find %s node: %s",
2141 : name, ldb_errstring(samdb)));
2142 : }
2143 :
2144 1 : el = ldb_msg_find_element(msg, "dnsRecord");
2145 1 : torture_assert_not_null(tctx, el, "el");
2146 1 : torture_assert_int_equal(tctx, el->num_values,
2147 : testdata->num_records,
2148 : "num_values != num_records");
2149 :
2150 : {
2151 : /* we're arbitrarily picking on record 3 */
2152 0 : struct dnsp_DnssrvRpcRecord rec;
2153 1 : ret = ndr_pull_struct_blob(
2154 1 : &(el->values[3]),
2155 : msg,
2156 : &rec,
2157 : (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
2158 1 : torture_assert_ndr_success(tctx, ret, "failed to pull record");
2159 :
2160 1 : rec.dwTimeStamp = 0;
2161 :
2162 1 : ret = ndr_push_struct_blob(
2163 1 : &el->values[3],
2164 : msg,
2165 : &rec,
2166 : (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord);
2167 1 : torture_assert_ndr_success(tctx, ret, "failed to PUSH record");
2168 : }
2169 1 : el->flags = LDB_FLAG_MOD_REPLACE;
2170 :
2171 1 : ret = ldb_modify(samdb, msg);
2172 1 : torture_assert_int_equal(tctx, ret, 0, "failed to ldb_modify");
2173 1 : print_node_records(tctx, samdb, node_dn, "after ldb_modify");
2174 :
2175 :
2176 : /*
2177 : * Step 12. Do updates on some records, zeroing their timestamps
2178 : *
2179 : * Zero means static. A single zero timestamp is infectious, so other
2180 : * records get it when they are updated.
2181 : */
2182 :
2183 4 : for (i = 0; i < testdata->num_records - 2; i++) {
2184 3 : struct test_expected_record r = testdata->records[i];
2185 :
2186 3 : ret = dlz_newversion(domain, dbdata, &version);
2187 3 : torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
2188 : "Failed to start transaction");
2189 :
2190 3 : ret = dlz_addrdataset(name, r.rdata, dbdata, version);
2191 3 : dlz_closeversion(domain, ret == ISC_R_SUCCESS, dbdata,
2192 : &version);
2193 3 : torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
2194 : "Failed to update record\n");
2195 : }
2196 1 : print_node_records(tctx, samdb, node_dn, "after update to static");
2197 :
2198 :
2199 : /*
2200 : * Step 13. Check that the record timeouts are *mostly* zero.
2201 : *
2202 : * one or two will be non-zero: we updated all but two, but one of
2203 : * excluded ones might be the el->records[3] that we explicitly set to
2204 : * zero.
2205 : */
2206 1 : ret = dsdb_search_one(samdb, tctx, &msg, node_dn,
2207 : LDB_SCOPE_BASE, attrs,
2208 : 0, NULL);
2209 1 : if (ret != LDB_SUCCESS) {
2210 0 : torture_fail(tctx,
2211 : talloc_asprintf(
2212 : tctx,
2213 : "Failed to find %s node: %s",
2214 : name, ldb_errstring(samdb)));
2215 : }
2216 :
2217 1 : el = ldb_msg_find_element(msg, "dnsRecord");
2218 : {
2219 1 : unsigned n_zero = 0;
2220 6 : for (i = 0; i < el->num_values; i++) {
2221 0 : struct dnsp_DnssrvRpcRecord rec;
2222 5 : ret = ndr_pull_struct_blob(
2223 5 : &(el->values[i]),
2224 : msg,
2225 : &rec,
2226 : (ndr_pull_flags_fn_t)\
2227 : ndr_pull_dnsp_DnssrvRpcRecord);
2228 5 : torture_assert_ndr_success(tctx, ret,
2229 : "failed to pull record");
2230 5 : if (rec.dwTimeStamp == 0) {
2231 3 : n_zero++;
2232 : }
2233 : }
2234 1 : if (n_zero != el->num_values - 1 &&
2235 1 : n_zero != el->num_values - 2) {
2236 0 : torture_comment(tctx, "got %u zeros, expected %u or %u",
2237 : n_zero,
2238 0 : el->num_values - 2,
2239 0 : el->num_values - 1);
2240 0 : torture_fail(tctx,
2241 : "static node not setting zero timestamps\n");
2242 :
2243 : }
2244 : }
2245 :
2246 :
2247 : /*
2248 : * Step 14. Turn aging off.
2249 : */
2250 1 : torture_comment(tctx, "step 14: turn aging off\n");
2251 1 : ok = set_zone_aging(tctx, domain, 0);
2252 1 : torture_assert(tctx, ok, "failed to disable aging");
2253 1 : print_node_records(tctx, samdb, node_dn, "aging off");
2254 :
2255 : /*
2256 : * Step 15. Update, setting timestamps to zero.
2257 : *
2258 : * Even with aging off, timestamps are still changed to static.
2259 : */
2260 6 : for (i = 0; i < testdata->num_records; i++) {
2261 5 : struct test_expected_record r = testdata->records[i];
2262 :
2263 5 : ret = dlz_newversion(domain, dbdata, &version);
2264 5 : torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
2265 : "Failed to start transaction");
2266 :
2267 5 : ret = dlz_addrdataset(name, r.rdata, dbdata, version);
2268 5 : dlz_closeversion(domain, ret == ISC_R_SUCCESS, dbdata,
2269 : &version);
2270 5 : torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
2271 : "Failed to update record\n");
2272 : }
2273 1 : print_node_records(tctx, samdb, node_dn, "after update with aging off");
2274 :
2275 :
2276 : /*
2277 : * Step 16. Check that the timestamps are all zero.
2278 : */
2279 1 : ret = dsdb_search_one(samdb, tctx, &msg, node_dn,
2280 : LDB_SCOPE_BASE, attrs,
2281 : 0, NULL);
2282 1 : if (ret != LDB_SUCCESS) {
2283 0 : torture_fail(tctx,
2284 : talloc_asprintf(
2285 : tctx,
2286 : "Failed to find %s node: %s",
2287 : name, ldb_errstring(samdb)));
2288 : }
2289 :
2290 1 : el = ldb_msg_find_element(msg, "dnsRecord");
2291 6 : for (i = 0; i < el->num_values; i++) {
2292 0 : struct dnsp_DnssrvRpcRecord rec;
2293 5 : ret = ndr_pull_struct_blob(
2294 5 : &(el->values[i]),
2295 : msg,
2296 : &rec,
2297 : (ndr_pull_flags_fn_t) ndr_pull_dnsp_DnssrvRpcRecord);
2298 5 : torture_assert_ndr_success(tctx, ret,
2299 : "failed to pull record");
2300 5 : torture_assertf(tctx, rec.dwTimeStamp == 0,
2301 : "record[%zu].dwTimeStamp is %u, expected 0\n",
2302 : i, rec.dwTimeStamp);
2303 :
2304 : }
2305 :
2306 :
2307 : /*
2308 : * Step 17. Reset to non-zero via ldb, with aging still off.
2309 : *
2310 : * We chose timestamps in the distant past that would all be updated
2311 : * if aging was on.
2312 : */
2313 1 : torture_comment(tctx, "step 17: reset to non-zero timestamps\n");
2314 1 : ret = dsdb_search_one(samdb, tctx, &msg, node_dn,
2315 : LDB_SCOPE_BASE, attrs,
2316 : 0, NULL);
2317 1 : if (ret != LDB_SUCCESS) {
2318 0 : torture_fail(tctx,
2319 : talloc_asprintf(
2320 : tctx,
2321 : "Failed to find %s node: %s",
2322 : name, ldb_errstring(samdb)));
2323 : }
2324 :
2325 1 : el = ldb_msg_find_element(msg, "dnsRecord");
2326 :
2327 6 : for (i = 0; i < el->num_values; i++) {
2328 0 : struct dnsp_DnssrvRpcRecord rec;
2329 5 : ret = ndr_pull_struct_blob(
2330 5 : &(el->values[i]),
2331 : msg,
2332 : &rec,
2333 : (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
2334 5 : torture_assert_ndr_success(tctx, ret, "failed to pull record");
2335 :
2336 5 : rec.dwTimeStamp = 10000 + i; /* a long time ago */
2337 :
2338 5 : ret = ndr_push_struct_blob(
2339 5 : &el->values[i],
2340 : msg,
2341 : &rec,
2342 : (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord);
2343 5 : torture_assert_ndr_success(tctx, ret, "failed to PUSH record");
2344 : }
2345 1 : el->flags = LDB_FLAG_MOD_REPLACE;
2346 :
2347 1 : ret = ldb_modify(samdb, msg);
2348 1 : torture_assert_int_equal(tctx, ret, 0, "failed to ldb_modify");
2349 1 : print_node_records(tctx, samdb, node_dn, "timestamps no-zero, aging off");
2350 :
2351 :
2352 : /*
2353 : * Step 18. Update with aging off. Nothing should change.
2354 : *
2355 : */
2356 :
2357 : /* now, with another update, some will be updated and some won't */
2358 6 : for (i = 0; i < testdata->num_records; i++) {
2359 5 : struct test_expected_record r = testdata->records[i];
2360 :
2361 5 : ret = dlz_newversion(domain, dbdata, &version);
2362 5 : torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
2363 : "Failed to start transaction");
2364 :
2365 5 : ret = dlz_addrdataset(name, r.rdata, dbdata, version);
2366 5 : dlz_closeversion(domain, ret == ISC_R_SUCCESS, dbdata,
2367 : &version);
2368 5 : torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
2369 : "Failed to update record\n");
2370 : }
2371 1 : print_node_records(tctx, samdb, node_dn, "after update");
2372 :
2373 :
2374 : /*
2375 : * Step 19. Check that the timestamps didn't change.
2376 : */
2377 1 : el = ldb_msg_find_element(msg, "dnsRecord");
2378 1 : torture_assert_not_null(tctx, el, "el");
2379 1 : torture_assert_int_equal(tctx, el->num_values,
2380 : testdata->num_records,
2381 : "num_values != num_records");
2382 :
2383 6 : for (i = 0; i < el->num_values; i++) {
2384 0 : struct dnsp_DnssrvRpcRecord rec;
2385 5 : ret = ndr_pull_struct_blob(
2386 5 : &(el->values[i]),
2387 : msg,
2388 : &rec,
2389 : (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
2390 5 : torture_assert_ndr_success(tctx, ret, "failed to pull record");
2391 5 : torture_assertf(
2392 : tctx,
2393 : rec.dwTimeStamp == 10000 + i,
2394 : "record[%zu] timestamp should not be altered.\n",
2395 : i);
2396 : }
2397 :
2398 :
2399 : /*
2400 : * Step 20. Delete all the records, 1 by 1.
2401 : *
2402 : */
2403 1 : torture_comment(tctx, "step 20: delete the records\n");
2404 :
2405 6 : for (i = 0; i < testdata->num_records; i++) {
2406 5 : struct test_expected_record r = testdata->records[i];
2407 :
2408 5 : ret = dlz_newversion(domain, dbdata, &version);
2409 5 : torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
2410 : "Failed to start transaction");
2411 :
2412 5 : ret = dlz_subrdataset(name, r.rdata, dbdata, version);
2413 5 : torture_assert_int_equal_goto(
2414 : tctx, ret, ISC_R_SUCCESS, ok,
2415 : cancel_version,
2416 : talloc_asprintf(tctx,
2417 : "Failed to delete record %zu «%s»\n",
2418 : i, r.rdata));
2419 :
2420 5 : dlz_closeversion(domain, true, dbdata, &version);
2421 :
2422 5 : testdata->num_rr = 0;
2423 :
2424 5 : ret = dlz_lookup(domain, testdata->query_name, dbdata,
2425 : (dns_sdlzlookup_t *)testdata, NULL, NULL);
2426 :
2427 5 : if (i == testdata->num_records - 1) {
2428 1 : torture_assert_int_equal(tctx, ret,
2429 : ISC_R_NOTFOUND,
2430 : "no records should exist");
2431 : } else {
2432 4 : torture_assert_int_equal(tctx, ret,
2433 : ISC_R_SUCCESS,
2434 : "records not found");
2435 : }
2436 :
2437 5 : torture_assert_int_equal(tctx,
2438 : testdata->num_rr,
2439 : testdata->num_records - 1 - i,
2440 : "Got wrong record count");
2441 :
2442 30 : for (j = 0; j < testdata->num_records; j++) {
2443 25 : struct test_expected_record *r2 = &testdata->records[j];
2444 25 : if (j > i) {
2445 10 : torture_assert(
2446 : tctx,
2447 : r2->printed,
2448 : talloc_asprintf(tctx,
2449 : "putrr callback not run on %s «%s»",
2450 : r2->type, r2->name));
2451 : } else {
2452 15 : torture_assert(
2453 : tctx,
2454 : ! r2->printed,
2455 : talloc_asprintf(tctx,
2456 : "putrr callback should not see %s «%s»",
2457 : r2->type, r2->name));
2458 : }
2459 25 : r2->printed = false;
2460 : }
2461 : }
2462 :
2463 1 : dlz_destroy(dbdata);
2464 :
2465 1 : return true;
2466 :
2467 0 : cancel_version:
2468 0 : DBG_ERR("exiting with %d\n", ret);
2469 0 : dlz_closeversion(domain, false, dbdata, &version);
2470 0 : return ret;
2471 : }
2472 :
2473 :
2474 1515 : static struct torture_suite *dlz_bind9_suite(TALLOC_CTX *ctx)
2475 : {
2476 1515 : struct torture_suite *suite = torture_suite_create(ctx, "dlz_bind9");
2477 :
2478 1515 : suite->description = talloc_strdup(suite,
2479 : "Tests for the BIND 9 DLZ module");
2480 1515 : torture_suite_add_simple_test(suite, "version", test_dlz_bind9_version);
2481 1515 : torture_suite_add_simple_test(suite, "create", test_dlz_bind9_create);
2482 1515 : torture_suite_add_simple_test(suite, "configure", test_dlz_bind9_configure);
2483 1515 : torture_suite_add_simple_test(suite, "destroyoldestfirst",
2484 : test_dlz_bind9_destroy_oldest_first);
2485 1515 : torture_suite_add_simple_test(suite, "destroynewestfirst",
2486 : test_dlz_bind9_destroy_newest_first);
2487 1515 : torture_suite_add_simple_test(suite, "multipleconfigure",
2488 : test_dlz_bind9_multiple_configure);
2489 :
2490 1515 : torture_suite_add_simple_test(suite, "gssapi", test_dlz_bind9_gssapi);
2491 1515 : torture_suite_add_simple_test(suite, "spnego", test_dlz_bind9_spnego);
2492 1515 : torture_suite_add_simple_test(suite, "lookup", test_dlz_bind9_lookup);
2493 1515 : torture_suite_add_simple_test(suite, "zonedump", test_dlz_bind9_zonedump);
2494 1515 : torture_suite_add_simple_test(suite, "update01", test_dlz_bind9_update01);
2495 1515 : torture_suite_add_simple_test(suite, "aging", test_dlz_bind9_aging);
2496 1515 : torture_suite_add_simple_test(suite, "allowzonexfr", test_dlz_bind9_allowzonexfr);
2497 1515 : return suite;
2498 : }
2499 :
2500 : /**
2501 : * DNS torture module initialization
2502 : */
2503 : NTSTATUS torture_bind_dns_init(TALLOC_CTX *);
2504 1515 : NTSTATUS torture_bind_dns_init(TALLOC_CTX *ctx)
2505 : {
2506 125 : struct torture_suite *suite;
2507 :
2508 : /* register DNS related test cases */
2509 1515 : suite = dlz_bind9_suite(ctx);
2510 1515 : if (!suite) return NT_STATUS_NO_MEMORY;
2511 1515 : torture_register_suite(ctx, suite);
2512 :
2513 1515 : return NT_STATUS_OK;
2514 : }
|