/* read a entry from the secrets database - the caller must free the result if size is non-null then the size of the entry is put in there */ void *secrets_fetch(const char *key, size_t *size) { TDB_DATA dbuf; void *result; NTSTATUS status; if (!secrets_init()) { return NULL; } status = dbwrap_fetch(db_ctx, talloc_tos(), string_tdb_data(key), &dbuf); if (!NT_STATUS_IS_OK(status)) { return NULL; } result = memdup(dbuf.dptr, dbuf.dsize); if (result == NULL) { return NULL; } TALLOC_FREE(dbuf.dptr); if (size) { *size = dbuf.dsize; } return result; }
struct share_mode_lock *fetch_share_mode_unlocked(TALLOC_CTX *mem_ctx, struct file_id id) { struct share_mode_lock *lck; TDB_DATA key = locking_key(&id); TDB_DATA data; NTSTATUS status; status = dbwrap_fetch(lock_db, talloc_tos(), key, &data); if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("Could not fetch share entry\n")); return NULL; } if (data.dptr == NULL) { return NULL; } lck = talloc(mem_ctx, struct share_mode_lock); if (lck == NULL) { TALLOC_FREE(data.dptr); return NULL; } lck->data = parse_share_modes(lck, data); TALLOC_FREE(data.dptr); if (lck->data == NULL) { TALLOC_FREE(lck); return NULL; } return lck; }
static NTSTATUS get_acl_blob(TALLOC_CTX *ctx, vfs_handle_struct *handle, files_struct *fsp, const struct smb_filename *smb_fname, DATA_BLOB *pblob) { uint8_t id_buf[16]; TDB_DATA data; struct file_id id; struct db_context *db = acl_db; NTSTATUS status = NT_STATUS_OK; SMB_STRUCT_STAT sbuf; ZERO_STRUCT(sbuf); if (fsp) { status = vfs_stat_fsp(fsp); sbuf = fsp->fsp_name->st; } else { int ret = vfs_stat_smb_basename(handle->conn, smb_fname, &sbuf); if (ret == -1) { status = map_nt_error_from_unix(errno); } } if (!NT_STATUS_IS_OK(status)) { return status; } id = vfs_file_id_from_sbuf(handle->conn, &sbuf); /* For backwards compatibility only store the dev/inode. */ push_file_id_16((char *)id_buf, &id); status = dbwrap_fetch(db, ctx, make_tdb_data(id_buf, sizeof(id_buf)), &data); if (!NT_STATUS_IS_OK(status)) { return NT_STATUS_INTERNAL_DB_CORRUPTION; } pblob->data = data.dptr; pblob->length = data.dsize; DEBUG(10,("get_acl_blob: returned %u bytes from file %s\n", (unsigned int)data.dsize, smb_fname->base_name )); if (pblob->length == 0 || pblob->data == NULL) { return NT_STATUS_NOT_FOUND; } return NT_STATUS_OK; }
static NTSTATUS dbwrap_cache_parse_record( struct db_context *db, TDB_DATA key, void (*parser)(TDB_DATA key, TDB_DATA data, void *private_data), void *private_data) { struct db_cache_ctx *ctx = talloc_get_type_abort( db->private_data, struct db_cache_ctx); TDB_DATA value; NTSTATUS status; if (!dbwrap_cache_validate(ctx)) { return NT_STATUS_NO_MEMORY; } if (dbwrap_exists(ctx->negative, key)) { return NT_STATUS_NOT_FOUND; } status = dbwrap_parse_record(ctx->positive, key, parser, private_data); if (NT_STATUS_IS_OK(status)) { return status; } status = dbwrap_fetch(ctx->backing, talloc_tos(), key, &value); if (NT_STATUS_IS_OK(status)) { dbwrap_store(ctx->positive, key, value, 0); parser(key, value, private_data); TALLOC_FREE(value.dptr); return NT_STATUS_OK; } if (NT_STATUS_EQUAL(status, NT_STATUS_NOT_FOUND)) { char c = '\0'; value.dptr = (uint8_t *)&c; value.dsize = sizeof(c); dbwrap_store(ctx->negative, key, value, 0); return NT_STATUS_NOT_FOUND; } return status; }
NTSTATUS dbwrap_fetch_bystring(struct db_context *db, TALLOC_CTX *mem_ctx, const char *key, TDB_DATA *value) { return dbwrap_fetch(db, mem_ctx, string_term_tdb_data(key), value); }
/* load the notify array */ static NTSTATUS notify_load(struct notify_context *notify, struct db_record *rec) { TDB_DATA dbuf; DATA_BLOB blob; NTSTATUS status; int seqnum; seqnum = dbwrap_get_seqnum(notify->db_recursive); if (seqnum == notify->seqnum && notify->array != NULL) { return NT_STATUS_OK; } notify->seqnum = seqnum; talloc_free(notify->array); notify->array = talloc_zero(notify, struct notify_array); NT_STATUS_HAVE_NO_MEMORY(notify->array); if (!rec) { status = dbwrap_fetch(notify->db_recursive, notify, notify->key, &dbuf); if (!NT_STATUS_IS_OK(status)) { return NT_STATUS_INTERNAL_DB_CORRUPTION; } } else { dbuf = dbwrap_record_get_value(rec); } blob.data = (uint8 *)dbuf.dptr; blob.length = dbuf.dsize; status = NT_STATUS_OK; if (blob.length > 0) { enum ndr_err_code ndr_err; ndr_err = ndr_pull_struct_blob(&blob, notify->array, notify->array, (ndr_pull_flags_fn_t)ndr_pull_notify_array); if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) { /* 1. log that we got a corrupt notify_array * 2. clear the variable the garbage was stored into to not trip * over it next time this method is entered with the same seqnum * 3. delete it from the database */ DEBUG(2, ("notify_array is corrupt, discarding it\n")); ZERO_STRUCTP(notify->array); if (rec != NULL) { dbwrap_record_delete(rec); } } else { if (DEBUGLEVEL >= 10) { DEBUG(10, ("notify_load:\n")); NDR_PRINT_DEBUG(notify_array, notify->array); } } } if (!rec) { talloc_free(dbuf.dptr); } 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; }
TDB_DATA dbwrap_fetch_bystring(struct db_context *db, TALLOC_CTX *mem_ctx, const char *key) { return dbwrap_fetch(db, mem_ctx, string_term_tdb_data(key)); }
static int traverse_tcon_fn(struct smbXsrv_tcon_global0 *global, void *connections_forall_state) { NTSTATUS status; struct connections_forall_state *state = (struct connections_forall_state*)connections_forall_state; struct connections_key key; struct connections_data data; uint32_t sess_id = global->session_global_id; struct connections_forall_session sess = { .uid = -1, .gid = -1, }; TDB_DATA val = tdb_null; /* * Note: that share_name is defined as array without a pointer. * that's why it's always a valid pointer here. */ if (strlen(global->share_name) == 0) { /* * when a smbXsrv_tcon is created it's created * with emtpy share_name first in order to allocate * an id, before filling in the details. */ return 0; } status = dbwrap_fetch(state->session_by_pid, state, make_tdb_data((void*)&sess_id, sizeof(sess_id)), &val); if (NT_STATUS_IS_OK(status)) { memcpy((uint8_t *)&sess, val.dptr, val.dsize); } ZERO_STRUCT(key); ZERO_STRUCT(data); key.pid = data.pid = global->server_id; key.cnum = data.cnum = global->tcon_global_id; fstrcpy(key.name, global->share_name); fstrcpy(data.servicename, global->share_name); data.uid = sess.uid; data.gid = sess.gid; fstrcpy(data.addr, sess.addr); fstrcpy(data.machine, sess.machine); data.start = nt_time_to_unix(global->creation_time); data.encryption_flags = global->encryption_flags; data.cipher = sess.cipher; data.dialect = sess.dialect; data.signing_flags = global->signing_flags; state->count++; return state->fn(&key, &data, state->private_data); } int connections_forall_read(int (*fn)(const struct connections_key *key, const struct connections_data *data, void *private_data), void *private_data) { TALLOC_CTX *frame = talloc_stackframe(); struct connections_forall_state *state = talloc_zero(talloc_tos(), struct connections_forall_state); NTSTATUS status; int ret = -1; state->session_by_pid = db_open_rbt(state); state->fn = fn; state->private_data = private_data; status = smbXsrv_session_global_traverse(collect_sessions_fn, state); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to traverse sessions: %s\n", nt_errstr(status))); goto done; } status = smbXsrv_tcon_global_traverse(traverse_tcon_fn, state); if (!NT_STATUS_IS_OK(status)) { DEBUG(0, ("Failed to traverse tree connects: %s\n", nt_errstr(status))); goto done; } ret = state->count; done: talloc_free(frame); return ret; }