2013-01-08 00:02:06 +01:00
|
|
|
;;; dispass.el --- Emacs wrapper for DisPass
|
2012-06-09 21:47:12 +02:00
|
|
|
|
|
|
|
;; Copyright (C) 2012 Tom Willemsen <tom@ryuslash.org>
|
|
|
|
|
|
|
|
;; Author: Tom Willemsen <tom@ryuslash.org>
|
|
|
|
;; Created: Jun 8, 2012
|
2013-05-04 17:02:49 +02:00
|
|
|
;; Version: 1.1.2
|
2012-07-08 22:45:53 +02:00
|
|
|
;; Keywords: processes
|
2013-05-04 16:59:26 +02:00
|
|
|
;; URL: http://projects.ryuslash.org/dispass.el/
|
2012-06-09 21:47:12 +02:00
|
|
|
|
|
|
|
;; Permission to use, copy, modify, and distribute this software for any
|
|
|
|
;; purpose with or without fee is hereby granted, provided that the
|
|
|
|
;; above copyright notice and this permission notice appear in all
|
|
|
|
;; copies.
|
|
|
|
|
|
|
|
;; THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
|
|
|
|
;; WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
|
|
|
|
;; WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
|
|
|
|
;; AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
|
|
|
|
;; CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
|
|
|
;; OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
|
|
|
|
;; NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
|
|
|
|
;; CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
|
|
|
|
|
|
;;; Commentary:
|
|
|
|
|
2013-05-04 16:59:26 +02:00
|
|
|
;; dispass.el is an Emacs wrapper around DisPass
|
2012-12-16 17:32:36 +01:00
|
|
|
;; (http://dispass.babab.nl). For more information see the README.org
|
|
|
|
;; and NEWS files.
|
2012-12-03 22:51:38 +01:00
|
|
|
|
2013-05-04 16:59:26 +02:00
|
|
|
;; This version is written for use with DisPass v0.2.0.
|
|
|
|
|
2012-06-09 21:47:12 +02:00
|
|
|
;;; Code:
|
2013-05-04 16:59:26 +02:00
|
|
|
|
2012-06-17 22:38:43 +02:00
|
|
|
(defgroup dispass nil
|
|
|
|
"Customization options for the DisPass wrapper."
|
|
|
|
:group 'external)
|
|
|
|
|
2012-07-06 00:26:27 +02:00
|
|
|
(defcustom dispass-default-length 30
|
|
|
|
"The default length to use when generating passphrases."
|
|
|
|
:package-version '(dispass . "1")
|
|
|
|
:group 'dispass
|
|
|
|
:type '(integer))
|
|
|
|
|
2012-06-17 22:38:43 +02:00
|
|
|
(defcustom dispass-executable "dispass"
|
|
|
|
"The location of the dispass executable."
|
|
|
|
:package-version '(dispass . "0.1a7.3")
|
|
|
|
:group 'dispass
|
|
|
|
:type '(string)
|
|
|
|
:risky t)
|
2012-06-09 21:47:12 +02:00
|
|
|
|
2013-05-25 13:34:26 +02:00
|
|
|
(defcustom dispass-labels-executable nil
|
2012-09-15 16:09:41 +02:00
|
|
|
"The location of the dispass-label executable."
|
2013-05-25 13:34:26 +02:00
|
|
|
:package-version '(dispass . "1.1.3")
|
2012-09-15 16:09:41 +02:00
|
|
|
:group 'dispass
|
|
|
|
:type 'string
|
|
|
|
:risky t)
|
2013-05-25 13:34:26 +02:00
|
|
|
(make-obsolete-variable 'dispass-labels-executable
|
|
|
|
"dispass-label is no longer used by DisPass."
|
|
|
|
"dispass 1.1.3")
|
2012-09-15 16:09:41 +02:00
|
|
|
|
2013-01-20 15:58:35 +01:00
|
|
|
(defcustom dispass-labelfile nil
|
2013-05-04 16:59:26 +02:00
|
|
|
"The location of your preferred labelfile.
|
|
|
|
|
|
|
|
A value of nil means to just let DisPass figure it out."
|
2013-01-20 15:58:35 +01:00
|
|
|
:package-version '(dispass . "1.1.1")
|
|
|
|
:group 'dispass
|
|
|
|
:type 'file
|
|
|
|
:risky t)
|
|
|
|
|
2012-07-05 02:14:58 +02:00
|
|
|
(defvar dispass-labels-mode-map
|
|
|
|
(let ((map (make-sparse-keymap)))
|
|
|
|
(set-keymap-parent map tabulated-list-mode-map)
|
2012-07-06 00:22:06 +02:00
|
|
|
(define-key map "c" 'dispass-create)
|
2012-07-06 00:30:15 +02:00
|
|
|
(define-key map "a" 'dispass-add-label)
|
2012-07-08 16:05:07 +02:00
|
|
|
(define-key map "d" 'dispass-remove-label)
|
2012-07-08 18:29:45 +02:00
|
|
|
map)
|
2013-05-04 16:59:26 +02:00
|
|
|
"Keymap for `dispass-labels-mode'.
|
2012-07-05 02:14:58 +02:00
|
|
|
|
2013-05-04 16:59:26 +02:00
|
|
|
Uses `tabulated-list-mode-map' as its parent.")
|
|
|
|
|
|
|
|
;; This should be extracted from DisPass at some point.
|
2013-01-20 14:29:17 +01:00
|
|
|
(defconst dispass-algorithms
|
|
|
|
'("dispass1" "dispass2")
|
2013-05-04 16:59:26 +02:00
|
|
|
"The list of algorithms supported by DisPass.")
|
2013-01-20 14:29:17 +01:00
|
|
|
|
2012-06-09 21:47:12 +02:00
|
|
|
(defun dispass-process-sentinel (proc status)
|
|
|
|
"Report PROC's status change to STATUS."
|
|
|
|
(let ((status (substring status 0 -1))
|
|
|
|
(buffer (process-buffer proc)))
|
|
|
|
(unless (string-equal status "finished")
|
2012-06-17 14:44:46 +02:00
|
|
|
(message "dispass %s" status))
|
2012-06-09 21:47:12 +02:00
|
|
|
|
|
|
|
(unless (eq (current-buffer) proc)
|
|
|
|
(kill-buffer buffer))))
|
|
|
|
|
|
|
|
(defun dispass-erase-buffer (buffer)
|
2013-05-04 16:59:26 +02:00
|
|
|
"Completely erase the contents of BUFFER."
|
2012-06-09 21:47:12 +02:00
|
|
|
(save-current-buffer
|
|
|
|
(set-buffer buffer)
|
|
|
|
(buffer-disable-undo buffer)
|
|
|
|
(kill-buffer buffer)))
|
|
|
|
|
2013-01-08 00:35:57 +01:00
|
|
|
(defun dispass-label-at-point ()
|
|
|
|
"When in `dispass-labels-mode', get the label at `point'."
|
|
|
|
(let ((labels-mode-p (eq major-mode 'dispass-labels-mode)))
|
|
|
|
(tabulated-list-get-id)))
|
|
|
|
|
2012-06-09 21:47:12 +02:00
|
|
|
(defun dispass-process-filter-for (label)
|
2013-05-04 16:59:26 +02:00
|
|
|
"Create a specialized filter for LABEL.
|
|
|
|
|
|
|
|
This filter checks if a password has been asked for or if the
|
|
|
|
label shows up in a line, which will be the line with the
|
|
|
|
passphrase that has been generated."
|
2012-06-09 21:47:12 +02:00
|
|
|
`(lambda (proc string)
|
|
|
|
"Process STRING coming from PROC."
|
2012-07-05 02:07:38 +02:00
|
|
|
(cond ((string-match "^\\(Password[^:]*\\|Again\\): ?$" string)
|
2012-11-18 21:03:32 +01:00
|
|
|
(process-send-string
|
|
|
|
proc
|
|
|
|
(concat (read-passwd
|
|
|
|
(concat (replace-regexp-in-string
|
|
|
|
"^[ \t\n]+\\|[ \t\n]+$" "" string) " ")
|
|
|
|
nil) "\n")))
|
2012-06-09 21:47:12 +02:00
|
|
|
|
2012-06-17 14:44:46 +02:00
|
|
|
((string-match (concat "^[ \t]*" ,label "[ \t]*\\(.+\\)$")
|
2012-06-09 21:47:12 +02:00
|
|
|
string)
|
|
|
|
(let ((buffer (process-buffer proc)))
|
|
|
|
(with-current-buffer buffer
|
|
|
|
(insert (match-string 1 string))
|
|
|
|
(clipboard-kill-ring-save (point-min) (point-max))
|
2012-11-18 21:04:14 +01:00
|
|
|
(message "Password copied to clipboard.")))))))
|
2012-06-09 21:47:12 +02:00
|
|
|
|
2013-05-25 13:34:26 +02:00
|
|
|
(defun dispass-start-process (cmd label create length
|
|
|
|
&optional algo seqno args)
|
|
|
|
"Ask DisPass call CMD for LABEL.
|
2013-05-04 16:59:26 +02:00
|
|
|
|
|
|
|
When CREATE is non-nil send along the -c switch to make it ask
|
|
|
|
for a password twice. When LENGTH is an integer and greater than
|
|
|
|
0, we request that DisPass make the passphrase LENGTH long. ALGO
|
|
|
|
should be one of `dispass-algorithms' and requests a certain
|
|
|
|
algorithm be used by DisPass to generate the passphrase. SEQNO
|
|
|
|
asks DisPass to use SEQNO as a sequence number.
|
|
|
|
|
|
|
|
If specified add ARGS to the command."
|
2013-05-25 13:34:26 +02:00
|
|
|
(let ((args `(,cmd ,@args "-o"))
|
2012-06-17 14:44:46 +02:00
|
|
|
proc)
|
|
|
|
(when create
|
2013-05-25 13:34:26 +02:00
|
|
|
(setq args (append args '("-v"))))
|
2012-06-17 14:44:46 +02:00
|
|
|
|
|
|
|
(when (and (integerp length) (> length 0))
|
2013-05-25 13:34:26 +02:00
|
|
|
(setq args (append args `("-l" ,(number-to-string length)))))
|
2012-06-17 14:44:46 +02:00
|
|
|
|
2013-01-20 14:29:17 +01:00
|
|
|
(when (and algo (not (equal algo ""))
|
|
|
|
(member algo dispass-algorithms))
|
2013-05-25 13:34:26 +02:00
|
|
|
(setq args (append args `("-a" ,algo))))
|
2013-01-20 14:29:17 +01:00
|
|
|
|
2013-01-20 15:06:01 +01:00
|
|
|
(when (and seqno (> seqno 0))
|
2013-05-25 13:34:26 +02:00
|
|
|
(setq args (append args `("-s" ,(number-to-string seqno)))))
|
2013-01-20 15:12:29 +01:00
|
|
|
|
2013-01-20 15:58:35 +01:00
|
|
|
(when dispass-labelfile
|
|
|
|
(setq args (append `("-f" ,dispass-labelfile) args)))
|
|
|
|
|
2013-05-25 13:34:26 +02:00
|
|
|
(message "%s" `(,@args ,label))
|
2012-06-17 14:44:46 +02:00
|
|
|
(setq proc (apply 'start-process "dispass" "*dispass*"
|
2013-05-25 13:34:26 +02:00
|
|
|
dispass-executable `(,@args ,label)))
|
2012-06-09 21:47:12 +02:00
|
|
|
(set-process-sentinel proc 'dispass-process-sentinel)
|
|
|
|
(set-process-filter proc (dispass-process-filter-for label))))
|
|
|
|
|
2012-09-15 16:09:41 +02:00
|
|
|
(defun dispass-get-labels ()
|
|
|
|
"Get the list of labels and their information."
|
|
|
|
(let ((result '()))
|
|
|
|
(with-temp-buffer
|
2013-01-20 14:29:17 +01:00
|
|
|
(dispass-read-labels)
|
|
|
|
(while (re-search-forward
|
2013-02-16 10:48:01 +01:00
|
|
|
"^\\(\\(?:\\sw\\|\\s_\\|\\.\\)+\\)"
|
2013-01-20 14:29:17 +01:00
|
|
|
nil t)
|
|
|
|
(add-to-list 'result (match-string 1)))
|
|
|
|
result)))
|
|
|
|
|
|
|
|
(defun dispass-get-labels-for-display ()
|
|
|
|
"Prepare the list of labels for info table."
|
|
|
|
(let ((result '()))
|
|
|
|
(with-temp-buffer
|
|
|
|
(dispass-read-labels)
|
2012-09-15 16:09:41 +02:00
|
|
|
(while (re-search-forward
|
2013-02-16 10:48:01 +01:00
|
|
|
"^\\(\\(?:\\sw\\|\\s_\\|\\.\\)+\\) +\\([0-9]+\\) +\\(\\(?:\\sw\\|\\s_\\)+\\)"
|
2012-09-15 16:09:41 +02:00
|
|
|
nil t)
|
|
|
|
(let ((label (match-string 1))
|
|
|
|
(length (match-string 2))
|
2013-01-08 00:40:32 +01:00
|
|
|
(algo (match-string 3)))
|
2012-09-15 16:09:41 +02:00
|
|
|
(add-to-list 'result
|
|
|
|
(list label
|
|
|
|
`[(,label
|
|
|
|
face link
|
|
|
|
help-echo ,(concat "Generate passphrase for " label)
|
|
|
|
follow-link t
|
|
|
|
dispass-label ,label
|
|
|
|
dispass-length ,length
|
|
|
|
action dispass-from-button)
|
|
|
|
,length
|
2013-01-08 00:40:32 +01:00
|
|
|
,algo])))))
|
2012-09-15 16:09:41 +02:00
|
|
|
result))
|
|
|
|
|
2013-01-20 14:29:17 +01:00
|
|
|
(defun dispass-read-labels ()
|
|
|
|
"Load a list of all labels into a buffer."
|
|
|
|
(insert (shell-command-to-string
|
2013-05-25 13:34:26 +02:00
|
|
|
(concat dispass-executable
|
2013-01-20 15:58:35 +01:00
|
|
|
(when dispass-labelfile
|
|
|
|
(concat " -f " dispass-labelfile))
|
2013-05-25 13:34:26 +02:00
|
|
|
" list --script")))
|
2013-01-20 14:29:17 +01:00
|
|
|
(goto-char (point-min)))
|
|
|
|
|
2012-06-09 21:47:12 +02:00
|
|
|
;;;###autoload
|
2013-01-20 15:06:01 +01:00
|
|
|
(defun dispass-create (label &optional length algo seqno)
|
2013-05-04 16:59:26 +02:00
|
|
|
"Create a new password for LABEL.
|
|
|
|
|
|
|
|
Optionally also specify to make the passphrase LENGTH long, use
|
|
|
|
the ALGO algorithm with sequence number SEQNO."
|
2013-01-20 14:29:17 +01:00
|
|
|
(interactive (list
|
|
|
|
(read-from-minibuffer "Label: ")
|
|
|
|
current-prefix-arg
|
2013-01-20 15:06:01 +01:00
|
|
|
(completing-read "Algorithm: " dispass-algorithms)
|
|
|
|
(read-from-minibuffer
|
|
|
|
"Sequence no. (1): " nil nil t nil "1")))
|
2012-07-06 00:26:27 +02:00
|
|
|
(let ((length (or length dispass-default-length)))
|
2013-05-25 13:34:26 +02:00
|
|
|
(dispass-start-process "generate" label t length algo seqno)))
|
2012-06-09 21:47:12 +02:00
|
|
|
|
|
|
|
;;;###autoload
|
2013-01-20 15:06:01 +01:00
|
|
|
(defun dispass (label &optional length algo seqno)
|
2013-05-04 16:59:26 +02:00
|
|
|
"Recreate a passphrase for LABEL.
|
|
|
|
|
|
|
|
Optionally also specify to make the passphrase LENGTH long, use
|
|
|
|
the ALGO algorithm with sequence number SEQNO. This is useful
|
|
|
|
when you would like to generate a one-shot passphrase, or prefer
|
|
|
|
not to have LABEL added to your labelfile for some other reason."
|
2012-09-15 16:09:41 +02:00
|
|
|
(interactive (list
|
|
|
|
(completing-read
|
2013-01-20 14:29:17 +01:00
|
|
|
"Label: " (dispass-get-labels))
|
2012-09-15 16:09:41 +02:00
|
|
|
current-prefix-arg))
|
2013-01-20 15:06:01 +01:00
|
|
|
(when (and (called-interactively-p 'any)
|
|
|
|
(not (member label (dispass-get-labels))))
|
|
|
|
(setq algo (completing-read "Algorithm: " dispass-algorithms))
|
|
|
|
(setq seqno (read-from-minibuffer
|
|
|
|
"Sequence no. (1): " nil nil t nil "1")))
|
2012-07-06 00:26:27 +02:00
|
|
|
(let ((length (or length dispass-default-length)))
|
2013-01-20 14:29:17 +01:00
|
|
|
(dispass-start-process
|
2013-05-25 13:34:26 +02:00
|
|
|
"generate" label nil length algo seqno)))
|
2012-06-09 21:47:12 +02:00
|
|
|
|
2012-07-05 01:11:07 +02:00
|
|
|
;; Labels management
|
2012-07-06 00:30:15 +02:00
|
|
|
;;;###autoload
|
2013-01-20 15:06:01 +01:00
|
|
|
(defun dispass-add-label (label length algo &optional seqno)
|
2013-05-04 16:59:26 +02:00
|
|
|
"Add LABEL with length LENGTH and algorithm ALGO to DisPass.
|
|
|
|
|
|
|
|
Optionally also specify sequence number SEQNO."
|
2013-01-08 00:35:57 +01:00
|
|
|
(interactive
|
|
|
|
(list (read-from-minibuffer "Label: ")
|
|
|
|
(read-from-minibuffer
|
|
|
|
(format "Length (%d): " dispass-default-length) nil nil t nil
|
|
|
|
(number-to-string dispass-default-length))
|
2013-01-20 14:29:17 +01:00
|
|
|
(completing-read
|
|
|
|
"Algorithm (dispass1): "
|
2013-01-20 15:06:01 +01:00
|
|
|
dispass-algorithms nil nil nil nil "dispass1")
|
|
|
|
(read-from-minibuffer "Sequnce no. (1): " nil nil t nil "1")))
|
2013-01-08 00:35:57 +01:00
|
|
|
(shell-command
|
2013-05-25 13:34:26 +02:00
|
|
|
(format "%s %s add %s:%d:%s:%s"
|
|
|
|
dispass-executable
|
2013-01-20 15:58:35 +01:00
|
|
|
(if dispass-labelfile
|
|
|
|
(concat "-f " dispass-labelfile)
|
|
|
|
"")
|
|
|
|
label length algo seqno)))
|
2013-01-08 00:35:57 +01:00
|
|
|
|
|
|
|
;;;###autoload
|
|
|
|
(defun dispass-remove-label (label)
|
2013-05-04 16:59:26 +02:00
|
|
|
"Remove LABEL from DisPass.
|
|
|
|
|
|
|
|
If LABEL is not given `tabulated-list-get-id' will be used to get
|
|
|
|
the currently pointed-at label. If neither LABEL is not found an
|
|
|
|
error is thrown."
|
2013-01-08 00:35:57 +01:00
|
|
|
(interactive
|
|
|
|
(list (or (dispass-label-at-point)
|
|
|
|
(completing-read
|
2013-01-20 14:29:17 +01:00
|
|
|
"Label: " (dispass-get-labels)))))
|
2013-01-08 00:35:57 +01:00
|
|
|
(shell-command
|
2013-05-25 13:34:26 +02:00
|
|
|
(format "%s %s rm %s" dispass-executable
|
2013-01-20 15:58:35 +01:00
|
|
|
(if dispass-labelfile
|
|
|
|
(concat "-f " dispass-labelfile)
|
|
|
|
"")
|
|
|
|
label)))
|
2012-07-08 16:05:07 +02:00
|
|
|
|
2012-07-05 01:41:41 +02:00
|
|
|
(defun dispass-from-button (button)
|
|
|
|
"Call dispass with information from BUTTON."
|
|
|
|
(dispass (button-get button 'dispass-label)
|
|
|
|
(button-get button 'dispass-length)))
|
|
|
|
|
2012-07-05 01:11:07 +02:00
|
|
|
(defun dispass-labels--refresh ()
|
|
|
|
"Reload labels from dispass."
|
|
|
|
(setq tabulated-list-entries nil)
|
|
|
|
|
|
|
|
(let ((tmp-list '()))
|
2013-01-20 14:29:17 +01:00
|
|
|
(setq tabulated-list-entries (dispass-get-labels-for-display))))
|
2012-07-05 01:11:07 +02:00
|
|
|
|
|
|
|
(define-derived-mode dispass-labels-mode tabulated-list-mode "DisPass"
|
2012-07-05 02:14:58 +02:00
|
|
|
"Major mode for listing dispass labels.
|
|
|
|
|
2012-07-06 00:31:02 +02:00
|
|
|
\\<dispass-labels-mode-map>
|
2012-07-05 02:14:58 +02:00
|
|
|
\\{dispass-labels-mode-map}"
|
2012-07-05 01:11:07 +02:00
|
|
|
(setq tabulated-list-format [("Label" 30 t)
|
|
|
|
("Length" 6 nil)
|
2013-01-08 00:40:32 +01:00
|
|
|
("Algorithm" 0 t)]
|
2012-07-05 01:11:07 +02:00
|
|
|
tabulated-list-sort-key '("Label" . nil))
|
|
|
|
(add-hook 'tabulated-list-revert-hook 'dispass-labels--refresh)
|
|
|
|
(tabulated-list-init-header))
|
|
|
|
|
2012-07-05 01:45:55 +02:00
|
|
|
;;;###autoload
|
2012-07-05 01:11:07 +02:00
|
|
|
(defun dispass-list-labels ()
|
|
|
|
"Display a list of labels for dispass."
|
|
|
|
(interactive)
|
|
|
|
(let ((buffer (get-buffer-create "*DisPass Labels*")))
|
|
|
|
(with-current-buffer buffer
|
|
|
|
(dispass-labels-mode)
|
|
|
|
(dispass-labels--refresh)
|
|
|
|
(tabulated-list-print))
|
2012-07-05 02:20:39 +02:00
|
|
|
(switch-to-buffer-other-window buffer))
|
2012-07-05 01:11:07 +02:00
|
|
|
nil)
|
|
|
|
|
2012-06-09 21:47:12 +02:00
|
|
|
(provide 'dispass)
|
|
|
|
|
|
|
|
;;; dispass.el ends here
|
2013-05-04 16:59:26 +02:00
|
|
|
|
|
|
|
;; Local Variables:
|
|
|
|
;; sentence-end-double-space: t
|
|
|
|
;; End:
|