Create and document auth-source-reveal-mode

* lisp/auth-source.el (auth-source-reveal-mode): Add new minor
mode to hide passwords. Remove authinfo-mode which provided a
major mode for the same purpose before. Use the text-coverup API.

* doc/misc/auth.texi (Hiding passwords in text buffers): Document
auth-source-reveal-mode.
parent 0256303f
Pipeline #6046 failed with stage
in 40 minutes and 25 seconds
\input texinfo @c -*-texinfo-*-
@set VERSION 0.3
@set VERSION 0.4
@setfilename ../../info/auth.info
@settitle Emacs auth-source Library @value{VERSION}
......@@ -58,6 +58,7 @@ It is a way for multiple applications to share a single configuration
* Overview:: Overview of the auth-source library.
* Help for users::
* Multiple GMail accounts with Gnus::
* Hiding passwords in text buffers::
* Secret Service API::
* The Unix password store::
* Help for developers::
......@@ -280,6 +281,48 @@ machine gmail login account@@gmail.com password "account password" port imap
machine gmail2 login account2@@gmail.com password "account2 password" port imap
@end example
@node Hiding passwords in text buffers
@chapter Hiding passwords in text buffers
Emacs users and developers have to look at netrc files in text or JSON
formats sometimes. Pro Tip: one easy way to protect from
password-shoulder-surfers is to enter a hair band, grow long hair,
curl it daily until it creates a visual barrier, become famous, keep
using Emacs.
An alternative is to enable @code{auth-source-reveal-mode} as follows:
@example
(require 'auth-source)
(setq prettify-symbols-unprettify-at-point 'right-edge) ;; or customize it
(add-hook 'prog-mode-hook 'turn-on-auth-source-reveal-mode)
(add-hook 'text-mode-hook 'turn-on-auth-source-reveal-mode)
(add-hook 'json-mode-hook 'turn-on-auth-source-reveal-mode)
@end example
Underneath, the @code{prettify-text} API is used to hide passwords
based on a regular expression for netrc plain text or JSON files.
You should definitely customize
@code{prettify-text-unprettify-at-point} to be t or
@code{right-edge}. If it's nil (the default), the password will not be
revealed when you're inside it, which will annoy you AND
password-shoulder-surfers. Note this is different from
@code{prettify-symbols-unprettify-at-point} which only governs
@code{prettify-symbols-mode} behavior.
You can further customize the following.
@defvar auth-source-reveal-regex
A regular expression matching the text preceding the password (or, in JSON format, the key under which the password lives). By default it will be just ``password'' which also matches e.g. ``my_password''.
Use only non-capturing parens inside this regular expression.
@end defvar
@defvar auth-source-reveal-json-modes
This is a list of modes where the JSON regular expression logic should be installed, instead of the plaintext logic. By default this includes @code{json-mode} for instance.
@end defvar
@node Secret Service API
@chapter Secret Service API
......
......@@ -44,6 +44,7 @@
(require 'cl-lib)
(require 'eieio)
(require 'prog-mode)
(autoload 'secrets-create-item "secrets")
(autoload 'secrets-delete-item "secrets")
......@@ -2405,44 +2406,91 @@ MODE can be \"login\" or \"password\"."
(setq password (funcall password)))
(list user password auth-info)))
;;; Tiny mode for editing .netrc/.authinfo modes (that basically just
;;; hides passwords).
;;; Tiny minor mode for editing .netrc/.authinfo modes (that basically
;;; just hides passwords).
(defcustom authinfo-hidden "password"
"Regexp matching elements in .authinfo/.netrc files that should be hidden."
(defcustom auth-source-reveal-regex "password"
"Regexp matching tokens or JSON keys in .authinfo/.netrc/JSON files.
The text following the tokens or under the JSON keys will be hidden."
:type 'regexp
:version "27.1")
;;;###autoload
(define-derived-mode authinfo-mode fundamental-mode "Authinfo"
"Mode for editing .authinfo/.netrc files.
(defcustom auth-source-reveal-json-modes '(json-mode js-mode js2-mode rjsx-mode)
"List of symbols for modes that should use JSON parsing logic."
:type 'list
:version "27.1")
This is just like `fundamental-mode', but hides passwords. The
passwords are revealed when point moved into the password.
(defcustom auth-source-reveal-hider '(?* (base-right . base-left) ?© (base-right . base-left) ?© (base-right . base-left) ?*)
"A character or a composition list to hide passwords.
In the composition list form, you can use the format
(?h (base-right . base-left) ?i (base-right . base-left) ?d (base-right . base-left) ?e)
to show the string \"hide\" (by aligning character left/right baselines).
\\{authinfo-mode-map}"
(authinfo--hide-passwords (point-min) (point-max))
(reveal-mode))
Other composition keywords you can use: top-left/tl,
top-center/tc, top-right/tr, base-left/Bl, base-center/Bc,
base-right/Br, bottom-left/bl, bottom-center/bc, bottom-right/br,
center-left/cl, center-center/cc, center-right/cr."
:type '(choice
(const :tag "A single copyright sign" ?©)
(character :tag "Any character")
(sexp :tag "A composition list"))
:version "27.1")
(defun authinfo--hide-passwords (start end)
(save-excursion
(save-restriction
(narrow-to-region start end)
(goto-char start)
(while (re-search-forward (format "\\(\\s-\\|^\\)\\(%s\\)\\s-+"
authinfo-hidden)
nil t)
(when (auth-source-netrc-looking-at-token)
(let ((overlay (make-overlay (match-beginning 0) (match-end 0))))
(overlay-put overlay 'display (propertize "****"
'face 'warning))
(overlay-put overlay 'reveal-toggle-invisible
#'authinfo--toggle-display)))))))
(defun authinfo--toggle-display (overlay hide)
(if hide
(overlay-put overlay 'display (propertize "****" 'face 'warning))
(overlay-put overlay 'display nil)))
(defun auth-source-reveal-compose-p (start end _outer_match _true_match)
"Return true iff the text between START and END should be composed.
All arguments are currently ignored, always returning t for
`auth-source-reveal-mode'. This overrides the default for
`text-coverup-compose-predicate'."
;; Check that the chars should really be composed into a symbol.
t)
;;;###autoload
(define-minor-mode auth-source-reveal-mode
"Toggle password hiding for auth-source files using `text-coverup-mode'.
If called interactively, enable auth-source-reveal mode if ARG is
positive, and disable it if ARG is zero or negative. If called
from Lisp, also enable the mode if ARG is omitted or nil, and
toggle it if ARG is toggle; disable the mode otherwise.
When auth-source-reveal mode is enabled, passwords will be
hidden. To reveal them when point is inside them, see
`text-coverup-uncover-at-point'.
See `auth-source-password-hide-regex' for the regex matching the
tokens and keys associated with passwords."
;; The initial value.
:init-value nil
;; The indicator for the mode line.
:lighter " asr"
:group 'auth-source
(let ((identifier 'auth-source-reveal-regexp)) ; The identifier symbol.
(if auth-source-reveal-mode
;; Install the coverup magic.
(when (text-coverup-add-coverup
identifier
;; The regexp to hide/reveal.
(if (apply #'derived-mode-p auth-source-reveal-json-modes)
(format "\"?password\"?[:[:blank:]]+\"\\([^\t\r\n\"]+\\)\""
auth-source-reveal-regex)
(format "\\b%s\\b\\s-+\\([^ \t\r\n]+\\)"
auth-source-reveal-regex))
;; The replacement symbol or composed string.
auth-source-reveal-hider
;; A custom compose matcher.
#'auth-source-reveal-compose-p)
(unless text-coverup-uncover-at-point
(auth-source-do-warn
"Please set `%s' to _see_ passwords at point"
'text-coverup-uncover-at-point)))
;; Else, when disabling, remove the coverups for our identifier.
(text-coverup-remove-coverups identifier))))
;;;###autoload
(defun turn-on-auth-source-reveal-mode ()
(when (not auth-source-reveal-mode)
(auth-source-reveal-mode 1)))
(provide 'auth-source)
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment