diff options
Diffstat (limited to 'lisp/gnus/auth-source.el')
-rw-r--r-- | lisp/gnus/auth-source.el | 164 |
1 files changed, 91 insertions, 73 deletions
diff --git a/lisp/gnus/auth-source.el b/lisp/gnus/auth-source.el index 34fe5afe7af..47359500dc4 100644 --- a/lisp/gnus/auth-source.el +++ b/lisp/gnus/auth-source.el @@ -42,7 +42,6 @@ (require 'password-cache) (require 'mm-util) (require 'gnus-util) -(require 'assoc) (eval-when-compile (require 'cl)) (require 'eieio) @@ -92,9 +91,9 @@ let-binding." (const :tag "30 Minutes" 1800) (integer :tag "Seconds"))) -;;; The slots below correspond with the `auth-source-search' spec, -;;; so a backend with :host set, for instance, would match only -;;; searches for that host. Normally they are nil. +;; The slots below correspond with the `auth-source-search' spec, +;; so a backend with :host set, for instance, would match only +;; searches for that host. Normally they are nil. (defclass auth-source-backend () ((type :initarg :type :initform 'netrc @@ -149,8 +148,8 @@ let-binding." (repeat :tag "Names" (string :tag "Name"))))) -;;; generate all the protocols in a format Customize can use -;;; TODO: generate on the fly from auth-source-protocols +;; Generate all the protocols in a format Customize can use. +;; TODO: generate on the fly from auth-source-protocols (defconst auth-source-protocols-customize (mapcar (lambda (a) (let ((p (car-safe a))) @@ -339,7 +338,7 @@ If the value is not a list, symmetric encryption will be used." msg)) -;;; (auth-source-read-char-choice "enter choice? " '(?a ?b ?q)) +;; (auth-source-read-char-choice "enter choice? " '(?a ?b ?q)) (defun auth-source-read-char-choice (prompt choices) "Read one of CHOICES by `read-char-choice', or `read-char'. `dropdown-list' support is disabled because it doesn't work reliably. @@ -711,10 +710,10 @@ must call it to obtain the actual value." (setq matches (append matches bmatches)))))) matches)) -;;; (auth-source-search :max 1) -;;; (funcall (plist-get (nth 0 (auth-source-search :max 1)) :secret)) -;;; (auth-source-search :host "nonesuch" :type 'netrc :K 1) -;;; (auth-source-search :host "nonesuch" :type 'secrets) +;; (auth-source-search :max 1) +;; (funcall (plist-get (nth 0 (auth-source-search :max 1)) :secret)) +;; (auth-source-search :host "nonesuch" :type 'netrc :K 1) +;; (auth-source-search :host "nonesuch" :type 'secrets) (defun* auth-source-delete (&rest spec &key delete @@ -776,16 +775,16 @@ This is the same SPEC you passed to `auth-source-search'. Returns t or nil for forgotten or not found." (password-cache-remove (auth-source-format-cache-entry spec))) -;;; (loop for sym being the symbols of password-data when (string-match (concat "^" auth-source-magic) (symbol-name sym)) collect (symbol-name sym)) +;; (loop for sym being the symbols of password-data when (string-match (concat "^" auth-source-magic) (symbol-name sym)) collect (symbol-name sym)) -;;; (auth-source-remember '(:host "wedd") '(4 5 6)) -;;; (auth-source-remembered-p '(:host "wedd")) -;;; (auth-source-remember '(:host "xedd") '(1 2 3)) -;;; (auth-source-remembered-p '(:host "xedd")) -;;; (auth-source-remembered-p '(:host "zedd")) -;;; (auth-source-recall '(:host "xedd")) -;;; (auth-source-recall '(:host t)) -;;; (auth-source-forget+ :host t) +;; (auth-source-remember '(:host "wedd") '(4 5 6)) +;; (auth-source-remembered-p '(:host "wedd")) +;; (auth-source-remember '(:host "xedd") '(1 2 3)) +;; (auth-source-remembered-p '(:host "xedd")) +;; (auth-source-remembered-p '(:host "zedd")) +;; (auth-source-recall '(:host "xedd")) +;; (auth-source-recall '(:host t)) +;; (auth-source-forget+ :host t) (defun* auth-source-forget+ (&rest spec &allow-other-keys) "Forget any cached data matching SPEC. Returns forgotten count. @@ -819,8 +818,8 @@ while \(:host t) would find all host entries." (return 'no))) 'no)))) -;;; (auth-source-pick-first-password :host "z.lifelogs.com") -;;; (auth-source-pick-first-password :port "imap") +;; (auth-source-pick-first-password :host "z.lifelogs.com") +;; (auth-source-pick-first-password :port "imap") (defun auth-source-pick-first-password (&rest spec) "Pick the first secret found from applying SPEC to `auth-source-search'." (let* ((result (nth 0 (apply 'auth-source-search (plist-put spec :max 1)))) @@ -853,7 +852,22 @@ while \(:host t) would find all host entries." ;;; Backend specific parsing: netrc/authinfo backend -;;; (auth-source-netrc-parse "~/.authinfo.gpg") +(defun auth-source--aput-1 (alist key val) + (let ((seen ()) + (rest alist)) + (while (and (consp rest) (not (equal key (caar rest)))) + (push (pop rest) seen)) + (cons (cons key val) + (if (null rest) alist + (nconc (nreverse seen) + (if (equal key (caar rest)) (cdr rest) rest)))))) +(defmacro auth-source--aput (var key val) + `(setq ,var (auth-source--aput-1 ,var ,key ,val))) + +(defun auth-source--aget (alist key) + (cdr (assoc key alist))) + +;; (auth-source-netrc-parse "~/.authinfo.gpg") (defun* auth-source-netrc-parse (&rest spec &key file max host user port delete require @@ -888,10 +902,11 @@ Note that the MAX parameter is used so we can exit the parse early." ;; cache all netrc files (used to be just .gpg files) ;; Store the contents of the file heavily encrypted in memory. ;; (note for the irony-impaired: they are just obfuscated) - (aput 'auth-source-netrc-cache file - (list :mtime (nth 5 (file-attributes file)) - :secret (lexical-let ((v (mapcar '1+ (buffer-string)))) - (lambda () (apply 'string (mapcar '1- v))))))) + (auth-source--aput + auth-source-netrc-cache file + (list :mtime (nth 5 (file-attributes file)) + :secret (lexical-let ((v (mapcar '1+ (buffer-string)))) + (lambda () (apply 'string (mapcar '1- v))))))) (goto-char (point-min)) ;; Go through the file, line by line. (while (and (not (eobp)) @@ -937,21 +952,21 @@ Note that the MAX parameter is used so we can exit the parse early." (auth-source-search-collection host (or - (aget alist "machine") - (aget alist "host") + (auth-source--aget alist "machine") + (auth-source--aget alist "host") t)) (auth-source-search-collection user (or - (aget alist "login") - (aget alist "account") - (aget alist "user") + (auth-source--aget alist "login") + (auth-source--aget alist "account") + (auth-source--aget alist "user") t)) (auth-source-search-collection port (or - (aget alist "port") - (aget alist "protocol") + (auth-source--aget alist "port") + (auth-source--aget alist "protocol") t)) (or ;; the required list of keys is nil, or @@ -1086,8 +1101,8 @@ FILE is the file from which we obtained this token." ret)) alist)) -;;; (setq secret (plist-get (nth 0 (auth-source-search :host t :type 'netrc :K 1 :max 1)) :secret)) -;;; (funcall secret) +;; (setq secret (plist-get (nth 0 (auth-source-search :host t :type 'netrc :K 1 :max 1)) :secret)) +;; (funcall secret) (defun* auth-source-netrc-search (&rest spec @@ -1133,8 +1148,8 @@ See `auth-source-search' for details on SPEC." (nth 0 v) v)) -;;; (auth-source-search :host "nonesuch" :type 'netrc :max 1 :create t) -;;; (auth-source-search :host "nonesuch" :type 'netrc :max 1 :create t :create-extra-keys '((A "default A") (B))) +;; (auth-source-search :host "nonesuch" :type 'netrc :max 1 :create t) +;; (auth-source-search :host "nonesuch" :type 'netrc :max 1 :create t :create-extra-keys '((A "default A") (B))) (defun* auth-source-netrc-create (&rest spec &key backend @@ -1166,7 +1181,7 @@ See `auth-source-search' for details on SPEC." ;; just the value otherwise (t (symbol-value br))))) (when br-choice - (aput 'valist br br-choice))))) + (auth-source--aput valist br br-choice))))) ;; for extra required elements, see if the spec includes a value for them (dolist (er create-extra) @@ -1175,17 +1190,18 @@ See `auth-source-search' for details on SPEC." collect (nth i spec)))) (dolist (k keys) (when (equal (symbol-name k) name) - (aput 'valist er (plist-get spec k)))))) + (auth-source--aput valist er (plist-get spec k)))))) ;; for each required element (dolist (r required) - (let* ((data (aget valist r)) + (let* ((data (auth-source--aget valist r)) ;; take the first element if the data is a list (data (or (auth-source-netrc-element-or-first data) (plist-get current-data (intern (format ":%s" r) obarray)))) ;; this is the default to be offered - (given-default (aget auth-source-creation-defaults r)) + (given-default (auth-source--aget + auth-source-creation-defaults r)) ;; the default supplementals are simple: ;; for the user, try `given-default' and then (user-login-name); ;; otherwise take `given-default' @@ -1197,22 +1213,22 @@ See `auth-source-search' for details on SPEC." (cons 'user (or (auth-source-netrc-element-or-first - (aget valist 'user)) + (auth-source--aget valist 'user)) (plist-get artificial :user) "[any user]")) (cons 'host (or (auth-source-netrc-element-or-first - (aget valist 'host)) + (auth-source--aget valist 'host)) (plist-get artificial :host) "[any host]")) (cons 'port (or (auth-source-netrc-element-or-first - (aget valist 'port)) + (auth-source--aget valist 'port)) (plist-get artificial :port) "[any port]")))) - (prompt (or (aget auth-source-creation-prompts r) + (prompt (or (auth-source--aget auth-source-creation-prompts r) (case r (secret "%p password for %u@%h: ") (user "%p user name for %h: ") @@ -1221,9 +1237,9 @@ See `auth-source-search' for details on SPEC." (format "Enter %s (%%u@%%h:%%p): " r))) (prompt (auth-source-format-prompt prompt - `((?u ,(aget printable-defaults 'user)) - (?h ,(aget printable-defaults 'host)) - (?p ,(aget printable-defaults 'port)))))) + `((?u ,(auth-source--aget printable-defaults 'user)) + (?h ,(auth-source--aget printable-defaults 'host)) + (?p ,(auth-source--aget printable-defaults 'port)))))) ;; Store the data, prompting for the password if needed. (setq data (or data @@ -1384,16 +1400,16 @@ Respects `auth-source-save-behavior'. Uses file) (message "Saved new authentication information to %s" file) nil)))) - (aput 'auth-source-netrc-cache key "ran")))) + (auth-source--aput auth-source-netrc-cache key "ran")))) ;;; Backend specific parsing: Secrets API backend -;;; (let ((auth-sources '(default))) (auth-source-search :max 1 :create t)) -;;; (let ((auth-sources '(default))) (auth-source-search :max 1 :delete t)) -;;; (let ((auth-sources '(default))) (auth-source-search :max 1)) -;;; (let ((auth-sources '(default))) (auth-source-search)) -;;; (let ((auth-sources '("secrets:Login"))) (auth-source-search :max 1)) -;;; (let ((auth-sources '("secrets:Login"))) (auth-source-search :max 1 :signon_realm "https://git.gnus.org/Git")) +;; (let ((auth-sources '(default))) (auth-source-search :max 1 :create t)) +;; (let ((auth-sources '(default))) (auth-source-search :max 1 :delete t)) +;; (let ((auth-sources '(default))) (auth-source-search :max 1)) +;; (let ((auth-sources '(default))) (auth-source-search)) +;; (let ((auth-sources '("secrets:Login"))) (auth-source-search :max 1)) +;; (let ((auth-sources '("secrets:Login"))) (auth-source-search :max 1 :signon_realm "https://git.gnus.org/Git")) (defun* auth-source-secrets-search (&rest spec @@ -1609,7 +1625,7 @@ authentication tokens: ;; just the value otherwise (t (symbol-value br))))) (when br-choice - (aput 'valist br br-choice))))) + (auth-source--aput valist br br-choice))))) ;; for extra required elements, see if the spec includes a value for them (dolist (er create-extra) @@ -1618,17 +1634,18 @@ authentication tokens: collect (nth i spec)))) (dolist (k keys) (when (equal (symbol-name k) name) - (aput 'valist er (plist-get spec k)))))) + (auth-source--aput valist er (plist-get spec k)))))) ;; for each required element (dolist (r required) - (let* ((data (aget valist r)) + (let* ((data (auth-source--aget valist r)) ;; take the first element if the data is a list (data (or (auth-source-netrc-element-or-first data) (plist-get current-data (intern (format ":%s" r) obarray)))) ;; this is the default to be offered - (given-default (aget auth-source-creation-defaults r)) + (given-default (auth-source--aget + auth-source-creation-defaults r)) ;; the default supplementals are simple: ;; for the user, try `given-default' and then (user-login-name); ;; otherwise take `given-default' @@ -1640,22 +1657,22 @@ authentication tokens: (cons 'user (or (auth-source-netrc-element-or-first - (aget valist 'user)) + (auth-source--aget valist 'user)) (plist-get artificial :user) "[any user]")) (cons 'host (or (auth-source-netrc-element-or-first - (aget valist 'host)) + (auth-source--aget valist 'host)) (plist-get artificial :host) "[any host]")) (cons 'port (or (auth-source-netrc-element-or-first - (aget valist 'port)) + (auth-source--aget valist 'port)) (plist-get artificial :port) "[any port]")))) - (prompt (or (aget auth-source-creation-prompts r) + (prompt (or (auth-source--aget auth-source-creation-prompts r) (case r (secret "%p password for %u@%h: ") (user "%p user name for %h: ") @@ -1664,20 +1681,21 @@ authentication tokens: (format "Enter %s (%%u@%%h:%%p): " r))) (prompt (auth-source-format-prompt prompt - `((?u ,(aget printable-defaults 'user)) - (?h ,(aget printable-defaults 'host)) - (?p ,(aget printable-defaults 'port)))))) + `((?u ,(auth-source--aget printable-defaults 'user)) + (?h ,(auth-source--aget printable-defaults 'host)) + (?p ,(auth-source--aget printable-defaults 'port)))))) ;; Store the data, prompting for the password if needed. (setq data (or data (if (eq r 'secret) (or (eval default) (read-passwd prompt)) (if (stringp default) - (read-string (if (string-match ": *\\'" prompt) - (concat (substring prompt 0 (match-beginning 0)) - " (default " default "): ") - (concat prompt "(default " default ") ")) - nil nil default) + (read-string + (if (string-match ": *\\'" prompt) + (concat (substring prompt 0 (match-beginning 0)) + " (default " default "): ") + (concat prompt "(default " default ") ")) + nil nil default) (eval default))))) (when data @@ -1701,7 +1719,7 @@ authentication tokens: ;;; older API -;;; (auth-source-user-or-password '("login" "password") "imap.myhost.com" t "tzz") +;; (auth-source-user-or-password '("login" "password") "imap.myhost.com" t "tzz") ;; deprecate the old interface (make-obsolete 'auth-source-user-or-password |