struct db_context *db_open_cache(TALLOC_CTX *mem_ctx, struct db_context *backing) { struct db_context *db; struct db_cache_ctx *ctx; db = talloc_zero(mem_ctx, struct db_context); if (db == NULL) { return NULL; } ctx = talloc_zero(db, struct db_cache_ctx); if (ctx == NULL) { TALLOC_FREE(db); return NULL; } ctx->seqnum = -1; ctx->backing = talloc_move(ctx, &backing); db->private_data = ctx; if (!dbwrap_cache_validate(ctx)) { TALLOC_FREE(db); return NULL; } db->fetch_locked = dbwrap_cache_fetch_locked; db->traverse = dbwrap_cache_traverse; db->traverse_read = dbwrap_cache_traverse_read; db->get_seqnum = dbwrap_cache_get_seqnum; db->transaction_start = dbwrap_cache_transaction_start; db->transaction_commit = dbwrap_cache_transaction_commit; db->transaction_cancel = dbwrap_cache_transaction_cancel; db->parse_record = dbwrap_cache_parse_record; db->exists = dbwrap_cache_exists; db->id = dbwrap_cache_id; db->name = dbwrap_name(ctx->backing); db->hash_size = dbwrap_hash_size(ctx->backing); return db; }
NTSTATUS smbXsrv_open_cleanup(uint64_t persistent_id) { NTSTATUS status = NT_STATUS_OK; TALLOC_CTX *frame = talloc_stackframe(); struct smbXsrv_open_global0 *op = NULL; TDB_DATA val; struct db_record *rec; bool delete_open = false; uint32_t global_id = persistent_id & UINT32_MAX; rec = smbXsrv_open_global_fetch_locked(smbXsrv_open_global_db_ctx, global_id, frame); if (rec == NULL) { status = NT_STATUS_NOT_FOUND; goto done; } val = dbwrap_record_get_value(rec); if (val.dsize == 0) { DEBUG(10, ("smbXsrv_open_cleanup[global: 0x%08x] " "empty record in %s, skipping...\n", global_id, dbwrap_name(smbXsrv_open_global_db_ctx))); goto done; } status = smbXsrv_open_global_parse_record(talloc_tos(), rec, &op); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("smbXsrv_open_cleanup[global: 0x%08x] " "failed to read record: %s\n", global_id, nt_errstr(status))); goto done; } if (server_id_is_disconnected(&op->server_id)) { struct timeval now, disconnect_time; int64_t tdiff; now = timeval_current(); nttime_to_timeval(&disconnect_time, op->disconnect_time); tdiff = usec_time_diff(&now, &disconnect_time); delete_open = (tdiff >= 1000*op->durable_timeout_msec); DEBUG(10, ("smbXsrv_open_cleanup[global: 0x%08x] " "disconnected at [%s] %us ago with " "timeout of %us -%s reached\n", global_id, nt_time_string(frame, op->disconnect_time), (unsigned)(tdiff/1000000), op->durable_timeout_msec / 1000, delete_open ? "" : " not")); } else if (!serverid_exists(&op->server_id)) { struct server_id_buf idbuf; DEBUG(10, ("smbXsrv_open_cleanup[global: 0x%08x] " "server[%s] does not exist\n", global_id, server_id_str_buf(op->server_id, &idbuf))); delete_open = true; } if (!delete_open) { goto done; } status = dbwrap_record_delete(rec); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("smbXsrv_open_cleanup[global: 0x%08x] " "failed to delete record" "from %s: %s\n", global_id, dbwrap_name(smbXsrv_open_global_db_ctx), nt_errstr(status))); goto done; } DEBUG(10, ("smbXsrv_open_cleanup[global: 0x%08x] " "delete record from %s\n", global_id, dbwrap_name(smbXsrv_open_global_db_ctx))); done: talloc_free(frame); return status; }
/** * Fill in credentials for the machine trust account, from the * secrets.ldb or passed in handle to secrets.tdb (perhaps in CTDB). * * This version is used in parts of the code that can link in the * CTDB dbwrap backend, by passing down the already open handle. * * @param cred Credentials structure to fill in * @param db_ctx dbwrap context for secrets.tdb * @retval NTSTATUS error detailing any failure */ _PUBLIC_ NTSTATUS cli_credentials_set_machine_account_db_ctx(struct cli_credentials *cred, struct loadparm_context *lp_ctx, struct db_context *db_ctx) { NTSTATUS status; char *filter; char *error_string = NULL; const char *domain; bool secrets_tdb_password_more_recent; time_t secrets_tdb_lct = 0; char *secrets_tdb_password = NULL; char *secrets_tdb_old_password = NULL; uint32_t secrets_tdb_secure_channel_type = SEC_CHAN_NULL; char *keystr; char *keystr_upper = NULL; TALLOC_CTX *tmp_ctx = talloc_named(cred, 0, "cli_credentials_set_secrets from ldb"); if (!tmp_ctx) { return NT_STATUS_NO_MEMORY; } /* 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; } keystr = talloc_asprintf(tmp_ctx, "%s/%s", SECRETS_MACHINE_PASSWORD_PREV, 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_old_password = (char *)dbuf.dptr; } keystr = talloc_asprintf(tmp_ctx, "%s/%s", SECRETS_MACHINE_SEC_CHANNEL_TYPE, 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_secure_channel_type = IVAL(dbuf.dptr,0); } } 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_old_password(cred, secrets_tdb_old_password, CRED_SPECIFIED); cli_credentials_set_domain(cred, domain, CRED_SPECIFIED); if (strequal(domain, lpcfg_workgroup(lp_ctx))) { cli_credentials_set_realm(cred, lpcfg_realm(lp_ctx), CRED_SPECIFIED); } cli_credentials_set_username(cred, machine_account, CRED_SPECIFIED); cli_credentials_set_password_last_changed_time(cred, secrets_tdb_lct); cli_credentials_set_secure_channel_type(cred, secrets_tdb_secure_channel_type); status = NT_STATUS_OK; } else if (!NT_STATUS_IS_OK(status)) { if (db_ctx) { error_string = talloc_asprintf(cred, "Failed to fetch machine account password for %s from both " "secrets.ldb (%s) and from %s", domain, error_string == NULL ? "error" : error_string, dbwrap_name(db_ctx)); } else { char *secrets_tdb_path; secrets_tdb_path = lpcfg_private_db_path(tmp_ctx, lp_ctx, "secrets"); if (secrets_tdb_path == NULL) { return NT_STATUS_NO_MEMORY; } error_string = talloc_asprintf(cred, "Failed to fetch machine account password from " "secrets.ldb: %s and failed to open %s", error_string == NULL ? "error" : error_string, secrets_tdb_path); } DEBUG(1, ("Could not find machine account in secrets database: %s: %s\n", error_string == NULL ? "error" : 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; }