Ejemplo n.º 1
0
/* 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;
}
Ejemplo n.º 2
0
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;
}
Ejemplo n.º 3
0
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;
}
Ejemplo n.º 4
0
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;
}
Ejemplo n.º 5
0
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);
}
Ejemplo n.º 6
0
/*
  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;
}
Ejemplo n.º 7
0
/**
 * 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;
}
Ejemplo n.º 8
0
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));
}
Ejemplo n.º 9
0
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;
}