Beispiel #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) {
		_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);
}
Beispiel #2
0
static void lpass_log(enum log_level level, char *fmt, ...)
{
	struct timeval tv;
	struct timezone tz;
	va_list ap;

	int req_level = lpass_log_level();

	if (req_level < level)
		return;

	gettimeofday(&tv, &tz);
	printf("<%d> [" TIME_FMT "] ", level, TIME_ARGS(&tv));
	va_start(ap, fmt);
	vprintf(fmt, ap);
	va_end(ap);
}
Beispiel #3
0
char *http_post_lastpass(const char *page, const struct session *session, size_t *final_len, ...)
{
	va_list args;
	struct http_param_set params = {
		.argv = NULL,
		.n_alloced = 0
	};

	va_start(args, final_len);
	vhttp_post_add_params(&params, args);
	char *result = http_post_lastpass_param_set(page, session, final_len, &params);
	free(params.argv);
	return result;
}

#ifndef TEST_BUILD
char *http_post_lastpass_v_noexit(const char *server, const char *page, const struct session *session, size_t *final_len, char **argv, int *curl_ret, long *http_code)
{
	_cleanup_free_ char *url = NULL;
	_cleanup_free_ char *postdata = NULL;
	_cleanup_free_ char *cookie = NULL;
	_cleanup_fclose_ FILE *logstream = NULL;
	char *param, *encoded_param;
	CURL *curl = NULL;
	char separator;
	size_t len, new_len;
	int ret;
	struct mem_chunk result;
	const char *login_server;

	/* if we have a session, use that server, otherwise use whatever was passed */
	login_server = session ? session->server : server;

	/* if nothing passed, use lastpass */
	if (!login_server)
		login_server = LASTPASS_SERVER;

	xasprintf(&url, "https://%s/%s", login_server, page);

	lpass_log(LOG_DEBUG, "Making request to %s\n", url);

	curl = curl_easy_init();
	if (!curl)
		die("Could not init curl");

	len = 0;
	for (separator = '=', param = *argv;
	     param;
	     separator = (separator == '=') ? '&' : '=', param = *(++argv)) {
		encoded_param = curl_easy_escape(curl, param, 0);
		if (!encoded_param)
			die("Could not escape %s with curl", param);
		new_len = strlen(encoded_param) + 1 /* separator */;
		postdata = xrealloc(postdata, len + new_len + 1 /* null */);
		snprintf(postdata + len, new_len + 1, "%s%c", encoded_param, separator);
		len += new_len;
		curl_free(encoded_param);
	}
	if (len && postdata)
		postdata[len - 1] = '\0';

	memset(&result, 0, sizeof(result));
	curl_easy_setopt(curl, CURLOPT_URL, url);
	curl_easy_setopt(curl, CURLOPT_USERAGENT, LASTPASS_CLI_USERAGENT);

	/* TODO: Make this optional via either env vars and/or an option for
	 *       lpass -4 or lpass -6
	 */
	curl_easy_setopt(curl, CURLOPT_IPRESOLVE, CURL_IPRESOLVE_V4);

	if (lpass_log_level() >= LOG_VERBOSE) {
		logstream = lpass_log_open();
		if (logstream) {
			curl_easy_setopt(curl, CURLOPT_STDERR, logstream);
			curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);
		}
	}
#if defined(DO_NOT_ENABLE_ME_MITM_PROXY_FOR_DEBUGGING_ONLY)
	curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0);
	curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0);
	curl_easy_setopt(curl, CURLOPT_PROXY, "http://localhost:8080");
#else
	curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2);
	curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1);
	curl_easy_setopt(curl, CURLOPT_SSL_CTX_FUNCTION, pin_keys);
#endif
	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);
	curl_easy_setopt(curl, CURLOPT_WRITEDATA, &result);
	curl_easy_setopt(curl, CURLOPT_FAILONERROR, 1);
	curl_easy_setopt(curl, CURLOPT_PROGRESSFUNCTION, check_interruption);
	curl_easy_setopt(curl, CURLOPT_NOPROGRESS, 0);
	if (postdata)
		curl_easy_setopt(curl, CURLOPT_POSTFIELDS, postdata);
	if (session) {
		xasprintf(&cookie, "PHPSESSID=%s", session->sessionid);
		curl_easy_setopt(curl, CURLOPT_COOKIE, cookie);
	}

	set_interrupt_detect();
	ret = curl_easy_perform(curl);
	unset_interrupt_detect();

	curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, http_code);
	curl_easy_cleanup(curl);
	*curl_ret = ret;

	if (ret != CURLE_OK) {
		result.len = 0;
		free(result.ptr);
		result.ptr = NULL;
	} else if (!result.ptr)
		result.ptr = xstrdup("");
	if (final_len)
		*final_len = result.len;

	return result.ptr;
}