]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix errors in Tramp's password cache expiration
authorMichael Albinus <michael.albinus@gmx.de>
Thu, 14 Nov 2024 16:29:07 +0000 (17:29 +0100)
committerEshel Yaron <me@eshelyaron.com>
Wed, 20 Nov 2024 16:11:32 +0000 (17:11 +0100)
* doc/misc/tramp.texi (Password handling): Mention expiration of
cached passwords when a session timeout happens.

* lisp/net/tramp-adb.el (tramp-adb-maybe-open-connection): Rename
file property "process-attributes" to connection property
" process-attributes".

* lisp/net/tramp.el (tramp-read-passwd):
* lisp/net/tramp-sh.el (tramp-maybe-open-connection):
* lisp/net/tramp-sudoedit.el (tramp-sudoedit-send-command):
Rename connection property "password-vector" to "pw-vector".

* lisp/net/tramp-sh.el (tramp-maybe-open-connection):
Use connection property "hop-vector".

* lisp/net/tramp.el (tramp-get-process-attributes)
(tramp-handle-list-system-processes): Rename file property
"process-attributes" to connection property " process-attributes".
(tramp-compute-multi-hops): Check for
`tramp-sh-file-name-handler-p', it works only for this.
(tramp-action-password, tramp-process-actions): Use connection
property "hop-vector".
(tramp-read-passwd, tramp-clear-passwd): Rewrite.  (Bug#74105)

(cherry picked from commit 6d42c70fd3e2e63c8f993a10c83dee7425f185d5)

doc/misc/tramp.texi
lisp/net/tramp-adb.el
lisp/net/tramp-sh.el
lisp/net/tramp-sudoedit.el
lisp/net/tramp.el

index 51ba55e2f5e4c181fbe03305df9be9d6d1e31764..ccbfff7ed2bf3824c4709febedd2bbcdc19a88f9 100644 (file)
@@ -2258,6 +2258,12 @@ this interactively.
 @vindex auth-source-do-cache
 Set @code{auth-source-do-cache} to @code{nil} to disable password caching.
 
+For connections which use a session-timeout, like @option{sudo},
+@option{doas} and @option{run0}, the password cache is expired by
+@value{tramp} when the session expires (@pxref{Predefined connection
+information}).  However, this makes only sense if the password cannot
+be retrieved from a persistent authentication file or store.
+
 
 @node Connection caching
 @section Reusing connection related information
index 5a7176c3ec8140c662335314b229820b7b9763c6..2e9df00668b4c76e9faab92f4265664196c69fa5 100644 (file)
@@ -1106,7 +1106,8 @@ connection if a previous connection has died for some reason."
       ;; Maybe we know already that "su" is not supported.  We cannot
       ;; use a connection property, because we have not checked yet
       ;; whether it is still the same device.
-      (when (and user (not (tramp-get-file-property vec "/" "su-command-p" t)))
+      (when
+         (and user (not (tramp-get-connection-property vec " su-command-p" t)))
        (tramp-error vec 'file-error "Cannot switch to user `%s'" user))
 
       (unless (process-live-p p)
@@ -1191,7 +1192,7 @@ connection if a previous connection has died for some reason."
                (unless (tramp-adb-send-command-and-check vec nil)
                  (delete-process p)
                  ;; Do not flush, we need the nil value.
-                 (tramp-set-file-property vec "/" "su-command-p" nil)
+                 (tramp-set-connection-property vec " su-command-p" nil)
                  (tramp-error
                   vec 'file-error "Cannot switch to user `%s'" user)))
 
index eab1dd41d76097cc4cd108c92b88f893a788f6c6..d81420d1b5fdbc6c2e9a302f286e6512f1a613ad 100644 (file)
@@ -5253,9 +5253,10 @@ connection if a previous connection has died for some reason."
                        (setq r-shell t)))
                    (setq current-host l-host)
 
-                   ;; Set password prompt vector.
+                   ;; Set hop and password prompt vector.
+                   (tramp-set-connection-property p "hop-vector" hop)
                    (tramp-set-connection-property
-                    p "password-vector"
+                    p "pw-vector"
                     (if (tramp-get-method-parameter
                          hop 'tramp-password-previous-hop)
                         (let ((pv (copy-tramp-file-name previous-hop)))
@@ -5311,6 +5312,8 @@ connection if a previous connection has died for some reason."
                       tramp-actions-before-shell connection-timeout))
 
                    ;; Next hop.
+                   (tramp-flush-connection-property p "hop-vector")
+                   (tramp-flush-connection-property p "pw-vector")
                    (setq options ""
                          target-alist (cdr target-alist)
                          previous-hop hop)))
index 1149e4d07b84ce7e7e4703021fccc51fce74cc6e..6216364ba782b8119c94af88dd7ac146da4d550e 100644 (file)
@@ -787,7 +787,7 @@ in case of error, t otherwise."
       ;; Avoid process status message in output buffer.
       (set-process-sentinel p #'ignore)
       (tramp-post-process-creation p vec)
-      (tramp-set-connection-property p "password-vector" tramp-sudoedit-null-hop)
+      (tramp-set-connection-property p "pw-vector" tramp-sudoedit-null-hop)
       (tramp-process-actions p vec nil tramp-sudoedit-sudo-actions)
       (tramp-message vec 6 "%s\n%s" (process-exit-status p) (buffer-string))
       (prog1
index 6e1b9e66478976bbb99b99608a827248da57c462..e7c3bb1c536f2f8af7d150ae716120f3425c50d6 100644 (file)
@@ -4702,7 +4702,7 @@ Parsing the remote \"ps\" output is controlled by
 It is not guaranteed, that all process attributes as described in
 `process-attributes' are returned.  The additional attribute
 `pid' shall be returned always."
-  (with-tramp-file-property vec "/" "process-attributes"
+  (with-tramp-connection-property vec " process-attributes"
     (ignore-errors
       (with-temp-buffer
         (hack-connection-local-variables-apply
@@ -4749,7 +4749,7 @@ It is not guaranteed, that all process attributes as described in
 (defun tramp-handle-list-system-processes ()
   "Like `list-system-processes' for Tramp files."
   (let ((v (tramp-dissect-file-name default-directory)))
-    (tramp-flush-file-property v "/" "process-attributes")
+    (tramp-flush-connection-property v " process-attributes")
     (mapcar (lambda (x) (cdr (assq 'pid x))) (tramp-get-process-attributes v))))
 
 (defun tramp-get-lock-file (file)
@@ -4957,74 +4957,74 @@ Do not set it manually, it is used buffer-local in `tramp-get-lock-pid'.")
        (item vec)
        choices proxy)
 
-    ;; Ad-hoc proxy definitions.
-    (tramp-add-hops vec)
-
-    ;; Look for proxy hosts to be passed.
-    (setq choices tramp-default-proxies-alist)
-    (while choices
-      (setq item (pop choices)
-           proxy (eval (nth 2 item) t))
-      (when (and
-            ;; Host.
-            (string-match-p
-             (or (eval (nth 0 item) t) "")
-             (or (tramp-file-name-host-port (car target-alist)) ""))
-            ;; User.
-            (string-match-p
-             (or (eval (nth 1 item) t) "")
-             (or (tramp-file-name-user-domain (car target-alist)) "")))
-       (if (null proxy)
-           ;; No more hops needed.
-           (setq choices nil)
-         ;; Replace placeholders.  The proxy could contain "%" which
-         ;; is not intended as format character, for example in
-         ;; USER%DOMAIN or POD%NAMESPACE.
-         (setq proxy
-               (replace-regexp-in-string
-                (rx "%" (group (= 2 alnum))) "%%\\1" proxy)
-               proxy
-               (format-spec
-                proxy
-                (format-spec-make
-                 ?u (or (tramp-file-name-user (car target-alist)) "")
-                 ?h (or (tramp-file-name-host (car target-alist)) ""))))
-         (with-parsed-tramp-file-name proxy l
-           ;; Add the hop.
-           (push l target-alist)
-           ;; Start next search.
-           (setq choices tramp-default-proxies-alist)))))
-
-    ;; Foreign and out-of-band methods are not supported for multi-hops.
-    (when (cdr target-alist)
-      (setq choices target-alist)
-      (while (setq item (pop choices))
-       (unless (tramp-multi-hop-p item)
-         (setq tramp-default-proxies-alist saved-tdpa)
-         (tramp-user-error
-          vec "Method `%s' is not supported for multi-hops"
-          (tramp-file-name-method item)))))
-
-    ;; Some methods ("su", "sg", "sudo", "doas", "run0", "ksu") do not
-    ;; use the host name in their command template.  In this case, the
-    ;; remote file name must use either a local host name (first hop),
-    ;; or a host name matching the previous hop.
-    (let ((previous-host (or tramp-local-host-regexp "")))
-      (setq choices target-alist)
-      (while (setq item (pop choices))
-       (let ((host (tramp-file-name-host item)))
-         (unless
-             (or
-              ;; The host name is used for the remote shell command.
-              (member
-               "%h" (flatten-tree
-                     (tramp-get-method-parameter item 'tramp-login-args)))
-              ;; The host name must match previous hop.
-              (string-match-p previous-host host))
+    ;; `tramp-compute-multi-hops' could be called also for other file
+    ;; name handlers, for example in `tramp-clear-passwd'.
+    (when (tramp-sh-file-name-handler-p vec)
+
+      ;; Ad-hoc proxy definitions.
+      (tramp-add-hops vec)
+
+      ;; Look for proxy hosts to be passed.
+      (setq choices tramp-default-proxies-alist)
+      (while choices
+       (setq item (pop choices)
+             proxy (eval (nth 2 item) t))
+       (when (and
+              ;; Host.
+              (string-match-p
+               (or (eval (nth 0 item) t) "")
+               (or (tramp-file-name-host-port (car target-alist)) ""))
+              ;; User.
+              (string-match-p
+               (or (eval (nth 1 item) t) "")
+               (or (tramp-file-name-user-domain (car target-alist)) "")))
+         (if (null proxy)
+             ;; No more hops needed.
+             (setq choices nil)
+           ;; Replace placeholders.
+           (setq proxy
+                 (format-spec
+                  proxy
+                  (format-spec-make
+                   ?u (or (tramp-file-name-user (car target-alist)) "")
+                   ?h (or (tramp-file-name-host (car target-alist)) ""))))
+           (with-parsed-tramp-file-name proxy l
+             ;; Add the hop.
+             (push l target-alist)
+             ;; Start next search.
+             (setq choices tramp-default-proxies-alist)))))
+
+      ;; Foreign and out-of-band methods are not supported for
+      ;; multi-hops.
+      (when (cdr target-alist)
+       (setq choices target-alist)
+       (while (setq item (pop choices))
+         (unless (tramp-multi-hop-p item)
            (setq tramp-default-proxies-alist saved-tdpa)
            (tramp-user-error
-            vec "Host name `%s' does not match `%s'" host previous-host))
-         (setq previous-host (rx bol (literal host) eol)))))
+            vec "Method `%s' is not supported for multi-hops"
+            (tramp-file-name-method item)))))
+
+      ;; Some methods ("su", "sg", "sudo", "doas", "run0", "ksu") do
+      ;; not use the host name in their command template.  In this
+      ;; case, the remote file name must use either a local host name
+      ;; (first hop), or a host name matching the previous hop.
+      (let ((previous-host (or tramp-local-host-regexp "")))
+       (setq choices target-alist)
+       (while (setq item (pop choices))
+         (let ((host (tramp-file-name-host item)))
+           (unless
+               (or
+                ;; The host name is used for the remote shell command.
+                (member
+                 "%h" (flatten-tree
+                       (tramp-get-method-parameter item 'tramp-login-args)))
+                ;; The host name must match previous hop.
+                (string-match-p previous-host host))
+             (setq tramp-default-proxies-alist saved-tdpa)
+             (tramp-user-error
+              vec "Host name `%s' does not match `%s'" host previous-host))
+           (setq previous-host (rx bol (literal host) eol))))))
 
     ;; Result.
     target-alist))
@@ -5689,7 +5689,11 @@ of."
       ;; Sometimes, the process returns a new password request
       ;; immediately after rejecting the previous (wrong) one.
       (unless (or tramp-password-prompt-not-unique
-                 (tramp-get-connection-property vec " first-password-request"))
+                 (tramp-get-connection-property
+                  (tramp-get-connection-property
+                   proc "hop-vector"
+                   (process-get proc 'tramp-vector))
+                  " first-password-request"))
        (tramp-clear-passwd vec))
       (goto-char (point-min))
       (tramp-check-for-regexp proc tramp-process-action-regexp)
@@ -5892,10 +5896,10 @@ because the shell prompt has been detected), it shall throw a
 result.  The symbol `ok' means that all ACTIONs have been
 performed successfully.  Any other value means an error."
   ;; Enable `auth-source', unless "emacs -Q" has been called.  We must
-  ;; use the "password-vector" property in case we have several hops.
+  ;; use the "hop-vector" property in case we have several hops.
   (tramp-set-connection-property
    (tramp-get-connection-property
-    proc "password-vector" (process-get proc 'tramp-vector))
+    proc "hop-vector" (process-get proc 'tramp-vector))
    " first-password-request" tramp-cache-read-persistent-data)
   (save-restriction
     (with-tramp-progress-reporter
@@ -6868,15 +6872,16 @@ Consults the auth-source package."
         ;; adapt `default-directory'.  (Bug#39389, Bug#39489)
         (default-directory tramp-compat-temporary-file-directory)
         (case-fold-search t)
-        ;; In tramp-sh.el, we must use "password-vector" due to
-        ;; multi-hop.
-        (vec (tramp-get-connection-property
-              proc "password-vector" (process-get proc 'tramp-vector)))
-        (key (tramp-make-tramp-file-name vec 'noloc))
-        (method (tramp-file-name-method vec))
-        (user-domain (or (tramp-file-name-user-domain vec)
-                         (tramp-get-connection-property key "login-as")))
-        (host-port (tramp-file-name-host-port vec))
+        ;; In tramp-sh.el, we must use "hop-vector" and "pw-vector"
+        ;; due to multi-hop.
+        (vec (process-get proc 'tramp-vector))
+        (hop-vec (tramp-get-connection-property proc "hop-vector" vec))
+        (pw-vec (tramp-get-connection-property proc "pw-vector" hop-vec))
+        (key (tramp-make-tramp-file-name pw-vec 'noloc))
+        (method (tramp-file-name-method pw-vec))
+        (user-domain (or (tramp-file-name-user-domain pw-vec)
+                         (tramp-get-connection-property pw-vec "login-as")))
+        (host-port (tramp-file-name-host-port pw-vec))
         (pw-prompt
          (string-trim-left
           (or prompt
@@ -6885,29 +6890,23 @@ Consults the auth-source package."
                 (if (string-match-p "passphrase" (match-string 1))
                     (match-string 0)
                   (format "%s for %s " (capitalize (match-string 1)) key))))))
+        ;; If there is no user name, `:create' triggers to ask for.
+        ;; We suppress it.
+        (pw-spec (list :max 1 :user user-domain :host host-port :port method
+                       :require (cons :secret (and user-domain '(:user)))
+                       :create (and user-domain t)))
         (auth-source-creation-prompts `((secret . ,pw-prompt)))
         ;; Use connection-local value.
         (auth-sources (buffer-local-value 'auth-sources (process-buffer proc)))
         auth-info auth-passwd tramp-dont-suspend-timers)
 
     (unwind-protect
-       ;; We cannot use `with-parsed-tramp-file-name', because it
-       ;; expands the file name.
        (or
         (setq tramp-password-save-function nil)
-        ;; See if auth-sources contains something useful.
+        ;; See if `auth-sources' contains something useful.
         (ignore-errors
-          (and auth-sources
-                (tramp-get-connection-property vec " first-password-request")
-               ;; Try with Tramp's current method.  If there is no
-               ;; user name, `:create' triggers to ask for.  We
-               ;; suppress it.
-               (setq auth-info
-                     (car
-                      (auth-source-search
-                       :max 1 :user user-domain :host host-port :port method
-                       :require (cons :secret (and user-domain '(:user)))
-                       :create (and user-domain t)))
+          (and (tramp-get-connection-property hop-vec " first-password-request")
+               (setq auth-info (car (apply #'auth-source-search pw-spec))
                      tramp-password-save-function
                      (plist-get auth-info :save-function)
                      auth-passwd
@@ -6915,12 +6914,19 @@ Consults the auth-source package."
 
         ;; Try the password cache.
         (with-tramp-suspended-timers
-          (setq auth-passwd (password-read pw-prompt key)
+          (setq auth-passwd
+                (password-read
+                 pw-prompt (auth-source-format-cache-entry pw-spec))
                 tramp-password-save-function
-                (lambda () (password-cache-add key auth-passwd)))
+                 (when auth-source-do-cache
+                  (lambda ()
+                    (password-cache-add
+                     (auth-source-format-cache-entry pw-spec) auth-passwd))))
           auth-passwd))
 
-      (tramp-set-connection-property vec " first-password-request" nil))))
+      ;; Remember the values.
+      (tramp-set-connection-property hop-vec " pw-spec" pw-spec)
+      (tramp-set-connection-property hop-vec " first-password-request" nil))))
 
 (defun tramp-read-passwd-without-cache (proc &optional prompt)
   "Read a password from user (compat function)."
@@ -6937,17 +6943,11 @@ Consults the auth-source package."
 (defun tramp-clear-passwd (vec)
   "Clear password cache for connection related to VEC."
   (declare (tramp-suppress-trace t))
-  (let ((method (tramp-file-name-method vec))
-       (user-domain (tramp-file-name-user-domain vec))
-       (host-port (tramp-file-name-host-port vec))
-       (hop (tramp-file-name-hop vec)))
-    (when hop
-      ;; Clear also the passwords of the hops.
-      (tramp-clear-passwd (tramp-dissect-hop-name hop)))
-    (auth-source-forget
-     `(:max 1 ,(and user-domain :user) ,user-domain
-       :host ,host-port :port ,method))
-    (password-cache-remove (tramp-make-tramp-file-name vec 'noloc))))
+  (when-let* ((hop (cadr (reverse (tramp-compute-multi-hops vec)))))
+    ;; Clear also the passwords of the hops.
+    (tramp-clear-passwd hop))
+  (when-let* ((pw-spec (tramp-get-connection-property vec " pw-spec")))
+    (auth-source-forget pw-spec)))
 
 (defun tramp-time-diff (t1 t2)
   "Return the difference between the two times, in seconds.