]> git.eshelyaron.com Git - emacs.git/commitdiff
Support fingerprint readers in Tramp
authorMichael Albinus <michael.albinus@gmx.de>
Tue, 26 Nov 2024 11:45:06 +0000 (12:45 +0100)
committerEshel Yaron <me@eshelyaron.com>
Wed, 27 Nov 2024 19:55:49 +0000 (20:55 +0100)
* doc/misc/tramp.texi (Frequently Asked Questions): Speak about
fingerprint readers.

* lisp/net/tramp-sh.el (tramp-actions-before-shell):
Use `tramp-fingerprint-prompt-regexp'.

* lisp/net/tramp.el (tramp-wrong-passwd-regexp): Add fingerprint
messages.
(tramp-fingerprint-prompt-regexp, tramp-use-fingerprint):
New defcustoms.
(tramp-action-fingerprint, tramp-action-show-message): New defuns.
(tramp-action-show-and-confirm-message): Start check at (point-min).

* test/lisp/net/tramp-tests.el (tramp-test47-read-fingerprint):
New test.

(cherry picked from commit 3fe787ad4d5894df5b540dbd195128118c949c7c)

doc/misc/tramp.texi
lisp/net/tramp-sh.el
lisp/net/tramp.el
test/lisp/net/tramp-tests.el

index 98e52ce5be1dc31da5912abcd9491bd4b5c2f87a..5851ad3abafe46cc013f5ff1843acbdf52795232 100644 (file)
@@ -5577,6 +5577,23 @@ nitrokey, or titankey.
 (residential) keys by @command{ssh-agent}.  As workaround, you might
 disable @command{ssh-agent} for such keys.
 
+
+@item
+Does @value{tramp} support a fingerprint reader?
+
+Yes.  A fingerprint reader could be used as additional authentication
+method for @option{sudo}-based logins.  @value{tramp} supports the
+additional handshaking messages for it@footnote{It supports
+fingerprint readers driven by @command{fprintd}.}.  If the fingerprint
+isn't recognized by the fingerprint reader in time, the authentication
+falls back to request a password.
+
+@vindex tramp-use-fingerprint
+If the user option @code{tramp-use-fingerprint} is @code{nil},
+@value{tramp} interrupts the fingerprint request, falling back to
+password authentication immediately.
+
+
 @item
 @value{tramp} does not connect to Samba or MS Windows hosts running
 SMB1 connection protocol
index e8fd251457c49ee34c9d500d960529ae9b829bd0..205b0d6304cc9566679e62f78335206436c411b3 100644 (file)
@@ -601,6 +601,7 @@ shell from reading its init file."
   '((tramp-login-prompt-regexp tramp-action-login)
     (tramp-password-prompt-regexp tramp-action-password)
     (tramp-otp-password-prompt-regexp tramp-action-otp-password)
+    (tramp-fingerprint-prompt-regexp tramp-action-fingerprint)
     (tramp-wrong-passwd-regexp tramp-action-permission-denied)
     (shell-prompt-pattern tramp-action-succeed)
     (tramp-shell-prompt-pattern tramp-action-succeed)
index 6347286b71586897a2eb245eecf832991acbc53a..2b64c386e5cbbcd3da5594756d0ffdcaa7218fd9 100644 (file)
@@ -723,13 +723,52 @@ The regexp should match at end of buffer."
         "No supported authentication methods left to try!"
         (: "Login " (| "Incorrect" "incorrect"))
         (: "Connection " (| "refused" "closed"))
-        (: "Received signal " (+ digit)))
+        (: "Received signal " (+ digit))
+        ;; Fingerprint.
+        "Verification timed out"
+        "Failed to match fingerprint"
+        "An unknown error occurred")
       (* nonl))
   "Regexp matching a `login failed' message.
 The regexp should match at end of buffer."
   :type 'regexp
   :link '(tramp-info-link :tag "Tramp manual" tramp-wrong-passwd-regexp))
 
+;; <https://gitlab.freedesktop.org/libfprint/fprintd/-/blob/master/pam/fingerprint-strings.h?ref_type=heads>
+(defcustom tramp-fingerprint-prompt-regexp
+  (rx (| "Place your finger on"
+        "Swipe your finger across"
+        "Place your left thumb on"
+        "Swipe your left thumb across"
+        "Place your left index finger on"
+        "Swipe your left index finger across"
+        "Place your left middle finger on"
+        "Swipe your left middle finger across"
+        "Place your left ring finger on"
+        "Swipe your left ring finger across"
+        "Place your left little finger on"
+        "Swipe your left little finger across"
+        "Place your right thumb on"
+        "Swipe your right thumb across"
+        "Place your right index finger on"
+        "Swipe your right index finger across"
+        "Place your right middle finger on"
+        "Swipe your right middle finger across"
+        "Place your right ring finger on"
+        "Swipe your right ring finger across"
+        "Place your right little finger on"
+        "Swipe your right little finger across"
+        "Place your finger on the reader again"
+        "Swipe your finger again"
+        "Swipe was too short, try again"
+        "Your finger was not centred, try swiping your finger again"
+        "Remove your finger, and try swiping your finger again")
+      (* nonl) (* (any "\r\n")))
+  "Regexp matching fingerprint prompts.
+The regexp should match at end of buffer."
+  :version "30.2"
+  :type 'regexp)
+
 (defcustom tramp-yesno-prompt-regexp
   (rx "Are you sure you want to continue connecting (yes/no"
       (? "/[fingerprint]") ")?"
@@ -5737,6 +5776,23 @@ of."
       (narrow-to-region (point-max) (point-max))))
   t)
 
