Add some helper functions to interact with pass
This commit is contained in:
parent
96ee23d777
commit
0419c90c9b
1 changed files with 65 additions and 0 deletions
65
modules/ordo/password-store.scm
Normal file
65
modules/ordo/password-store.scm
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
(define-module (ordo password-store)
|
||||||
|
#:use-module (ice-9 exceptions)
|
||||||
|
#:use-module (ice-9 format)
|
||||||
|
#:use-module (ice-9 popen)
|
||||||
|
#:use-module ((srfi srfi-1) #:select (last))
|
||||||
|
#:use-module ((srfi srfi-9) #:select (define-record-type))
|
||||||
|
#:use-module (ordo util read-lines)
|
||||||
|
#:use-module (ordo util shell-quote)
|
||||||
|
#:export (make-password-store
|
||||||
|
get-password
|
||||||
|
generate-password))
|
||||||
|
|
||||||
|
(define-exception-type &password-store-error &external-error
|
||||||
|
make-password-store-error
|
||||||
|
password-store-error?
|
||||||
|
(message password-store-error-message)
|
||||||
|
(cause password-store-error-cause))
|
||||||
|
|
||||||
|
(define-record-type <password-store>
|
||||||
|
(make-password-store dir)
|
||||||
|
password-store?
|
||||||
|
(dir password-store-dir))
|
||||||
|
|
||||||
|
(define (pass-command store . args)
|
||||||
|
(let ((base-cmd (if (password-store-dir store)
|
||||||
|
(format #f "env PASSWORD_STORE_DIR=~a pass" (string-shell-quote (password-store-dir store)))
|
||||||
|
"pass")))
|
||||||
|
(string-append base-cmd
|
||||||
|
" "
|
||||||
|
(string-join (map string-shell-quote args) " ")
|
||||||
|
" 2>&1")))
|
||||||
|
|
||||||
|
(define (get-password store path)
|
||||||
|
(let* ((command (pass-command store "show" path))
|
||||||
|
(port (open-input-pipe command))
|
||||||
|
(data (read-lines port))
|
||||||
|
(status (close-pipe port)))
|
||||||
|
(unless (zero? (status:exit-val status))
|
||||||
|
(raise-exception (make-password-store-error (format #f "Error getting password ~a" path) data)))
|
||||||
|
(car data)))
|
||||||
|
|
||||||
|
(define (password-exists? store path)
|
||||||
|
(and (false-if-exception (get-password store path)) #t))
|
||||||
|
|
||||||
|
(define* (generate-password store path #:key (overwrite? #f) (password-length 25))
|
||||||
|
;; WARNING: there is a race condition here between checking the password
|
||||||
|
;; exists and calling pass generate to create it. We have to pass the
|
||||||
|
;; -f option to generate in case we hit this race condition, when pass will prompt
|
||||||
|
;; for confirmation to overwrite an existing file. With the -f option, we will
|
||||||
|
;; go ahead and overwrite it, which seems the lesser of two evils.
|
||||||
|
(unless (or overwrite? (not (password-exists? store path)))
|
||||||
|
(raise-exception (make-password-store-error (format #f "Error generating password ~a" path)
|
||||||
|
"Password already exists")))
|
||||||
|
(let* ((command (pass-command store "generate" "-f" path (number->string password-length)))
|
||||||
|
(port (open-input-pipe command))
|
||||||
|
(data (read-lines port))
|
||||||
|
(status (close-pipe port)))
|
||||||
|
(unless (zero? (status:exit-val status))
|
||||||
|
(raise-exception (make-password-store-error (format #f "Error generating password for ~a" path) data)))
|
||||||
|
(let ((password (last data)))
|
||||||
|
;; Pass wraps the generated password in an escape sequence to change the
|
||||||
|
;; displayed colour: we strip this from the result.
|
||||||
|
(define prefix-len (string-length "\x1b[1m\x1b[93m"))
|
||||||
|
(define suffix-len (string-length "\x1b[0m"))
|
||||||
|
(substring password prefix-len (- (string-length password) suffix-len)))))
|
Loading…
Add table
Add a link
Reference in a new issue