示例#1
0
bool agent_get_decryption_key(unsigned char key[KDF_HASH_LEN])
{
	char *disable_str;

	if (config_exists("plaintext_key")) {
		_cleanup_free_ char *key_buffer = NULL;
		if (config_read_buffer("plaintext_key", &key_buffer) == KDF_HASH_LEN) {
			_cleanup_free_ char *verify = config_read_encrypted_string("verify", (unsigned char *)key_buffer);
			if (!verify || strcmp(verify, AGENT_VERIFICATION_STRING))
				goto badkey;
			memcpy(key, key_buffer, KDF_HASH_LEN);
			secure_clear(key_buffer, KDF_HASH_LEN);
			mlock(key, KDF_HASH_LEN);
			return true;
		}
		badkey: config_unlink("plaintext_key");
	}
	if (!agent_ask(key)) {
		if (!agent_load_key(key))
			return false;
		disable_str = getenv("LPASS_AGENT_DISABLE");
		if (!disable_str || strcmp(disable_str, "1")) {
			agent_start(key);
		}
	}
	mlock(key, KDF_HASH_LEN);
	return true;
}
示例#2
0
void session_kill()
{
	if (!config_unlink("verify") || !config_unlink("username") || !config_unlink("session_sessionid") || !config_unlink("iterations"))
		die_errno("could not log out.");
	config_unlink("blob");
	config_unlink("session_token");
	config_unlink("session_uid");
	config_unlink("session_privatekey");
	config_unlink("session_server");
	config_unlink("plaintext_key");
	agent_kill();
	upload_queue_kill();
}
示例#3
0
int cmd_logout(int argc, char **argv)
{
	static struct option long_options[] = {
		{"force", no_argument, NULL, 'f'},
		{0, 0, 0, 0}
	};
	int option;
	int option_index;
	bool force = false;
	struct session *session = NULL;
	unsigned char key[KDF_HASH_LEN];

	while ((option = getopt_long(argc, argv, "f", long_options, &option_index)) != -1) {
		switch (option) {
			case 'f':
				force = true;
				break;
			case '?':
			default:
				die_usage(cmd_logout_usage);
		}
	}
	if (optind < argc)
		die_usage(cmd_logout_usage);

	if (!config_exists("verify"))
		die("Not currently logged in.");

	if (!force && !ask_yes_no(true, "Are you sure you would like to log out?")) {
		terminal_printf(TERMINAL_FG_YELLOW TERMINAL_BOLD "Log out" TERMINAL_RESET ": aborted.\n");
		return 1;
	}

	init_all(0, key, &session, NULL);

	if (!config_unlink("verify") || !config_unlink("username") || !config_unlink("session_sessionid") || !config_unlink("iterations"))
		die_errno("could not log out.");
	config_unlink("blob");
	config_unlink("session_token");
	config_unlink("session_uid");
	config_unlink("session_privatekey");
	config_unlink("plaintext_key");
	agent_kill();
	upload_queue_kill();
	lastpass_logout(session);
	terminal_printf(TERMINAL_FG_YELLOW TERMINAL_BOLD "Log out" TERMINAL_RESET ": complete.\n");
	return 0;
}
示例#4
0
int cmd_login(int argc, char **argv)
{
    static struct option long_options[] = {
        {"trust", no_argument, NULL, 't'},
        {"plaintext-key", no_argument, NULL, 'P'},
        {"force", no_argument, NULL, 'f'},
        {"color", required_argument, NULL, 'C'},
        {0, 0, 0, 0}
    };
    int option;
    int option_index;
    bool trust = false;
    bool plaintext_key = false;
    bool force = false;
    char *username;
    _cleanup_free_ char *error = NULL;
    _cleanup_free_ char *password = NULL;
    int iterations;
    struct session *session;
    unsigned char key[KDF_HASH_LEN];
    char hex[KDF_HEX_LEN];

    while ((option = getopt_long(argc, argv, "f", long_options, &option_index)) != -1) {
        switch (option) {
        case 't':
            trust = true;
            break;
        case 'P':
            plaintext_key = true;
            break;
        case 'f':
            force = true;
            break;
        case 'C':
            terminal_set_color_mode(
                parse_color_mode_string(optarg));
            break;
        case '?':
        default:
            die_usage(cmd_login_usage);
        }
    }
    if (argc - optind != 1)
        die_usage(cmd_login_usage);

    if (!force && plaintext_key && !ask_yes_no(false, "You have used the --plaintext-key option. This option will greatly reduce the security of your passwords. You are advised, instead, to use the agent, whose timeout can be disabled by settting LPASS_AGENT_TIMEOUT=0. Are you sure you would like to do this?"))
        die("Login aborted. Try again without --plaintext-key.");

    username = argv[optind];
    iterations = lastpass_iterations(username);
    if (!iterations)
        die("Unable to fetch iteration count. Check your internet connection and be sure your username is valid.");

    do {
        free(password);
        password = password_prompt("Master Password", error, "Please enter the LastPass master password for <%s>.", username);
        if (!password)
            die("Failed to enter correct password.");

        kdf_login_key(username, password, iterations, hex);
        kdf_decryption_key(username, password, iterations, key);

        free(error);
        error = NULL;
        session = lastpass_login(username, hex, key, iterations, &error, trust);
    } while (!session_is_valid(session));

    config_unlink("plaintext_key");
    if (plaintext_key)
        config_write_buffer("plaintext_key", (char *)key, KDF_HASH_LEN);

    agent_save(username, iterations, key);

    session_save(session, key);
    session_free(session);
    session = NULL;

    terminal_printf(TERMINAL_FG_GREEN TERMINAL_BOLD "Success" TERMINAL_RESET ": Logged in as " TERMINAL_UNDERLINE "%s" TERMINAL_RESET ".\n", username);

    return 0;
}
示例#5
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));
}
示例#6
0
static void upload_queue_cleanup(int signal)
{
	UNUSED(signal);
	config_unlink("uploader.pid");
	_exit(EXIT_SUCCESS);
}
示例#7
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;
}