#!/bin/bash -pe # SPDX-License-Identifier: GPL-3.0-or-later # Copyright 2024, Gerrit-John Los prog="${0##*/}" default_timeout=5s secstore=~/opt/etc/"$prog" cd "$secstore" show_usage() { cat <<-EOT 1>&2 usage: $prog [-q|-e|-r|-l] [-C] [-t TIMEOUT] SECLABEL $prog {h|-l} -h: show this help -l: list configured SECLABELs -q: query SECLABEL -e: add or edit a SECLABEL -r: remove SECLABEL -C: work around a chrome bug for query mode -t: set timeout for xclip (default: $default_timeout) EOT } show_help() { show_usage cat <<-EOT 1>&2 A SECLABEL is an encrypted file containing lines with credential data, with an optional leading tag. The first empty tag is assumed to be 'user', the second 'password'. In query mode (the default) credentials are placed in turn into a one-time paste buffer while the tag is shown on stdout. If the data isn't pasted within the timeout '$prog' aborts. To abort editing a SECLABEL exit the editor with the tmpfile empty. Chrome has trouble to count to one, and reads the cut-buffer twice to get at its content. Use '-C' to enable a workaround for this broken behaviour. EOT } usage() { show_usage ; exit 1 ; } timeout=$default_timeout list=false mode='' workaround='' while getopts "hlaert:C" opt ;do case "$opt" in h) show_help ;; l) list=true ;; q) mode=query ;; a|e) mode=edit ;; r) mode=remove ;; t) timeout="$OPTARG" ;; C) workaround=chrome ;; --) break ;; *) usage ;; esac done shift $((OPTIND-1)) if $list ;then ls "${secstore}" if [ -z "$mode" -a $# -eq 0 ] ;then exit 0 fi fi [ -n "$mode" ] || mode=query [ $# -eq 1 ] || usage SECLABEL="$1" [[ "$SECLABEL" != */* ]] || usage case "$mode" in edit) passfile="${secstore}/$SECLABEL" trap "rm -f '${passfile}.tmp' || true" EXIT [ ! -e "${passfile}" ] || cp "${passfile}" "${passfile}.tmp" vi "${passfile}.tmp" if [ -s "${passfile}.tmp" ] ;then mcrypt "${passfile}.tmp" || mcrypt "${passfile}.tmp" && mv "${passfile}.tmp.nc" "${passfile}" fi ;; query) : <"$secstore/$SECLABEL" case "$workaround" in chrome) xclip_opts=(-C -t "$timeout") ;; *) xclip_opts=(-t "$timeout") ;; esac echo -n "$1: " { mcrypt -q -d <"$secstore/$1" || mcrypt -q -d <"$secstore/$1" } |xclip-credentials "${xclip_opts[@]}" ;; remove) rm -v "$secstore/$SECLABEL" ;; *) echo "${0##/}: $mode: not implemented yet" 1>&2 exit 1 ;; esac