diff options
| author | Ted Zlatanov | 2020-06-23 18:19:32 -0400 |
|---|---|---|
| committer | Ted Zlatanov | 2020-07-12 16:44:10 -0400 |
| commit | da5b4b6d0856501a163217529c2db2f891e284c0 (patch) | |
| tree | 9690b6c43bce85a46b01c3769fc2558a7fa923f0 | |
| parent | 0256303f24b1fc193f1d6c1861abf81fd5ee374a (diff) | |
| download | emacs-scratch/tzz/prettify-text-mode.tar.gz emacs-scratch/tzz/prettify-text-mode.zip | |
Create and document auth-source-reveal-modescratch/tzz/prettify-text-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.
| -rw-r--r-- | doc/misc/auth.texi | 45 | ||||
| -rw-r--r-- | lisp/auth-source.el | 110 |
2 files changed, 123 insertions, 32 deletions
diff --git a/doc/misc/auth.texi b/doc/misc/auth.texi index 61dc62e7711..fc98b773432 100644 --- a/doc/misc/auth.texi +++ b/doc/misc/auth.texi | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | \input texinfo @c -*-texinfo-*- | 1 | \input texinfo @c -*-texinfo-*- |
| 2 | 2 | ||
| 3 | @set VERSION 0.3 | 3 | @set VERSION 0.4 |
| 4 | 4 | ||
| 5 | @setfilename ../../info/auth.info | 5 | @setfilename ../../info/auth.info |
| 6 | @settitle Emacs auth-source Library @value{VERSION} | 6 | @settitle Emacs auth-source Library @value{VERSION} |
| @@ -58,6 +58,7 @@ It is a way for multiple applications to share a single configuration | |||
| 58 | * Overview:: Overview of the auth-source library. | 58 | * Overview:: Overview of the auth-source library. |
| 59 | * Help for users:: | 59 | * Help for users:: |
| 60 | * Multiple GMail accounts with Gnus:: | 60 | * Multiple GMail accounts with Gnus:: |
| 61 | * Hiding passwords in text buffers:: | ||
| 61 | * Secret Service API:: | 62 | * Secret Service API:: |
| 62 | * The Unix password store:: | 63 | * The Unix password store:: |
| 63 | * Help for developers:: | 64 | * Help for developers:: |
| @@ -280,6 +281,48 @@ machine gmail login account@@gmail.com password "account password" port imap | |||
| 280 | machine gmail2 login account2@@gmail.com password "account2 password" port imap | 281 | machine gmail2 login account2@@gmail.com password "account2 password" port imap |
| 281 | @end example | 282 | @end example |
| 282 | 283 | ||
| 284 | @node Hiding passwords in text buffers | ||
| 285 | @chapter Hiding passwords in text buffers | ||
| 286 | |||
| 287 | Emacs users and developers have to look at netrc files in text or JSON | ||
| 288 | formats sometimes. Pro Tip: one easy way to protect from | ||
| 289 | password-shoulder-surfers is to enter a hair band, grow long hair, | ||
| 290 | curl it daily until it creates a visual barrier, become famous, keep | ||
| 291 | using Emacs. | ||
| 292 | |||
| 293 | An alternative is to enable @code{auth-source-reveal-mode} as follows: | ||
| 294 | |||
| 295 | @example | ||
| 296 | (require 'auth-source) | ||
| 297 | (setq prettify-symbols-unprettify-at-point 'right-edge) ;; or customize it | ||
| 298 | |||
| 299 | (add-hook 'prog-mode-hook 'turn-on-auth-source-reveal-mode) | ||
| 300 | (add-hook 'text-mode-hook 'turn-on-auth-source-reveal-mode) | ||
| 301 | (add-hook 'json-mode-hook 'turn-on-auth-source-reveal-mode) | ||
| 302 | @end example | ||
| 303 | |||
| 304 | Underneath, the @code{prettify-text} API is used to hide passwords | ||
| 305 | based on a regular expression for netrc plain text or JSON files. | ||
| 306 | |||
| 307 | You should definitely customize | ||
| 308 | @code{prettify-text-unprettify-at-point} to be t or | ||
| 309 | @code{right-edge}. If it's nil (the default), the password will not be | ||
| 310 | revealed when you're inside it, which will annoy you AND | ||
| 311 | password-shoulder-surfers. Note this is different from | ||
| 312 | @code{prettify-symbols-unprettify-at-point} which only governs | ||
| 313 | @code{prettify-symbols-mode} behavior. | ||
| 314 | |||
| 315 | You can further customize the following. | ||
| 316 | @defvar auth-source-reveal-regex | ||
| 317 | 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''. | ||
| 318 | |||
| 319 | Use only non-capturing parens inside this regular expression. | ||
| 320 | @end defvar | ||
| 321 | |||
| 322 | @defvar auth-source-reveal-json-modes | ||
| 323 | 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. | ||
| 324 | @end defvar | ||
| 325 | |||
| 283 | @node Secret Service API | 326 | @node Secret Service API |
| 284 | @chapter Secret Service API | 327 | @chapter Secret Service API |
| 285 | 328 | ||
diff --git a/lisp/auth-source.el b/lisp/auth-source.el index 7a0e09b9e8e..2892cc09925 100644 --- a/lisp/auth-source.el +++ b/lisp/auth-source.el | |||
| @@ -44,6 +44,7 @@ | |||
| 44 | 44 | ||
| 45 | (require 'cl-lib) | 45 | (require 'cl-lib) |
| 46 | (require 'eieio) | 46 | (require 'eieio) |
| 47 | (require 'prog-mode) | ||
| 47 | 48 | ||
| 48 | (autoload 'secrets-create-item "secrets") | 49 | (autoload 'secrets-create-item "secrets") |
| 49 | (autoload 'secrets-delete-item "secrets") | 50 | (autoload 'secrets-delete-item "secrets") |
| @@ -2405,44 +2406,91 @@ MODE can be \"login\" or \"password\"." | |||
| 2405 | (setq password (funcall password))) | 2406 | (setq password (funcall password))) |
| 2406 | (list user password auth-info))) | 2407 | (list user password auth-info))) |
| 2407 | 2408 | ||
| 2408 | ;;; Tiny mode for editing .netrc/.authinfo modes (that basically just | 2409 | ;;; Tiny minor mode for editing .netrc/.authinfo modes (that basically |
| 2409 | ;;; hides passwords). | 2410 | ;;; just hides passwords). |
| 2410 | 2411 | ||
| 2411 | (defcustom authinfo-hidden "password" | 2412 | (defcustom auth-source-reveal-regex "password" |
| 2412 | "Regexp matching elements in .authinfo/.netrc files that should be hidden." | 2413 | "Regexp matching tokens or JSON keys in .authinfo/.netrc/JSON files. |
| 2414 | The text following the tokens or under the JSON keys will be hidden." | ||
| 2413 | :type 'regexp | 2415 | :type 'regexp |
| 2414 | :version "27.1") | 2416 | :version "27.1") |
| 2415 | 2417 | ||
| 2416 | ;;;###autoload | 2418 | (defcustom auth-source-reveal-json-modes '(json-mode js-mode js2-mode rjsx-mode) |
| 2417 | (define-derived-mode authinfo-mode fundamental-mode "Authinfo" | 2419 | "List of symbols for modes that should use JSON parsing logic." |
| 2418 | "Mode for editing .authinfo/.netrc files. | 2420 | :type 'list |
| 2421 | :version "27.1") | ||
| 2419 | 2422 | ||
| 2420 | This is just like `fundamental-mode', but hides passwords. The | 2423 | (defcustom auth-source-reveal-hider '(?* (base-right . base-left) ?© (base-right . base-left) ?© (base-right . base-left) ?*) |
| 2421 | passwords are revealed when point moved into the password. | 2424 | "A character or a composition list to hide passwords. |
| 2425 | In the composition list form, you can use the format | ||
| 2426 | (?h (base-right . base-left) ?i (base-right . base-left) ?d (base-right . base-left) ?e) | ||
| 2427 | to show the string \"hide\" (by aligning character left/right baselines). | ||
| 2422 | 2428 | ||
| 2423 | \\{authinfo-mode-map}" | 2429 | Other composition keywords you can use: top-left/tl, |
| 2424 | (authinfo--hide-passwords (point-min) (point-max)) | 2430 | top-center/tc, top-right/tr, base-left/Bl, base-center/Bc, |
| 2425 | (reveal-mode)) | 2431 | base-right/Br, bottom-left/bl, bottom-center/bc, bottom-right/br, |
| 2432 | center-left/cl, center-center/cc, center-right/cr." | ||
| 2433 | :type '(choice | ||
| 2434 | (const :tag "A single copyright sign" ?©) | ||
| 2435 | (character :tag "Any character") | ||
| 2436 | (sexp :tag "A composition list")) | ||
| 2437 | :version "27.1") | ||
| 2426 | 2438 | ||
| 2427 | (defun authinfo--hide-passwords (start end) | 2439 | (defun auth-source-reveal-compose-p (start end _outer_match _true_match) |
| 2428 | (save-excursion | 2440 | "Return true iff the text between START and END should be composed. |
| 2429 | (save-restriction | 2441 | All arguments are currently ignored, always returning t for |
| 2430 | (narrow-to-region start end) | 2442 | `auth-source-reveal-mode'. This overrides the default for |
| 2431 | (goto-char start) | 2443 | `text-coverup-compose-predicate'." |
| 2432 | (while (re-search-forward (format "\\(\\s-\\|^\\)\\(%s\\)\\s-+" | 2444 | ;; Check that the chars should really be composed into a symbol. |
| 2433 | authinfo-hidden) | 2445 | t) |
| 2434 | nil t) | 2446 | |
| 2435 | (when (auth-source-netrc-looking-at-token) | 2447 | ;;;###autoload |
| 2436 | (let ((overlay (make-overlay (match-beginning 0) (match-end 0)))) | 2448 | (define-minor-mode auth-source-reveal-mode |
| 2437 | (overlay-put overlay 'display (propertize "****" | 2449 | "Toggle password hiding for auth-source files using `text-coverup-mode'. |
| 2438 | 'face 'warning)) | 2450 | |
| 2439 | (overlay-put overlay 'reveal-toggle-invisible | 2451 | If called interactively, enable auth-source-reveal mode if ARG is |
| 2440 | #'authinfo--toggle-display))))))) | 2452 | positive, and disable it if ARG is zero or negative. If called |
| 2441 | 2453 | from Lisp, also enable the mode if ARG is omitted or nil, and | |
| 2442 | (defun authinfo--toggle-display (overlay hide) | 2454 | toggle it if ARG is toggle; disable the mode otherwise. |
| 2443 | (if hide | 2455 | |
| 2444 | (overlay-put overlay 'display (propertize "****" 'face 'warning)) | 2456 | When auth-source-reveal mode is enabled, passwords will be |
| 2445 | (overlay-put overlay 'display nil))) | 2457 | hidden. To reveal them when point is inside them, see |
| 2458 | `text-coverup-uncover-at-point'. | ||
| 2459 | |||
| 2460 | See `auth-source-password-hide-regex' for the regex matching the | ||
| 2461 | tokens and keys associated with passwords." | ||
| 2462 | ;; The initial value. | ||
| 2463 | :init-value nil | ||
| 2464 | ;; The indicator for the mode line. | ||
| 2465 | :lighter " asr" | ||
| 2466 | :group 'auth-source | ||
| 2467 | |||
| 2468 | (let ((identifier 'auth-source-reveal-regexp)) ; The identifier symbol. | ||
| 2469 | (if auth-source-reveal-mode | ||
| 2470 | ;; Install the coverup magic. | ||
| 2471 | (when (text-coverup-add-coverup | ||
| 2472 | identifier | ||
| 2473 | ;; The regexp to hide/reveal. | ||
| 2474 | (if (apply #'derived-mode-p auth-source-reveal-json-modes) | ||
| 2475 | (format "\"?password\"?[:[:blank:]]+\"\\([^\t\r\n\"]+\\)\"" | ||
| 2476 | auth-source-reveal-regex) | ||
| 2477 | (format "\\b%s\\b\\s-+\\([^ \t\r\n]+\\)" | ||
| 2478 | auth-source-reveal-regex)) | ||
| 2479 | ;; The replacement symbol or composed string. | ||
| 2480 | auth-source-reveal-hider | ||
| 2481 | ;; A custom compose matcher. | ||
| 2482 | #'auth-source-reveal-compose-p) | ||
| 2483 | (unless text-coverup-uncover-at-point | ||
| 2484 | (auth-source-do-warn | ||
| 2485 | "Please set `%s' to _see_ passwords at point" | ||
| 2486 | 'text-coverup-uncover-at-point))) | ||
| 2487 | ;; Else, when disabling, remove the coverups for our identifier. | ||
| 2488 | (text-coverup-remove-coverups identifier)))) | ||
| 2489 | |||
| 2490 | ;;;###autoload | ||
| 2491 | (defun turn-on-auth-source-reveal-mode () | ||
| 2492 | (when (not auth-source-reveal-mode) | ||
| 2493 | (auth-source-reveal-mode 1))) | ||
| 2446 | 2494 | ||
| 2447 | (provide 'auth-source) | 2495 | (provide 'auth-source) |
| 2448 | 2496 | ||