lib: Remove timeval_until()
[Samba.git] / source4 / torture / dns / dlz_bind9.c
blob32725b7136d29ebf397141d3951df21440d5d878
1 /*
2 Unix SMB/CIFS implementation.
3 SMB torture tester
4 Copyright (C) Andrew Bartlett 2012
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.
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.
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/>.
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"
40 #include "librpc/rpc/dcerpc.h"
41 #include "librpc/rpc/dcerpc_proto.h"
43 /* Tests that configure multiple DLZs will use this. Increase to add stress. */
44 #define NUM_DLZS_TO_CONFIGURE 4
46 struct torture_context *tctx_static;
48 static void dlz_bind9_log_wrapper(int level, const char *fmt, ...)
49 PRINTF_ATTRIBUTE(2,3);
51 static void dlz_bind9_log_wrapper(int level, const char *fmt, ...)
53 va_list ap;
54 char *msg;
55 va_start(ap, fmt);
56 msg = talloc_vasprintf(NULL, fmt, ap);
57 torture_comment(tctx_static, "%s\n", msg);
58 TALLOC_FREE(msg);
59 va_end(ap);
62 static bool test_dlz_bind9_version(struct torture_context *tctx)
64 unsigned int flags = 0;
65 torture_assert_int_equal(tctx, dlz_version(&flags),
66 DLZ_DLOPEN_VERSION, "got wrong DLZ version");
67 return true;
70 static char *dlz_bind9_binddns_dir(struct torture_context *tctx,
71 const char *file)
73 return talloc_asprintf(tctx,
74 "ldb://%s/%s",
75 lpcfg_binddns_dir(tctx->lp_ctx),
76 file);
79 static bool test_dlz_bind9_create(struct torture_context *tctx)
81 void *dbdata;
82 const char *argv[] = {
83 "samba_dlz",
84 "-H",
85 dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
86 NULL
88 tctx_static = tctx;
89 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");
93 dlz_destroy(dbdata);
95 return true;
98 static bool calls_zone_hook = false;
100 static isc_result_t dlz_bind9_writeable_zone_hook(dns_view_t *view,
101 dns_dlzdb_t *dlzdb,
102 const char *zone_name)
104 struct torture_context *tctx = talloc_get_type((void *)view, struct torture_context);
105 struct ldb_context *samdb = NULL;
106 char *errstring = NULL;
107 int ret = samdb_connect_url(
108 tctx,
109 NULL,
110 tctx->lp_ctx,
111 system_session(tctx->lp_ctx),
113 dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
114 NULL,
115 &samdb,
116 &errstring);
117 struct ldb_message *msg;
118 const char *attrs[] = {
119 NULL
121 if (ret != LDB_SUCCESS) {
122 torture_comment(tctx, "Failed to connect to samdb");
123 return ISC_R_FAILURE;
126 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 if (ret != LDB_SUCCESS) {
130 torture_comment(tctx,
131 "Failed to search for %s: %s",
132 zone_name,
133 ldb_errstring(samdb));
134 return ISC_R_FAILURE;
136 talloc_free(msg);
138 calls_zone_hook = true;
140 return ISC_R_SUCCESS;
143 static bool test_dlz_bind9_configure(struct torture_context *tctx)
145 void *dbdata = NULL;
146 dns_dlzdb_t *dlzdb = NULL;
147 int ret;
148 const char *argv[] = {
149 "samba_dlz",
150 "-H",
151 dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
152 NULL
154 tctx_static = tctx;
155 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 torture_assert_int_equal(tctx,
160 ret,
161 ISC_R_SUCCESS,
162 "Failed to create samba_dlz");
164 calls_zone_hook = false;
165 torture_assert_int_equal(tctx, dlz_configure((void*)tctx,
166 dlzdb,
167 dbdata),
168 ISC_R_SUCCESS,
169 "Failed to configure samba_dlz");
171 dlz_destroy(dbdata);
173 torture_assert_int_equal(tctx, calls_zone_hook, 1, "Hasn't called zone hook");
175 return true;
178 static bool test_dlz_bind9_multiple_configure(struct torture_context *tctx)
180 int i;
181 for(i = 0; i < NUM_DLZS_TO_CONFIGURE; i++){
182 test_dlz_bind9_configure(tctx);
184 return true;
187 static bool configure_multiple_dlzs(struct torture_context *tctx,
188 void **dbdata, int count)
190 int i, res;
191 dns_dlzdb_t *dlzdb = NULL;
192 const char *argv[] = {
193 "samba_dlz",
194 "-H",
195 dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
196 NULL
199 tctx_static = tctx;
200 for(i = 0; i < count; i++){
201 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 torture_assert_int_equal(tctx, res, ISC_R_SUCCESS,
206 "Failed to create samba_dlz");
208 res = dlz_configure((void*)tctx, dlzdb, dbdata[i]);
209 torture_assert_int_equal(tctx, res, ISC_R_SUCCESS,
210 "Failed to configure samba_dlz");
213 return true;
216 static bool test_dlz_bind9_destroy_oldest_first(struct torture_context *tctx)
218 void *dbdata[NUM_DLZS_TO_CONFIGURE];
219 int i;
220 bool ret = configure_multiple_dlzs(tctx,
221 dbdata,
222 NUM_DLZS_TO_CONFIGURE);
223 if (ret == false) {
224 /* failure: has already been printed */
225 return false;
228 /* Reload faults are reported to happen on the first destroy */
229 dlz_destroy(dbdata[0]);
231 for(i = 1; i < NUM_DLZS_TO_CONFIGURE; i++){
232 dlz_destroy(dbdata[i]);
235 return true;
238 static bool test_dlz_bind9_destroy_newest_first(struct torture_context *tctx)
240 void *dbdata[NUM_DLZS_TO_CONFIGURE];
241 int i;
242 bool ret = configure_multiple_dlzs(tctx,
243 dbdata,
244 NUM_DLZS_TO_CONFIGURE);
245 if (ret == false) {
246 /* failure: has already been printed */
247 return false;
250 for(i = NUM_DLZS_TO_CONFIGURE - 1; i >= 0; i--) {
251 dlz_destroy(dbdata[i]);
254 return true;
258 * Test that a ticket obtained for the DNS service will be accepted on the Samba DLZ side
261 static bool test_dlz_bind9_gensec(struct torture_context *tctx, const char *mech)
263 NTSTATUS status;
264 dns_dlzdb_t *dlzdb = NULL;
266 struct gensec_security *gensec_client_context;
268 DATA_BLOB client_to_server, server_to_client;
270 void *dbdata;
271 const char *argv[] = {
272 "samba_dlz",
273 "-H",
274 dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
275 NULL
277 tctx_static = tctx;
278 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");
284 torture_assert_int_equal(tctx, dlz_configure((void*)tctx,
285 dlzdb, dbdata),
286 ISC_R_SUCCESS,
287 "Failed to configure samba_dlz");
289 status = gensec_client_start(tctx, &gensec_client_context,
290 lpcfg_gensec_settings(tctx, tctx->lp_ctx));
291 torture_assert_ntstatus_ok(tctx, status, "gensec_client_start (client) failed");
294 * dlz_bind9 use the special dns/host.domain account
296 status = gensec_set_target_hostname(gensec_client_context,
297 talloc_asprintf(tctx,
298 "%s.%s",
299 torture_setting_string(tctx, "host", NULL),
300 lpcfg_dnsdomain(tctx->lp_ctx)));
301 torture_assert_ntstatus_ok(tctx, status, "gensec_set_target_hostname (client) failed");
303 status = gensec_set_target_service(gensec_client_context, "dns");
304 torture_assert_ntstatus_ok(tctx, status, "gensec_set_target_service failed");
306 status = gensec_set_credentials(gensec_client_context,
307 samba_cmdline_get_creds());
308 torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (client) failed");
310 status = gensec_start_mech_by_sasl_name(gensec_client_context, mech);
311 torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (client) failed");
313 server_to_client = data_blob(NULL, 0);
315 /* Do one step of the client-server update dance */
316 status = gensec_update(gensec_client_context, tctx, server_to_client, &client_to_server);
317 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {;
318 torture_assert_ntstatus_ok(tctx, status, "gensec_update (client) failed");
321 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");
332 dlz_destroy(dbdata);
334 return true;
337 static bool test_dlz_bind9_gssapi(struct torture_context *tctx)
339 return test_dlz_bind9_gensec(tctx, "GSSAPI");
342 static bool test_dlz_bind9_spnego(struct torture_context *tctx)
344 return test_dlz_bind9_gensec(tctx, "GSS-SPNEGO");
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;
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;
364 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)
370 size_t i;
372 torture_assert(expected->tctx, name != NULL,
373 talloc_asprintf(expected->tctx,
374 "Got unnamed record type[%s] data[%s]\n",
375 type, data));
377 expected->num_rr++;
378 torture_comment(expected->tctx, "%u: name[%s] type[%s] ttl[%u] data[%s]\n",
379 (unsigned)expected->num_rr, name, type, (unsigned)ttl, data);
381 for (i = 0; i < expected->num_records; i++) {
382 if (expected->records[i].name != NULL) {
383 if (strcmp(name, expected->records[i].name) != 0) {
384 continue;
388 if (strcmp(type, expected->records[i].type) != 0) {
389 continue;
392 if (expected->records[i].data != NULL) {
394 * For most types the data will have been reformatted
395 * or normalised, so we need to do approximately the
396 * same to compare.
398 const char *data2 = expected->records[i].data;
399 if (strcmp(type, "aaaa") == 0) {
400 struct in6_addr adr1;
401 struct in6_addr adr2;
402 int ret;
403 ret = inet_pton(AF_INET6, data, &adr1);
404 if (ret != 1) {
405 continue;
407 ret = inet_pton(AF_INET6, data2, &adr2);
408 if (ret != 1) {
409 continue;
411 if (memcmp(&adr1, &adr2, sizeof(adr1)) != 0) {
412 continue;
414 } else if (strcmp(type, "cname") == 0 ||
415 strcmp(type, "ptr") == 0 ||
416 strcmp(type, "ns") == 0) {
417 if (!samba_dns_name_equal(data, data2)) {
418 continue;
420 } else if (strcmp(type, "mx") == 0) {
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.
428 if (!samba_dns_name_equal(data, data2)) {
429 continue;
431 } else if (strcmp(data, data2) != 0) {
432 /* default, works for A records */
433 continue;
437 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));
443 expected->records[i].printed = true;
446 return true;
450 * Lookups in these tests end up coming round to run this function.
452 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)
457 struct test_expected_rr *expected =
458 talloc_get_type_abort(lookup, struct test_expected_rr);
459 bool ok;
461 ok = dlz_bind9_putnamedrr_torture_hook(expected, expected->query_name,
462 type, ttl, data);
463 if (!ok) {
464 return ISC_R_FAILURE;
467 return ISC_R_SUCCESS;
470 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)
476 struct test_expected_rr *expected =
477 talloc_get_type_abort(allnodes, struct test_expected_rr);
478 bool ok;
480 ok = dlz_bind9_putnamedrr_torture_hook(expected, name, type, ttl, data);
481 if (!ok) {
482 return ISC_R_FAILURE;
485 return ISC_R_SUCCESS;
489 * Tests some lookups
491 static bool test_dlz_bind9_lookup(struct torture_context *tctx)
493 size_t i;
494 void *dbdata = NULL;
495 dns_clientinfomethods_t *methods = NULL;
496 dns_clientinfo_t *clientinfo = NULL;
497 dns_dlzdb_t *dlzdb = NULL;
498 const char *argv[] = {
499 "samba_dlz",
500 "-H",
501 dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
502 NULL
504 struct test_expected_rr *expected1 = NULL;
505 struct test_expected_rr *expected2 = NULL;
507 tctx_static = tctx;
508 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");
517 torture_assert_int_equal(tctx,
518 dlz_configure((void*)tctx, dlzdb, dbdata),
519 ISC_R_SUCCESS,
520 "Failed to configure samba_dlz");
522 expected1 = talloc_zero(tctx, struct test_expected_rr);
523 torture_assert(tctx, expected1 != NULL, "talloc failed");
524 expected1->tctx = tctx;
526 expected1->query_name = "@";
528 expected1->num_records = 4;
529 expected1->records = talloc_zero_array(expected1,
530 struct test_expected_record,
531 expected1->num_records);
532 torture_assert(tctx, expected1->records != NULL, "talloc failed");
534 expected1->records[0].name = expected1->query_name;
535 expected1->records[0].type = "soa";
536 expected1->records[0].ttl = 3600;
537 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 torture_assert(tctx, expected1->records[0].data != NULL, "talloc failed");
544 expected1->records[1].name = expected1->query_name;
545 expected1->records[1].type = "ns";
546 expected1->records[1].ttl = 900;
547 expected1->records[1].data = talloc_asprintf(expected1->records, "%s.%s.",
548 torture_setting_string(tctx, "host", NULL),
549 lpcfg_dnsdomain(tctx->lp_ctx));
550 torture_assert(tctx, expected1->records[1].data != NULL, "talloc failed");
552 expected1->records[2].name = expected1->query_name;
553 expected1->records[2].type = "aaaa";
554 expected1->records[2].ttl = 900;
556 expected1->records[3].name = expected1->query_name;
557 expected1->records[3].type = "a";
558 expected1->records[3].ttl = 900;
560 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 for (i = 0; i < expected1->num_records; i++) {
567 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));
572 torture_assert_int_equal(tctx, expected1->num_rr,
573 expected1->num_records,
574 "Got too much data");
576 expected2 = talloc_zero(tctx, struct test_expected_rr);
577 torture_assert(tctx, expected2 != NULL, "talloc failed");
578 expected2->tctx = tctx;
580 expected2->query_name = torture_setting_string(tctx, "host", NULL);
581 torture_assert(tctx, expected2->query_name != NULL, "unknown host");
583 expected2->num_records = 2;
584 expected2->records = talloc_zero_array(expected2,
585 struct test_expected_record,
586 expected2->num_records);
587 torture_assert(tctx, expected2->records != NULL, "talloc failed");
589 expected2->records[0].name = expected2->query_name;
590 expected2->records[0].type = "aaaa";
591 expected2->records[0].ttl = 900;
593 expected2->records[1].name = expected2->query_name;
594 expected2->records[1].type = "a";
595 expected2->records[1].ttl = 900;
597 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 for (i = 0; i < expected2->num_records; i++) {
604 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));
610 torture_assert_int_equal(tctx, expected2->num_rr,
611 expected2->num_records,
612 "Got too much data");
614 dlz_destroy(dbdata);
616 return true;
620 * Test some zone dumps
622 static bool test_dlz_bind9_zonedump(struct torture_context *tctx)
624 size_t i;
625 void *dbdata = NULL;
626 dns_dlzdb_t *dlzdb = NULL;
627 const char *argv[] = {
628 "samba_dlz",
629 "-H",
630 dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
631 NULL
633 struct test_expected_rr *expected1 = NULL;
635 tctx_static = tctx;
636 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");
645 torture_assert_int_equal(tctx, dlz_configure((void*)tctx, dlzdb, dbdata),
646 ISC_R_SUCCESS,
647 "Failed to configure samba_dlz");
649 expected1 = talloc_zero(tctx, struct test_expected_rr);
650 torture_assert(tctx, expected1 != NULL, "talloc failed");
651 expected1->tctx = tctx;
653 expected1->num_records = 7;
654 expected1->records = talloc_zero_array(expected1,
655 struct test_expected_record,
656 expected1->num_records);
657 torture_assert(tctx, expected1->records != NULL, "talloc failed");
659 expected1->records[0].name = talloc_asprintf(expected1->records,
660 "%s.", lpcfg_dnsdomain(tctx->lp_ctx));
661 expected1->records[0].type = "soa";
662 expected1->records[0].ttl = 3600;
663 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 torture_assert(tctx, expected1->records[0].data != NULL, "talloc failed");
670 expected1->records[1].name = talloc_asprintf(expected1->records,
671 "%s.", lpcfg_dnsdomain(tctx->lp_ctx));
672 expected1->records[1].type = "ns";
673 expected1->records[1].ttl = 900;
674 expected1->records[1].data = talloc_asprintf(expected1->records, "%s.%s.",
675 torture_setting_string(tctx, "host", NULL),
676 lpcfg_dnsdomain(tctx->lp_ctx));
677 torture_assert(tctx, expected1->records[1].data != NULL, "talloc failed");
679 expected1->records[2].name = talloc_asprintf(expected1->records,
680 "%s.", lpcfg_dnsdomain(tctx->lp_ctx));
681 expected1->records[2].type = "aaaa";
682 expected1->records[2].ttl = 900;
684 expected1->records[3].name = talloc_asprintf(expected1->records,
685 "%s.", lpcfg_dnsdomain(tctx->lp_ctx));
686 expected1->records[3].type = "a";
687 expected1->records[3].ttl = 900;
689 expected1->records[4].name = talloc_asprintf(expected1->records, "%s.%s.",
690 torture_setting_string(tctx, "host", NULL),
691 lpcfg_dnsdomain(tctx->lp_ctx));
692 torture_assert(tctx, expected1->records[4].name != NULL, "unknown host");
693 expected1->records[4].type = "aaaa";
694 expected1->records[4].ttl = 900;
696 expected1->records[5].name = talloc_asprintf(expected1->records, "%s.%s.",
697 torture_setting_string(tctx, "host", NULL),
698 lpcfg_dnsdomain(tctx->lp_ctx));
699 torture_assert(tctx, expected1->records[5].name != NULL, "unknown host");
700 expected1->records[5].type = "a";
701 expected1->records[5].ttl = 900;
704 * We expect multiple srv records
706 expected1->records[6].name = NULL;
707 expected1->records[6].type = "srv";
708 expected1->records[6].ttl = 900;
710 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 for (i = 0; i < expected1->num_records; i++) {
715 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));
721 torture_assert_int_equal(tctx, expected1->num_rr, 24,
722 "Got wrong record count");
724 dlz_destroy(dbdata);
726 return true;
730 * Test some updates
732 static bool test_dlz_bind9_update01(struct torture_context *tctx)
734 NTSTATUS status;
735 struct gensec_security *gensec_client_context;
736 DATA_BLOB client_to_server, server_to_client;
737 void *dbdata = NULL;
738 dns_dlzdb_t *dlzdb = NULL;
739 void *version = NULL;
740 const char *argv[] = {
741 "samba_dlz",
742 "-H",
743 dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
744 NULL
746 struct test_expected_rr *expected1 = NULL;
747 char *name = NULL;
748 char *data0 = NULL;
749 char *data1 = NULL;
750 char *data2 = NULL;
751 bool ret = false;
752 dns_clientinfomethods_t *methods = NULL;
753 dns_clientinfo_t *clientinfo = NULL;
755 tctx_static = tctx;
756 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");
765 torture_assert_int_equal(tctx, dlz_configure((void*)tctx, dlzdb, dbdata),
766 ISC_R_SUCCESS,
767 "Failed to configure samba_dlz");
769 expected1 = talloc_zero(tctx, struct test_expected_rr);
770 torture_assert(tctx, expected1 != NULL, "talloc failed");
771 expected1->tctx = tctx;
773 expected1->query_name = __func__;
775 name = talloc_asprintf(expected1, "%s.%s",
776 expected1->query_name,
777 lpcfg_dnsdomain(tctx->lp_ctx));
778 torture_assert(tctx, name != NULL, "talloc failed");
780 expected1->num_records = 2;
781 expected1->records = talloc_zero_array(expected1,
782 struct test_expected_record,
783 expected1->num_records);
784 torture_assert(tctx, expected1->records != NULL, "talloc failed");
786 expected1->records[0].name = expected1->query_name;
787 expected1->records[0].type = "a";
788 expected1->records[0].ttl = 3600;
789 expected1->records[0].data = "127.1.2.3";
790 expected1->records[0].printed = false;
792 data0 = talloc_asprintf(expected1,
793 "%s.\t" "%u\t" "%s\t" "%s\t" "%s",
794 name,
795 (unsigned)expected1->records[0].ttl,
796 "in",
797 expected1->records[0].type,
798 expected1->records[0].data);
799 torture_assert(tctx, data0 != NULL, "talloc failed");
801 expected1->records[1].name = expected1->query_name;
802 expected1->records[1].type = "a";
803 expected1->records[1].ttl = 3600;
804 expected1->records[1].data = "127.3.2.1";
805 expected1->records[1].printed = false;
807 data1 = talloc_asprintf(expected1,
808 "%s.\t" "%u\t" "%s\t" "%s\t" "%s",
809 name,
810 (unsigned)expected1->records[1].ttl,
811 "in",
812 expected1->records[1].type,
813 expected1->records[1].data);
814 torture_assert(tctx, data1 != NULL, "talloc failed");
816 data2 = talloc_asprintf(expected1,
817 "%s.\t" "0\t" "in\t" "a\t" "127.3.3.3",
818 name);
819 torture_assert(tctx, data2 != NULL, "talloc failed");
822 * Prepare session info
824 status = gensec_client_start(tctx, &gensec_client_context,
825 lpcfg_gensec_settings(tctx, tctx->lp_ctx));
826 torture_assert_ntstatus_ok(tctx, status, "gensec_client_start (client) failed");
829 * dlz_bind9 use the special dns/host.domain account
831 status = gensec_set_target_hostname(gensec_client_context,
832 talloc_asprintf(tctx,
833 "%s.%s",
834 torture_setting_string(tctx, "host", NULL),
835 lpcfg_dnsdomain(tctx->lp_ctx)));
836 torture_assert_ntstatus_ok(tctx, status, "gensec_set_target_hostname (client) failed");
838 status = gensec_set_target_service(gensec_client_context, "dns");
839 torture_assert_ntstatus_ok(tctx, status, "gensec_set_target_service failed");
841 status = gensec_set_credentials(gensec_client_context,
842 samba_cmdline_get_creds());
843 torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (client) failed");
845 status = gensec_start_mech_by_sasl_name(gensec_client_context, "GSS-SPNEGO");
846 torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (client) failed");
848 server_to_client = data_blob(NULL, 0);
850 /* Do one step of the client-server update dance */
851 status = gensec_update(gensec_client_context, tctx, server_to_client, &client_to_server);
852 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {;
853 torture_assert_ntstatus_ok(tctx, status, "gensec_update (client) failed");
856 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");
870 * We test the following:
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
897 /* Step 1. */
898 expected1->num_rr = 0;
899 expected1->records[0].printed = false;
900 expected1->records[1].printed = false;
901 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 torture_assert_int_equal(tctx, expected1->num_rr, 0,
908 "Got wrong record count");
910 /* Step 2. */
911 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 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 dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), false, dbdata, &version);
924 /* Step 3. */
925 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 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 dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), false, dbdata, &version);
936 /* Step 4. */
937 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 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 dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version);
948 /* Step 5. */
949 expected1->num_rr = 0;
950 expected1->records[0].printed = false;
951 expected1->records[1].printed = false;
952 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 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 torture_assert_int_equal(tctx, expected1->num_rr, 1,
964 "Got wrong record count");
966 /* Step 6. */
967 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 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 dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version);
978 /* Step 7. */
979 expected1->num_rr = 0;
980 expected1->records[0].printed = false;
981 expected1->records[1].printed = false;
982 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 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 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 torture_assert_int_equal(tctx, expected1->num_rr, 2,
999 "Got wrong record count");
1001 /* Step 8. */
1002 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 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 dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version);
1013 /* Step 9. */
1014 expected1->num_rr = 0;
1015 expected1->records[0].printed = false;
1016 expected1->records[1].printed = false;
1017 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 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 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 torture_assert_int_equal(tctx, expected1->num_rr, 2,
1034 "Got wrong record count");
1036 /* Step 10. */
1037 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 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 dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version);
1048 /* Step 11. */
1049 expected1->num_rr = 0;
1050 expected1->records[0].printed = false;
1051 expected1->records[1].printed = false;
1052 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 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 torture_assert_int_equal(tctx, expected1->num_rr, 1,
1064 "Got wrong record count");
1066 /* Step 12. */
1067 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 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 dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version);
1078 /* Step 13. */
1079 expected1->num_rr = 0;
1080 expected1->records[0].printed = false;
1081 expected1->records[1].printed = false;
1082 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 torture_assert_int_equal(tctx, expected1->num_rr, 0,
1089 "Got wrong record count");
1091 /* Step 14. */
1092 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 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 dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version);
1103 /* Step 15. */
1104 expected1->num_rr = 0;
1105 expected1->records[0].printed = false;
1106 expected1->records[1].printed = false;
1107 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 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 torture_assert_int_equal(tctx, expected1->num_rr, 1,
1119 "Got wrong record count");
1121 /* Step 16. */
1122 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 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 dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version);
1133 /* Step 17. */
1134 expected1->num_rr = 0;
1135 expected1->records[0].printed = false;
1136 expected1->records[1].printed = false;
1137 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 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 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 torture_assert_int_equal(tctx, expected1->num_rr, 2,
1154 "Got wrong record count");
1156 /* Step 18. */
1157 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 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 dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version);
1168 /* Step 19. */
1169 expected1->num_rr = 0;
1170 expected1->records[0].printed = false;
1171 expected1->records[1].printed = false;
1172 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 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 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 torture_assert_int_equal(tctx, expected1->num_rr, 2,
1189 "Got wrong record count");
1191 /* Step 20. */
1192 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 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 dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), false, dbdata, &version);
1203 /* Step 21. */
1204 expected1->num_rr = 0;
1205 expected1->records[0].printed = false;
1206 expected1->records[1].printed = false;
1207 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 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 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 torture_assert_int_equal(tctx, expected1->num_rr, 2,
1224 "Got wrong record count");
1226 /* Step 22. */
1227 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 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 dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version);
1240 /* Step 23. */
1241 expected1->num_rr = 0;
1242 expected1->records[0].printed = false;
1243 expected1->records[1].printed = false;
1244 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 torture_assert_int_equal(tctx, expected1->num_rr, 0,
1251 "Got wrong record count");
1253 dlz_destroy(dbdata);
1255 return true;
1257 cancel_version:
1258 dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), false, dbdata, &version);
1259 return ret;
1263 * Test zone transfer requests restrictions
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.
1269 static bool test_dlz_bind9_allowzonexfr(struct torture_context *tctx)
1271 void *dbdata;
1272 const char *argv[] = {
1273 "samba_dlz",
1274 "-H",
1275 dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
1276 NULL
1278 isc_result_t ret;
1279 dns_dlzdb_t *dlzdb = NULL;
1280 bool ok;
1282 tctx_static = tctx;
1283 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");
1292 torture_assert_int_equal(tctx, dlz_configure((void*)tctx, dlzdb, dbdata),
1293 ISC_R_SUCCESS,
1294 "Failed to configure samba_dlz");
1296 /* Ask for zone transfer with no specific config => expect denied */
1297 ret = dlz_allowzonexfr(dbdata, lpcfg_dnsdomain(tctx->lp_ctx), "127.0.0.1");
1298 torture_assert_int_equal(tctx, ret, ISC_R_NOPERM,
1299 "Zone transfer accepted with default settings");
1301 /* Ask for zone transfer with authorizations set */
1302 ok = lpcfg_set_option(tctx->lp_ctx, "dns zone transfer clients allow=127.0.0.1,1234:5678::1,192.168.0.");
1303 torture_assert(tctx, ok, "Failed to set dns zone transfer clients allow option.");
1305 ok = lpcfg_set_option(tctx->lp_ctx, "dns zone transfer clients deny=192.168.0.2");
1306 torture_assert(tctx, ok, "Failed to set dns zone transfer clients deny option.");
1308 ret = dlz_allowzonexfr(dbdata, lpcfg_dnsdomain(tctx->lp_ctx), "127.0.0.1");
1309 torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
1310 "Zone transfer refused for authorized IPv4 address");
1312 ret = dlz_allowzonexfr(dbdata, lpcfg_dnsdomain(tctx->lp_ctx), "1234:5678::1");
1313 torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
1314 "Zone transfer refused for authorized IPv6 address.");
1316 ret = dlz_allowzonexfr(dbdata, lpcfg_dnsdomain(tctx->lp_ctx), "10.0.0.1");
1317 torture_assert_int_equal(tctx, ret, ISC_R_NOPERM,
1318 "Zone transfer accepted for unauthorized IP");
1320 ret = dlz_allowzonexfr(dbdata, lpcfg_dnsdomain(tctx->lp_ctx), "192.168.0.1");
1321 torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
1322 "Zone transfer refused for address in authorized IPv4 subnet.");
1324 ret = dlz_allowzonexfr(dbdata, lpcfg_dnsdomain(tctx->lp_ctx), "192.168.0.2");
1325 torture_assert_int_equal(tctx, ret, ISC_R_NOPERM,
1326 "Zone transfer allowed for denied client.");
1328 dlz_destroy(dbdata);
1329 return true;
1333 static int init_dlz(struct torture_context *tctx,
1334 void **dbdata)
1336 isc_result_t ret;
1337 const char *argv[] = {
1338 "samba_dlz",
1339 "-H",
1340 dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
1341 NULL
1344 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);
1351 torture_assert_int_equal(tctx,
1352 ret,
1353 ISC_R_SUCCESS,
1354 "Failed to create samba_dlz");
1356 ret = dlz_configure((void*)tctx, NULL, *dbdata);
1357 torture_assert_int_equal(tctx,
1358 ret,
1359 ISC_R_SUCCESS,
1360 "Failed to configure samba_dlz");
1362 return true;
1366 static int init_gensec(struct torture_context *tctx,
1367 struct gensec_security **gensec_client_context)
1369 NTSTATUS status;
1371 * Prepare session info
1373 status = gensec_client_start(tctx, gensec_client_context,
1374 lpcfg_gensec_settings(tctx, tctx->lp_ctx));
1375 torture_assert_ntstatus_ok(tctx, status,
1376 "gensec_client_start (client) failed");
1379 * dlz_bind9 use the special dns/host.domain account
1381 status = gensec_set_target_hostname(*gensec_client_context,
1382 talloc_asprintf(tctx,
1383 "%s.%s",
1384 torture_setting_string(tctx, "host", NULL),
1385 lpcfg_dnsdomain(tctx->lp_ctx)));
1386 torture_assert_ntstatus_ok(tctx, status,
1387 "gensec_set_target_hostname (client) failed");
1389 status = gensec_set_target_service(*gensec_client_context, "dns");
1390 torture_assert_ntstatus_ok(tctx, status,
1391 "gensec_set_target_service failed");
1393 status = gensec_set_credentials(*gensec_client_context,
1394 samba_cmdline_get_creds());
1395 torture_assert_ntstatus_ok(tctx, status,
1396 "gensec_set_credentials (client) failed");
1398 status = gensec_start_mech_by_sasl_name(*gensec_client_context,
1399 "GSS-SPNEGO");
1400 torture_assert_ntstatus_ok(tctx, status,
1401 "gensec_start_mech_by_sasl_name (client) failed");
1404 return true;
1409 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)
1415 unsigned int ttl = 3600;
1416 const char *rdata = talloc_asprintf(
1417 mem_ctx,
1418 "%s.\t" "%u\t" "in\t" "%s\t" "%s",
1419 name, ttl, type, data);
1420 if (rdata == NULL) {
1421 return false;
1424 *r = (struct test_expected_record){
1425 .name = name,
1426 .type = type,
1427 .data = data,
1428 .ttl = ttl,
1429 .printed = false,
1430 .rdata = rdata
1432 return true;
1436 struct dlz_test_handle {
1437 struct dcerpc_pipe *p;
1441 static bool set_zone_aging(struct torture_context *tctx,
1442 const char *zone,
1443 int value)
1445 int ret;
1446 char *cmd = talloc_asprintf(tctx,
1447 "bin/samba-tool dns zoneoptions "
1448 "$SERVER %s -U$USERNAME%%$PASSWORD "
1449 "--aging %d", zone, value);
1451 if (cmd == NULL) {
1452 return false;
1455 ret = system(cmd);
1456 if (ret != 0) {
1457 TALLOC_FREE(cmd);
1458 return false;
1460 TALLOC_FREE(cmd);
1461 return true;
1465 static struct ldb_context* get_samdb(struct torture_context *tctx)
1467 struct ldb_context *samdb = NULL;
1468 char *errstring;
1469 int ret = samdb_connect_url(
1470 tctx,
1471 NULL,
1472 tctx->lp_ctx,
1473 system_session(tctx->lp_ctx),
1475 dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
1476 NULL,
1477 &samdb,
1478 &errstring);
1479 if (ret != LDB_SUCCESS) {
1480 return NULL;
1482 return samdb;
1486 static void print_node_records(struct torture_context *tctx,
1487 struct ldb_context *samdb,
1488 struct ldb_dn *node_dn,
1489 const char *msg)
1491 int ret;
1492 struct ldb_result *result = NULL;
1493 struct dnsp_DnssrvRpcRecord rec;
1494 struct ldb_message_element *el = NULL;
1495 size_t i;
1497 if (msg != NULL) {
1498 torture_comment(tctx,
1499 "\033[1;32m%s\033[0m\n",
1500 msg);
1503 ret = dsdb_search(samdb, tctx, &result, node_dn,
1504 LDB_SCOPE_SUBTREE, NULL,
1505 0, NULL);
1506 if (ret != LDB_SUCCESS) {
1507 torture_comment(tctx,
1508 "Failed to find node: %s",
1509 ldb_errstring(samdb));
1512 el = ldb_msg_find_element(result->msgs[0], "dnsRecord");
1514 for (i = 0; i < el->num_values; i++) {
1515 ret = ndr_pull_struct_blob(
1516 &(el->values[i]),
1517 result,
1518 &rec,
1519 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
1520 if (!NDR_ERR_CODE_IS_SUCCESS(ret)) {
1521 DBG_ERR("Failed to pull dns rec blob [%zu].\n",
1523 TALLOC_FREE(result);
1525 torture_comment(tctx, "record[%zu]:\n", i);
1526 torture_comment(tctx, "type: %d\n", rec.wType);
1527 torture_comment(tctx, "timestamp: %u\n", rec.dwTimeStamp);
1528 torture_comment(tctx, "%s\n",
1529 NDR_PRINT_STRUCT_STRING(result,
1530 dnsp_DnssrvRpcRecord,
1531 &rec));
1538 * Test some MORE updates, this time focussing on more record types and aging.
1540 static bool test_dlz_bind9_aging(struct torture_context *tctx)
1542 struct gensec_security *gensec_client_context = NULL;
1543 DATA_BLOB client_to_server, server_to_client;
1544 NTSTATUS status;
1545 void *dbdata = NULL;
1546 void *version = NULL;
1547 struct test_expected_rr *testdata = NULL;
1548 bool ok = false;
1549 struct ldb_context *samdb = NULL;
1550 isc_result_t ret;
1551 size_t i, j;
1552 const char *domain = lpcfg_dnsdomain(tctx->lp_ctx);
1553 struct ldb_dn *domain_dn = NULL;
1554 struct ldb_dn *node_dn = NULL;
1555 struct ldb_result *result = NULL;
1556 uint32_t dns_timestamp_before;
1557 uint32_t dns_timestamp_after;
1558 const char *name = NULL;
1559 const char *attrs[] = {"dnsrecord", NULL};
1560 const char *node_dn_str = NULL;
1561 struct ldb_message_element *el = NULL;
1562 struct ldb_message *msg = NULL;
1564 tctx_static = tctx;
1566 /* Step 0. set things up */
1568 ok = init_dlz(tctx, &dbdata);
1569 if (! ok) {
1570 torture_fail(tctx, "Failed to init_dlz");
1572 ok = init_gensec(tctx, &gensec_client_context);
1573 if (! ok) {
1574 torture_fail(tctx, "Failed to init_gensec");
1577 samdb = get_samdb(tctx);
1578 if (samdb == NULL) {
1579 torture_fail(tctx, "Failed to connect to samdb");
1582 domain_dn = ldb_get_default_basedn(samdb);
1583 testdata = talloc_zero(tctx, struct test_expected_rr);
1584 torture_assert(tctx, testdata != NULL, "talloc failed");
1585 testdata->tctx = tctx;
1587 testdata->query_name = __func__;
1589 name = talloc_asprintf(testdata, "%s.%s",
1590 testdata->query_name,
1591 domain);
1592 torture_assert(tctx, name != NULL, "talloc failed");
1594 testdata->num_records = 6;
1595 testdata->records = talloc_zero_array(testdata,
1596 struct test_expected_record,
1597 testdata->num_records);
1598 torture_assert(tctx, testdata->records != NULL, "talloc failed");
1600 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");
1608 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 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");
1623 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");
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.
1637 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");
1645 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");
1654 server_to_client = data_blob(NULL, 0);
1656 /* Do one step of the client-server update dance */
1657 status = gensec_update(gensec_client_context, tctx, server_to_client,
1658 &client_to_server);
1659 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {;
1660 torture_assert_ntstatus_ok(tctx, status,
1661 "gensec_update (client) failed");
1664 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");
1677 /* remember the DN for use below */
1678 node_dn = ldb_dn_copy(testdata, domain_dn);
1679 if (node_dn == NULL) {
1680 torture_fail(tctx, "Failed to make node dn");
1683 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 if (! ok) {
1689 torture_fail(tctx, "Failed to make node dn");
1691 node_dn_str = ldb_dn_get_linearized(node_dn);
1692 if (node_dn_str == NULL) {
1693 torture_fail(tctx, "Failed to linearise node dn");
1696 /* LOOK: we are chopping off the last one (the CNAME) for now */
1697 testdata->num_records = 5;
1700 * We test the following:
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.
1726 * Step 1. Ensure we are starting with an empty node.
1728 torture_comment(tctx, "step 1: %s records are not there\n",
1729 testdata->query_name);
1730 testdata->num_rr = 0;
1731 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 torture_assert_int_equal(tctx, testdata->num_rr, 0,
1739 "Got records when there should be none");
1742 dns_timestamp_before = unix_to_dns_timestamp(time(NULL));
1745 * Step 2. Add all the records (with aging off).
1746 * After adding each one, expect to find it and earlier ones.
1748 torture_comment(tctx,
1749 "step 2: add %zu records\n",
1750 testdata->num_records);
1752 for (i = 0; i < testdata->num_records; i++) {
1753 struct test_expected_record r = testdata->records[i];
1754 ret = dlz_newversion(domain, dbdata, &version);
1755 torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
1756 "Failed to start transaction");
1758 ret = dlz_addrdataset(name, r.rdata, dbdata, version);
1759 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));
1766 dlz_closeversion(domain, true, dbdata, &version);
1768 testdata->num_rr = 0;
1770 ret = dlz_lookup(domain, testdata->query_name, dbdata,
1771 (dns_sdlzlookup_t *)testdata, NULL, NULL);
1773 torture_assert_int_equal(tctx, ret,
1774 ISC_R_SUCCESS,
1775 "Not found hostname");
1776 torture_assert_int_equal(tctx, testdata->num_rr, i + 1,
1777 "Got wrong record count");
1779 for (j = 0; j < testdata->num_records; j++) {
1780 struct test_expected_record *r2 = &testdata->records[j];
1781 if (j <= i) {
1782 torture_assertf(
1783 tctx,
1784 r2->printed,
1785 "putrr callback not run on %s «%s»",
1786 r2->type, r2->name);
1787 } else {
1788 torture_assertf(
1789 tctx,
1790 ! r2->printed,
1791 "putrr callback should not see %s «%s»",
1792 r2->type, r2->name);
1794 r2->printed = false;
1798 dns_timestamp_after = unix_to_dns_timestamp(time(NULL));
1800 * Step 3. Check the timestamps are now-ish.
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).
1806 ret = dsdb_search(samdb, tctx, &result, node_dn,
1807 LDB_SCOPE_SUBTREE, NULL,
1808 0, NULL);
1809 if (ret != LDB_SUCCESS) {
1810 torture_fail(tctx,
1811 talloc_asprintf(
1812 tctx,
1813 "Failed to find %s node: %s",
1814 name, ldb_errstring(samdb)));
1816 torture_assert_int_equal(tctx, result->count, 1,
1817 "Should be one node");
1819 el = ldb_msg_find_element(result->msgs[0], "dnsRecord");
1820 torture_assert_not_null(tctx, el, "el");
1821 torture_assert(tctx, dns_timestamp_before <= dns_timestamp_after, "<");
1822 torture_assert_int_equal(tctx, el->num_values, testdata->num_records,
1823 "num_values != num_records");
1825 for (i = 0; i < el->num_values; i++) {
1826 struct dnsp_DnssrvRpcRecord rec;
1827 ret = ndr_pull_struct_blob(
1828 &(el->values[i]),
1829 result,
1830 &rec,
1831 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
1832 if (!NDR_ERR_CODE_IS_SUCCESS(ret)) {
1833 DBG_ERR("Failed to pull dns rec blob [%zu].\n",
1835 TALLOC_FREE(result);
1836 torture_fail(tctx, "Failed to pull dns rec blob");
1838 torture_comment(tctx, "record[%zu]:\n", i);
1839 torture_comment(tctx, "type: %d\n", rec.wType);
1840 torture_comment(tctx, "timestamp: %u\n", rec.dwTimeStamp);
1841 torture_comment(tctx, "%s\n",
1842 NDR_PRINT_STRUCT_STRING(result,
1843 dnsp_DnssrvRpcRecord,
1844 &rec));
1846 torture_assert(tctx, rec.dwTimeStamp >= dns_timestamp_before,
1847 "timestamp < dns_timestamp_before");
1848 torture_assert(tctx, rec.dwTimeStamp <= dns_timestamp_after,
1849 "timestamp > dns_timestamp_after");
1852 talloc_free(result);
1855 * Step 4. Add all the records AGAIN.
1857 * After adding each one, we expect no change in the number or nature
1858 * of records.
1860 torture_comment(tctx, "step 4: add the records again\n");
1861 for (i = 0; i < testdata->num_records; i++) {
1862 struct test_expected_record r = testdata->records[i];
1864 ret = dlz_newversion(domain, dbdata, &version);
1865 torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
1866 "Failed to start transaction");
1868 ret = dlz_addrdataset(name, r.rdata, dbdata, version);
1869 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));
1876 dlz_closeversion(domain, true, dbdata, &version);
1878 testdata->num_rr = 0;
1880 ret = dlz_lookup(domain, testdata->query_name, dbdata,
1881 (dns_sdlzlookup_t *)testdata, NULL, NULL);
1883 torture_assert_int_equal(tctx, ret,
1884 ISC_R_SUCCESS,
1885 "Not found hostname");
1886 torture_assert_int_equal(tctx,
1887 testdata->num_rr,
1888 testdata->num_records,
1889 "Got wrong record count");
1891 for (j = 0; j <= i; j++) {
1892 /* these ones are printed again. */
1893 struct test_expected_record *r2 = &testdata->records[j];
1894 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 r2->printed = false;
1905 print_node_records(tctx, samdb, node_dn, "after adding again");
1909 * Step 5: Turn aging on.
1911 torture_comment(tctx, "step 5: turn aging on\n");
1912 ok = set_zone_aging(tctx, domain, 1);
1913 torture_assert(tctx, ok, "failed to enable aging");
1915 print_node_records(tctx, samdb, node_dn, "aging on");
1918 * Step 6. Add all the records again.
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).
1924 torture_comment(tctx, "step 6: add records again\n");
1926 for (i = 0; i < testdata->num_records; i++) {
1927 struct test_expected_record r = testdata->records[i];
1929 ret = dlz_newversion(domain, dbdata, &version);
1930 torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
1931 "Failed to start transaction");
1933 ret = dlz_addrdataset(domain, r.rdata, dbdata, version);
1934 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));
1941 dlz_closeversion(domain, true, dbdata, &version);
1944 print_node_records(tctx, samdb, node_dn, "add again");
1948 * Step 7. Check the timestamps are still now-ish.
1951 ret = dsdb_search(samdb, tctx, &result, node_dn,
1952 LDB_SCOPE_SUBTREE, NULL,
1953 0, NULL);
1954 if (ret != LDB_SUCCESS) {
1955 torture_fail(tctx,
1956 talloc_asprintf(
1957 tctx,
1958 "Failed to find %s node: %s",
1959 name, ldb_errstring(samdb)));
1961 torture_assert_int_equal(tctx, result->count, 1,
1962 "Should be one node");
1964 el = ldb_msg_find_element(result->msgs[0], "dnsRecord");
1965 torture_assert_not_null(tctx, el, "el");
1966 torture_assert(tctx, dns_timestamp_before <= dns_timestamp_after, "<");
1967 torture_assert_int_equal(tctx, el->num_values, testdata->num_records,
1968 "num_values != num_records");
1970 for (i = 0; i < el->num_values; i++) {
1971 struct dnsp_DnssrvRpcRecord rec;
1972 ret = ndr_pull_struct_blob(
1973 &(el->values[i]),
1974 result,
1975 &rec,
1976 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
1977 if (!NDR_ERR_CODE_IS_SUCCESS(ret)) {
1978 DBG_ERR("Failed to pull dns rec blob [%zu].\n",
1980 TALLOC_FREE(result);
1981 torture_fail(tctx, "Failed to pull dns rec blob");
1983 torture_comment(tctx, "record[%zu]:\n", i);
1984 torture_comment(tctx, "type: %d\n", rec.wType);
1985 torture_comment(tctx, "timestamp: %u\n", rec.dwTimeStamp);
1986 torture_comment(tctx, "%s\n",
1987 NDR_PRINT_STRUCT_STRING(result,
1988 dnsp_DnssrvRpcRecord,
1989 &rec));
1991 torture_assert(tctx, rec.dwTimeStamp >= dns_timestamp_before,
1992 "timestamp < dns_timestamp_before");
1993 torture_assert(tctx, rec.dwTimeStamp <= dns_timestamp_after,
1994 "timestamp > dns_timestamp_after");
1997 talloc_free(result);
2000 * Step 8. Wind back the timestamps in the database.
2002 * We use a different number of days for each record, so that some
2003 * should be refreshed, and some shouldn't.
2005 torture_comment(tctx, "step 8: alter timestamps\n");
2006 ret = dsdb_search_one(samdb, tctx, &msg, node_dn,
2007 LDB_SCOPE_BASE, attrs,
2008 0, NULL);
2009 if (ret != LDB_SUCCESS) {
2010 torture_fail(tctx,
2011 talloc_asprintf(
2012 tctx,
2013 "Failed to find %s node: %s",
2014 name, ldb_errstring(samdb)));
2017 el = ldb_msg_find_element(msg, "dnsRecord");
2018 torture_assert_not_null(tctx, el, "el");
2019 torture_assert_int_equal(tctx, el->num_values,
2020 testdata->num_records,
2021 "num_values != num_records");
2023 for (i = 0; i < el->num_values; i++) {
2024 struct dnsp_DnssrvRpcRecord rec;
2025 ret = ndr_pull_struct_blob(
2026 &(el->values[i]),
2027 msg,
2028 &rec,
2029 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
2030 torture_assert_ndr_success(tctx, ret, "failed to pull record");
2032 rec.dwTimeStamp = dns_timestamp_after + 3 - 24 * (i + 5);
2034 ret = ndr_push_struct_blob(
2035 &el->values[i],
2036 msg,
2037 &rec,
2038 (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord);
2039 torture_assert_ndr_success(tctx, ret, "failed to PUSH record");
2041 el->flags = LDB_FLAG_MOD_REPLACE;
2043 ret = ldb_modify(samdb, msg);
2044 torture_assert_int_equal(tctx, ret, 0, "failed to ldb_modify");
2045 print_node_records(tctx, samdb, node_dn, "after ldb_modify");
2049 * Step 9. Do another update, changing some timestamps
2052 for (i = 0; i < testdata->num_records; i++) {
2053 struct test_expected_record r = testdata->records[i];
2055 ret = dlz_newversion(domain, dbdata, &version);
2056 torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
2057 "Failed to start transaction");
2059 ret = dlz_addrdataset(name, r.rdata, dbdata, version);
2060 dlz_closeversion(domain, ret == ISC_R_SUCCESS, dbdata,
2061 &version);
2062 torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
2063 "Failed to update record\n");
2065 print_node_records(tctx, samdb, node_dn, "after update");
2068 * Step 10. Check that the timestamps are right.
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
2075 * NOTE: the ldb record order is different from the insertion order,
2076 * but it should stay the same between searches.
2078 ret = dsdb_search_one(samdb, tctx, &msg, node_dn,
2079 LDB_SCOPE_BASE, attrs,
2080 0, NULL);
2081 if (ret != LDB_SUCCESS) {
2082 torture_fail(tctx,
2083 talloc_asprintf(
2084 tctx,
2085 "Failed to find %s node: %s",
2086 name, ldb_errstring(samdb)));
2089 el = ldb_msg_find_element(msg, "dnsRecord");
2090 torture_assert_not_null(tctx, el, "el");
2091 torture_assert_int_equal(tctx, el->num_values,
2092 testdata->num_records,
2093 "num_values != num_records");
2095 for (i = 0; i < el->num_values; i++) {
2096 struct dnsp_DnssrvRpcRecord rec;
2097 ret = ndr_pull_struct_blob(
2098 &(el->values[i]),
2099 msg,
2100 &rec,
2101 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
2102 torture_assert_ndr_success(tctx, ret, "failed to pull record");
2103 if (i < 3) {
2104 /* records 0 and 1 should not have been renewed */
2105 int old_ts = dns_timestamp_after + 3 - 24 * (i + 5);
2106 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 int old_ts = dns_timestamp_after + 3 - 24 * (i + 5);
2115 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
2127 * Step 11. Set one record to be static.
2129 * This should make the node static, but it won't "know" that until we
2130 * force it with an update.
2132 torture_comment(tctx, "step 11: alter one timestamp to be 0\n");
2133 ret = dsdb_search_one(samdb, tctx, &msg, node_dn,
2134 LDB_SCOPE_BASE, attrs,
2135 0, NULL);
2136 if (ret != LDB_SUCCESS) {
2137 torture_fail(tctx,
2138 talloc_asprintf(
2139 tctx,
2140 "Failed to find %s node: %s",
2141 name, ldb_errstring(samdb)));
2144 el = ldb_msg_find_element(msg, "dnsRecord");
2145 torture_assert_not_null(tctx, el, "el");
2146 torture_assert_int_equal(tctx, el->num_values,
2147 testdata->num_records,
2148 "num_values != num_records");
2151 /* we're arbitrarily picking on record 3 */
2152 struct dnsp_DnssrvRpcRecord rec;
2153 ret = ndr_pull_struct_blob(
2154 &(el->values[3]),
2155 msg,
2156 &rec,
2157 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
2158 torture_assert_ndr_success(tctx, ret, "failed to pull record");
2160 rec.dwTimeStamp = 0;
2162 ret = ndr_push_struct_blob(
2163 &el->values[3],
2164 msg,
2165 &rec,
2166 (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord);
2167 torture_assert_ndr_success(tctx, ret, "failed to PUSH record");
2169 el->flags = LDB_FLAG_MOD_REPLACE;
2171 ret = ldb_modify(samdb, msg);
2172 torture_assert_int_equal(tctx, ret, 0, "failed to ldb_modify");
2173 print_node_records(tctx, samdb, node_dn, "after ldb_modify");
2177 * Step 12. Do updates on some records, zeroing their timestamps
2179 * Zero means static. A single zero timestamp is infectious, so other
2180 * records get it when they are updated.
2183 for (i = 0; i < testdata->num_records - 2; i++) {
2184 struct test_expected_record r = testdata->records[i];
2186 ret = dlz_newversion(domain, dbdata, &version);
2187 torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
2188 "Failed to start transaction");
2190 ret = dlz_addrdataset(name, r.rdata, dbdata, version);
2191 dlz_closeversion(domain, ret == ISC_R_SUCCESS, dbdata,
2192 &version);
2193 torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
2194 "Failed to update record\n");
2196 print_node_records(tctx, samdb, node_dn, "after update to static");
2200 * Step 13. Check that the record timeouts are *mostly* zero.
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.
2206 ret = dsdb_search_one(samdb, tctx, &msg, node_dn,
2207 LDB_SCOPE_BASE, attrs,
2208 0, NULL);
2209 if (ret != LDB_SUCCESS) {
2210 torture_fail(tctx,
2211 talloc_asprintf(
2212 tctx,
2213 "Failed to find %s node: %s",
2214 name, ldb_errstring(samdb)));
2217 el = ldb_msg_find_element(msg, "dnsRecord");
2219 unsigned n_zero = 0;
2220 for (i = 0; i < el->num_values; i++) {
2221 struct dnsp_DnssrvRpcRecord rec;
2222 ret = ndr_pull_struct_blob(
2223 &(el->values[i]),
2224 msg,
2225 &rec,
2226 (ndr_pull_flags_fn_t)\
2227 ndr_pull_dnsp_DnssrvRpcRecord);
2228 torture_assert_ndr_success(tctx, ret,
2229 "failed to pull record");
2230 if (rec.dwTimeStamp == 0) {
2231 n_zero++;
2234 if (n_zero != el->num_values - 1 &&
2235 n_zero != el->num_values - 2) {
2236 torture_comment(tctx, "got %u zeros, expected %u or %u",
2237 n_zero,
2238 el->num_values - 2,
2239 el->num_values - 1);
2240 torture_fail(tctx,
2241 "static node not setting zero timestamps\n");
2248 * Step 14. Turn aging off.
2250 torture_comment(tctx, "step 14: turn aging off\n");
2251 ok = set_zone_aging(tctx, domain, 0);
2252 torture_assert(tctx, ok, "failed to disable aging");
2253 print_node_records(tctx, samdb, node_dn, "aging off");
2256 * Step 15. Update, setting timestamps to zero.
2258 * Even with aging off, timestamps are still changed to static.
2260 for (i = 0; i < testdata->num_records; i++) {
2261 struct test_expected_record r = testdata->records[i];
2263 ret = dlz_newversion(domain, dbdata, &version);
2264 torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
2265 "Failed to start transaction");
2267 ret = dlz_addrdataset(name, r.rdata, dbdata, version);
2268 dlz_closeversion(domain, ret == ISC_R_SUCCESS, dbdata,
2269 &version);
2270 torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
2271 "Failed to update record\n");
2273 print_node_records(tctx, samdb, node_dn, "after update with aging off");
2277 * Step 16. Check that the timestamps are all zero.
2279 ret = dsdb_search_one(samdb, tctx, &msg, node_dn,
2280 LDB_SCOPE_BASE, attrs,
2281 0, NULL);
2282 if (ret != LDB_SUCCESS) {
2283 torture_fail(tctx,
2284 talloc_asprintf(
2285 tctx,
2286 "Failed to find %s node: %s",
2287 name, ldb_errstring(samdb)));
2290 el = ldb_msg_find_element(msg, "dnsRecord");
2291 for (i = 0; i < el->num_values; i++) {
2292 struct dnsp_DnssrvRpcRecord rec;
2293 ret = ndr_pull_struct_blob(
2294 &(el->values[i]),
2295 msg,
2296 &rec,
2297 (ndr_pull_flags_fn_t) ndr_pull_dnsp_DnssrvRpcRecord);
2298 torture_assert_ndr_success(tctx, ret,
2299 "failed to pull record");
2300 torture_assertf(tctx, rec.dwTimeStamp == 0,
2301 "record[%zu].dwTimeStamp is %u, expected 0\n",
2302 i, rec.dwTimeStamp);
2308 * Step 17. Reset to non-zero via ldb, with aging still off.
2310 * We chose timestamps in the distant past that would all be updated
2311 * if aging was on.
2313 torture_comment(tctx, "step 17: reset to non-zero timestamps\n");
2314 ret = dsdb_search_one(samdb, tctx, &msg, node_dn,
2315 LDB_SCOPE_BASE, attrs,
2316 0, NULL);
2317 if (ret != LDB_SUCCESS) {
2318 torture_fail(tctx,
2319 talloc_asprintf(
2320 tctx,
2321 "Failed to find %s node: %s",
2322 name, ldb_errstring(samdb)));
2325 el = ldb_msg_find_element(msg, "dnsRecord");
2327 for (i = 0; i < el->num_values; i++) {
2328 struct dnsp_DnssrvRpcRecord rec;
2329 ret = ndr_pull_struct_blob(
2330 &(el->values[i]),
2331 msg,
2332 &rec,
2333 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
2334 torture_assert_ndr_success(tctx, ret, "failed to pull record");
2336 rec.dwTimeStamp = 10000 + i; /* a long time ago */
2338 ret = ndr_push_struct_blob(
2339 &el->values[i],
2340 msg,
2341 &rec,
2342 (ndr_push_flags_fn_t)ndr_push_dnsp_DnssrvRpcRecord);
2343 torture_assert_ndr_success(tctx, ret, "failed to PUSH record");
2345 el->flags = LDB_FLAG_MOD_REPLACE;
2347 ret = ldb_modify(samdb, msg);
2348 torture_assert_int_equal(tctx, ret, 0, "failed to ldb_modify");
2349 print_node_records(tctx, samdb, node_dn, "timestamps no-zero, aging off");
2353 * Step 18. Update with aging off. Nothing should change.
2357 /* now, with another update, some will be updated and some won't */
2358 for (i = 0; i < testdata->num_records; i++) {
2359 struct test_expected_record r = testdata->records[i];
2361 ret = dlz_newversion(domain, dbdata, &version);
2362 torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
2363 "Failed to start transaction");
2365 ret = dlz_addrdataset(name, r.rdata, dbdata, version);
2366 dlz_closeversion(domain, ret == ISC_R_SUCCESS, dbdata,
2367 &version);
2368 torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
2369 "Failed to update record\n");
2371 print_node_records(tctx, samdb, node_dn, "after update");
2375 * Step 19. Check that the timestamps didn't change.
2377 el = ldb_msg_find_element(msg, "dnsRecord");
2378 torture_assert_not_null(tctx, el, "el");
2379 torture_assert_int_equal(tctx, el->num_values,
2380 testdata->num_records,
2381 "num_values != num_records");
2383 for (i = 0; i < el->num_values; i++) {
2384 struct dnsp_DnssrvRpcRecord rec;
2385 ret = ndr_pull_struct_blob(
2386 &(el->values[i]),
2387 msg,
2388 &rec,
2389 (ndr_pull_flags_fn_t)ndr_pull_dnsp_DnssrvRpcRecord);
2390 torture_assert_ndr_success(tctx, ret, "failed to pull record");
2391 torture_assertf(
2392 tctx,
2393 rec.dwTimeStamp == 10000 + i,
2394 "record[%zu] timestamp should not be altered.\n",
2400 * Step 20. Delete all the records, 1 by 1.
2403 torture_comment(tctx, "step 20: delete the records\n");
2405 for (i = 0; i < testdata->num_records; i++) {
2406 struct test_expected_record r = testdata->records[i];
2408 ret = dlz_newversion(domain, dbdata, &version);
2409 torture_assert_int_equal(tctx, ret, ISC_R_SUCCESS,
2410 "Failed to start transaction");
2412 ret = dlz_subrdataset(name, r.rdata, dbdata, version);
2413 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));
2420 dlz_closeversion(domain, true, dbdata, &version);
2422 testdata->num_rr = 0;
2424 ret = dlz_lookup(domain, testdata->query_name, dbdata,
2425 (dns_sdlzlookup_t *)testdata, NULL, NULL);
2427 if (i == testdata->num_records - 1) {
2428 torture_assert_int_equal(tctx, ret,
2429 ISC_R_NOTFOUND,
2430 "no records should exist");
2431 } else {
2432 torture_assert_int_equal(tctx, ret,
2433 ISC_R_SUCCESS,
2434 "records not found");
2437 torture_assert_int_equal(tctx,
2438 testdata->num_rr,
2439 testdata->num_records - 1 - i,
2440 "Got wrong record count");
2442 for (j = 0; j < testdata->num_records; j++) {
2443 struct test_expected_record *r2 = &testdata->records[j];
2444 if (j > i) {
2445 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 torture_assert(
2453 tctx,
2454 ! r2->printed,
2455 talloc_asprintf(tctx,
2456 "putrr callback should not see %s «%s»",
2457 r2->type, r2->name));
2459 r2->printed = false;
2463 dlz_destroy(dbdata);
2465 return true;
2467 cancel_version:
2468 DBG_ERR("exiting with %d\n", ret);
2469 dlz_closeversion(domain, false, dbdata, &version);
2470 return ret;
2474 static struct torture_suite *dlz_bind9_suite(TALLOC_CTX *ctx)
2476 struct torture_suite *suite = torture_suite_create(ctx, "dlz_bind9");
2478 suite->description = talloc_strdup(suite,
2479 "Tests for the BIND 9 DLZ module");
2480 torture_suite_add_simple_test(suite, "version", test_dlz_bind9_version);
2481 torture_suite_add_simple_test(suite, "create", test_dlz_bind9_create);
2482 torture_suite_add_simple_test(suite, "configure", test_dlz_bind9_configure);
2483 torture_suite_add_simple_test(suite, "destroyoldestfirst",
2484 test_dlz_bind9_destroy_oldest_first);
2485 torture_suite_add_simple_test(suite, "destroynewestfirst",
2486 test_dlz_bind9_destroy_newest_first);
2487 torture_suite_add_simple_test(suite, "multipleconfigure",
2488 test_dlz_bind9_multiple_configure);
2490 torture_suite_add_simple_test(suite, "gssapi", test_dlz_bind9_gssapi);
2491 torture_suite_add_simple_test(suite, "spnego", test_dlz_bind9_spnego);
2492 torture_suite_add_simple_test(suite, "lookup", test_dlz_bind9_lookup);
2493 torture_suite_add_simple_test(suite, "zonedump", test_dlz_bind9_zonedump);
2494 torture_suite_add_simple_test(suite, "update01", test_dlz_bind9_update01);
2495 torture_suite_add_simple_test(suite, "aging", test_dlz_bind9_aging);
2496 torture_suite_add_simple_test(suite, "allowzonexfr", test_dlz_bind9_allowzonexfr);
2497 return suite;
2501 * DNS torture module initialization
2503 NTSTATUS torture_bind_dns_init(TALLOC_CTX *);
2504 NTSTATUS torture_bind_dns_init(TALLOC_CTX *ctx)
2506 struct torture_suite *suite;
2508 /* register DNS related test cases */
2509 suite = dlz_bind9_suite(ctx);
2510 if (!suite) return NT_STATUS_NO_MEMORY;
2511 torture_register_suite(ctx, suite);
2513 return NT_STATUS_OK;