This document proposes some new features to be added to command-line version of pwsafe (called pwsafe-cli, in src/ui/cli). It will probably not achieve feature parity with the GUI version, but will make pwsafe a lot more useful at the command-line.
- Existing Actions
- New Actions
- Multi-safe operations
All commands require the safe to be operated on as the very first argument to pwsafe-cli. This is the "current" safe: any operation that requires another safe provides the path to that safe as the value to the operation (e.g. --diff=some/other/safe.psafe3).
Any operation that can modify the safe takes a --dry-run
argument which just skips the part that saves the safe file after making modifications.
pwsafe-cli already implements import from & export to text & xml formats:
pwsafe-cli mysafe.psafe3 --imp|--exp[=filename] --text|--xml
pwsafe-cli newsafe.psafe3 --new
newsafe.psafe3 must not exist.
`pwsafe-cli newsafe-psafe3 --add='Group=Forums,Title=AVSForum,email=me@newmail.com,password=secret'`
Password is auto-generated if unspecified. Its an error if entry already exists.
This is perhaps the most important command, because it lets you zero in on an entry and perform some operation on it. For search actions that modify the safe, pwsafe-cli would confirm before performing the action, once for each entry irrespective of the number of changes to that entry. --yes
suppresses the confirmation, and just goes ahead with the changes.
`pwsafe-cli mysafe.psafe3 --search=search-text [--ignore-case] [--subset=Group^=Banks/[Ii]] [--fields=autotype,dca,...] [--yes] ACTION`
The --subset
argument has the format <field><operator><value>
. Other supported operators (mimicking the GUI) are
- == (exactly equal-to)
- !== (not equal-to)
- ^= (begins with)
- !^= (does not begin with)
- $= (ends with)
- !$= (does not end-with)
- ~= (contains)
- !~= (does not contain)
A trailing /i makes the string operation case-insensitive, while /I makes it case sensitive.
The fields
argument is a comma-separated list of fields in which search-text
would be searched for. By default, all fields would be searched. The known valid field types are
- Group
- Title
- Username
- Notes
- Password
- Created Time
- Password Modified Time
- Last Access Time
- Password Expiry Date
- Record Modified Time
- URL
- AutoType
- History
- Password Policy
- Password Expiry Interval
- Run Command
- DCA
- Shift-DCA
- Protected
- Symbols
- Password Policy Name
- Keyboard Shortcut
ACTION represents the action to be performed on the search results. Default action is print
. Available search actions are
Results are printed on stdout one entry per line in the following format:
Group1 >> Title1[User1] Group2 >> Title2[User2] Title3[User3] Group4 >> Title4 Title5
Printing just prints the Group, Title & User of matching entries on stdout, but Title is the only field that's guaranteed to be present for an entry. However, other fields can be printed by explicitly specifying the search action to be --print
with the desired fields:
pwsafe-cli <safe> --search=gmail --print=e-mail,URL
pwsafe-cli ~/Sample123.psafe3 --search=gmail --delete
pwsafe-cli <safe> --search=gmail --update=Field1=Value1,Field2=Value2...
pwsafe-cli <safe> --search=gmail --clear=field1,field2...
This will use the safe's and entry's password policy to generate the new password
`pwsafe-cli mysafe.psafe3 --search=Hotmail --fields=Title --new-password`
`pwsafe-cli mysafe.psafe3 --diff=othersafe.psafe3 [--subset=Group^=Banks/[Ii]] [--fields=autotype,dca,...] [ --unified | --context | --sidebyside [--colwidth=<number>]]`
Show unified (default), context or side-by-side diff. Entries selected for comparison can be restricted by --subset
, just like --search
. Fields to be compared can be restricted with --fields
.
`pwsafe-cli mysafe.psafe3 --sync=othersafe.psafe3 [--subset=Group^=Banks/[Ii]] [--fields=autotype,dca,...] [--yes]`
Update entries of mysafe.psafe3 with matching entries from othersafe.psafe3, wherever they differ. Entries in othersafe.psafe3 that don't exist in mysafe.psafe3 are ignored. Fields selected for sync'ing and the fields sync'ed in matching entries can be restricted just like --search.
--yes
suppresses the "yes, no, no-to-all, yes-to-all, quit, abort" prompt before making each change.
`pwsafe-cli mysafe.psafe3 --merge=othersafe.psafe3 [--subset=Group^=Banks/[Ii]] --yes`
Merges all fields of matching entries. The entries selected for merging can be restricted, but NOT the fields.
--yes
suppresses the "yes, no, no-to-all, yes-to-all, quit, abort" prompt before making each change.
For all operations that require a passphrase, pwsafe-cli would read it by turning terminal echo off. It won't support entering the passphrase on the command-line due to security concerns: it would probably get logged in shell history, be visible in ps
output and could be visible in a scrollable terminal window. However, for performing multiple operations on a safe, it might sometimes be convenient to automate the passphrase input for pwsafe-cli, in a secure mannerl.
export PASSWORSAFE_PASSWORD=mysecret
pwsafe-cli mysafe.psafe3 --combination-env=PASSWORDSAFE_PASSWORD --select='Title:ebay' --view
This idea is from ipmitool, which works somewhat like that.
There are possibly security issues with this feature, so it is under review. The arguments in favor are:
-
The user has to set the environment variable with the passphrase himself. It doesn't get set automatically.
-
The user controls the name of the environment variable. So it could be different for each user, e.g. MY_TEMP_FOO, every single time they set the variable.
-
Any attempt to exploit this feature requires the machine to be exploited already. In which case, the malicious code would use a keylogger or screenshot generator. Basically, on a compromised machine, the game is over anyway. Any "external" code would run in a browser, which won't allow access to environment variables.
-
It could be compiled in conditionally, with exclusion being the default.
And lastly, this is a very useful feature which allows users to not have to type long & hard to remember (& type) passphrases for every invocation of pwsafe-cli. The only other secure alternative is to type it each time which is very inconvenient for long & hard passphrases, which would push users choose weak & short passphrases for their safes (but the passphrase entry would be secure). The keyring option, IMO, is less secure than this. Using file descriptor is only good for scripting.
The keyring manager should prompt the user to allow/disallow specific apps from accessing the password.
`pwsafe-cli mysafe.psafe3 --combination-keyring --search=AVSForum --print=Notes`
An application having access to a safe's combination might want to launch pwsafe-cli and pass the combination to it securely. Passing safe combination as command line parameter has the security issue that the combination could be visible in the output of ps
command. Instead, the parent application could create an fd and fork pwsafe such that pwsafe inherits it. The combination then be securely written to & read from the fd by the parent application and pwsafe-cli respectively.
`pwsafe-cli mysafe.psafe3 --combination-fd=5 --search=SomeTitle --autotype`
`pwsafe-cli mysafe.psafe3 --search=Github --fields=Title --to-clipboard=password`
I'm not sure if copy/paste makes sense outside of a GUI enviroment like X. Therefore, this feature would probably depend on conditional compilation, and be available only if the required system headers are found at compilation time. Alternatively, it could work like expect
for non-gui purposes, although I don't know right now how expect
works. If not compiled in, it could probably use xsel
if available at runtime.
`pwsafe-cli mysafe.psafe3 --search='Gmail' --fields=Title --autotype`
This feature is subject to further review & investigation. But for now, it seems that on Linux, since it requires compiling & linking with X windows headers, it would compiled conditionally. Though pwsafe-cli is intended for a non-GUI server-like environment, the feature itself would be useful in an xterm-like app in a GUI environment like Gnome. Alternatively, it could use an external tool like xdotool to do the autotyping, if not compiled with this feature natively.
Run an external command as configured in the entry
`pwsafe-cli mysafe.psafe3 --search=HomeNAS --fields=Title --run-command`
Run Command feature has not been implemented in the Linux/wxWidgets port yet.