--- /dev/null
+passman -- simple password manager
+It stores passwords in single recfile
+(https://www.gnu.org/software/recutils/), that is by default encrypted
+by age (https://github.com/FiloSottile/age) with the passphrase and
+compressed by zstd.
+
+* passman add NAME [PASSWORD]
+ Appends NAME credential with optional password to the database. If
+ password is not provided, then it will be autogenerated.
+* passman has NAME
+ Just returns if specified credential exists.
+* passman gen
+ Prints autogenerated password.
+* passman mod
+ Decrypts whole database to temporary file and runs editor on it.
+* passman NAME
+ Search for specified credential. That can be regexp. If more than
+ single entity is found, then print found names. If single entity is
+ found, then its basename (last part after the slash) is copied to
+ primary X11 buffer, and password is copied to clipboard buffer. Then
+ sleep for ten seconds and clear the clipboard.
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-DB=~/.passmandb
+DB=${PASSMANDB:-$HOME/.passmandb}
+
+dec() {
+ if [ -s $DB ] ; then
+ age -d $DB | zstd -d
+ else
+ cat <<EOF
+%rec: Credential
+%key: Name
+%mandatory: Name Passwd
+%allowed: Data
+EOF
+ fi
+}
+
+enc() {
+ zstd | age -p
+}
generator() {
- gpg --armor --gen-random 1 16 | tr '+/' '-_' | tr -d =
+ dd if=/dev/random bs=16 count=1 status=none | base64 | tr "+/" "-_" | tr -d =
}
cliper() {
xclip -in -selection $1
}
-ENTITY=""
+tmp=`mktemp`.rec
+trap "rm -f $tmp" HUP PIPE INT QUIT TERM EXIT
finder() {
- cd $DB
- result=$(find . -type d -path "*$1*" | while read ent; do
- [ -e "$ent/passwd" ] || continue
- echo "$ent" | sed 's#^\./##'
- done)
- if [ $(echo "$result" | wc -l) -ne 1 ]; then
- echo "$result"
+ dec | recsel -e "Name ~ '$1'" > $tmp
+ [ $(recsel -c $tmp) -eq 1 ] || {
+ recsel -C -P Name $tmp
exit 1
- fi
- [ -n "$result" ] || exit 1
- ENTITY=$result
- echo "$result"
+ }
+}
+
+commit() {
+ enc < $tmp > ${DB}.tmp
+ fsync ${DB}.tmp
+ mv ${DB}.tmp $DB
}
case "$1" in
passwd="$3"
[ -n "$dst" ]
[ -n "$passwd" ] || passwd=$(generator)
- echo Adding password for $dst
- mkdir -p $DB/$dst
- umask 077
- echo "$passwd" > $DB/$dst/passwd
+ echo ${dst}...
+ dec | recins -t Credential -f Name -v "$dst" -f Passwd -v "$passwd" > $tmp
+ commit
+ ;;
+mod)
+ dec > $tmp
+ $EDITOR $tmp
+ commit
;;
*)
finder "$1"
- if [ -e "$ENTITY"/data ]; then
- echo -n "Associated data: "
- cat "$ENTITY"/data
- fi
- perl -ne 'chop and print' "$ENTITY"/passwd | cliper clipboard
- echo $(basename "$ENTITY") | perl -ne 'chop and print' | cliper primary
+ name=$(recsel -P Name $tmp)
+ echo $name >&2
+ data=$(recsel -P Data $tmp)
+ [ -z "$data" ] || echo "Associated data: $data"
+ echo -n $(recsel -P Passwd $tmp) | cliper clipboard
+ echo -n ${name##*/} | cliper primary
sleep 10
echo -n | cliper clipboard
;;