+(defcustom tramp-use-fingerprint t
+  "Whether fingerprint prompts shall be used for authentication."
+  :version "30.2"
+  :type 'boolean
+  :link '(tramp-info-link :tag "Tramp manual" tramp-use-fingerprint))
+
+(defun tramp-action-fingerprint (proc vec)
+  "Query the user for a fingerprint verification.
+Interrupt the query if `tramp-use-fingerprint' is nil."
+  (with-current-buffer (process-buffer proc)
+    (if tramp-use-fingerprint
+       (tramp-action-show-message proc vec)
+      (interrupt-process proc)
+      ;; Hide message.
+      (narrow-to-region (point-max) (point-max))))
+  t)
+
 (defun tramp-action-succeed (_proc _vec)
   "Signal success in finding shell prompt."
   (throw 'tramp-action 'ok))
@@ -5783,6 +5839,26 @@ The terminal type can be configured with `tramp-terminal-type'."
   (tramp-send-string vec (concat tramp-terminal-type tramp-local-end-of-line))
   t)
 
+(defun tramp-action-show-message (proc vec)
+  "Show the user a message for confirmation.
+Wait, until the connection buffer changes."
+  (with-current-buffer (process-buffer proc)
+    (let ((cursor-in-echo-area t)
+         set-message-function clear-message-function tramp-dont-suspend-timers)
+      (with-tramp-suspended-timers
+       ;; Silence byte compiler.
+       (ignore set-message-function clear-message-function)
+       (tramp-message vec 6 "\n%s" (buffer-string))
+       (goto-char (point-min))
+       (tramp-check-for-regexp proc tramp-process-action-regexp)
+       (with-temp-message (concat (string-trim (match-string 0)) " ")
+         ;; Hide message in buffer.
+         (narrow-to-region (point-max) (point-max))
+         ;; Wait for new output.
+         (while (length= (buffer-string) 0)
+           (tramp-accept-process-output proc))))))
+  t)
+
 (defun tramp-action-confirm-message (_proc vec)
   "Return RET in order to confirm the message."
   (tramp-message
@@ -5800,6 +5876,7 @@ Wait, until the connection buffer changes."
        ;; Silence byte compiler.
        (ignore set-message-function clear-message-function)
        (tramp-message vec 6 "\n%s" (buffer-string))
+       (goto-char (point-min))
        (tramp-check-for-regexp proc tramp-process-action-regexp)
        (with-temp-message (concat (string-trim (match-string 0)) " ")
          ;; Hide message in buffer.
index 3a770648b25cb700fb42c55135b36b47aaf45116..96dbdc53af0815c4edabcc0bf8577b8247a1dd62 100644 (file)
@@ -7812,6 +7812,49 @@ process sentinels.  They shall not disturb each other."
            (should-error
             (file-exists-p ert-remote-temporary-file-directory)))))))))
 
+(ert-deftest tramp-test47-read-fingerprint ()
+  "Check Tramp fingerprint handling."
+  :tags '(:expensive-test)
+  (skip-unless (tramp--test-mock-p))
+
+  (let (;; Suppress "exec".
+       (tramp-restricted-shell-hosts-alist `(,tramp-system-name)))
+
+    ;; Reading fingerprint works.
+    (tramp-cleanup-connection tramp-test-vec 'keep-debug)
+    (let ((tramp-connection-properties
+          `((nil "login-args"
+                 (("-c")
+                  (,(tramp-shell-quote-argument
+                     "echo Place your finger on the fingerprint reader"))
+                  (";") ("sleep" "1")
+                  (";") ("sh" "-i"))))))
+      (should (file-exists-p ert-remote-temporary-file-directory)))
+
+    ;; Falling back after a timeout works.
+    (tramp-cleanup-connection tramp-test-vec 'keep-debug)
+    (let ((tramp-connection-properties
+          `((nil "login-args"
+                 (("-c")
+                  (,(tramp-shell-quote-argument
+                     "echo Place your finger on the fingerprint reader"))
+                  (";") ("sleep" "1")
+                  (";") ("echo" "Failed to match fingerprint")
+                  (";") ("sh" "-i"))))))
+      (should (file-exists-p ert-remote-temporary-file-directory)))
+
+    ;; Interrupting the fingerprint handshaking works.
+    (tramp-cleanup-connection tramp-test-vec 'keep-debug)
+    (let ((tramp-connection-properties
+          `((nil "login-args"
+                 (("-c")
+                  (,(tramp-shell-quote-argument
+                     "echo Place your finger on the fingerprint reader"))
+                  (";") ("sleep" "1")
+                  (";") ("sh" "-i")))))
+         tramp-use-fingerprint)
+      (should (file-exists-p ert-remote-temporary-file-directory)))))
+
 ;; This test is inspired by Bug#29163.
 (ert-deftest tramp-test48-auto-load ()
   "Check that Tramp autoloads properly."