42b104e070ccb819f90c5bf21fe2f21adca6c6ff
[metze/samba/wip.git] / source4 / torture / dns / dlz_bind9.c
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 "dns_server/dlz_minimal.h"
23 #include <talloc.h>
24 #include <ldb.h>
25 #include "lib/param/param.h"
26 #include "dsdb/samdb/samdb.h"
27 #include "dsdb/common/util.h"
28 #include "auth/session.h"
29 #include "auth/gensec/gensec.h"
30 #include "auth/credentials/credentials.h"
31 #include "lib/cmdline/popt_common.h"
32
33 struct torture_context *tctx_static;
34
35 static void dlz_bind9_log_wrapper(int level, const char *fmt, ...)
36                                   PRINTF_ATTRIBUTE(2,3);
37
38 static void dlz_bind9_log_wrapper(int level, const char *fmt, ...)
39 {
40         va_list ap;
41         char *msg;
42         va_start(ap, fmt);
43         msg = talloc_vasprintf(NULL, fmt, ap);
44         torture_comment(tctx_static, "%s\n", msg);
45         TALLOC_FREE(msg);
46         va_end(ap);
47 }
48
49 static bool test_dlz_bind9_version(struct torture_context *tctx)
50 {
51         unsigned int flags = 0;
52         torture_assert_int_equal(tctx, dlz_version(&flags),
53                                  DLZ_DLOPEN_VERSION, "got wrong DLZ version");
54         return true;
55 }
56
57 static char *test_dlz_bind9_binddns_dir(struct torture_context *tctx,
58                                         const char *file)
59 {
60         return talloc_asprintf(tctx,
61                                "ldb://%s/%s",
62                                lpcfg_binddns_dir(tctx->lp_ctx),
63                                file);
64 }
65
66 static bool test_dlz_bind9_create(struct torture_context *tctx)
67 {
68         void *dbdata;
69         const char *argv[] = {
70                 "samba_dlz",
71                 "-H",
72                 test_dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
73                 NULL
74         };
75         tctx_static = tctx;
76         torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, argv, &dbdata,
77                                                   "log", dlz_bind9_log_wrapper, NULL), ISC_R_SUCCESS,
78                 "Failed to create samba_dlz");
79
80         dlz_destroy(dbdata);
81
82         return true;
83 }
84
85 static isc_result_t dlz_bind9_writeable_zone_hook(dns_view_t *view,
86                                            const char *zone_name)
87 {
88         struct torture_context *tctx = talloc_get_type((void *)view, struct torture_context);
89         struct ldb_context *samdb = NULL;
90         char *errstring = NULL;
91         int ret = samdb_connect_url(tctx, NULL, tctx->lp_ctx,
92                                     system_session(tctx->lp_ctx),
93                                     0,
94                                     test_dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
95                                     &samdb, &errstring);
96         struct ldb_message *msg;
97         const char *attrs[] = {
98                 NULL
99         };
100         if (ret != LDB_SUCCESS) {
101                 torture_fail(tctx, "Failed to connect to samdb");
102                 return ISC_R_FAILURE;
103         }
104
105         ret = dsdb_search_one(samdb, tctx, &msg, NULL,
106                               LDB_SCOPE_SUBTREE, attrs, DSDB_SEARCH_SEARCH_ALL_PARTITIONS,
107                               "(&(objectClass=dnsZone)(name=%s))", zone_name);
108         if (ret != LDB_SUCCESS) {
109                 torture_fail(tctx, talloc_asprintf(tctx, "Failed to search for %s: %s", zone_name, ldb_errstring(samdb)));
110                 return ISC_R_FAILURE;
111         }
112         talloc_free(msg);
113
114         return ISC_R_SUCCESS;
115 }
116
117 static bool test_dlz_bind9_configure(struct torture_context *tctx)
118 {
119         void *dbdata;
120         const char *argv[] = {
121                 "samba_dlz",
122                 "-H",
123                 test_dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
124                 NULL
125         };
126         tctx_static = tctx;
127         torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, argv, &dbdata,
128                                                   "log", dlz_bind9_log_wrapper,
129                                                   "writeable_zone", dlz_bind9_writeable_zone_hook, NULL),
130                                  ISC_R_SUCCESS,
131                                  "Failed to create samba_dlz");
132
133         torture_assert_int_equal(tctx, dlz_configure((void*)tctx, dbdata),
134                                                      ISC_R_SUCCESS,
135                                  "Failed to configure samba_dlz");
136
137         dlz_destroy(dbdata);
138
139         return true;
140 }
141
142 /*
143  * Test that a ticket obtained for the DNS service will be accepted on the Samba DLZ side
144  *
145  */
146 static bool test_dlz_bind9_gensec(struct torture_context *tctx, const char *mech)
147 {
148         NTSTATUS status;
149
150         struct gensec_security *gensec_client_context;
151
152         DATA_BLOB client_to_server, server_to_client;
153
154         void *dbdata;
155         const char *argv[] = {
156                 "samba_dlz",
157                 "-H",
158                 test_dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
159                 NULL
160         };
161         tctx_static = tctx;
162         torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, argv, &dbdata,
163                                                   "log", dlz_bind9_log_wrapper,
164                                                   "writeable_zone", dlz_bind9_writeable_zone_hook, NULL),
165                                  ISC_R_SUCCESS,
166                                  "Failed to create samba_dlz");
167
168         torture_assert_int_equal(tctx, dlz_configure((void*)tctx, dbdata),
169                                                      ISC_R_SUCCESS,
170                                  "Failed to configure samba_dlz");
171
172         status = gensec_client_start(tctx, &gensec_client_context,
173                                      lpcfg_gensec_settings(tctx, tctx->lp_ctx));
174         torture_assert_ntstatus_ok(tctx, status, "gensec_client_start (client) failed");
175
176         /*
177          * dlz_bind9 use the special dns/host.domain account
178          */
179         status = gensec_set_target_hostname(gensec_client_context,
180                                             talloc_asprintf(tctx,
181                                 "%s.%s",
182                                 torture_setting_string(tctx, "host", NULL),
183                                 lpcfg_dnsdomain(tctx->lp_ctx)));
184         torture_assert_ntstatus_ok(tctx, status, "gensec_set_target_hostname (client) failed");
185
186         status = gensec_set_target_service(gensec_client_context, "dns");
187         torture_assert_ntstatus_ok(tctx, status, "gensec_set_target_service failed");
188
189         status = gensec_set_credentials(gensec_client_context,
190                         popt_get_cmdline_credentials());
191         torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (client) failed");
192
193         status = gensec_start_mech_by_sasl_name(gensec_client_context, mech);
194         torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (client) failed");
195
196         server_to_client = data_blob(NULL, 0);
197
198         /* Do one step of the client-server update dance */
199         status = gensec_update(gensec_client_context, tctx, server_to_client, &client_to_server);
200         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {;
201                 torture_assert_ntstatus_ok(tctx, status, "gensec_update (client) failed");
202         }
203
204         torture_assert_int_equal(tctx, dlz_ssumatch(
205                                         cli_credentials_get_username(
206                                                 popt_get_cmdline_credentials()),
207                                         lpcfg_dnsdomain(tctx->lp_ctx),
208                                         "127.0.0.1", "type", "key",
209                                         client_to_server.length,
210                                         client_to_server.data,
211                                         dbdata),
212                                         ISC_TRUE,
213                          "Failed to check key for update rights samba_dlz");
214
215         dlz_destroy(dbdata);
216
217         return true;
218 }
219
220 static bool test_dlz_bind9_gssapi(struct torture_context *tctx)
221 {
222         return test_dlz_bind9_gensec(tctx, "GSSAPI");
223 }
224
225 static bool test_dlz_bind9_spnego(struct torture_context *tctx)
226 {
227         return test_dlz_bind9_gensec(tctx, "GSS-SPNEGO");
228 }
229
230 struct test_expected_record {
231         const char *name;
232         const char *type;
233         const char *data;
234         int ttl;
235         bool printed;
236 };
237
238 struct test_expected_rr {
239         struct torture_context *tctx;
240         const char *query_name;
241         size_t num_records;
242         struct test_expected_record *records;
243         size_t num_rr;
244 };
245
246 static bool dlz_bind9_putnamedrr_torture_hook(struct test_expected_rr *expected,
247                                               const char *name,
248                                               const char *type,
249                                               dns_ttl_t ttl,
250                                               const char *data)
251 {
252         size_t i;
253
254         torture_assert(expected->tctx, name != NULL,
255                        talloc_asprintf(expected->tctx,
256                        "Got unnamed record type[%s] data[%s]\n",
257                        type, data));
258
259         expected->num_rr++;
260         torture_comment(expected->tctx, "%u: name[%s] type[%s] ttl[%u] data[%s]\n",
261                         (unsigned)expected->num_rr, name, type, (unsigned)ttl, data);
262
263         for (i = 0; i < expected->num_records; i++) {
264                 if (expected->records[i].name != NULL) {
265                         if (strcmp(name, expected->records[i].name) != 0) {
266                                 continue;
267                         }
268                 }
269
270                 if (strcmp(type, expected->records[i].type) != 0) {
271                         continue;
272                 }
273
274                 if (expected->records[i].data != NULL) {
275                         if (strcmp(data, expected->records[i].data) != 0) {
276                                 continue;
277                         }
278                 }
279
280                 torture_assert_int_equal(expected->tctx, ttl,
281                                          expected->records[i].ttl,
282                                          talloc_asprintf(expected->tctx,
283                                          "TTL did not match expectations for type %s",
284                                          type));
285
286                 expected->records[i].printed = true;
287         }
288
289         return true;
290 }
291
292 static isc_result_t dlz_bind9_putrr_hook(dns_sdlzlookup_t *lookup,
293                                          const char *type,
294                                          dns_ttl_t ttl,
295                                          const char *data)
296 {
297         struct test_expected_rr *expected =
298                 talloc_get_type_abort(lookup, struct test_expected_rr);
299         bool ok;
300
301         ok = dlz_bind9_putnamedrr_torture_hook(expected, expected->query_name,
302                                                type, ttl, data);
303         if (!ok) {
304                 return ISC_R_FAILURE;
305         }
306
307         return ISC_R_SUCCESS;
308 }
309
310 static isc_result_t dlz_bind9_putnamedrr_hook(dns_sdlzallnodes_t *allnodes,
311                                               const char *name,
312                                               const char *type,
313                                               dns_ttl_t ttl,
314                                               const char *data)
315 {
316         struct test_expected_rr *expected =
317                 talloc_get_type_abort(allnodes, struct test_expected_rr);
318         bool ok;
319
320         ok = dlz_bind9_putnamedrr_torture_hook(expected, name, type, ttl, data);
321         if (!ok) {
322                 return ISC_R_FAILURE;
323         }
324
325         return ISC_R_SUCCESS;
326 }
327
328 /*
329  * Tests some lookups
330  */
331 static bool test_dlz_bind9_lookup(struct torture_context *tctx)
332 {
333         size_t i;
334         void *dbdata;
335         const char *argv[] = {
336                 "samba_dlz",
337                 "-H",
338                 test_dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
339                 NULL
340         };
341         struct test_expected_rr *expected1 = NULL;
342         struct test_expected_rr *expected2 = NULL;
343
344         tctx_static = tctx;
345         torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, argv, &dbdata,
346                                                   "log", dlz_bind9_log_wrapper,
347                                                   "writeable_zone", dlz_bind9_writeable_zone_hook,
348                                                   "putrr", dlz_bind9_putrr_hook,
349                                                   "putnamedrr", dlz_bind9_putnamedrr_hook,
350                                                   NULL),
351                                  ISC_R_SUCCESS,
352                                  "Failed to create samba_dlz");
353
354         torture_assert_int_equal(tctx, dlz_configure((void*)tctx, dbdata),
355                                                      ISC_R_SUCCESS,
356                                  "Failed to configure samba_dlz");
357
358         expected1 = talloc_zero(tctx, struct test_expected_rr);
359         torture_assert(tctx, expected1 != NULL, "talloc failed");
360         expected1->tctx = tctx;
361
362         expected1->query_name = "@";
363
364         expected1->num_records = 4;
365         expected1->records = talloc_zero_array(expected1,
366                                                struct test_expected_record,
367                                                expected1->num_records);
368         torture_assert(tctx, expected1->records != NULL, "talloc failed");
369
370         expected1->records[0].name = expected1->query_name;
371         expected1->records[0].type = "soa";
372         expected1->records[0].ttl = 3600;
373         expected1->records[0].data = talloc_asprintf(expected1->records,
374                                 "%s.%s. hostmaster.%s. 1 900 600 86400 3600",
375                                 torture_setting_string(tctx, "host", NULL),
376                                 lpcfg_dnsdomain(tctx->lp_ctx),
377                                 lpcfg_dnsdomain(tctx->lp_ctx));
378         torture_assert(tctx, expected1->records[0].data != NULL, "talloc failed");
379
380         expected1->records[1].name = expected1->query_name;
381         expected1->records[1].type = "ns";
382         expected1->records[1].ttl = 900;
383         expected1->records[1].data = talloc_asprintf(expected1->records, "%s.%s.",
384                                 torture_setting_string(tctx, "host", NULL),
385                                 lpcfg_dnsdomain(tctx->lp_ctx));
386         torture_assert(tctx, expected1->records[1].data != NULL, "talloc failed");
387
388         expected1->records[2].name = expected1->query_name;
389         expected1->records[2].type = "aaaa";
390         expected1->records[2].ttl = 900;
391
392         expected1->records[3].name = expected1->query_name;
393         expected1->records[3].type = "a";
394         expected1->records[3].ttl = 900;
395
396         torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx),
397                                                   expected1->query_name, dbdata,
398                                                   (dns_sdlzlookup_t *)expected1),
399                                  ISC_R_SUCCESS,
400                                  "Failed to lookup @");
401         for (i = 0; i < expected1->num_records; i++) {
402                 torture_assert(tctx, expected1->records[i].printed,
403                                talloc_asprintf(tctx,
404                                "Failed to have putrr callback run for type %s",
405                                expected1->records[i].type));
406         }
407         torture_assert_int_equal(tctx, expected1->num_rr,
408                                  expected1->num_records,
409                                  "Got too much data");
410
411         expected2 = talloc_zero(tctx, struct test_expected_rr);
412         torture_assert(tctx, expected2 != NULL, "talloc failed");
413         expected2->tctx = tctx;
414
415         expected2->query_name = torture_setting_string(tctx, "host", NULL);
416         torture_assert(tctx, expected2->query_name != NULL, "unknown host");
417
418         expected2->num_records = 2;
419         expected2->records = talloc_zero_array(expected2,
420                                                struct test_expected_record,
421                                                expected2->num_records);
422         torture_assert(tctx, expected2->records != NULL, "talloc failed");
423
424         expected2->records[0].name = expected2->query_name;
425         expected2->records[0].type = "aaaa";
426         expected2->records[0].ttl = 900;
427
428         expected2->records[1].name = expected2->query_name;
429         expected2->records[1].type = "a";
430         expected2->records[1].ttl = 900;
431
432         torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx),
433                                                   expected2->query_name, dbdata,
434                                                   (dns_sdlzlookup_t *)expected2),
435                                  ISC_R_SUCCESS,
436                                  "Failed to lookup hostname");
437         for (i = 0; i < expected2->num_records; i++) {
438                 torture_assert(tctx, expected2->records[i].printed,
439                                talloc_asprintf(tctx,
440                                "Failed to have putrr callback run name[%s] for type %s",
441                                expected2->records[i].name,
442                                expected2->records[i].type));
443         }
444         torture_assert_int_equal(tctx, expected2->num_rr,
445                                  expected2->num_records,
446                                  "Got too much data");
447
448         dlz_destroy(dbdata);
449
450         return true;
451 }
452
453 /*
454  * Test some zone dumps
455  */
456 static bool test_dlz_bind9_zonedump(struct torture_context *tctx)
457 {
458         size_t i;
459         void *dbdata;
460         const char *argv[] = {
461                 "samba_dlz",
462                 "-H",
463                 test_dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
464                 NULL
465         };
466         struct test_expected_rr *expected1 = NULL;
467
468         tctx_static = tctx;
469         torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, argv, &dbdata,
470                                                   "log", dlz_bind9_log_wrapper,
471                                                   "writeable_zone", dlz_bind9_writeable_zone_hook,
472                                                   "putrr", dlz_bind9_putrr_hook,
473                                                   "putnamedrr", dlz_bind9_putnamedrr_hook,
474                                                   NULL),
475                                  ISC_R_SUCCESS,
476                                  "Failed to create samba_dlz");
477
478         torture_assert_int_equal(tctx, dlz_configure((void*)tctx, dbdata),
479                                                      ISC_R_SUCCESS,
480                                  "Failed to configure samba_dlz");
481
482         expected1 = talloc_zero(tctx, struct test_expected_rr);
483         torture_assert(tctx, expected1 != NULL, "talloc failed");
484         expected1->tctx = tctx;
485
486         expected1->num_records = 7;
487         expected1->records = talloc_zero_array(expected1,
488                                                struct test_expected_record,
489                                                expected1->num_records);
490         torture_assert(tctx, expected1->records != NULL, "talloc failed");
491
492         expected1->records[0].name = talloc_asprintf(expected1->records,
493                                 "%s.", lpcfg_dnsdomain(tctx->lp_ctx));
494         expected1->records[0].type = "soa";
495         expected1->records[0].ttl = 3600;
496         expected1->records[0].data = talloc_asprintf(expected1->records,
497                                 "%s.%s. hostmaster.%s. 1 900 600 86400 3600",
498                                 torture_setting_string(tctx, "host", NULL),
499                                 lpcfg_dnsdomain(tctx->lp_ctx),
500                                 lpcfg_dnsdomain(tctx->lp_ctx));
501         torture_assert(tctx, expected1->records[0].data != NULL, "talloc failed");
502
503         expected1->records[1].name = talloc_asprintf(expected1->records,
504                                 "%s.", lpcfg_dnsdomain(tctx->lp_ctx));
505         expected1->records[1].type = "ns";
506         expected1->records[1].ttl = 900;
507         expected1->records[1].data = talloc_asprintf(expected1->records, "%s.%s.",
508                                 torture_setting_string(tctx, "host", NULL),
509                                 lpcfg_dnsdomain(tctx->lp_ctx));
510         torture_assert(tctx, expected1->records[1].data != NULL, "talloc failed");
511
512         expected1->records[2].name = talloc_asprintf(expected1->records,
513                                 "%s.", lpcfg_dnsdomain(tctx->lp_ctx));
514         expected1->records[2].type = "aaaa";
515         expected1->records[2].ttl = 900;
516
517         expected1->records[3].name = talloc_asprintf(expected1->records,
518                                 "%s.", lpcfg_dnsdomain(tctx->lp_ctx));
519         expected1->records[3].type = "a";
520         expected1->records[3].ttl = 900;
521
522         expected1->records[4].name = talloc_asprintf(expected1->records, "%s.%s.",
523                                 torture_setting_string(tctx, "host", NULL),
524                                 lpcfg_dnsdomain(tctx->lp_ctx));
525         torture_assert(tctx, expected1->records[4].name != NULL, "unknown host");
526         expected1->records[4].type = "aaaa";
527         expected1->records[4].ttl = 900;
528
529         expected1->records[5].name = talloc_asprintf(expected1->records, "%s.%s.",
530                                 torture_setting_string(tctx, "host", NULL),
531                                 lpcfg_dnsdomain(tctx->lp_ctx));
532         torture_assert(tctx, expected1->records[5].name != NULL, "unknown host");
533         expected1->records[5].type = "a";
534         expected1->records[5].ttl = 900;
535
536         /*
537          * We expect multiple srv records
538          */
539         expected1->records[6].name = NULL;
540         expected1->records[6].type = "srv";
541         expected1->records[6].ttl = 900;
542
543         torture_assert_int_equal(tctx, dlz_allnodes(lpcfg_dnsdomain(tctx->lp_ctx),
544                                                     dbdata, (dns_sdlzallnodes_t *)expected1),
545                                  ISC_R_SUCCESS,
546                                  "Failed to configure samba_dlz");
547         for (i = 0; i < expected1->num_records; i++) {
548                 torture_assert(tctx, expected1->records[i].printed,
549                                talloc_asprintf(tctx,
550                                "Failed to have putrr callback run name[%s] for type %s",
551                                expected1->records[i].name,
552                                expected1->records[i].type));
553         }
554         torture_assert_int_equal(tctx, expected1->num_rr, 24,
555                                  "Got wrong record count");
556
557         dlz_destroy(dbdata);
558
559         return true;
560 }
561
562 /*
563  * Test some updates
564  */
565 static bool test_dlz_bind9_update01(struct torture_context *tctx)
566 {
567         NTSTATUS status;
568         struct gensec_security *gensec_client_context;
569         DATA_BLOB client_to_server, server_to_client;
570         void *dbdata;
571         void *version = NULL;
572         const char *argv[] = {
573                 "samba_dlz",
574                 "-H",
575                 test_dlz_bind9_binddns_dir(tctx, "dns/sam.ldb"),
576                 NULL
577         };
578         struct test_expected_rr *expected1 = NULL;
579         char *name = NULL;
580         char *data0 = NULL;
581         char *data1 = NULL;
582         char *data2 = NULL;
583         bool ret = false;
584
585         tctx_static = tctx;
586         torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, argv, &dbdata,
587                                                   "log", dlz_bind9_log_wrapper,
588                                                   "writeable_zone", dlz_bind9_writeable_zone_hook,
589                                                   "putrr", dlz_bind9_putrr_hook,
590                                                   "putnamedrr", dlz_bind9_putnamedrr_hook,
591                                                   NULL),
592                                  ISC_R_SUCCESS,
593                                  "Failed to create samba_dlz");
594
595         torture_assert_int_equal(tctx, dlz_configure((void*)tctx, dbdata),
596                                                      ISC_R_SUCCESS,
597                                  "Failed to configure samba_dlz");
598
599         expected1 = talloc_zero(tctx, struct test_expected_rr);
600         torture_assert(tctx, expected1 != NULL, "talloc failed");
601         expected1->tctx = tctx;
602
603         expected1->query_name = __func__;
604
605         name = talloc_asprintf(expected1, "%s.%s",
606                                 expected1->query_name,
607                                 lpcfg_dnsdomain(tctx->lp_ctx));
608         torture_assert(tctx, name != NULL, "talloc failed");
609
610         expected1->num_records = 2;
611         expected1->records = talloc_zero_array(expected1,
612                                                struct test_expected_record,
613                                                expected1->num_records);
614         torture_assert(tctx, expected1->records != NULL, "talloc failed");
615
616         expected1->records[0].name = expected1->query_name;
617         expected1->records[0].type = "a";
618         expected1->records[0].ttl = 3600;
619         expected1->records[0].data = "127.1.2.3";
620         expected1->records[0].printed = false;
621
622         data0 = talloc_asprintf(expected1,
623                                 "%s.\t" "%u\t" "%s\t" "%s\t" "%s",
624                                 name,
625                                 (unsigned)expected1->records[0].ttl,
626                                 "in",
627                                 expected1->records[0].type,
628                                 expected1->records[0].data);
629         torture_assert(tctx, data0 != NULL, "talloc failed");
630
631         expected1->records[1].name = expected1->query_name;
632         expected1->records[1].type = "a";
633         expected1->records[1].ttl = 3600;
634         expected1->records[1].data = "127.3.2.1";
635         expected1->records[1].printed = false;
636
637         data1 = talloc_asprintf(expected1,
638                                 "%s.\t" "%u\t" "%s\t" "%s\t" "%s",
639                                 name,
640                                 (unsigned)expected1->records[1].ttl,
641                                 "in",
642                                 expected1->records[1].type,
643                                 expected1->records[1].data);
644         torture_assert(tctx, data1 != NULL, "talloc failed");
645
646         data2 = talloc_asprintf(expected1,
647                                 "%s.\t" "0\t" "in\t" "a\t" "127.3.3.3",
648                                 name);
649         torture_assert(tctx, data2 != NULL, "talloc failed");
650
651         /*
652          * Prepare session info
653          */
654         status = gensec_client_start(tctx, &gensec_client_context,
655                                      lpcfg_gensec_settings(tctx, tctx->lp_ctx));
656         torture_assert_ntstatus_ok(tctx, status, "gensec_client_start (client) failed");
657
658         /*
659          * dlz_bind9 use the special dns/host.domain account
660          */
661         status = gensec_set_target_hostname(gensec_client_context,
662                                             talloc_asprintf(tctx,
663                                 "%s.%s",
664                                 torture_setting_string(tctx, "host", NULL),
665                                 lpcfg_dnsdomain(tctx->lp_ctx)));
666         torture_assert_ntstatus_ok(tctx, status, "gensec_set_target_hostname (client) failed");
667
668         status = gensec_set_target_service(gensec_client_context, "dns");
669         torture_assert_ntstatus_ok(tctx, status, "gensec_set_target_service failed");
670
671         status = gensec_set_credentials(gensec_client_context,
672                         popt_get_cmdline_credentials());
673         torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (client) failed");
674
675         status = gensec_start_mech_by_sasl_name(gensec_client_context, "GSS-SPNEGO");
676         torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (client) failed");
677
678         server_to_client = data_blob(NULL, 0);
679
680         /* Do one step of the client-server update dance */
681         status = gensec_update(gensec_client_context, tctx, server_to_client, &client_to_server);
682         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {;
683                 torture_assert_ntstatus_ok(tctx, status, "gensec_update (client) failed");
684         }
685
686         torture_assert_int_equal(tctx, dlz_ssumatch(
687                                 cli_credentials_get_username(
688                                         popt_get_cmdline_credentials()),
689                                 name,
690                                 "127.0.0.1",
691                                 expected1->records[0].type,
692                                 "key",
693                                 client_to_server.length,
694                                 client_to_server.data,
695                                 dbdata),
696                                 ISC_TRUE,
697                          "Failed to check key for update rights samba_dlz");
698
699         /*
700          * We test the following:
701          *
702          *  1. lookup the records => NOT_FOUND
703          *  2. delete all records => NOT_FOUND
704          *  3. delete 1st record => NOT_FOUND
705          *  4. create 1st record => SUCCESS
706          *  5. lookup the records => found 1st
707          *  6. create 2nd record => SUCCESS
708          *  7. lookup the records => found 1st and 2nd
709          *  8. delete unknown record => NOT_FOUND
710          *  9. lookup the records => found 1st and 2nd
711          * 10. delete 1st record => SUCCESS
712          * 11. lookup the records => found 2nd
713          * 12. delete 2nd record => SUCCESS
714          * 13. lookup the records => NOT_FOUND
715          * 14. create 1st record => SUCCESS
716          * 15. lookup the records => found 1st
717          * 16. create 2nd record => SUCCESS
718          * 17. lookup the records => found 1st and 2nd
719          * 18. update 1st record => SUCCESS
720          * 19. lookup the records => found 1st and 2nd
721          * 20. delete all unknown type records => NOT_FOUND
722          * 21. lookup the records => found 1st and 2nd
723          * 22. delete all records => SUCCESS
724          * 23. lookup the records => NOT_FOUND
725          */
726
727         /* Step 1. */
728         expected1->num_rr = 0;
729         expected1->records[0].printed = false;
730         expected1->records[1].printed = false;
731         torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx),
732                                                   expected1->query_name, dbdata,
733                                                   (dns_sdlzlookup_t *)expected1),
734                                  ISC_R_NOTFOUND,
735                                  "Found hostname");
736         torture_assert_int_equal(tctx, expected1->num_rr, 0,
737                                  "Got wrong record count");
738
739         /* Step 2. */
740         torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx),
741                                                       dbdata, &version),
742                                  ISC_R_SUCCESS,
743                                  "Failed to start transaction");
744         torture_assert_int_equal_goto(tctx,
745                         dlz_delrdataset(name,
746                                         expected1->records[0].type,
747                                         dbdata, version),
748                         ISC_R_NOTFOUND, ret, cancel_version,
749                         talloc_asprintf(tctx, "Deleted name[%s] type[%s]\n",
750                         name, expected1->records[0].type));
751         dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), false, dbdata, &version);
752
753         /* Step 3. */
754         torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx),
755                                                       dbdata, &version),
756                                  ISC_R_SUCCESS,
757                                  "Failed to start transaction");
758         torture_assert_int_equal_goto(tctx,
759                         dlz_subrdataset(name, data0, dbdata, version),
760                         ISC_R_NOTFOUND, ret, cancel_version,
761                         talloc_asprintf(tctx, "Deleted name[%s] data[%s]\n",
762                         name, data0));
763         dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), false, dbdata, &version);
764
765         /* Step 4. */
766         torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx),
767                                                       dbdata, &version),
768                                  ISC_R_SUCCESS,
769                                  "Failed to start transaction");
770         torture_assert_int_equal_goto(tctx,
771                         dlz_addrdataset(name, data0, dbdata, version),
772                         ISC_R_SUCCESS, ret, cancel_version,
773                         talloc_asprintf(tctx, "Failed to add name[%s] data[%s]\n",
774                         name, data0));
775         dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version);
776
777         /* Step 5. */
778         expected1->num_rr = 0;
779         expected1->records[0].printed = false;
780         expected1->records[1].printed = false;
781         torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx),
782                                                   expected1->query_name, dbdata,
783                                                   (dns_sdlzlookup_t *)expected1),
784                                  ISC_R_SUCCESS,
785                                  "Not found hostname");
786         torture_assert(tctx, expected1->records[0].printed,
787                        talloc_asprintf(tctx,
788                        "Failed to have putrr callback run name[%s] for type %s",
789                        expected1->records[0].name,
790                        expected1->records[0].type));
791         torture_assert_int_equal(tctx, expected1->num_rr, 1,
792                                  "Got wrong record count");
793
794         /* Step 6. */
795         torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx),
796                                                       dbdata, &version),
797                                  ISC_R_SUCCESS,
798                                  "Failed to start transaction");
799         torture_assert_int_equal_goto(tctx,
800                         dlz_addrdataset(name, data1, dbdata, version),
801                         ISC_R_SUCCESS, ret, cancel_version,
802                         talloc_asprintf(tctx, "Failed to add name[%s] data[%s]\n",
803                         name, data1));
804         dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version);
805
806         /* Step 7. */
807         expected1->num_rr = 0;
808         expected1->records[0].printed = false;
809         expected1->records[1].printed = false;
810         torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx),
811                                                   expected1->query_name, dbdata,
812                                                   (dns_sdlzlookup_t *)expected1),
813                                  ISC_R_SUCCESS,
814                                  "Not found hostname");
815         torture_assert(tctx, expected1->records[0].printed,
816                        talloc_asprintf(tctx,
817                        "Failed to have putrr callback run name[%s] for type %s",
818                        expected1->records[0].name,
819                        expected1->records[0].type));
820         torture_assert(tctx, expected1->records[1].printed,
821                        talloc_asprintf(tctx,
822                        "Failed to have putrr callback run name[%s] for type %s",
823                        expected1->records[1].name,
824                        expected1->records[1].type));
825         torture_assert_int_equal(tctx, expected1->num_rr, 2,
826                                  "Got wrong record count");
827
828         /* Step 8. */
829         torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx),
830                                                       dbdata, &version),
831                                  ISC_R_SUCCESS,
832                                  "Failed to start transaction");
833         torture_assert_int_equal_goto(tctx,
834                         dlz_subrdataset(name, data2, dbdata, version),
835                         ISC_R_NOTFOUND, ret, cancel_version,
836                         talloc_asprintf(tctx, "Deleted name[%s] data[%s]\n",
837                         name, data2));
838         dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version);
839
840         /* Step 9. */
841         expected1->num_rr = 0;
842         expected1->records[0].printed = false;
843         expected1->records[1].printed = false;
844         torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx),
845                                                   expected1->query_name, dbdata,
846                                                   (dns_sdlzlookup_t *)expected1),
847                                  ISC_R_SUCCESS,
848                                  "Not found hostname");
849         torture_assert(tctx, expected1->records[0].printed,
850                        talloc_asprintf(tctx,
851                        "Failed to have putrr callback run name[%s] for type %s",
852                        expected1->records[0].name,
853                        expected1->records[0].type));
854         torture_assert(tctx, expected1->records[1].printed,
855                        talloc_asprintf(tctx,
856                        "Failed to have putrr callback run name[%s] for type %s",
857                        expected1->records[1].name,
858                        expected1->records[1].type));
859         torture_assert_int_equal(tctx, expected1->num_rr, 2,
860                                  "Got wrong record count");
861
862         /* Step 10. */
863         torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx),
864                                                       dbdata, &version),
865                                  ISC_R_SUCCESS,
866                                  "Failed to start transaction");
867         torture_assert_int_equal_goto(tctx,
868                         dlz_subrdataset(name, data0, dbdata, version),
869                         ISC_R_SUCCESS, ret, cancel_version,
870                         talloc_asprintf(tctx, "Failed to delete name[%s] data[%s]\n",
871                         name, data0));
872         dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version);
873
874         /* Step 11. */
875         expected1->num_rr = 0;
876         expected1->records[0].printed = false;
877         expected1->records[1].printed = false;
878         torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx),
879                                                   expected1->query_name, dbdata,
880                                                   (dns_sdlzlookup_t *)expected1),
881                                  ISC_R_SUCCESS,
882                                  "Not found hostname");
883         torture_assert(tctx, expected1->records[1].printed,
884                        talloc_asprintf(tctx,
885                        "Failed to have putrr callback run name[%s] for type %s",
886                        expected1->records[1].name,
887                        expected1->records[1].type));
888         torture_assert_int_equal(tctx, expected1->num_rr, 1,
889                                  "Got wrong record count");
890
891         /* Step 12. */
892         torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx),
893                                                       dbdata, &version),
894                                  ISC_R_SUCCESS,
895                                  "Failed to start transaction");
896         torture_assert_int_equal_goto(tctx,
897                         dlz_subrdataset(name, data1, dbdata, version),
898                         ISC_R_SUCCESS, ret, cancel_version,
899                         talloc_asprintf(tctx, "Failed to delete name[%s] data[%s]\n",
900                         name, data1));
901         dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version);
902
903         /* Step 13. */
904         expected1->num_rr = 0;
905         expected1->records[0].printed = false;
906         expected1->records[1].printed = false;
907         torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx),
908                                                   expected1->query_name, dbdata,
909                                                   (dns_sdlzlookup_t *)expected1),
910                                  ISC_R_NOTFOUND,
911                                  "Found hostname");
912         torture_assert_int_equal(tctx, expected1->num_rr, 0,
913                                  "Got wrong record count");
914
915         /* Step 14. */
916         torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx),
917                                                       dbdata, &version),
918                                  ISC_R_SUCCESS,
919                                  "Failed to start transaction");
920         torture_assert_int_equal_goto(tctx,
921                         dlz_addrdataset(name, data0, dbdata, version),
922                         ISC_R_SUCCESS, ret, cancel_version,
923                         talloc_asprintf(tctx, "Failed to add name[%s] data[%s]\n",
924                         name, data0));
925         dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version);
926
927         /* Step 15. */
928         expected1->num_rr = 0;
929         expected1->records[0].printed = false;
930         expected1->records[1].printed = false;
931         torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx),
932                                                   expected1->query_name, dbdata,
933                                                   (dns_sdlzlookup_t *)expected1),
934                                  ISC_R_SUCCESS,
935                                  "Not found hostname");
936         torture_assert(tctx, expected1->records[0].printed,
937                        talloc_asprintf(tctx,
938                        "Failed to have putrr callback run name[%s] for type %s",
939                        expected1->records[0].name,
940                        expected1->records[0].type));
941         torture_assert_int_equal(tctx, expected1->num_rr, 1,
942                                  "Got wrong record count");
943
944         /* Step 16. */
945         torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx),
946                                                       dbdata, &version),
947                                  ISC_R_SUCCESS,
948                                  "Failed to start transaction");
949         torture_assert_int_equal_goto(tctx,
950                         dlz_addrdataset(name, data1, dbdata, version),
951                         ISC_R_SUCCESS, ret, cancel_version,
952                         talloc_asprintf(tctx, "Failed to add name[%s] data[%s]\n",
953                         name, data1));
954         dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version);
955
956         /* Step 17. */
957         expected1->num_rr = 0;
958         expected1->records[0].printed = false;
959         expected1->records[1].printed = false;
960         torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx),
961                                                   expected1->query_name, dbdata,
962                                                   (dns_sdlzlookup_t *)expected1),
963                                  ISC_R_SUCCESS,
964                                  "Not found hostname");
965         torture_assert(tctx, expected1->records[0].printed,
966                        talloc_asprintf(tctx,
967                        "Failed to have putrr callback run name[%s] for type %s",
968                        expected1->records[0].name,
969                        expected1->records[0].type));
970         torture_assert(tctx, expected1->records[1].printed,
971                        talloc_asprintf(tctx,
972                        "Failed to have putrr callback run name[%s] for type %s",
973                        expected1->records[1].name,
974                        expected1->records[1].type));
975         torture_assert_int_equal(tctx, expected1->num_rr, 2,
976                                  "Got wrong record count");
977
978         /* Step 18. */
979         torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx),
980                                                       dbdata, &version),
981                                  ISC_R_SUCCESS,
982                                  "Failed to start transaction");
983         torture_assert_int_equal_goto(tctx,
984                         dlz_addrdataset(name, data0, dbdata, version),
985                         ISC_R_SUCCESS, ret, cancel_version,
986                         talloc_asprintf(tctx, "Failed to update name[%s] data[%s]\n",
987                         name, data0));
988         dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version);
989
990         /* Step 19. */
991         expected1->num_rr = 0;
992         expected1->records[0].printed = false;
993         expected1->records[1].printed = false;
994         torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx),
995                                                   expected1->query_name, dbdata,
996                                                   (dns_sdlzlookup_t *)expected1),
997                                  ISC_R_SUCCESS,
998                                  "Not found hostname");
999         torture_assert(tctx, expected1->records[0].printed,
1000                        talloc_asprintf(tctx,
1001                        "Failed to have putrr callback run name[%s] for type %s",
1002                        expected1->records[0].name,
1003                        expected1->records[0].type));
1004         torture_assert(tctx, expected1->records[1].printed,
1005                        talloc_asprintf(tctx,
1006                        "Failed to have putrr callback run name[%s] for type %s",
1007                        expected1->records[1].name,
1008                        expected1->records[1].type));
1009         torture_assert_int_equal(tctx, expected1->num_rr, 2,
1010                                  "Got wrong record count");
1011
1012         /* Step 20. */
1013         torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx),
1014                                                       dbdata, &version),
1015                                  ISC_R_SUCCESS,
1016                                  "Failed to start transaction");
1017         torture_assert_int_equal_goto(tctx,
1018                         dlz_delrdataset(name, "txt", dbdata, version),
1019                         ISC_R_FAILURE, ret, cancel_version,
1020                         talloc_asprintf(tctx, "Deleted name[%s] type[%s]\n",
1021                         name, "txt"));
1022         dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), false, dbdata, &version);
1023
1024         /* Step 21. */
1025         expected1->num_rr = 0;
1026         expected1->records[0].printed = false;
1027         expected1->records[1].printed = false;
1028         torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx),
1029                                                   expected1->query_name, dbdata,
1030                                                   (dns_sdlzlookup_t *)expected1),
1031                                  ISC_R_SUCCESS,
1032                                  "Not found hostname");
1033         torture_assert(tctx, expected1->records[0].printed,
1034                        talloc_asprintf(tctx,
1035                        "Failed to have putrr callback run name[%s] for type %s",
1036                        expected1->records[0].name,
1037                        expected1->records[0].type));
1038         torture_assert(tctx, expected1->records[1].printed,
1039                        talloc_asprintf(tctx,
1040                        "Failed to have putrr callback run name[%s] for type %s",
1041                        expected1->records[1].name,
1042                        expected1->records[1].type));
1043         torture_assert_int_equal(tctx, expected1->num_rr, 2,
1044                                  "Got wrong record count");
1045
1046         /* Step 22. */
1047         torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx),
1048                                                       dbdata, &version),
1049                                  ISC_R_SUCCESS,
1050                                  "Failed to start transaction");
1051         torture_assert_int_equal_goto(tctx,
1052                         dlz_delrdataset(name,
1053                                         expected1->records[0].type,
1054                                         dbdata, version),
1055                         ISC_R_SUCCESS, ret, cancel_version,
1056                         talloc_asprintf(tctx, "Failed to delete name[%s] type[%s]\n",
1057                         name, expected1->records[0].type));
1058         dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version);
1059
1060         /* Step 23. */
1061         expected1->num_rr = 0;
1062         expected1->records[0].printed = false;
1063         expected1->records[1].printed = false;
1064         torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx),
1065                                                   expected1->query_name, dbdata,
1066                                                   (dns_sdlzlookup_t *)expected1),
1067                                  ISC_R_NOTFOUND,
1068                                  "Found hostname");
1069         torture_assert_int_equal(tctx, expected1->num_rr, 0,
1070                                  "Got wrong record count");
1071
1072         dlz_destroy(dbdata);
1073
1074         return true;
1075
1076 cancel_version:
1077         dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), false, dbdata, &version);
1078         return ret;
1079 }
1080
1081 static struct torture_suite *dlz_bind9_suite(TALLOC_CTX *ctx)
1082 {
1083         struct torture_suite *suite = torture_suite_create(ctx, "dlz_bind9");
1084
1085         suite->description = talloc_strdup(suite,
1086                                            "Tests for the BIND 9 DLZ module");
1087         torture_suite_add_simple_test(suite, "version", test_dlz_bind9_version);
1088         torture_suite_add_simple_test(suite, "create", test_dlz_bind9_create);
1089         torture_suite_add_simple_test(suite, "configure", test_dlz_bind9_configure);
1090         torture_suite_add_simple_test(suite, "gssapi", test_dlz_bind9_gssapi);
1091         torture_suite_add_simple_test(suite, "spnego", test_dlz_bind9_spnego);
1092         torture_suite_add_simple_test(suite, "lookup", test_dlz_bind9_lookup);
1093         torture_suite_add_simple_test(suite, "zonedump", test_dlz_bind9_zonedump);
1094         torture_suite_add_simple_test(suite, "update01", test_dlz_bind9_update01);
1095         return suite;
1096 }
1097
1098 /**
1099  * DNS torture module initialization
1100  */
1101 NTSTATUS torture_bind_dns_init(TALLOC_CTX *);
1102 NTSTATUS torture_bind_dns_init(TALLOC_CTX *ctx)
1103 {
1104         struct torture_suite *suite;
1105
1106         /* register DNS related test cases */
1107         suite = dlz_bind9_suite(ctx);
1108         if (!suite) return NT_STATUS_NO_MEMORY;
1109         torture_register_suite(ctx, suite);
1110
1111         return NT_STATUS_OK;
1112 }