示例#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;
}
示例#2
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'},
		{0, 0, 0, 0}
	};
	char 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 '?':
			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)
示例#3
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);
}
示例#4
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;
}