]> Sergey Matveev's repositories - passman.git/commitdiff
Use recfile and age
authorSergey Matveev <stargrave@stargrave.org>
Sun, 3 Sep 2023 12:46:34 +0000 (15:46 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Sun, 3 Sep 2023 12:47:27 +0000 (15:47 +0300)
README [new file with mode: 0644]
passman

diff --git a/README b/README
new file mode 100644 (file)
index 0000000..356fd49
--- /dev/null
+++ b/README
@@ -0,0 +1,21 @@
+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.
diff --git a/passman b/passman
index a8e825ece39cec650ae113a4fbf9778c590c2181..2ade1acdb4e388bbef662654cd29e726d7492752 100755 (executable)
--- a/passman
+++ b/passman
 # 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
@@ -53,19 +70,23 @@ add)
     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
     ;;