diff options
| author | Michael R. Mauger | 2019-12-22 23:56:05 -0500 |
|---|---|---|
| committer | Michael R. Mauger | 2019-12-22 23:56:05 -0500 |
| commit | 3df7d06d4187d402e4df1177461862af638d96de (patch) | |
| tree | ceb522ae690fec95a1ee7118293cd93edd460479 | |
| parent | eea05713bef7b86ff84ca843948f944e4c856119 (diff) | |
| download | emacs-3df7d06d4187d402e4df1177461862af638d96de.tar.gz emacs-3df7d06d4187d402e4df1177461862af638d96de.zip | |
Added `comint-password-function' hook
* etc/NEWS:
* lisp/comint.el (comint-password-function): New variable.
(comint-send-invisible): Use it.
* test/lisp/comint-tests.el (comint-test-no-password-function,
comint-test-password-function-with-value,
comint-test-password-function-with-nil): Test new variable.
| -rw-r--r-- | etc/NEWS | 13 | ||||
| -rw-r--r-- | lisp/comint.el | 16 | ||||
| -rw-r--r-- | test/lisp/comint-tests.el | 68 |
3 files changed, 95 insertions, 2 deletions
| @@ -1131,6 +1131,19 @@ end. | |||
| 1131 | *** 'comint-run' can now accept a list of switches to pass to the program. | 1131 | *** 'comint-run' can now accept a list of switches to pass to the program. |
| 1132 | 'C-u M-x comint-run' will prompt for the switches interactively. | 1132 | 'C-u M-x comint-run' will prompt for the switches interactively. |
| 1133 | 1133 | ||
| 1134 | *** Abnormal hook `comint-password-function' has been added. | ||
| 1135 | This hook permits a derived mode to supply a password for the | ||
| 1136 | underlying command interpreter without prompting the user. For | ||
| 1137 | example, in sql-mode, the password for connecting to the database may | ||
| 1138 | be stored in the connection wallet and may be passed on the command | ||
| 1139 | line to start the SQL interpreter. This is a potential security flaw | ||
| 1140 | that could expose user's database passwords on the command line | ||
| 1141 | through the use of a process list (Bug#8427). With this hook, it is | ||
| 1142 | possible to not pass the password on the command line and wait for the | ||
| 1143 | program to prompt for the password. When it does so, the password cam | ||
| 1144 | be supplied to the SQL interpreter without involving the user just as | ||
| 1145 | if it had been supplied on the command line. | ||
| 1146 | |||
| 1134 | ** SQL | 1147 | ** SQL |
| 1135 | 1148 | ||
| 1136 | *** SQL Indent Minor Mode | 1149 | *** SQL Indent Minor Mode |
diff --git a/lisp/comint.el b/lisp/comint.el index 4bb43670354..c06a63fbd24 100644 --- a/lisp/comint.el +++ b/lisp/comint.el | |||
| @@ -2356,6 +2356,13 @@ a buffer local variable." | |||
| 2356 | ;; saved -- typically passwords to ftp, telnet, or somesuch. | 2356 | ;; saved -- typically passwords to ftp, telnet, or somesuch. |
| 2357 | ;; Just enter m-x comint-send-invisible and type in your line. | 2357 | ;; Just enter m-x comint-send-invisible and type in your line. |
| 2358 | 2358 | ||
| 2359 | (defvar comint-password-function nil | ||
| 2360 | "Abnormal hook run when prompted for a password. | ||
| 2361 | This function gets one argument, a string containing the prompt. | ||
| 2362 | It may return a string containing the password, or nil if normal | ||
| 2363 | password prompting should occur.") | ||
| 2364 | (make-variable-buffer-local 'comint-password-function) | ||
| 2365 | |||
| 2359 | (defun comint-send-invisible (&optional prompt) | 2366 | (defun comint-send-invisible (&optional prompt) |
| 2360 | "Read a string without echoing. | 2367 | "Read a string without echoing. |
| 2361 | Then send it to the process running in the current buffer. | 2368 | Then send it to the process running in the current buffer. |
| @@ -2370,8 +2377,13 @@ Security bug: your string can still be temporarily recovered with | |||
| 2370 | (format "(In buffer %s) " | 2377 | (format "(In buffer %s) " |
| 2371 | (current-buffer))))) | 2378 | (current-buffer))))) |
| 2372 | (if proc | 2379 | (if proc |
| 2373 | (let ((str (read-passwd (concat prefix | 2380 | (let ((prefix-prompt (concat prefix |
| 2374 | (or prompt "Non-echoed text: "))))) | 2381 | (or prompt "Non-echoed text: "))) |
| 2382 | str) | ||
| 2383 | (when comint-password-function | ||
| 2384 | (setq str (funcall comint-password-function prefix-prompt))) | ||
| 2385 | (unless str | ||
| 2386 | (setq str (read-passwd prefix-prompt))) | ||
| 2375 | (if (stringp str) | 2387 | (if (stringp str) |
| 2376 | (progn | 2388 | (progn |
| 2377 | (comint-snapshot-last-prompt) | 2389 | (comint-snapshot-last-prompt) |
diff --git a/test/lisp/comint-tests.el b/test/lisp/comint-tests.el index 213a5c7c9e4..c04134599f6 100644 --- a/test/lisp/comint-tests.el +++ b/test/lisp/comint-tests.el | |||
| @@ -52,6 +52,74 @@ | |||
| 52 | (dolist (str comint-testsuite-password-strings) | 52 | (dolist (str comint-testsuite-password-strings) |
| 53 | (should (string-match comint-password-prompt-regexp str)))) | 53 | (should (string-match comint-password-prompt-regexp str)))) |
| 54 | 54 | ||
| 55 | (ert-deftest comint-test-no-password-function () | ||
| 56 | "Test that `comint-password-function' not being set does not | ||
| 57 | alter normal password flow." | ||
| 58 | (cl-letf | ||
| 59 | (((symbol-function 'read-passwd) | ||
| 60 | (lambda (_prompt &optional _confirm _default) | ||
| 61 | "PaSsWoRd123"))) | ||
| 62 | (let ((cat (executable-find "cat"))) | ||
| 63 | (when cat | ||
| 64 | (with-temp-buffer | ||
| 65 | (make-comint-in-buffer "test-comint-password" (current-buffer) cat) | ||
| 66 | (let ((proc (get-buffer-process (current-buffer)))) | ||
| 67 | (comint-send-string proc "Password: ") | ||
| 68 | (accept-process-output proc 0 1 t) | ||
| 69 | (comint-send-eof) | ||
| 70 | (accept-process-output proc 0 1 t) | ||
| 71 | (should (string-equal (buffer-substring-no-properties (point-min) (point-max)) | ||
| 72 | "Password: PaSsWoRd123\n")) | ||
| 73 | (when (process-live-p proc) | ||
| 74 | (kill-process proc)) | ||
| 75 | (accept-process-output proc 0 1 t))))))) | ||
| 76 | |||
| 77 | (ert-deftest comint-test-password-function-with-value () | ||
| 78 | "Test that `comint-password-function' alters normal password | ||
| 79 | flow. Hook function returns alternative password." | ||
| 80 | (cl-letf | ||
| 81 | (((symbol-function 'read-passwd) | ||
| 82 | (lambda (_prompt &optional _confirm _default) | ||
| 83 | "PaSsWoRd123"))) | ||
| 84 | (let ((cat (executable-find "cat")) | ||
| 85 | (comint-password-function (lambda (_prompt) "MaGiC-PaSsWoRd789"))) | ||
| 86 | (when cat | ||
| 87 | (with-temp-buffer | ||
| 88 | (make-comint-in-buffer "test-comint-password" (current-buffer) cat) | ||
| 89 | (let ((proc (get-buffer-process (current-buffer)))) | ||
| 90 | (comint-send-string proc "Password: ") | ||
| 91 | (accept-process-output proc 0 1 t) | ||
| 92 | (comint-send-eof) | ||
| 93 | (accept-process-output proc 0 1 t) | ||
| 94 | (should (string-equal (buffer-substring-no-properties (point-min) (point-max)) | ||
| 95 | "Password: MaGiC-PaSsWoRd789\n")) | ||
| 96 | (when (process-live-p proc) | ||
| 97 | (kill-process proc)) | ||
| 98 | (accept-process-output proc 0 1 t))))))) | ||
| 99 | |||
| 100 | (ert-deftest comint-test-password-function-with-nil () | ||
| 101 | "Test that `comint-password-function' does not alter the normal | ||
| 102 | password flow if it returns a nil value." | ||
| 103 | (cl-letf | ||
| 104 | (((symbol-function 'read-passwd) | ||
| 105 | (lambda (_prompt &optional _confirm _default) | ||
| 106 | "PaSsWoRd456"))) | ||
| 107 | (let ((cat (executable-find "cat")) | ||
| 108 | (comint-password-function (lambda (_prompt) nil))) | ||
| 109 | (when cat | ||
| 110 | (with-temp-buffer | ||
| 111 | (make-comint-in-buffer "test-comint-password" (current-buffer) cat) | ||
| 112 | (let ((proc (get-buffer-process (current-buffer)))) | ||
| 113 | (comint-send-string proc "Password: ") | ||
| 114 | (accept-process-output proc 0 1 t) | ||
| 115 | (comint-send-eof) | ||
| 116 | (accept-process-output proc 0 1 t) | ||
| 117 | (should (string-equal (buffer-substring-no-properties (point-min) (point-max)) | ||
| 118 | "Password: PaSsWoRd456\n")) | ||
| 119 | (when (process-live-p proc) | ||
| 120 | (kill-process proc)) | ||
| 121 | (accept-process-output proc 0 1 t))))))) | ||
| 122 | |||
| 55 | ;; Local Variables: | 123 | ;; Local Variables: |
| 56 | ;; no-byte-compile: t | 124 | ;; no-byte-compile: t |
| 57 | ;; End: | 125 | ;; End: |