Ejemplo n.º 1
0
int cmd_rm(int argc, char **argv)
{
	unsigned char key[KDF_HASH_LEN];
	struct session *session = NULL;
	struct blob *blob = NULL;
	static struct option long_options[] = {
		{"sync", required_argument, NULL, 'S'},
		{"color", required_argument, NULL, 'C'},
		{0, 0, 0, 0}
	};
	int option;
	int option_index;
	char *name;
	enum blobsync sync = BLOB_SYNC_AUTO;
	struct account *found;

	while ((option = getopt_long(argc, argv, "", long_options, &option_index)) != -1) {
		switch (option) {
			case 'S':
				sync = parse_sync_string(optarg);
				break;
			case 'C':
				terminal_set_color_mode(
					parse_color_mode_string(optarg));
				break;
			case '?':
			default:
				die_usage(cmd_rm_usage);
		}
	}

	if (argc - optind != 1)
		die_usage(cmd_rm_usage);
	name = argv[optind];

	init_all(sync, key, &session, &blob);
	found = find_unique_account(blob, name);
	if (!found)
		die("Could not find specified account '%s'.", name);
	if (found->share && found->share->readonly)
		die("%s is a readonly shared entry from %s. It cannot be deleted.", found->fullname, found->share->name);

	list_del(&found->list);

	lastpass_remove_account(sync, key, session, found, blob);
	blob_save(blob, key);
	account_free(found);

	session_free(session);
	blob_free(blob);
	return 0;
}
Ejemplo n.º 2
0
int cmd_sync(int argc, char **argv)
{
	unsigned char key[KDF_HASH_LEN];
	struct session *session = NULL;
	struct blob *blob = NULL;
	static struct option long_options[] = {
		{"background", no_argument, NULL, 'b'},
		{"color", required_argument, NULL, 'C'},
		{0, 0, 0, 0}
	};
	int option;
	int option_index;
	bool background = false;

	while ((option = getopt_long(argc, argv, "b", long_options, &option_index)) != -1) {
		switch (option) {
			case 'b':
				background = true;
				break;
			case 'C':
				terminal_set_color_mode(
					parse_color_mode_string(optarg));
				break;
			case '?':
			default:
				die_usage(cmd_sync_usage);
		}
	}

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

	upload_queue_ensure_running(key, session);
	if (!background) {
		while (upload_queue_is_running())
			usleep(1000000 / 3);
	}


	session_free(session);
	blob_free(blob);
	return 0;
}
Ejemplo n.º 3
0
int cmd_status(int argc, char **argv)
{
	unsigned char key[KDF_HASH_LEN];
	static struct option long_options[] = {
		{"quiet", no_argument, NULL, 'q'},
		{"color", required_argument, NULL, 'C'},
		{0, 0, 0, 0}
	};
	int option;
	int option_index;
	bool quiet = false;
	_cleanup_free_ char *username = NULL;

	while ((option = getopt_long(argc, argv, "q", long_options, &option_index)) != -1) {
		switch (option) {
			case 'q':
				quiet = true;
				break;
			case 'C':
				terminal_set_color_mode(
					parse_color_mode_string(optarg));
				break;
			case '?':
			default:
				die_usage(cmd_status_usage);
		}
	}

	if (!agent_ask(key)) {
		if(!quiet) {
			terminal_printf(TERMINAL_FG_RED TERMINAL_BOLD "Not logged in" TERMINAL_RESET ".\n");
		}
		return 1;
	} else {
		if(!quiet) {
			username = config_read_string("username");
			terminal_printf(TERMINAL_FG_GREEN TERMINAL_BOLD "Logged in" TERMINAL_RESET " as " TERMINAL_UNDERLINE "%s" TERMINAL_RESET ".\n", username);
		}
		return 0;
	}
}
Ejemplo n.º 4
0
int cmd_edit(int argc, char **argv)
{
	unsigned char key[KDF_HASH_LEN];
	struct session *session = NULL;
	struct blob *blob = NULL;
	static struct option long_options[] = {
		{"sync", required_argument, NULL, 'S'},
		{"username", no_argument, NULL, 'U'},
		{"password", no_argument, NULL, 'P'},
		{"url", no_argument, NULL, 'L'},
		{"field", required_argument, NULL, 'F'},
		{"name", no_argument, NULL, 'N'},
		{"notes", no_argument, NULL, 'O'},
		{"non-interactive", no_argument, NULL, 'X'},
		{"color", required_argument, NULL, 'C'},
		{0, 0, 0, 0}
	};
	int option;
	int option_index;
	enum { NONE, USERNAME, PASSWORD, URL, FIELD, NAME, NOTES } choice = NONE;
	_cleanup_free_ char *field = NULL;
	_cleanup_free_ char *tmppath = NULL;
	_cleanup_free_ char *tmpdir = NULL;
	_cleanup_free_ char *editcmd = NULL;
	int tmpfd;
	FILE *tmpfile;
	char *name;
	char *value;
	bool non_interactive = false;
	enum blobsync sync = BLOB_SYNC_AUTO;
	struct account *editable;
	struct account *notes_expansion, *notes_collapsed = NULL;
	struct field *editable_field = NULL;
	size_t len, read;
	bool should_log_read = false;

	#define ensure_choice() if (choice != NONE) goto choice_die;
	while ((option = getopt_long(argc, argv, "", long_options, &option_index)) != -1) {
		switch (option) {
			case 'S':
				sync = parse_sync_string(optarg);
				break;
			case 'U':
				ensure_choice();
				choice = USERNAME;
				break;
			case 'P':
				ensure_choice();
				choice = PASSWORD;
				break;
			case 'L':
				ensure_choice();
				choice = URL;
				break;
			case 'F':
				ensure_choice();
				choice = FIELD;
				field = xstrdup(optarg);
				break;
			case 'N':
				ensure_choice();
				choice = NAME;
				break;
			case 'O':
				ensure_choice();
				choice = NOTES;
				break;
			case 'X':
				non_interactive = true;
				break;
			case 'C':
				terminal_set_color_mode(
					parse_color_mode_string(optarg));
				break;
			case '?':
			default:
				die_usage(cmd_edit_usage);
		}
	}
	#undef ensure_choice

	if (argc - optind != 1)
		die_usage(cmd_edit_usage);
	if (choice == NONE)
		choice_die: die_usage("edit ... {--name|--username|--password|--url|--notes|--field=FIELD}");
	name = argv[optind];

	init_all(sync, key, &session, &blob);

	editable = find_unique_account(blob, name);
	if (editable) {
		if (editable->share && editable->share->readonly)
			die("%s is a readonly shared entry from %s. It cannot be edited.", editable->fullname, editable->share->name);
		should_log_read = true;
	} else {
		editable = new0(struct account, 1);
		editable->id = xstrdup("0");
		account_set_password(editable, xstrdup(""), key);
		account_set_fullname(editable, xstrdup(name), key);
		account_set_username(editable, xstrdup(""), key);
		account_set_note(editable, xstrdup(""), key);
		editable->url = xstrdup("");

		editable->next = blob->account_head;
		blob->account_head = editable;
	}
	notes_expansion = notes_expand(editable);
	if (notes_expansion) {
		notes_collapsed = editable;
		editable = notes_expansion;
	} else if (choice == FIELD)
		die("Editing fields of entries that are not secure notes is currently not supported.");

	if (choice == USERNAME)
		value = editable->username;
	else if (choice == PASSWORD)
		value = editable->password;
	else if (choice == URL)
		value = editable->url;
	else if (choice == NAME)
		value = editable->fullname;
	else if (choice == FIELD) {
		for (editable_field = editable->field_head; editable_field; editable_field = editable_field->next) {
			if (!strcmp(editable_field->name, field))
				break;
		}
		if (!editable_field) {
			editable_field = new0(struct field, 1);
			editable_field->type = xstrdup("text");
			editable_field->name = xstrdup(field);
			field_set_value(editable, editable_field, xstrdup(""), key);

			editable_field->next = editable->field_head;
			editable->field_head = editable_field;
		}
		value = editable_field->value;
	} else if (choice == NOTES)
Ejemplo n.º 5
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;
}
Ejemplo n.º 6
0
int cmd_edit(int argc, char **argv)
{
	unsigned char key[KDF_HASH_LEN];
	struct session *session = NULL;
	struct blob *blob = NULL;
	static struct option long_options[] = {
		{"sync", required_argument, NULL, 'S'},
		{"username", no_argument, NULL, 'u'},
		{"password", no_argument, NULL, 'p'},
		{"url", no_argument, NULL, 'L'},
		{"field", required_argument, NULL, 'F'},
		{"name", no_argument, NULL, 'N'},
		{"notes", no_argument, NULL, 'O'},
		{"non-interactive", no_argument, NULL, 'X'},
		{"color", required_argument, NULL, 'C'},
		{0, 0, 0, 0}
	};
	int option;
	int option_index;
	_cleanup_free_ char *field = NULL;
	char *name;
	bool non_interactive = false;
	enum blobsync sync = BLOB_SYNC_AUTO;
	struct account *editable;
	enum edit_choice choice = EDIT_ANY;
	enum note_type note_type = NOTE_TYPE_NONE;

	#define ensure_choice() if (choice != EDIT_ANY) goto choice_die;
	while ((option = getopt_long(argc, argv, "up", long_options, &option_index)) != -1) {
		switch (option) {
			case 'S':
				sync = parse_sync_string(optarg);
				break;
			case 'u':
				ensure_choice();
				choice = EDIT_USERNAME;
				break;
			case 'p':
				ensure_choice();
				choice = EDIT_PASSWORD;
				break;
			case 'L':
				ensure_choice();
				choice = EDIT_URL;
				break;
			case 'F':
				ensure_choice();
				choice = EDIT_FIELD;
				field = xstrdup(optarg);
				break;
			case 'N':
				ensure_choice();
				choice = EDIT_NAME;
				break;
			case 'O':
				ensure_choice();
				choice = EDIT_NOTES;
				break;
			case 'X':
				non_interactive = true;
				break;
			case 'C':
				terminal_set_color_mode(
					parse_color_mode_string(optarg));
				break;
			case '?':
			default:
				die_usage(cmd_edit_usage);
		}
	}
	#undef ensure_choice

	if (argc - optind != 1)
		die_usage(cmd_edit_usage);
	if (choice == EDIT_NONE)
		choice_die: die_usage("edit ... {--name|--username|--password|--url|--notes|--field=FIELD}");
	name = argv[optind];

	init_all(sync, key, &session, &blob);

	editable = find_unique_account(blob, name);
	if (!editable)
		return edit_new_account(session, blob, sync, name, choice,
					field, non_interactive, false,
					note_type, key);

	if (editable->share && editable->share->readonly)
		die("%s is a readonly shared entry from %s. It cannot be edited.",
		    editable->fullname, editable->share->name);

	return edit_account(session, blob, sync, editable, choice, field,
			    non_interactive, key);
}
Ejemplo n.º 7
0
int cmd_export(int argc, char **argv)
{
	static struct option long_options[] = {
		{"sync", required_argument, NULL, 'S'},
		{"color", required_argument, NULL, 'C'},
		{0, 0, 0, 0}
	};
	int option;
	int option_index;
	enum blobsync sync = BLOB_SYNC_AUTO;
	while ((option = getopt_long(argc, argv, "c", long_options, &option_index)) != -1) {
		switch (option) {
			case 'S':
				sync = parse_sync_string(optarg);
				break;
			case 'C':
				terminal_set_color_mode(
					parse_color_mode_string(optarg));
				break;
			case '?':
			default:
				die_usage(cmd_export_usage);
		}
	}

	unsigned char key[KDF_HASH_LEN];
	struct session *session = NULL;
	struct blob *blob = NULL;
	init_all(sync, key, &session, &blob);

	/* reprompt once if any one account is password protected */
	for (struct account *account = blob->account_head; account; account = account->next) {
		if (account->pwprotect) {
			unsigned char pwprotect_key[KDF_HASH_LEN];
			if (!agent_load_key(pwprotect_key))
				die("Could not authenticate for protected entry.");
			if (memcmp(pwprotect_key, key, KDF_HASH_LEN))
				die("Current key is not on-disk key.");
			break;
		}
	}

	printf("url,username,password,hostname,name,grouping\r\n");
	for (struct account *account = blob->account_head; account; account = account->next) {

		/* skip shared notes */
		if (!strcmp(account->url, "http://sn"))
			continue;

		lastpass_log_access(sync, session, key, account);
		print_csv_cell(account->url, false);
		print_csv_cell(account->username, false);
		print_csv_cell(account->password, false);
		print_csv_cell(account->fullname, false);
		print_csv_cell(account->name, false);
		print_csv_cell(account->group, true);
	}

	session_free(session);
	blob_free(blob);
	return 0;
}