From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.org!.POSTED!not-for-mail From: Tino Calancha Newsgroups: gmane.emacs.bugs Subject: bug#30190: 27.0.50; term run in line mode shows user passwords Date: Sun, 04 Feb 2018 01:15:54 +0900 Message-ID: <87efm259s5.fsf@gmail.com> References: <87r2qjh0fs.fsf@gmail.com> <87mv17nwe4.fsf@users.sourceforge.net> NNTP-Posting-Host: blaine.gmane.org Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Trace: blaine.gmane.org 1517674645 21397 195.159.176.226 (3 Feb 2018 16:17:25 GMT) X-Complaints-To: usenet@blaine.gmane.org NNTP-Posting-Date: Sat, 3 Feb 2018 16:17:25 +0000 (UTC) User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.0.50 (gnu/linux) Cc: 30190@debbugs.gnu.org To: Noam Postavsky Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Sat Feb 03 17:17:20 2018 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane.org Original-Received: from lists.gnu.org ([208.118.235.17]) by blaine.gmane.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ei0Ux-0004IH-OU for geb-bug-gnu-emacs@m.gmane.org; Sat, 03 Feb 2018 17:17:04 +0100 Original-Received: from localhost ([::1]:47716 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ei0Wy-0007kf-SB for geb-bug-gnu-emacs@m.gmane.org; Sat, 03 Feb 2018 11:19:08 -0500 Original-Received: from eggs.gnu.org ([2001:4830:134:3::10]:57915) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1ei0VH-0006OG-OS for bug-gnu-emacs@gnu.org; Sat, 03 Feb 2018 11:17:39 -0500 Original-Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1ei0Uw-0001yI-Mk for bug-gnu-emacs@gnu.org; Sat, 03 Feb 2018 11:17:23 -0500 Original-Received: from debbugs.gnu.org ([208.118.235.43]:47924) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1ei0Uw-0001wq-9P for bug-gnu-emacs@gnu.org; Sat, 03 Feb 2018 11:17:02 -0500 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1ei0Uv-0005d4-SN for bug-gnu-emacs@gnu.org; Sat, 03 Feb 2018 11:17:01 -0500 X-Loop: help-debbugs@gnu.org Resent-From: Tino Calancha Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Sat, 03 Feb 2018 16:17:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 30190 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: confirmed Original-Received: via spool by 30190-submit@debbugs.gnu.org id=B30190.151767457121572 (code B ref 30190); Sat, 03 Feb 2018 16:17:01 +0000 Original-Received: (at 30190) by debbugs.gnu.org; 3 Feb 2018 16:16:11 +0000 Original-Received: from localhost ([127.0.0.1]:55821 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ei0U6-0005br-U9 for submit@debbugs.gnu.org; Sat, 03 Feb 2018 11:16:11 -0500 Original-Received: from mail-pl0-f44.google.com ([209.85.160.44]:41280) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1ei0U5-0005bg-Jl for 30190@debbugs.gnu.org; Sat, 03 Feb 2018 11:16:10 -0500 Original-Received: by mail-pl0-f44.google.com with SMTP id k8so6400558pli.8 for <30190@debbugs.gnu.org>; Sat, 03 Feb 2018 08:16:09 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:references:date:in-reply-to:message-id :user-agent:mime-version:content-transfer-encoding; bh=UvWfnLrb0F2l2NLf4DBnxsYKU5R66klBUEETfKBHtDE=; b=bKN3yPbXerKN5cyaxmDoSwGiYVaXX3l9GbvU7nxWxbjP8S01IwomrRexfnkViCrw4p 3H+eK/xQVuNY8RFSLnVwB0AkHxOHivGgAzWss5xJhmyMMAvAoXmYFwwGPjMd4JgFRjtN V5MCgpDxGpHnppsbsIaQd3j5QMH78XSP8DOOfILLJugRgKApO2AuvVbRqyhedHBBs50M A93vzLIRIUHKSMJtWtlewOBI4vDxGR3CgySr2QD7b9spPy9paPtbTXZWQzX4AT82mxRj Jebj54P2Y0NuwM5yyvcqHyTSb6MbIYj2j04Z765XqcKpyjO9SQk+5bbULF8K6GCqzPku dDFA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:references:date:in-reply-to :message-id:user-agent:mime-version:content-transfer-encoding; bh=UvWfnLrb0F2l2NLf4DBnxsYKU5R66klBUEETfKBHtDE=; b=bWU47lcZJO8ZbddGNbjUMCx6PY+NoiZRpuJW6wG/zvmVqIJLsH01lOeL0v+MbVy9v2 LIubzxdkHS+++ezkr+ueunLXY94xTJCHqihrVUAbZaQF2lk9EalFBIu7y1f2KaqMdLxZ gmtcDu1wjJ5fb9hqG4TqU59wZcfnzZu/05FxatSwKHnUX25xQmB088OJgF0QIaokpgrh rPtnuCpJAdRB3Tk4Fp77pgS7omUEc2eg3dUKsVev8F3wBr2kwsJzqsJ/ueOkmRy4vgP+ AsULVSzwT2U1PDHOk5tQsmOxpYPDR2qeePhfVuU6f9x3jV+E2wYAnlgrQnIiU9k9S49v tnSw== X-Gm-Message-State: AKwxytd15FitlFG8oj0hLWG+Ygnc+gM8SuJd7nIJsKq9iO+ulwYd0PcH BgWERGIb6Qlduqpo3gDaV1oHIQ== X-Google-Smtp-Source: AH8x2240vkNl7XaX8h0JOmPX+5tt8wWQBvlIaGxyWf1jBe4D8eM6si/ub84clg+uvJuGF6RuGV7chg== X-Received: by 2002:a17:902:8f8b:: with SMTP id z11-v6mr16555832plo.43.1517674563457; Sat, 03 Feb 2018 08:16:03 -0800 (PST) Original-Received: from calancha-pc (146.219.128.101.dy.bbexcite.jp. [101.128.219.146]) by smtp.gmail.com with ESMTPSA id 184sm8918907pfd.156.2018.02.03.08.16.00 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Sat, 03 Feb 2018 08:16:01 -0800 (PST) In-Reply-To: <87mv17nwe4.fsf@users.sourceforge.net> (Noam Postavsky's message of "Sun, 21 Jan 2018 09:01:39 -0500") X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 208.118.235.43 X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane.org@gnu.org Original-Sender: "bug-gnu-emacs" Xref: news.gmane.org gmane.emacs.bugs:142849 Archived-At: Noam Postavsky writes: > Yes, seems to have been the case for a long time, I can reproduce back > to 24.3 (oldest Emacs version I have running). This is a security risk. I would like to have it fixed ASAP. Below patch seems to work. Any feedback would be appreciated. --8<-----------------------------cut here---------------start------------->= 8--- commit 089c86c2d8e46fd3f134826881c010409b65d364 Author: tino calancha Date: Sun Feb 4 01:00:29 2018 +0900 Prevent term run in line mode from showing user passwords =20=20=20=20 For buffers whose mode derive from comint-mode, the user password is read from the minibuffer and it's hidden. A buffer in term-mode and line submode, instead shows the passwords. This commit forces buffers in line term-mode to hide passwords (Bug#30190). =20=20=20=20 * lisp/term-utils: New file. Move into it some common code shared by comint.el and term.el. =20=20=20=20 * lisp/comint.el (comint-password-prompt-regexp): (send-invisible) Move them to the new file. Prefix them with 'term-utils-'. Define aliases to the original names. =20=20=20=20 * lisp/term.el (term-output-filter-functions): New hook. (term-send-input, term-emulate-terminal): Call it. diff --git a/lisp/comint.el b/lisp/comint.el index 8dba317099..0e9e13f12e 100644 --- a/lisp/comint.el +++ b/lisp/comint.el @@ -104,6 +104,7 @@ (require 'ring) (require 'ansi-color) (require 'regexp-opt) ;For regexp-opt-charset. +(require 'term-utils) ;; Buffer Local Variables: ;;=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D @@ -342,35 +343,6 @@ comint-process-echoes :type 'boolean :group 'comint) =20 -;; AIX puts the name of the person being su'd to in front of the prompt. -;; kinit prints a prompt like `Password for devnull@GNU.ORG: '. -;; ksu prints a prompt like `Kerberos password for devnull/root@GNU.ORG: '. -;; ssh-add prints a prompt like `Enter passphrase: '. -;; plink prints a prompt like `Passphrase for key "root@GNU.ORG": '. -;; Ubuntu's sudo prompts like `[sudo] password for user:' -;; Some implementations of passwd use "Password (again)" as the 2nd prompt. -;; Something called "perforce" uses "Enter password:". -;; See M-x comint-testsuite--test-comint-password-prompt-regexp. -(defcustom comint-password-prompt-regexp - (concat - "\\(^ *\\|" - (regexp-opt - '("Enter" "enter" "Enter same" "enter same" "Enter the" "enter the" - "Old" "old" "New" "new" "'s" "login" - "Kerberos" "CVS" "UNIX" " SMB" "LDAP" "PEM" "SUDO" - "[sudo]" "Repeat" "Bad" "Retype") - t) - " +\\)" - "\\(?:" (regexp-opt password-word-equivalents) "\\|Response\\)" - "\\(?:\\(?:, try\\)? *again\\| (empty for no passphrase)\\| (again)\\)?" - ;; "[[:alpha:]]" used to be "for", which fails to match non-English. - "\\(?: [[:alpha:]]+ .+\\)?[\\s =C2=A0]*[:=EF=BC=9A=E1=9F=96][\\s =C2=A0= ]*\\'") - "Regexp matching prompts for passwords in the inferior process. -This is used by `comint-watch-for-password-prompt'." - :version "27.1" - :type 'regexp - :group 'comint) - ;; Here are the per-interpreter hooks. (defvar comint-get-old-input (function comint-get-old-input-default) "Function that returns old text in Comint mode. @@ -399,7 +371,7 @@ comint-input-filter-functions These functions get one argument, a string containing the text to send.") =20 ;;;###autoload -(defvar comint-output-filter-functions '(ansi-color-process-output comint-= postoutput-scroll-to-bottom comint-watch-for-password-prompt) +(defvar comint-output-filter-functions '(ansi-color-process-output comint-= postoutput-scroll-to-bottom term-utils-watch-for-password-prompt) "Functions to call after output is inserted into the buffer. One possible function is `comint-postoutput-scroll-to-bottom'. These functions get one argument, a string containing the text as original= ly @@ -2342,41 +2314,8 @@ comint-read-noecho ;; saved -- typically passwords to ftp, telnet, or somesuch. ;; Just enter m-x send-invisible and type in your line. =20 -(defun send-invisible (&optional prompt) - "Read a string without echoing. -Then send it to the process running in the current buffer. -The string is sent using `comint-input-sender'. -Security bug: your string can still be temporarily recovered with -\\[view-lossage]; `clear-this-command-keys' can fix that." - (interactive "P") ; Defeat snooping via C-x ESC ESC - (let ((proc (get-buffer-process (current-buffer))) - (prefix - (if (eq (window-buffer) (current-buffer)) - "" - (format "(In buffer %s) " - (current-buffer))))) - (if proc - (let ((str (read-passwd (concat prefix - (or prompt "Non-echoed text: "))))) - (if (stringp str) - (progn - (comint-snapshot-last-prompt) - (funcall comint-input-sender proc str)) - (message "Warning: text will be echoed"))) - (error "Buffer %s has no process" (current-buffer))))) - -(defun comint-watch-for-password-prompt (string) - "Prompt in the minibuffer for password and send without echoing. -This function uses `send-invisible' to read and send a password to the buf= fer's -process if STRING contains a password prompt defined by -`comint-password-prompt-regexp'. - -This function could be in the list `comint-output-filter-functions'." - (when (let ((case-fold-search t)) - (string-match comint-password-prompt-regexp string)) - (when (string-match "^[ \n\r\t\v\f\b\a]+" string) - (setq string (replace-match "" t t string))) - (send-invisible string))) +(defalias 'comint-watch-for-password-prompt 'term-utils-watch-for-password= -prompt) + ;; Low-level process communication =20 diff --git a/lisp/term-utils.el b/lisp/term-utils.el new file mode 100644 index 0000000000..7edb741bc3 --- /dev/null +++ b/lisp/term-utils.el @@ -0,0 +1,118 @@ +;;; term-utils.el --- Common code used by term.el and comint.el -*- lexic= al-binding: t; -*- + +;; Copyright (C) 2018 Tino Calancha + +;; Author: Tino Calancha +;; Keywords: processes, terminals + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation, either version 3 of the License, or +;; (at your option) any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with this program. If not, see . + +;;; Commentary: + +;; + +;;; code: + + +;; Retrieve the right defvar value according with the buffer mode. +(defmacro term-utils--defvar-value (suffix) + "Build a defvar with the `major-mode' and SUFFIX, return its value. +The buffer major mode must be `term-mode' or `comint-mode'." + (declare (debug (symbolp)) (indent 0)) + `(symbol-value + (intern-soft + (format "%S%S" (if (derived-mode-p 'term-mode) 'term- 'comint-) + ',suffix)))) + +;; AIX puts the name of the person being su'd to in front of the prompt. +;; kinit prints a prompt like `Password for devnull@GNU.ORG: '. +;; ksu prints a prompt like `Kerberos password for devnull/root@GNU.ORG: '. +;; ssh-add prints a prompt like `Enter passphrase: '. +;; plink prints a prompt like `Passphrase for key "root@GNU.ORG": '. +;; Ubuntu's sudo prompts like `[sudo] password for user:' +;; Some implementations of passwd use "Password (again)" as the 2nd prompt. +;; Something called "perforce" uses "Enter password:". +;; See M-x comint-testsuite--test-comint-password-prompt-regexp. +(defcustom term-utils-password-prompt-regexp + (concat + "\\(^ *\\|" + (regexp-opt + '("Enter" "enter" "Enter same" "enter same" "Enter the" "enter the" + "Old" "old" "New" "new" "'s" "login" + "Kerberos" "CVS" "UNIX" " SMB" "LDAP" "PEM" "SUDO" + "[sudo]" "Repeat" "Bad" "Retype") + t) + " +\\)" + "\\(?:" (regexp-opt password-word-equivalents) "\\|Response\\)" + "\\(?:\\(?:, try\\)? *again\\| (empty for no passphrase)\\| (again)\\)?" + ;; "[[:alpha:]]" used to be "for", which fails to match non-English. + "\\(?: [[:alpha:]]+ .+\\)?[\\s =C2=A0]*[:=EF=BC=9A=E1=9F=96][\\s =C2=A0= ]*\\'") + "Regexp matching prompts for passwords in the inferior process. +This is used by `term-utils-watch-for-password-prompt'." + :version "27.1" + :type 'regexp + :group 'term-utils) + +(declare-function comint-snapshot-last-prompt "comint") + +(defun term-utils-send-invisible (&optional prompt) + "Read a string without echoing with PROMPT. +Then send it to the process running in the current buffer. +The string is sent using `comint-input-sender' or `term-input-sender' +depending of the buffer mode. +Security bug: your string can still be temporarily recovered with +\\[view-lossage]; `clear-this-command-keys' can fix that." + (interactive "P") ; Defeat snooping via C-x ESC ESC + (let ((proc (get-buffer-process (current-buffer))) + (prefix + (if (eq (window-buffer) (current-buffer)) + "" + (format "(In buffer %s) " + (current-buffer))))) + (if proc + (let ((str (read-passwd (concat prefix + (or prompt "Non-echoed text: "))))) + (if (stringp str) + (let ((input-sender-fun (term-utils--defvar-value input-sender))) + (if (derived-mode-p 'comint-mode) (comint-snapshot-last-prompt)) + (funcall input-sender-fun proc str)) + (message "Warning: text will be echoed"))) + (error "Buffer %s has no process" (current-buffer))))) + +(defalias 'send-invisible 'term-utils-send-invisible) + +(defvar term-raw-map) ; Defined in term.el +(defun term-utils-term-in-line-mode-p () + "Return non-nil if the buffer is in `term-mode' and line submode." + (and (derived-mode-p 'term-mode) (eq (current-local-map) term-raw-map))) + +(defun term-utils-watch-for-password-prompt (string) + "Prompt in the minibuffer for password and send without echoing. +This function uses `send-invisible' to read and send a password to the buf= fer's +process if STRING contains a password prompt defined by +`term-utils-password-prompt-regexp'. + +This function could be in the lists `comint-output-filter-functions' +and `term-output-filter-functions'." + ;; Do nothing if buffer is in term-mode with line submode + (unless (term-utils-term-in-line-mode-p) + (when (let ((case-fold-search t)) + (string-match term-utils-password-prompt-regexp string)) + (when (string-match "^[ \n\r\t\v\f\b\a]+" string) + (setq string (replace-match "" t t string))) + (term-utils-send-invisible string)))) + + +(provide 'term-utils) +;;; term-utils.el ends here diff --git a/lisp/term.el b/lisp/term.el index a0313d88da..ed0f1715b2 100644 --- a/lisp/term.el +++ b/lisp/term.el @@ -340,6 +340,7 @@ term-protocol-version (eval-when-compile (require 'cl-lib)) (require 'ring) (require 'ehelp) +(require 'term-utils) =20 (declare-function ring-empty-p "ring" (ring)) (declare-function ring-ref "ring" (ring index)) @@ -575,6 +576,16 @@ term-input-filter-functions =20 This variable is buffer-local.") =20 +;;;###autoload +(defvar term-output-filter-functions '(term-utils-watch-for-password-promp= t) + "Functions to call after output is inserted into the buffer. +One possible function is `term-utils-watch-for-password-prompt'. +These functions get one argument, a string containing the text as original= ly +inserted. + +You can use `add-hook' to add functions to this list +either globally or locally.") + (defvar term-input-sender (function term-simple-send) "Function to actually send to PROCESS the STRING submitted by user. Usually this is just `term-simple-send', but if your mode needs to @@ -2106,7 +2117,8 @@ term-send-input (set-marker term-pending-delete-marker pmark-val) (set-marker (process-mark proc) (point))) (goto-char pmark) - (funcall term-input-sender proc input))))) + (funcall term-input-sender proc input) + (run-hook-with-args 'term-output-filter-functions ""))))) =20 (defun term-get-old-input-default () "Default for `term-get-old-input'. @@ -3017,6 +3029,8 @@ term-emulate-terminal (term-handle-deferred-scroll)) =20 (set-marker (process-mark proc) (point)) + ;; Run these hooks with point where the user had it. + (run-hook-with-args 'term-output-filter-functions str) (when save-point (goto-char save-point) (set-marker save-point nil)) --8<-----------------------------cut here---------------end--------------->= 8---