summaryrefslogtreecommitdiff
path: root/lisp/auth-source-pass.el
diff options
context:
space:
mode:
authorDamien Cassou <damien@cassou.me>2017-11-09 10:40:19 +0100
committerNicolas Petton <nicolas@petton.fr>2018-06-05 15:51:14 +0200
commitb43ed61ef985e01975b90d7e0ec3cac70d0afefa (patch)
treebc4414f8595bc6ddee73cb4822062fb34b8a9cef /lisp/auth-source-pass.el
parenta52661b58bc9cffa13cb5f0749cdb3a4c24fbf74 (diff)
downloademacs-b43ed61ef985e01975b90d7e0ec3cac70d0afefa.tar.gz
emacs-b43ed61ef985e01975b90d7e0ec3cac70d0afefa.tar.bz2
emacs-b43ed61ef985e01975b90d7e0ec3cac70d0afefa.zip
auth-source-pass: Take care of matching hosts when port is provided
* lisp/auth-source-pass.el (auth-source-pass--find-match): Add PORT parameter and reorganize code by extracting `find-match-unambiguous'. (auth-source-pass--find-match-unambiguous): New function. (auth-source-pass--build-result): Fix the call to `find-match'. (auth-source-pass--hostname, auth-source-pass--hostname-with-user, auth-source-pass--user): Remove functions. * test/lisp/auth-source-pass-tests.el: Fix the calls to `find-match'. (auth-source-pass-find-host-without-port) Add corresponding test.
Diffstat (limited to 'lisp/auth-source-pass.el')
-rw-r--r--lisp/auth-source-pass.el68
1 files changed, 30 insertions, 38 deletions
diff --git a/lisp/auth-source-pass.el b/lisp/auth-source-pass.el
index 1785ca32550..96aefc8dd7e 100644
--- a/lisp/auth-source-pass.el
+++ b/lisp/auth-source-pass.el
@@ -52,7 +52,7 @@ See `auth-source-search' for details on SPEC."
(defun auth-source-pass--build-result (host port user)
"Build auth-source-pass entry matching HOST, PORT and USER."
- (let ((entry (auth-source-pass--find-match host user)))
+ (let ((entry (auth-source-pass--find-match host user port)))
(when entry
(let ((retval (list
:host host
@@ -139,26 +139,6 @@ CONTENTS is the contents of a password-store formatted file."
(mapconcat #'identity (cdr pair) ":")))))
(cdr lines)))))
-(defun auth-source-pass--hostname (host)
- "Extract hostname from HOST."
- (let ((url (url-generic-parse-url host)))
- (or (url-host url) host)))
-
-(defun auth-source-pass--hostname-with-user (host)
- "Extract hostname and user from HOST."
- (let* ((url (url-generic-parse-url host))
- (user (url-user url))
- (hostname (url-host url)))
- (cond
- ((and user hostname) (format "%s@%s" user hostname))
- (hostname hostname)
- (t host))))
-
-(defun auth-source-pass--user (host)
- "Extract user from HOST and return it.
-Return nil if no match was found."
- (url-user (url-generic-parse-url host)))
-
(defun auth-source-pass--do-debug (&rest msg)
"Call `auth-source-do-debug` with MSG and a prefix."
(apply #'auth-source-do-debug
@@ -230,27 +210,39 @@ matching USER."
(car matching-entries))
(_ (auth-source-pass--select-one-entry matching-entries user)))))
-(defun auth-source-pass--find-match (host user)
- "Return a password-store entry name matching HOST and USER.
-If many matches are found, return the first one. If no match is
-found, return nil."
+(defun auth-source-pass--find-match (host user port)
+ "Return a password-store entry name matching HOST, USER and PORT.
+
+Disambiguate between user provided inside HOST (e.g., user@server.com) and
+inside USER by giving priority to USER. Same for PORT."
+ (let* ((url (url-generic-parse-url (if (string-match-p ".*://" host)
+ host
+ (format "https://%s" host)))))
+ (auth-source-pass--find-match-unambiguous
+ (or (url-host url) host)
+ (or user (url-user url))
+ ;; url-port returns 443 (because of the https:// above) by default
+ (or port (number-to-string (url-port url))))))
+
+(defun auth-source-pass--find-match-unambiguous (hostname user port)
+ "Return a password-store entry name matching HOSTNAME, USER and PORT.
+If many matches are found, return the first one. If no match is found,
+return nil.
+
+HOSTNAME should not contain any username or port number."
(or
- (if (auth-source-pass--user host)
- ;; if HOST contains a user (e.g., "user@host.com"), <HOST>
- (auth-source-pass--find-one-by-entry-name (auth-source-pass--hostname-with-user host) user)
- ;; otherwise, if USER is provided, search for <USER>@<HOST>
- (when (stringp user)
- (auth-source-pass--find-one-by-entry-name (concat user "@" (auth-source-pass--hostname host)) user)))
- ;; if that didn't work, search for HOST without its user component, if any
- (auth-source-pass--find-one-by-entry-name (auth-source-pass--hostname host) user)
- ;; if that didn't work, search for HOST with user extracted from it
- (auth-source-pass--find-one-by-entry-name
- (auth-source-pass--hostname host) (auth-source-pass--user host))
+ (and user port (auth-source-pass--find-one-by-entry-name (format "%s@%s:%s" user hostname port) user))
+ (and user (auth-source-pass--find-one-by-entry-name (format "%s@%s" user hostname) user))
+ (and port (auth-source-pass--find-one-by-entry-name (format "%s:%s" hostname port) nil))
+ (auth-source-pass--find-one-by-entry-name hostname user)
;; if that didn't work, remove subdomain: foo.bar.com -> bar.com
- (let ((components (split-string host "\\.")))
+ (let ((components (split-string hostname "\\.")))
(when (= (length components) 3)
;; start from scratch
- (auth-source-pass--find-match (mapconcat 'identity (cdr components) ".") user)))))
+ (auth-source-pass--find-match-unambiguous
+ (mapconcat 'identity (cdr components) ".")
+ user
+ port)))))
(provide 'auth-source-pass)
;;; auth-source-pass.el ends here