Пример #1
0
static void upload_queue_run(const struct session *session, unsigned const char key[KDF_HASH_LEN])
{
	_cleanup_free_ char *pid = NULL;
	upload_queue_kill();
	pid_t child = fork();
	if (child < 0)
		die_errno("fork(agent)");
	if (child == 0) {
		int null = open("/dev/null", 0);
		if (null >= 0) {
			dup2(null, 0);
			dup2(null, 1);
			dup2(null, 2);
			close(null);
		}
		setsid();
		IGNORE_RESULT(chdir("/"));
		process_set_name("lpass [upload queue]");
		signal(SIGHUP, upload_queue_cleanup);
		signal(SIGINT, upload_queue_cleanup);
		signal(SIGQUIT, upload_queue_cleanup);
		signal(SIGTERM, upload_queue_cleanup);
		signal(SIGALRM, upload_queue_cleanup);
		upload_queue_upload_all(session, key);
		upload_queue_cleanup(0);
		_exit(EXIT_SUCCESS);
	}
	pid = xultostr(child);
	config_write_string("uploader.pid", pid);
}
Пример #2
0
void agent_save(const char *username, int iterations, unsigned const char key[KDF_HASH_LEN])
{
	_cleanup_free_ char *iterations_str = xultostr(iterations);
	config_write_string("iterations", iterations_str);
	config_write_string("username", username);
	config_write_encrypted_string("verify", AGENT_VERIFICATION_STRING, key);
	agent_start(key);
}
Пример #3
0
static void upload_queue_run(const struct session *session, unsigned const char key[KDF_HASH_LEN])
{
	_cleanup_free_ char *pid = NULL;
	upload_queue_kill();
	pid_t child = fork();
	if (child < 0)
		die_errno("fork(agent)");
	if (child == 0) {
		_cleanup_free_ char *upload_log_path = NULL;

		int null = open("/dev/null", 0);
		int upload_log = null;

		if (lpass_log_level() >= 0) {
			upload_log_path = config_path("lpass.log");
			upload_log = open(upload_log_path,
					  O_WRONLY | O_CREAT | O_APPEND, 0600);
		}
		if (null >= 0) {
			dup2(null, 0);
			dup2(upload_log, 1);
			dup2(null, 2);
			close(null);
			close(upload_log);
		}
		setsid();
		IGNORE_RESULT(chdir("/"));
		process_set_name("lpass [upload queue]");
		signal(SIGHUP, upload_queue_cleanup);
		signal(SIGINT, upload_queue_cleanup);
		signal(SIGQUIT, upload_queue_cleanup);
		signal(SIGTERM, upload_queue_cleanup);
		signal(SIGALRM, upload_queue_cleanup);
		setvbuf(stdout, NULL, _IOLBF, 0);

		if (http_init()) {
			lpass_log(LOG_ERROR, "UQ: unable to restart curl\n");
			_exit(EXIT_FAILURE);
		}

		lpass_log(LOG_DEBUG, "UQ: starting queue run\n");
		upload_queue_upload_all(session, key);
		lpass_log(LOG_DEBUG, "UQ: queue run complete\n");
		upload_queue_cleanup(0);
		_exit(EXIT_SUCCESS);
	}
	pid = xultostr(child);
	config_write_string("uploader.pid", pid);
}
Пример #4
0
static void write_share_chunk(struct buffer *buffer, struct share *share)
{
	struct buffer sharebuf = { .bytes = share->chunk, .len = share->chunk_len, .max = share->chunk_len };
	write_chunk(buffer, &sharebuf, "SHAR");
}

size_t blob_write(const struct blob *blob, const unsigned char key[KDF_HASH_LEN], char **out)
{
	struct buffer buffer;
	struct share *last_share = NULL;
	_cleanup_free_ char *version;

	memset(&buffer, 0, sizeof(buffer));

	version = xultostr(blob->version);
	buffer_append(&buffer, "LPAV", 4);
	write_plain_string(&buffer, version);
	buffer_append(&buffer, "LOCL", 4);
	write_plain_string(&buffer, LASTPASS_CLI_VERSION);

	for (struct account *account = blob->account_head; account; account = account->next) {
		if (!account->share)
			write_account_chunk(&buffer, account, key);
	}
	for (struct account *account = blob->account_head; account; account = account->next) {
		if (!account->share)
			continue;
		if (last_share != account->share) {
			write_share_chunk(&buffer, account->share);
			last_share = account->share;
		}
		write_account_chunk(&buffer, account, account->share->key);
	}

	*out = buffer.bytes;
	return buffer.len;
}

static struct blob *local_blob(const unsigned char key[KDF_HASH_LEN], const struct private_key *private_key)
{
	_cleanup_free_ char *blob = NULL;
	size_t len = config_read_encrypted_buffer("blob", &blob, key);
	if (!blob)
		return NULL;
	return blob_parse(blob, len, key, private_key);
}
Пример #5
0
static char *upload_queue_next_entry(unsigned const char key[KDF_HASH_LEN], char **name, char **lock)
{
	unsigned long long smallest = ULLONG_MAX, current;
	_cleanup_free_ char *smallest_name = NULL;
	_cleanup_free_ char *base_path = config_path("upload-queue");
	_cleanup_free_ char *pidstr = NULL;
	pid_t pid;
	char *result, *p;
	DIR *dir = opendir(base_path);
	struct dirent *entry;

	if (!dir)
		return NULL;
	while ((entry = readdir(dir))) {
		if (entry->d_type != DT_REG)
			continue;
		for (p = entry->d_name; *p; ++p) {
			if (!isdigit(*p))
				break;
		}
		if (*p)
			continue;
		current = strtoull(entry->d_name, NULL, 10);
		if (!current)
			continue;
		if (current < smallest) {
			smallest = current;
			free(smallest_name);
			smallest_name = xstrdup(entry->d_name);
		}
	}
	closedir(dir);
	if (smallest == ULLONG_MAX)
		return NULL;

	xasprintf(name, "upload-queue/%s", smallest_name);
	xasprintf(lock, "%s.lock", *name);
	while (config_exists(*lock)) {
		free(pidstr);
		pidstr = config_read_encrypted_string(*lock, key);
		if (!pidstr) {
			config_unlink(*lock);
			break;
		}
		pid = strtoul(pidstr, NULL, 10);
		if (!pid) {
			config_unlink(*lock);
			break;
		}
		if (process_is_same_executable(pid))
			sleep(1);
		else {
			config_unlink(*lock);
			break;
		}
	}
	free(pidstr);
	pidstr = xultostr(getpid());
	config_write_encrypted_string(*lock, pidstr, key);
	result = config_read_encrypted_string(*name, key);
	if (!result) {
		/* could not decrypt: drop this file */
		upload_queue_drop(*name);
		config_unlink(*lock);
		return NULL;
	}
	return result;
}