/* * Test that a ticket obtained for the DNS service will be accepted on the Samba DLZ side * */ static bool test_dlz_bind9_gensec(struct torture_context *tctx, const char *mech) { NTSTATUS status; struct gensec_security *gensec_client_context; DATA_BLOB client_to_server, server_to_client; void *dbdata; const char *argv[] = { "samba_dlz", "-H", lpcfg_private_path(tctx, tctx->lp_ctx, "dns/sam.ldb"), NULL }; tctx_static = tctx; torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, discard_const_p(char *, argv), &dbdata, "log", dlz_bind9_log_wrapper, "writeable_zone", dlz_bind9_writeable_zone_hook, NULL), ISC_R_SUCCESS, "Failed to create samba_dlz"); torture_assert_int_equal(tctx, dlz_configure((void*)tctx, dbdata), ISC_R_SUCCESS, "Failed to configure samba_dlz"); status = gensec_client_start(tctx, &gensec_client_context, lpcfg_gensec_settings(tctx, tctx->lp_ctx)); torture_assert_ntstatus_ok(tctx, status, "gensec_client_start (client) failed"); status = gensec_set_target_hostname(gensec_client_context, torture_setting_string(tctx, "host", NULL)); torture_assert_ntstatus_ok(tctx, status, "gensec_set_target_hostname (client) failed"); status = gensec_set_credentials(gensec_client_context, cmdline_credentials); torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (client) failed"); status = gensec_start_mech_by_sasl_name(gensec_client_context, mech); torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (client) failed"); server_to_client = data_blob(NULL, 0); /* Do one step of the client-server update dance */ status = gensec_update(gensec_client_context, tctx, tctx->ev, server_to_client, &client_to_server); if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {; torture_assert_ntstatus_ok(tctx, status, "gensec_update (client) failed"); } torture_assert_int_equal(tctx, dlz_ssumatch(cli_credentials_get_username(cmdline_credentials), lpcfg_dnsdomain(tctx->lp_ctx), "127.0.0.1", "type", "key", client_to_server.length, client_to_server.data, dbdata), ISC_R_SUCCESS, "Failed to check key for update rights samba_dlz"); dlz_destroy(dbdata); return true; }
/* * Called to initialize the driver */ isc_result_t dlz_create(const char *dlzname, unsigned int argc, char *argv[], void **dbdata, ...) { struct dlz_example_data *state; const char *helper_name; va_list ap; char soa_data[200]; UNUSED(dlzname); state = calloc(1, sizeof(struct dlz_example_data)); if (state == NULL) return (ISC_R_NOMEMORY); /* Fill in the helper functions */ va_start(ap, dbdata); while ((helper_name = va_arg(ap, const char *)) != NULL) { b9_add_helper(state, helper_name, va_arg(ap, void*)); } va_end(ap); if (argc < 2) { state->log(ISC_LOG_ERROR, "dlz_example: please specify a zone name"); dlz_destroy(state); return (ISC_R_FAILURE); } state->zone_name = strdup(argv[1]); sprintf(soa_data, "%s hostmaster.%s 123 900 600 86400 3600", state->zone_name, state->zone_name); add_name(state, &state->current[0], state->zone_name, "soa", 3600, soa_data); add_name(state, &state->current[0], state->zone_name, "ns", 3600, state->zone_name); add_name(state, &state->current[0], state->zone_name, "a", 1800, "10.53.0.1"); state->log(ISC_LOG_INFO, "dlz_example: started for zone %s", state->zone_name); *dbdata = state; return (ISC_R_SUCCESS); }
static bool test_dlz_bind9_create(struct torture_context *tctx) { void *dbdata; const char *argv[] = { "samba_dlz", "-H", lpcfg_private_path(tctx, tctx->lp_ctx, "dns/sam.ldb"), NULL }; tctx_static = tctx; torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, argv, &dbdata, "log", dlz_bind9_log_wrapper, NULL), ISC_R_SUCCESS, "Failed to create samba_dlz"); dlz_destroy(dbdata); return true; }
/* * Test some updates */ static bool test_dlz_bind9_update01(struct torture_context *tctx) { NTSTATUS status; struct gensec_security *gensec_client_context; DATA_BLOB client_to_server, server_to_client; void *dbdata; void *version = NULL; const char *argv[] = { "samba_dlz", "-H", lpcfg_private_path(tctx, tctx->lp_ctx, "dns/sam.ldb"), NULL }; struct test_expected_rr *expected1 = NULL; char *name = NULL; char *data0 = NULL; char *data1 = NULL; char *data2 = NULL; bool ret = false; tctx_static = tctx; torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, argv, &dbdata, "log", dlz_bind9_log_wrapper, "writeable_zone", dlz_bind9_writeable_zone_hook, "putrr", dlz_bind9_putrr_hook, "putnamedrr", dlz_bind9_putnamedrr_hook, NULL), ISC_R_SUCCESS, "Failed to create samba_dlz"); torture_assert_int_equal(tctx, dlz_configure((void*)tctx, dbdata), ISC_R_SUCCESS, "Failed to configure samba_dlz"); expected1 = talloc_zero(tctx, struct test_expected_rr); torture_assert(tctx, expected1 != NULL, "talloc failed"); expected1->tctx = tctx; expected1->query_name = __func__; name = talloc_asprintf(expected1, "%s.%s", expected1->query_name, lpcfg_dnsdomain(tctx->lp_ctx)); torture_assert(tctx, name != NULL, "talloc failed"); expected1->num_records = 2; expected1->records = talloc_zero_array(expected1, struct test_expected_record, expected1->num_records); torture_assert(tctx, expected1->records != NULL, "talloc failed"); expected1->records[0].name = expected1->query_name; expected1->records[0].type = "a"; expected1->records[0].ttl = 3600; expected1->records[0].data = "127.1.2.3"; expected1->records[0].printed = false; data0 = talloc_asprintf(expected1, "%s.\t" "%u\t" "%s\t" "%s\t" "%s", name, (unsigned)expected1->records[0].ttl, "in", expected1->records[0].type, expected1->records[0].data); torture_assert(tctx, data0 != NULL, "talloc failed"); expected1->records[1].name = expected1->query_name; expected1->records[1].type = "a"; expected1->records[1].ttl = 3600; expected1->records[1].data = "127.3.2.1"; expected1->records[1].printed = false; data1 = talloc_asprintf(expected1, "%s.\t" "%u\t" "%s\t" "%s\t" "%s", name, (unsigned)expected1->records[1].ttl, "in", expected1->records[1].type, expected1->records[1].data); torture_assert(tctx, data1 != NULL, "talloc failed"); data2 = talloc_asprintf(expected1, "%s.\t" "0\t" "in\t" "a\t" "127.3.3.3", name); torture_assert(tctx, data2 != NULL, "talloc failed"); /* * Prepare session info */ status = gensec_client_start(tctx, &gensec_client_context, lpcfg_gensec_settings(tctx, tctx->lp_ctx)); torture_assert_ntstatus_ok(tctx, status, "gensec_client_start (client) failed"); /* * dlz_bind9 use the special dns/host.domain account */ status = gensec_set_target_hostname(gensec_client_context, talloc_asprintf(tctx, "%s.%s", torture_setting_string(tctx, "host", NULL), lpcfg_dnsdomain(tctx->lp_ctx))); torture_assert_ntstatus_ok(tctx, status, "gensec_set_target_hostname (client) failed"); status = gensec_set_target_service(gensec_client_context, "dns"); torture_assert_ntstatus_ok(tctx, status, "gensec_set_target_service failed"); status = gensec_set_credentials(gensec_client_context, cmdline_credentials); torture_assert_ntstatus_ok(tctx, status, "gensec_set_credentials (client) failed"); status = gensec_start_mech_by_sasl_name(gensec_client_context, "GSS-SPNEGO"); torture_assert_ntstatus_ok(tctx, status, "gensec_start_mech_by_sasl_name (client) failed"); server_to_client = data_blob(NULL, 0); /* Do one step of the client-server update dance */ status = gensec_update(gensec_client_context, tctx, tctx->ev, server_to_client, &client_to_server); if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {; torture_assert_ntstatus_ok(tctx, status, "gensec_update (client) failed"); } torture_assert_int_equal(tctx, dlz_ssumatch(cli_credentials_get_username(cmdline_credentials), name, "127.0.0.1", expected1->records[0].type, "key", client_to_server.length, client_to_server.data, dbdata), ISC_TRUE, "Failed to check key for update rights samba_dlz"); /* * We test the following: * * 1. lookup the records => NOT_FOUND * 2. delete all records => NOT_FOUND * 3. delete 1st record => NOT_FOUND * 4. create 1st record => SUCCESS * 5. lookup the records => found 1st * 6. create 2nd record => SUCCESS * 7. lookup the records => found 1st and 2nd * 8. delete unknown record => NOT_FOUND * 9. lookup the records => found 1st and 2nd * 10. delete 1st record => SUCCESS * 11. lookup the records => found 2nd * 12. delete 2nd record => SUCCESS * 13. lookup the records => NOT_FOUND * 14. create 1st record => SUCCESS * 15. lookup the records => found 1st * 16. create 2nd record => SUCCESS * 17. lookup the records => found 1st and 2nd * 18. update 1st record => SUCCESS * 19. lookup the records => found 1st and 2nd * 20. delete all unknown type records => NOT_FOUND * 21. lookup the records => found 1st and 2nd * 22. delete all records => SUCCESS * 23. lookup the records => NOT_FOUND */ /* Step 1. */ expected1->num_rr = 0; expected1->records[0].printed = false; expected1->records[1].printed = false; torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx), expected1->query_name, dbdata, (dns_sdlzlookup_t *)expected1), ISC_R_NOTFOUND, "Found hostname"); torture_assert_int_equal(tctx, expected1->num_rr, 0, "Got wrong record count"); /* Step 2. */ torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx), dbdata, &version), ISC_R_SUCCESS, "Failed to start transaction"); torture_assert_int_equal_goto(tctx, dlz_delrdataset(name, expected1->records[0].type, dbdata, version), ISC_R_NOTFOUND, ret, cancel_version, talloc_asprintf(tctx, "Deleted name[%s] type[%s]\n", name, expected1->records[0].type)); dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), false, dbdata, &version); /* Step 3. */ torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx), dbdata, &version), ISC_R_SUCCESS, "Failed to start transaction"); torture_assert_int_equal_goto(tctx, dlz_subrdataset(name, data0, dbdata, version), ISC_R_NOTFOUND, ret, cancel_version, talloc_asprintf(tctx, "Deleted name[%s] data[%s]\n", name, data0)); dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), false, dbdata, &version); /* Step 4. */ torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx), dbdata, &version), ISC_R_SUCCESS, "Failed to start transaction"); torture_assert_int_equal_goto(tctx, dlz_addrdataset(name, data0, dbdata, version), ISC_R_SUCCESS, ret, cancel_version, talloc_asprintf(tctx, "Failed to add name[%s] data[%s]\n", name, data0)); dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version); /* Step 5. */ expected1->num_rr = 0; expected1->records[0].printed = false; expected1->records[1].printed = false; torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx), expected1->query_name, dbdata, (dns_sdlzlookup_t *)expected1), ISC_R_SUCCESS, "Not found hostname"); torture_assert(tctx, expected1->records[0].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[0].name, expected1->records[0].type)); torture_assert_int_equal(tctx, expected1->num_rr, 1, "Got wrong record count"); /* Step 6. */ torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx), dbdata, &version), ISC_R_SUCCESS, "Failed to start transaction"); torture_assert_int_equal_goto(tctx, dlz_addrdataset(name, data1, dbdata, version), ISC_R_SUCCESS, ret, cancel_version, talloc_asprintf(tctx, "Failed to add name[%s] data[%s]\n", name, data1)); dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version); /* Step 7. */ expected1->num_rr = 0; expected1->records[0].printed = false; expected1->records[1].printed = false; torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx), expected1->query_name, dbdata, (dns_sdlzlookup_t *)expected1), ISC_R_SUCCESS, "Not found hostname"); torture_assert(tctx, expected1->records[0].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[0].name, expected1->records[0].type)); torture_assert(tctx, expected1->records[1].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[1].name, expected1->records[1].type)); torture_assert_int_equal(tctx, expected1->num_rr, 2, "Got wrong record count"); /* Step 8. */ torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx), dbdata, &version), ISC_R_SUCCESS, "Failed to start transaction"); torture_assert_int_equal_goto(tctx, dlz_subrdataset(name, data2, dbdata, version), ISC_R_NOTFOUND, ret, cancel_version, talloc_asprintf(tctx, "Deleted name[%s] data[%s]\n", name, data2)); dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version); /* Step 9. */ expected1->num_rr = 0; expected1->records[0].printed = false; expected1->records[1].printed = false; torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx), expected1->query_name, dbdata, (dns_sdlzlookup_t *)expected1), ISC_R_SUCCESS, "Not found hostname"); torture_assert(tctx, expected1->records[0].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[0].name, expected1->records[0].type)); torture_assert(tctx, expected1->records[1].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[1].name, expected1->records[1].type)); torture_assert_int_equal(tctx, expected1->num_rr, 2, "Got wrong record count"); /* Step 10. */ torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx), dbdata, &version), ISC_R_SUCCESS, "Failed to start transaction"); torture_assert_int_equal_goto(tctx, dlz_subrdataset(name, data0, dbdata, version), ISC_R_SUCCESS, ret, cancel_version, talloc_asprintf(tctx, "Failed to delete name[%s] data[%s]\n", name, data0)); dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version); /* Step 11. */ expected1->num_rr = 0; expected1->records[0].printed = false; expected1->records[1].printed = false; torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx), expected1->query_name, dbdata, (dns_sdlzlookup_t *)expected1), ISC_R_SUCCESS, "Not found hostname"); torture_assert(tctx, expected1->records[1].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[1].name, expected1->records[1].type)); torture_assert_int_equal(tctx, expected1->num_rr, 1, "Got wrong record count"); /* Step 12. */ torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx), dbdata, &version), ISC_R_SUCCESS, "Failed to start transaction"); torture_assert_int_equal_goto(tctx, dlz_subrdataset(name, data1, dbdata, version), ISC_R_SUCCESS, ret, cancel_version, talloc_asprintf(tctx, "Failed to delete name[%s] data[%s]\n", name, data1)); dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version); /* Step 13. */ expected1->num_rr = 0; expected1->records[0].printed = false; expected1->records[1].printed = false; torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx), expected1->query_name, dbdata, (dns_sdlzlookup_t *)expected1), ISC_R_NOTFOUND, "Found hostname"); torture_assert_int_equal(tctx, expected1->num_rr, 0, "Got wrong record count"); /* Step 14. */ torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx), dbdata, &version), ISC_R_SUCCESS, "Failed to start transaction"); torture_assert_int_equal_goto(tctx, dlz_addrdataset(name, data0, dbdata, version), ISC_R_SUCCESS, ret, cancel_version, talloc_asprintf(tctx, "Failed to add name[%s] data[%s]\n", name, data0)); dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version); /* Step 15. */ expected1->num_rr = 0; expected1->records[0].printed = false; expected1->records[1].printed = false; torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx), expected1->query_name, dbdata, (dns_sdlzlookup_t *)expected1), ISC_R_SUCCESS, "Not found hostname"); torture_assert(tctx, expected1->records[0].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[0].name, expected1->records[0].type)); torture_assert_int_equal(tctx, expected1->num_rr, 1, "Got wrong record count"); /* Step 16. */ torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx), dbdata, &version), ISC_R_SUCCESS, "Failed to start transaction"); torture_assert_int_equal_goto(tctx, dlz_addrdataset(name, data1, dbdata, version), ISC_R_SUCCESS, ret, cancel_version, talloc_asprintf(tctx, "Failed to add name[%s] data[%s]\n", name, data1)); dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version); /* Step 17. */ expected1->num_rr = 0; expected1->records[0].printed = false; expected1->records[1].printed = false; torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx), expected1->query_name, dbdata, (dns_sdlzlookup_t *)expected1), ISC_R_SUCCESS, "Not found hostname"); torture_assert(tctx, expected1->records[0].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[0].name, expected1->records[0].type)); torture_assert(tctx, expected1->records[1].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[1].name, expected1->records[1].type)); torture_assert_int_equal(tctx, expected1->num_rr, 2, "Got wrong record count"); /* Step 18. */ torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx), dbdata, &version), ISC_R_SUCCESS, "Failed to start transaction"); torture_assert_int_equal_goto(tctx, dlz_addrdataset(name, data0, dbdata, version), ISC_R_SUCCESS, ret, cancel_version, talloc_asprintf(tctx, "Failed to update name[%s] data[%s]\n", name, data0)); dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version); /* Step 19. */ expected1->num_rr = 0; expected1->records[0].printed = false; expected1->records[1].printed = false; torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx), expected1->query_name, dbdata, (dns_sdlzlookup_t *)expected1), ISC_R_SUCCESS, "Not found hostname"); torture_assert(tctx, expected1->records[0].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[0].name, expected1->records[0].type)); torture_assert(tctx, expected1->records[1].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[1].name, expected1->records[1].type)); torture_assert_int_equal(tctx, expected1->num_rr, 2, "Got wrong record count"); /* Step 20. */ torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx), dbdata, &version), ISC_R_SUCCESS, "Failed to start transaction"); torture_assert_int_equal_goto(tctx, dlz_delrdataset(name, "txt", dbdata, version), ISC_R_FAILURE, ret, cancel_version, talloc_asprintf(tctx, "Deleted name[%s] type[%s]\n", name, "txt")); dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), false, dbdata, &version); /* Step 21. */ expected1->num_rr = 0; expected1->records[0].printed = false; expected1->records[1].printed = false; torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx), expected1->query_name, dbdata, (dns_sdlzlookup_t *)expected1), ISC_R_SUCCESS, "Not found hostname"); torture_assert(tctx, expected1->records[0].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[0].name, expected1->records[0].type)); torture_assert(tctx, expected1->records[1].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[1].name, expected1->records[1].type)); torture_assert_int_equal(tctx, expected1->num_rr, 2, "Got wrong record count"); /* Step 22. */ torture_assert_int_equal(tctx, dlz_newversion(lpcfg_dnsdomain(tctx->lp_ctx), dbdata, &version), ISC_R_SUCCESS, "Failed to start transaction"); torture_assert_int_equal_goto(tctx, dlz_delrdataset(name, expected1->records[0].type, dbdata, version), ISC_R_SUCCESS, ret, cancel_version, talloc_asprintf(tctx, "Failed to delete name[%s] type[%s]\n", name, expected1->records[0].type)); dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), true, dbdata, &version); /* Step 23. */ expected1->num_rr = 0; expected1->records[0].printed = false; expected1->records[1].printed = false; torture_assert_int_equal(tctx, dlz_lookup(lpcfg_dnsdomain(tctx->lp_ctx), expected1->query_name, dbdata, (dns_sdlzlookup_t *)expected1), ISC_R_NOTFOUND, "Found hostname"); torture_assert_int_equal(tctx, expected1->num_rr, 0, "Got wrong record count"); dlz_destroy(dbdata); return true; cancel_version: dlz_closeversion(lpcfg_dnsdomain(tctx->lp_ctx), false, dbdata, &version); return ret; }
/* * Test some zone dumps */ static bool test_dlz_bind9_zonedump(struct torture_context *tctx) { size_t i; void *dbdata; const char *argv[] = { "samba_dlz", "-H", lpcfg_private_path(tctx, tctx->lp_ctx, "dns/sam.ldb"), NULL }; struct test_expected_rr *expected1 = NULL; tctx_static = tctx; torture_assert_int_equal(tctx, dlz_create("samba_dlz", 3, argv, &dbdata, "log", dlz_bind9_log_wrapper, "writeable_zone", dlz_bind9_writeable_zone_hook, "putrr", dlz_bind9_putrr_hook, "putnamedrr", dlz_bind9_putnamedrr_hook, NULL), ISC_R_SUCCESS, "Failed to create samba_dlz"); torture_assert_int_equal(tctx, dlz_configure((void*)tctx, dbdata), ISC_R_SUCCESS, "Failed to configure samba_dlz"); expected1 = talloc_zero(tctx, struct test_expected_rr); torture_assert(tctx, expected1 != NULL, "talloc failed"); expected1->tctx = tctx; expected1->num_records = 7; expected1->records = talloc_zero_array(expected1, struct test_expected_record, expected1->num_records); torture_assert(tctx, expected1->records != NULL, "talloc failed"); expected1->records[0].name = talloc_asprintf(expected1->records, "%s.", lpcfg_dnsdomain(tctx->lp_ctx)); expected1->records[0].type = "soa"; expected1->records[0].ttl = 3600; expected1->records[0].data = talloc_asprintf(expected1->records, "%s.%s. hostmaster.%s. 1 900 600 86400 3600", torture_setting_string(tctx, "host", NULL), lpcfg_dnsdomain(tctx->lp_ctx), lpcfg_dnsdomain(tctx->lp_ctx)); torture_assert(tctx, expected1->records[0].data != NULL, "talloc failed"); expected1->records[1].name = talloc_asprintf(expected1->records, "%s.", lpcfg_dnsdomain(tctx->lp_ctx)); expected1->records[1].type = "ns"; expected1->records[1].ttl = 900; expected1->records[1].data = talloc_asprintf(expected1->records, "%s.%s.", torture_setting_string(tctx, "host", NULL), lpcfg_dnsdomain(tctx->lp_ctx)); torture_assert(tctx, expected1->records[1].data != NULL, "talloc failed"); expected1->records[2].name = talloc_asprintf(expected1->records, "%s.", lpcfg_dnsdomain(tctx->lp_ctx)); expected1->records[2].type = "aaaa"; expected1->records[2].ttl = 900; expected1->records[3].name = talloc_asprintf(expected1->records, "%s.", lpcfg_dnsdomain(tctx->lp_ctx)); expected1->records[3].type = "a"; expected1->records[3].ttl = 900; expected1->records[4].name = talloc_asprintf(expected1->records, "%s.%s.", torture_setting_string(tctx, "host", NULL), lpcfg_dnsdomain(tctx->lp_ctx)); torture_assert(tctx, expected1->records[4].name != NULL, "unknown host"); expected1->records[4].type = "aaaa"; expected1->records[4].ttl = 900; expected1->records[5].name = talloc_asprintf(expected1->records, "%s.%s.", torture_setting_string(tctx, "host", NULL), lpcfg_dnsdomain(tctx->lp_ctx)); torture_assert(tctx, expected1->records[5].name != NULL, "unknown host"); expected1->records[5].type = "a"; expected1->records[5].ttl = 900; /* * We expect multiple srv records */ expected1->records[6].name = NULL; expected1->records[6].type = "srv"; expected1->records[6].ttl = 900; torture_assert_int_equal(tctx, dlz_allnodes(lpcfg_dnsdomain(tctx->lp_ctx), dbdata, (dns_sdlzallnodes_t *)expected1), ISC_R_SUCCESS, "Failed to configure samba_dlz"); for (i = 0; i < expected1->num_records; i++) { torture_assert(tctx, expected1->records[i].printed, talloc_asprintf(tctx, "Failed to have putrr callback run name[%s] for type %s", expected1->records[i].name, expected1->records[i].type)); } torture_assert_int_equal(tctx, expected1->num_rr, 24, "Got wrong record count"); dlz_destroy(dbdata); return true; }
/*% * Create an instance of the module. */ isc_result_t dlz_create(const char *dlzname, unsigned int argc, char *argv[], void **dbdata, ...) { isc_result_t result = ISC_R_FAILURE; mysql_instance_t *mysql = NULL; dbinstance_t *dbi = NULL; MYSQL *dbc; char *tmp = NULL; char *endp; int j; const char *helper_name; #if MYSQL_VERSION_ID >= 50000 my_bool auto_reconnect = 1; #endif #if PTHREADS int dbcount; int i; #endif /* PTHREADS */ va_list ap; UNUSED(dlzname); /* allocate memory for MySQL instance */ mysql = calloc(1, sizeof(mysql_instance_t)); if (mysql == NULL) return (ISC_R_NOMEMORY); memset(mysql, 0, sizeof(mysql_instance_t)); /* Fill in the helper functions */ va_start(ap, dbdata); while ((helper_name = va_arg(ap, const char*)) != NULL) b9_add_helper(mysql, helper_name, va_arg(ap, void*)); va_end(ap); #if PTHREADS /* if debugging, let user know we are multithreaded. */ mysql->log(ISC_LOG_DEBUG(1), "MySQL module running multithreaded"); #else /* PTHREADS */ /* if debugging, let user know we are single threaded. */ mysql->log(ISC_LOG_DEBUG(1), "MySQL module running single threaded"); #endif /* PTHREADS */ /* verify we have at least 4 arg's passed to the module */ if (argc < 4) { mysql->log(ISC_LOG_ERROR, "MySQL module requires " "at least 4 command line args."); return (ISC_R_FAILURE); } /* no more than 8 arg's should be passed to the module */ if (argc > 8) { mysql->log(ISC_LOG_ERROR, "MySQL module cannot accept " "more than 7 command line args."); return (ISC_R_FAILURE); } /* get db name - required */ mysql->dbname = get_parameter_value(argv[1], "dbname="); if (mysql->dbname == NULL) { mysql->log(ISC_LOG_ERROR, "MySQL module requires a dbname parameter."); result = ISC_R_FAILURE; goto cleanup; } /* get db port. Not required, but must be > 0 if specified */ tmp = get_parameter_value(argv[1], "port="); if (tmp == NULL) mysql->port = 0; else { mysql->port = strtol(tmp, &endp, 10); if (*endp != '\0' || mysql->port < 0) { mysql->log(ISC_LOG_ERROR, "Mysql module: port " "must be a positive number."); free(tmp); result = ISC_R_FAILURE; goto cleanup; } free(tmp); } mysql->host = get_parameter_value(argv[1], "host="); mysql->user = get_parameter_value(argv[1], "user="******"pass="******"socket="); mysql->flags = CLIENT_REMEMBER_OPTIONS; tmp = get_parameter_value(argv[1], "compress="); if (tmp != NULL) { if (strcasecmp(tmp, "true") == 0) mysql->flags |= CLIENT_COMPRESS; free(tmp); } tmp = get_parameter_value(argv[1], "ssl="); if (tmp != NULL) { if (strcasecmp(tmp, "true") == 0) mysql->flags |= CLIENT_SSL; free(tmp); } tmp = get_parameter_value(argv[1], "space="); if (tmp != NULL) { if (strcasecmp(tmp, "ignore") == 0) mysql->flags |= CLIENT_IGNORE_SPACE; free(tmp); } #if PTHREADS /* multithreaded build can have multiple DB connections */ tmp = get_parameter_value(argv[1], "threads="); if (tmp == NULL) dbcount = 1; else { dbcount = strtol(tmp, &endp, 10); if (*endp != '\0' || dbcount < 1) { mysql->log(ISC_LOG_ERROR, "MySQL database connection count " "must be positive."); free(tmp); result = ISC_R_FAILURE; goto cleanup; } free(tmp); } /* allocate memory for database connection list */ mysql->db = calloc(1, sizeof(db_list_t)); if (mysql->db == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } /* initialize DB connection list */ DLZ_LIST_INIT(*(mysql->db)); /* * create the appropriate number of database instances (DBI) * append each new DBI to the end of the list */ for (i = 0; i < dbcount; i++) { #endif /* PTHREADS */ switch(argc) { case 4: result = build_dbinstance(NULL, NULL, NULL, argv[2], argv[3], NULL, &dbi, mysql->log); break; case 5: result = build_dbinstance(NULL, NULL, argv[4], argv[2], argv[3], NULL, &dbi, mysql->log); break; case 6: result = build_dbinstance(argv[5], NULL, argv[4], argv[2], argv[3], NULL, &dbi, mysql->log); break; case 7: result = build_dbinstance(argv[5], argv[6], argv[4], argv[2], argv[3], NULL, &dbi, mysql->log); break; case 8: result = build_dbinstance(argv[5], argv[6], argv[4], argv[2], argv[3], argv[7], &dbi, mysql->log); break; default: result = ISC_R_FAILURE; } if (result != ISC_R_SUCCESS) { mysql->log(ISC_LOG_ERROR, "MySQL module could not create " "database instance object."); result = ISC_R_FAILURE; goto cleanup; } #if PTHREADS /* when multithreaded, build a list of DBI's */ DLZ_LINK_INIT(dbi, link); DLZ_LIST_APPEND(*(mysql->db), dbi, link); #else /* * when single threaded, hold onto the one connection * instance. */ mysql->db = dbi; #endif /* create and set db connection */ dbi->dbconn = mysql_init(NULL); if (dbi->dbconn == NULL) { mysql->log(ISC_LOG_ERROR, "MySQL module could not allocate " "memory for database connection"); result = ISC_R_FAILURE; goto cleanup; } dbc = NULL; #if MYSQL_VERSION_ID >= 50000 /* enable automatic reconnection. */ if (mysql_options((MYSQL *) dbi->dbconn, MYSQL_OPT_RECONNECT, &auto_reconnect) != 0) { mysql->log(ISC_LOG_WARNING, "MySQL module failed to set " "MYSQL_OPT_RECONNECT option, continuing"); } #endif for (j = 0; dbc == NULL && j < 4; j++) { dbc = mysql_real_connect((MYSQL *) dbi->dbconn, mysql->host, mysql->user, mysql->pass, mysql->dbname, mysql->port, mysql->socket, mysql->flags); if (dbc == NULL) mysql->log(ISC_LOG_ERROR, "MySQL connection failed: %s", mysql_error((MYSQL *) dbi->dbconn)); } if (dbc == NULL) { mysql->log(ISC_LOG_ERROR, "MySQL module failed to create " "database connection after 4 attempts"); result = ISC_R_FAILURE; goto cleanup; } #if PTHREADS /* set DBI = null for next loop through. */ dbi = NULL; } #endif /* PTHREADS */ *dbdata = mysql; return (ISC_R_SUCCESS); cleanup: dlz_destroy(mysql); return (result); }
isc_result_t dlz_create(const char *dlzname, unsigned int argc, char *argv[], void **dbdata, ...) { isc_result_t result = ISC_R_FAILURE; ldap_instance_t *ldap = NULL; dbinstance_t *dbi = NULL; const char *helper_name; int protocol; int method; #if PTHREADS int dbcount; char *endp; int i; #endif /* PTHREADS */ va_list ap; UNUSED(dlzname); /* allocate memory for LDAP instance */ ldap = calloc(1, sizeof(ldap_instance_t)); if (ldap == NULL) return (ISC_R_NOMEMORY); memset(ldap, 0, sizeof(ldap_instance_t)); /* Fill in the helper functions */ va_start(ap, dbdata); while ((helper_name = va_arg(ap, const char*)) != NULL) b9_add_helper(ldap, helper_name, va_arg(ap, void*)); va_end(ap); #if PTHREADS /* if debugging, let user know we are multithreaded. */ ldap->log(ISC_LOG_DEBUG(1), "LDAP driver running multithreaded"); #else /* PTHREADS */ /* if debugging, let user know we are single threaded. */ ldap->log(ISC_LOG_DEBUG(1), "LDAP driver running single threaded"); #endif /* PTHREADS */ if (argc < 9) { ldap->log(ISC_LOG_ERROR, "LDAP driver requires at least " "8 command line args."); goto cleanup; } /* no more than 13 arg's should be passed to the driver */ if (argc > 12) { ldap->log(ISC_LOG_ERROR, "LDAP driver cannot accept more than " "11 command line args."); goto cleanup; } /* determine protocol version. */ if (strncasecmp(argv[2], V2, strlen(V2)) == 0) protocol = 2; else if (strncasecmp(argv[2], V3, strlen(V3)) == 0) protocol = 3; else { ldap->log(ISC_LOG_ERROR, "LDAP driver protocol must be either %s or %s", V2, V3); goto cleanup; } /* determine connection method. */ if (strncasecmp(argv[3], SIMPLE, strlen(SIMPLE)) == 0) method = LDAP_AUTH_SIMPLE; else if (strncasecmp(argv[3], KRB41, strlen(KRB41)) == 0) method = LDAP_AUTH_KRBV41; else if (strncasecmp(argv[3], KRB42, strlen(KRB42)) == 0) method = LDAP_AUTH_KRBV42; else { ldap->log(ISC_LOG_ERROR, "LDAP driver authentication method must be " "one of %s, %s or %s", SIMPLE, KRB41, KRB42); goto cleanup; } /* multithreaded build can have multiple DB connections */ #if PTHREADS /* check how many db connections we should create */ dbcount = strtol(argv[1], &endp, 10); if (*endp != '\0' || dbcount < 0) { ldap->log(ISC_LOG_ERROR, "LDAP driver database connection count " "must be positive."); goto cleanup; } #endif /* check that LDAP URL parameters make sense */ switch (argc) { case 12: result = ldap_checkURL(ldap, argv[11], 0, "allow zone transfer"); if (result != ISC_R_SUCCESS) goto cleanup; case 11: result = ldap_checkURL(ldap, argv[10], 3, "all nodes"); if (result != ISC_R_SUCCESS) goto cleanup; case 10: if (strlen(argv[9]) > 0) { result = ldap_checkURL(ldap, argv[9], 3, "authority"); if (result != ISC_R_SUCCESS) goto cleanup; } case 9: result = ldap_checkURL(ldap, argv[8], 3, "lookup"); if (result != ISC_R_SUCCESS) goto cleanup; result = ldap_checkURL(ldap, argv[7], 0, "find zone"); if (result != ISC_R_SUCCESS) goto cleanup; break; default: /* not really needed, should shut up compiler. */ result = ISC_R_FAILURE; } /* store info needed to automatically re-connect. */ ldap->protocol = protocol; ldap->method = method; ldap->hosts = strdup(argv[6]); if (ldap->hosts == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } ldap->user = strdup(argv[4]); if (ldap->user == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } ldap->cred = strdup(argv[5]); if (ldap->cred == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } #if PTHREADS /* allocate memory for database connection list */ ldap->db = calloc(1, sizeof(db_list_t)); if (ldap->db == NULL) { result = ISC_R_NOMEMORY; goto cleanup; } /* initialize DB connection list */ DLZ_LIST_INIT(*(ldap->db)); /* * create the appropriate number of database instances (DBI) * append each new DBI to the end of the list */ for (i = 0; i < dbcount; i++) { #endif /* PTHREADS */ /* how many queries were passed in from config file? */ switch (argc) { case 9: result = build_dbinstance(NULL, NULL, NULL, argv[7], argv[8], NULL, &dbi, ldap->log); break; case 10: result = build_dbinstance(NULL, NULL, argv[9], argv[7], argv[8], NULL, &dbi, ldap->log); break; case 11: result = build_dbinstance(argv[10], NULL, argv[9], argv[7], argv[8], NULL, &dbi, ldap->log); break; case 12: result = build_dbinstance(argv[10], argv[11], argv[9], argv[7], argv[8], NULL, &dbi, ldap->log); break; default: /* not really needed, should shut up compiler. */ result = ISC_R_FAILURE; } if (result == ISC_R_SUCCESS) { ldap->log(ISC_LOG_DEBUG(2), "LDAP driver created " "database instance object."); } else { /* unsuccessful?, log err msg and cleanup. */ ldap->log(ISC_LOG_ERROR, "LDAP driver could not create " "database instance object."); goto cleanup; } #if PTHREADS /* when multithreaded, build a list of DBI's */ DLZ_LINK_INIT(dbi, link); DLZ_LIST_APPEND(*(ldap->db), dbi, link); #else /* * when single threaded, hold onto the one connection * instance. */ ldap->db = dbi; #endif /* attempt to connect */ result = ldap_connect(ldap, dbi); /* * if db connection cannot be created, log err msg and * cleanup. */ switch (result) { /* success, do nothing */ case ISC_R_SUCCESS: break; /* * no memory means ldap_init could not * allocate memory */ case ISC_R_NOMEMORY: #if PTHREADS ldap->log(ISC_LOG_ERROR, "LDAP driver could not allocate memory " "for connection number %u", i + 1); #else ldap->log(ISC_LOG_ERROR, "LDAP driver could not allocate memory " "for connection"); #endif goto cleanup; /* * no perm means ldap_set_option could not set * protocol version */ case ISC_R_NOPERM: ldap->log(ISC_LOG_ERROR, "LDAP driver could not " "set protocol version."); result = ISC_R_FAILURE; goto cleanup; /* failure means couldn't connect to ldap server */ case ISC_R_FAILURE: #if PTHREADS ldap->log(ISC_LOG_ERROR, "LDAP driver could not bind " "connection number %u to server.", i + 1); #else ldap->log(ISC_LOG_ERROR, "LDAP driver could not " "bind connection to server."); #endif goto cleanup; /* * default should never happen. If it does, * major errors. */ default: ldap->log(ISC_LOG_ERROR, "dlz_create() failed (%d)", result); result = ISC_R_UNEXPECTED; goto cleanup; } #if PTHREADS /* set DBI = null for next loop through. */ dbi = NULL; } #endif /* PTHREADS */ /* set dbdata to the ldap_instance we created. */ *dbdata = ldap; return (ISC_R_SUCCESS); cleanup: dlz_destroy(ldap); return (result); }
/* * Called to initialize the driver */ isc_result_t dlz_create(const char *dlzname, unsigned int argc, char *argv[], void **dbdata, ...) { struct dlz_example_data *state; const char *helper_name; va_list ap; char soa_data[1024]; const char *extra; isc_result_t result; int n; UNUSED(dlzname); state = calloc(1, sizeof(struct dlz_example_data)); if (state == NULL) return (ISC_R_NOMEMORY); /* Fill in the helper functions */ va_start(ap, dbdata); while ((helper_name = va_arg(ap, const char *)) != NULL) { b9_add_helper(state, helper_name, va_arg(ap, void *)); } va_end(ap); if (argc < 2) { if (state->log != NULL) state->log(ISC_LOG_ERROR, "dlz_example: please specify a zone name"); dlz_destroy(state); return (ISC_R_FAILURE); } state->zone_name = strdup(argv[1]); if (state->zone_name == NULL) { free(state); return (ISC_R_NOMEMORY); } if (strcmp(state->zone_name, ".") == 0) extra = ".root"; else extra = "."; n = sprintf(soa_data, "%s hostmaster%s%s 123 900 600 86400 3600", state->zone_name, extra, state->zone_name); if (n < 0) CHECK(ISC_R_FAILURE); if ((unsigned)n >= sizeof(soa_data)) CHECK(ISC_R_NOSPACE); add_name(state, &state->current[0], state->zone_name, "soa", 3600, soa_data); add_name(state, &state->current[0], state->zone_name, "ns", 3600, state->zone_name); add_name(state, &state->current[0], state->zone_name, "a", 1800, "10.53.0.1"); if (state->log != NULL) state->log(ISC_LOG_INFO, "dlz_example: started for zone %s", state->zone_name); *dbdata = state; return (ISC_R_SUCCESS); failure: free(state); return (result); }