summaryrefslogtreecommitdiff
path: root/lisp/auth-source-pass.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/auth-source-pass.el')
-rw-r--r--lisp/auth-source-pass.el91
1 files changed, 48 insertions, 43 deletions
diff --git a/lisp/auth-source-pass.el b/lisp/auth-source-pass.el
index d783b26b4e3..cebe8c26665 100644
--- a/lisp/auth-source-pass.el
+++ b/lisp/auth-source-pass.el
@@ -4,10 +4,10 @@
;; Author: Damien Cassou <damien@cassou.me>,
;; Nicolas Petton <nicolas@petton.fr>
-;; Version: 2.0.0
-;; Package-Requires: ((emacs "24.4")
+;; Version: 4.0.1
+;; Package-Requires: ((emacs "25"))
+;; Url: https://github.com/DamienCassou/auth-password-store
;; Created: 07 Jun 2015
-;; Keywords: pass password-store auth-source username password login
;; This file is part of GNU Emacs.
@@ -45,14 +45,22 @@
See `auth-source-search' for details on SPEC."
(cl-assert (or (null type) (eq type (oref backend type)))
t "Invalid password-store search: %s %s")
- (when (listp host)
+ (when (consp host)
+ (warn "auth-source-pass ignores all but first host in spec.")
;; Take the first non-nil item of the list of hosts
(setq host (seq-find #'identity host)))
- (list (auth-source-pass--build-result host port user)))
+ (cond ((eq host t)
+ (warn "auth-source-pass does not handle host wildcards.")
+ nil)
+ ((null host)
+ ;; Do not build a result, as none will match when HOST is nil
+ nil)
+ (t
+ (list (auth-source-pass--build-result host port user)))))
(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
@@ -73,7 +81,7 @@ See `auth-source-search' for details on SPEC."
(defvar auth-source-pass-backend
(auth-source-backend
- (format "Password store")
+ (when (<= emacs-major-version 25) "password-store")
:source "." ;; not used
:type 'password-store
:search-function #'auth-source-pass-search)
@@ -84,7 +92,9 @@ See `auth-source-search' for details on SPEC."
(when (eq entry 'password-store)
(auth-source-backend-parse-parameters entry auth-source-pass-backend)))
-(add-hook 'auth-source-backend-parser-functions #'auth-source-pass-backend-parse)
+(if (boundp 'auth-source-backend-parser-functions)
+ (add-hook 'auth-source-backend-parser-functions #'auth-source-pass-backend-parse)
+ (advice-add 'auth-source-backend-parse :before-until #'auth-source-pass-backend-parse))
(defun auth-source-pass-get (key entry)
@@ -139,30 +149,10 @@ CONTENTS is the contents of a password-store formatted file."
(mapconcat #'identity (cdr pair) ":")))))
(cdr lines)))))
-(defun auth-source-pass--user-match-p (entry user)
- "Return true iff ENTRY match USER."
- (or (null user)
- (string= user (auth-source-pass-get "user" entry))))
-
-(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--do-debug (&rest msg)
"Call `auth-source-do-debug` with MSG and a prefix."
(apply #'auth-source-do-debug
- (cons (concat "auth-source-password-store: " (car msg))
+ (cons (concat "auth-source-pass: " (car msg))
(cdr msg))))
(defun auth-source-pass--select-one-entry (entries user)
@@ -230,24 +220,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 (url-user (url-generic-parse-url 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 it's user component if any
- (auth-source-pass--find-one-by-entry-name (auth-source-pass--hostname host) user)
+ (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