static NTSTATUS sldb_init(TALLOC_CTX *mem_ctx, const struct share_ops *ops, struct tevent_context *ev_ctx, struct loadparm_context *lp_ctx, struct share_context **ctx) { struct ldb_context *sdb; *ctx = talloc(mem_ctx, struct share_context); if (!*ctx) { DEBUG(0, ("ERROR: Out of memory!\n")); return NT_STATUS_NO_MEMORY; } sdb = ldb_wrap_connect(*ctx, ev_ctx, lp_ctx, lpcfg_private_path(*ctx, lp_ctx, "share.ldb"), system_session(lp_ctx), NULL, 0); if (!sdb) { talloc_free(*ctx); return NT_STATUS_UNSUCCESSFUL; } (*ctx)->ops = ops; (*ctx)->priv_data = (void *)sdb; return NT_STATUS_OK; }
int samba_ldb_connect(struct ldb_context *ldb, struct loadparm_context *lp_ctx, const char *url, unsigned int flags) { int ret; char *real_url = NULL; /* allow admins to force non-sync ldb for all databases */ if (lpcfg_parm_bool(lp_ctx, NULL, "ldb", "nosync", false)) { flags |= LDB_FLG_NOSYNC; } if (DEBUGLVL(10)) { flags |= LDB_FLG_ENABLE_TRACING; } real_url = lpcfg_private_path(ldb, lp_ctx, url); if (real_url == NULL) { return LDB_ERR_OPERATIONS_ERROR; } ret = ldb_connect(ldb, real_url, flags, NULL); if (ret != LDB_SUCCESS) { return ret; } /* setup for leak detection */ ldb_set_opaque(ldb, "wrap_url", real_url); return LDB_SUCCESS; }
static isc_result_t dlz_bind9_writeable_zone_hook(dns_view_t *view, const char *zone_name) { struct torture_context *tctx = talloc_get_type((void *)view, struct torture_context); struct ldb_context *samdb = samdb_connect_url(tctx, NULL, tctx->lp_ctx, system_session(tctx->lp_ctx), 0, lpcfg_private_path(tctx, tctx->lp_ctx, "dns/sam.ldb")); struct ldb_message *msg; int ret; const char *attrs[] = { NULL }; if (!samdb) { torture_fail(tctx, "Failed to connect to samdb"); return ISC_R_FAILURE; } ret = dsdb_search_one(samdb, tctx, &msg, NULL, LDB_SCOPE_SUBTREE, attrs, DSDB_SEARCH_SEARCH_ALL_PARTITIONS, "(&(objectClass=dnsZone)(name=%s))", zone_name); if (ret != LDB_SUCCESS) { torture_fail(tctx, talloc_asprintf(tctx, "Failed to search for %s: %s", zone_name, ldb_errstring(samdb))); return ISC_R_FAILURE; } talloc_free(msg); return ISC_R_SUCCESS; }
/* * 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; }
/** * open up the randseed database and set the random number generator callback */ bool randseed_init(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx) { char *fname; uint8_t dummy; struct tdb_wrap *tdb; fname = lpcfg_private_path(mem_ctx, lp_ctx, "randseed.tdb"); tdb = tdb_wrap_open(mem_ctx, fname, 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); if (!tdb) { DEBUG(0,("Failed to open %s\n", fname)); talloc_free(fname); return false; } talloc_free(fname); /** * Set a reseed function for the crypto random generator * * This avoids a problem where systems without /dev/urandom * could send the same challenge to multiple clients */ set_rand_reseed_callback((void (*) (void *, int *))get_rand_seed, tdb); /* Ensure that the reseed is done now, while we are root, etc */ generate_random_buffer(&dummy, sizeof(dummy)); return true; }
/** return a path in the smbd.tmp directory, where all temporary file for smbd go. If NULL is passed for name then return the directory path itself */ char *smbd_tmp_path(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, const char *name) { char *fname, *dname; bool ok; dname = lpcfg_private_path(mem_ctx, lp_ctx, "smbd.tmp"); if (dname == NULL) { return NULL; } ok = directory_create_or_exist(dname, geteuid(), 0755); if (!ok) { return NULL; } if (name == NULL) { return dname; } fname = talloc_asprintf(mem_ctx, "%s/%s", dname, name); if (fname == NULL) { return dname; } talloc_free(dname); return fname; }
static PyObject *py_lp_ctx_private_path(py_talloc_Object *self, PyObject *args) { char *name, *path; PyObject *ret; if (!PyArg_ParseTuple(args, "s", &name)) return NULL; path = lpcfg_private_path(NULL, PyLoadparmContext_AsLoadparmContext(self), name); ret = PyString_FromString(path); talloc_free(path); return ret; }
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; }
/** return a path in the smbd.tmp directory, where all temporary file for smbd go. If NULL is passed for name then return the directory path itself */ char *smbd_tmp_path(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx, const char *name) { char *fname, *dname; dname = lpcfg_private_path(mem_ctx, lp_ctx, "smbd.tmp"); if (!directory_exist(dname)) { mkdir(dname,0755); } if (name == NULL) { return dname; } fname = talloc_asprintf(mem_ctx, "%s/%s", dname, name); talloc_free(dname); return fname; }
struct tdb_wrap *open_schannel_session_store(TALLOC_CTX *mem_ctx, struct loadparm_context *lp_ctx) { struct tdb_wrap *tdb_sc = NULL; char *fname = lpcfg_private_path(mem_ctx, lp_ctx, "schannel_store.tdb"); if (!fname) { return NULL; } tdb_sc = tdb_wrap_open(mem_ctx, fname, 0, TDB_CLEAR_IF_FIRST|TDB_NOSYNC, O_RDWR|O_CREAT, 0600, lp_ctx); if (!tdb_sc) { DEBUG(0,("open_schannel_session_store: Failed to open %s - %s\n", fname, strerror(errno))); TALLOC_FREE(fname); return NULL; } TALLOC_FREE(fname); return tdb_sc; }
/* called to initialise the driver */ _PUBLIC_ isc_result_t dlz_create(const char *dlzname, unsigned int argc, char *argv[], void **dbdata, ...) { struct dlz_bind9_data *state; const char *helper_name; va_list ap; isc_result_t result; TALLOC_CTX *tmp_ctx; int ret; struct ldb_dn *dn; struct b9_options options; ZERO_STRUCT(options); state = talloc_zero(NULL, struct dlz_bind9_data); if (state == NULL) { return ISC_R_NOMEMORY; } tmp_ctx = talloc_new(state); /* 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); state->ev_ctx = s4_event_context_init(state); if (state->ev_ctx == NULL) { result = ISC_R_NOMEMORY; goto failed; } state->samdb = ldb_init(state, state->ev_ctx); if (state->samdb == NULL) { state->log(ISC_LOG_ERROR, "samba_dlz: Failed to create ldb"); result = ISC_R_FAILURE; goto failed; } result = parse_options(state, argc, argv, &options); if (result != ISC_R_SUCCESS) { goto failed; } state->lp = loadparm_init_global(true); if (state->lp == NULL) { result = ISC_R_NOMEMORY; goto failed; } if (options.url == NULL) { options.url = talloc_asprintf(tmp_ctx, "ldapi://%s", lpcfg_private_path(tmp_ctx, state->lp, "ldap_priv/ldapi")); if (options.url == NULL) { result = ISC_R_NOMEMORY; goto failed; } } ret = ldb_connect(state->samdb, options.url, 0, NULL); if (ret != LDB_SUCCESS) { state->log(ISC_LOG_ERROR, "samba_dlz: Failed to connect to %s - %s", options.url, ldb_errstring(state->samdb)); result = ISC_R_FAILURE; goto failed; } ret = ldb_modules_hook(state->samdb, LDB_MODULE_HOOK_CMDLINE_POSTCONNECT); if (ret != LDB_SUCCESS) { state->log(ISC_LOG_ERROR, "samba_dlz: Failed postconnect for %s - %s", options.url, ldb_errstring(state->samdb)); result = ISC_R_FAILURE; goto failed; } dn = ldb_get_default_basedn(state->samdb); if (dn == NULL) { state->log(ISC_LOG_ERROR, "samba_dlz: Unable to get basedn for %s - %s", options.url, ldb_errstring(state->samdb)); result = ISC_R_FAILURE; goto failed; } state->log(ISC_LOG_INFO, "samba_dlz: started for DN %s", ldb_dn_get_linearized(dn)); *dbdata = state; talloc_free(tmp_ctx); return ISC_R_SUCCESS; failed: talloc_free(state); return result; }
/* * 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; }
/** * Fill in credentials for the machine trust account, from the secrets database. * * @param cred Credentials structure to fill in * @retval NTSTATUS error detailing any failure */ _PUBLIC_ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred, struct loadparm_context *lp_ctx) { NTSTATUS status; char *filter; char *error_string; const char *domain; bool secrets_tdb_password_more_recent; time_t secrets_tdb_lct = 0; char *secrets_tdb_password = NULL; char *keystr; char *keystr_upper = NULL; char *secrets_tdb; struct db_context *db_ctx; TALLOC_CTX *tmp_ctx = talloc_named(cred, 0, "cli_credentials_set_secrets from ldb"); if (!tmp_ctx) { return NT_STATUS_NO_MEMORY; } secrets_tdb = lpcfg_private_path(cred, lp_ctx, lpcfg_use_ntdb(lp_ctx) ? "secrets.ntdb" : "secrets.tdb"); if (!secrets_tdb) { TALLOC_FREE(tmp_ctx); return NT_STATUS_NO_MEMORY; } db_ctx = dbwrap_local_open(cred, lp_ctx, secrets_tdb, 0, TDB_DEFAULT, O_RDWR, 0600, DBWRAP_LOCK_ORDER_1); /* Bleh, nasty recursion issues: We are setting a machine * account here, so we don't want the 'pending' flag around * any more */ cred->machine_account_pending = false; /* We have to do this, as the fallback in * cli_credentials_set_secrets is to run as anonymous, so the domain is wiped */ domain = cli_credentials_get_domain(cred); if (db_ctx) { TDB_DATA dbuf; keystr = talloc_asprintf(tmp_ctx, "%s/%s", SECRETS_MACHINE_LAST_CHANGE_TIME, domain); keystr_upper = strupper_talloc(tmp_ctx, keystr); status = dbwrap_fetch(db_ctx, tmp_ctx, string_tdb_data(keystr_upper), &dbuf); if (NT_STATUS_IS_OK(status) && dbuf.dsize == 4) { secrets_tdb_lct = IVAL(dbuf.dptr,0); } keystr = talloc_asprintf(tmp_ctx, "%s/%s", SECRETS_MACHINE_PASSWORD, domain); keystr_upper = strupper_talloc(tmp_ctx, keystr); status = dbwrap_fetch(db_ctx, tmp_ctx, string_tdb_data(keystr_upper), &dbuf); if (NT_STATUS_IS_OK(status)) { secrets_tdb_password = (char *)dbuf.dptr; } } filter = talloc_asprintf(cred, SECRETS_PRIMARY_DOMAIN_FILTER, domain); status = cli_credentials_set_secrets_lct(cred, lp_ctx, NULL, SECRETS_PRIMARY_DOMAIN_DN, filter, secrets_tdb_lct, secrets_tdb_password, &error_string); if (secrets_tdb_password == NULL) { secrets_tdb_password_more_recent = false; } else if (NT_STATUS_EQUAL(NT_STATUS_CANT_ACCESS_DOMAIN_INFO, status) || NT_STATUS_EQUAL(NT_STATUS_NOT_FOUND, status)) { secrets_tdb_password_more_recent = true; } else if (secrets_tdb_lct > cli_credentials_get_password_last_changed_time(cred)) { secrets_tdb_password_more_recent = true; } else if (secrets_tdb_lct == cli_credentials_get_password_last_changed_time(cred)) { secrets_tdb_password_more_recent = strcmp(secrets_tdb_password, cli_credentials_get_password(cred)) != 0; } else { secrets_tdb_password_more_recent = false; } if (secrets_tdb_password_more_recent) { char *machine_account = talloc_asprintf(tmp_ctx, "%s$", lpcfg_netbios_name(lp_ctx)); cli_credentials_set_password(cred, secrets_tdb_password, CRED_SPECIFIED); cli_credentials_set_domain(cred, domain, CRED_SPECIFIED); cli_credentials_set_username(cred, machine_account, CRED_SPECIFIED); } else if (!NT_STATUS_IS_OK(status)) { if (db_ctx) { error_string = talloc_asprintf(cred, "Failed to fetch machine account password from " "secrets.ldb: %s and failed to fetch %s from %s", error_string, keystr_upper, secrets_tdb); } else { error_string = talloc_asprintf(cred, "Failed to fetch machine account password from " "secrets.ldb: %s and failed to open %s", error_string, secrets_tdb); } DEBUG(1, ("Could not find machine account in secrets database: %s: %s\n", error_string, nt_errstr(status))); /* set anonymous as the fallback, if the machine account won't work */ cli_credentials_set_anonymous(cred); } TALLOC_FREE(tmp_ctx); return status; }
/* called to initialise the driver */ _PUBLIC_ isc_result_t dlz_create(const char *dlzname, unsigned int argc, char *argv[], void **dbdata, ...) { struct dlz_bind9_data *state; const char *helper_name; va_list ap; isc_result_t result; struct ldb_dn *dn; NTSTATUS nt_status; state = talloc_zero(NULL, struct dlz_bind9_data); if (state == NULL) { return ISC_R_NOMEMORY; } talloc_set_destructor(state, dlz_state_debug_unregister); /* 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); /* Do not install samba signal handlers */ fault_setup_disable(); /* Start logging (to the bind9 logs) */ debug_set_callback(state, b9_debug); state->ev_ctx = s4_event_context_init(state); if (state->ev_ctx == NULL) { result = ISC_R_NOMEMORY; goto failed; } result = parse_options(state, argc, argv, &state->options); if (result != ISC_R_SUCCESS) { goto failed; } state->lp = loadparm_init_global(true); if (state->lp == NULL) { result = ISC_R_NOMEMORY; goto failed; } if (state->options.debug) { lpcfg_do_global_parameter(state->lp, "log level", state->options.debug); } else { lpcfg_do_global_parameter(state->lp, "log level", "0"); } if (smb_krb5_init_context(state, state->ev_ctx, state->lp, &state->smb_krb5_ctx) != 0) { result = ISC_R_NOMEMORY; goto failed; } nt_status = gensec_init(); if (!NT_STATUS_IS_OK(nt_status)) { result = ISC_R_NOMEMORY; goto failed; } state->auth_context = talloc_zero(state, struct auth4_context); if (state->auth_context == NULL) { result = ISC_R_NOMEMORY; goto failed; } if (state->options.url == NULL) { state->options.url = lpcfg_private_path(state, state->lp, "dns/sam.ldb"); if (state->options.url == NULL) { result = ISC_R_NOMEMORY; goto failed; } } state->samdb = samdb_connect_url(state, state->ev_ctx, state->lp, system_session(state->lp), 0, state->options.url); if (state->samdb == NULL) { state->log(ISC_LOG_ERROR, "samba_dlz: Failed to connect to %s", state->options.url); result = ISC_R_FAILURE; goto failed; } dn = ldb_get_default_basedn(state->samdb); if (dn == NULL) { state->log(ISC_LOG_ERROR, "samba_dlz: Unable to get basedn for %s - %s", state->options.url, ldb_errstring(state->samdb)); result = ISC_R_FAILURE; goto failed; } state->log(ISC_LOG_INFO, "samba_dlz: started for DN %s", ldb_dn_get_linearized(dn)); state->auth_context->event_ctx = state->ev_ctx; state->auth_context->lp_ctx = state->lp; state->auth_context->sam_ctx = state->samdb; state->auth_context->generate_session_info_pac = b9_generate_session_info_pac; *dbdata = state; return ISC_R_SUCCESS; failed: talloc_free(state); return result; }