Example #1
0
static struct blob *blob_get_latest(struct session *session, const unsigned char key[KDF_HASH_LEN])
{
	struct blob *local;
	unsigned long long remote_version;

	local = local_blob(key, &session->private_key);
	if (!local)
		return lastpass_get_blob(session, key);
	remote_version = lastpass_get_blob_version(session, key);
	if (remote_version == 0) {
		blob_free(local);
		return NULL;
	}
	if (local->version < remote_version || (local->local_version && local->version == remote_version)) {
		blob_free(local);
		return lastpass_get_blob(session, key);
	}
	config_touch("blob");
	return local;
}
Example #2
0
static void upload_queue_upload_all(const struct session *session, unsigned const char key[KDF_HASH_LEN])
{
	char *entry, *next_entry, *result;
	int size;
	char **argv = NULL;
	char **argv_ptr;
	char *name, *lock, *p;
	bool do_break;
	bool should_fetch_new_blob_after = false;
	int curl_ret;
	long http_code;
	bool http_failed_all;
	int backoff;

	while ((entry = upload_queue_next_entry(key, &name, &lock))) {
		size = 0;
		for (p = entry; *p; ++p) {
			if (*p == '\n')
				++size;
		}
		if (p > entry && p[-1] != '\n')
			++size;
		if (size < 1) {
			config_unlink(name);
			config_unlink(lock);
			goto end;
		}
		argv_ptr = argv = xcalloc(size + 1, sizeof(char **));
		for (do_break = false, p = entry, next_entry = entry; ; ++p) {
			if (!*p)
				do_break = true;
			if (*p == '\n' || !*p) {
				*p = '\0';
				*(argv_ptr++) = pinentry_unescape(next_entry);
				next_entry = p + 1;
				if (do_break)
					break;
			}
		}
		argv[size] = NULL;

		http_failed_all = true;
		backoff = 1;
		for (int i = 0; i < 5; ++i) {
			if (i) {
				sleep(backoff);
				backoff *= 8;
			}

			result = http_post_lastpass_v_noexit(argv[0],
				session->sessionid, NULL, &argv[1],
				&curl_ret, &http_code);

			http_failed_all &=
				(curl_ret == HTTP_ERROR_CODE ||
				 curl_ret == HTTP_ERROR_CONNECT);

			if (result && strlen(result))
				should_fetch_new_blob_after = true;
			free(result);
			if (result)
				break;
		}
		if (!result) {
			/* server failed response 5 times, remove it */
			if (http_failed_all)
				upload_queue_drop(name);

			config_unlink(lock);
		} else {
			config_unlink(name);
			config_unlink(lock);
		}
		for (argv_ptr = argv; *argv_ptr; ++argv_ptr)
			free(*argv_ptr);
		free(argv);
end:
		free(name);
		free(lock);
		free(entry);
	}

	if (should_fetch_new_blob_after)
		blob_free(lastpass_get_blob(session, key));
}