Commit b8e0f0cd authored by Gnus developers's avatar Gnus developers Committed by Katsumi Yamaoka
Browse files

Merge changes made in Gnus trunk.

auth.texi (Overview, Help for users, Help for developers): Update docs.
 (Help for users): Talk about spaces.
sieve-manage.el: Autoload `auth-source-search'.
 (sieve-sasl-auth): Use it.
nnimap.el: Autoload `auth-source-forget+'.
 (nnimap-open-connection-1): Use it if the connection fails.
auth-source.el: Require `password-cache'.
 (auth-source-hide-passwords, auth-source-cache): Remove and mark obsolete.
 (auth-source-magic): Marker for `password-cache' keys.
 (auth-source-do-cache): Update docstring.
 (auth-source-search): Use and check cache.
 (auth-source-forget-all-cached, auth-source-remember)
 (auth-source-recall, auth-source-forget, auth-source-forget+)
 (auth-source-specmatchp): Caching support functions.
 (auth-source-forget-user-or-password, auth-source-forget-all-cached): Remove and obsolete.
 (auth-source-user-or-password): Remove caching to further discourage using it.  Always hide passwords.
password-cache.el (password-cache-remove): Accept secrets that are not strings.
mail-source.el: Autoload `auth-source-search'.
 (mail-source-keyword-map): Note order matters.
 (mail-source-set-1): Get all the mail-source source values and defaults and search auth-source on those if needed.  This can all probably be simplified.
nnimap.el: Autoload `auth-source-search'.
 (nnimap-credentials): Use it.
 (nnimap-open-connection-1): Ask for the virtual server and physical address in one shot.
nntp.el: Autoload `auth-source-search'.
 (nntp-send-authinfo): Use it.  Note TODO.
auth-source.el (auth-source-secrets-search, auth-source-user-or-password): Use `append' instead of `nconc'.
 (auth-source-user-or-password): Build return list better and protect against nil :secret.
auth-source.el (top): Require 'eieio unconditionally.  Autoload `secrets-get-attributes' instead of `secrets-get-attribute'.
 (auth-source-secrets-search): Limit search when `max' is greater than number of results.
auth-source.el (auth-source-secrets-search): Add examples.
auth-source.el (auth-sources): Allow for simpler defaults for Secrets API with a string "secrets:collection-name" and with 'default.
 (auth-source-backend-parse): Parse "secrets:collection-name" and 'default.  Recurse on parses instead of repeating code.  Use the Secrets API is the source is not nil and 'ignore otherwise.  Emit a message when ignoring a source.
 (auth-source-search): List ignored search keys at the top level.
 (auth-source-netrc-create): Use `case' instead of `cond'.
 (auth-source-secrets-search): Created with TODOs.
 (auth-source-secrets-create): Created with TODOs.
 (auth-source-retrieve, auth-source-create, auth-source-delete)
 (auth-source-protocol-defaults, auth-source-user-or-password-imap)
 (auth-source-user-or-password-pop3, auth-source-user-or-password-ssh)
 (auth-source-user-or-password-sftp)
 (auth-source-user-or-password-smtp): Removed.
 (auth-source-user-or-password): Deprecated and modified to be a wrapper around `auth-source-search'.  Not tested thoroughly.
auth-source.el: Bring in assoc and eioeio libraries.
 (secrets-enabled): New variable to track the status of the Secrets API.
 (auth-source-backend): New EIOEIO class to represent a backend.
 (auth-source-creation-defaults): New variable to set prompt defaults during token creation (see the `auth-source-search' docstring for details).
 (auth-sources): Simplify to allow a simple string as a netrc backend spec.
 (auth-source-backend-parse): Parse a backend from an `auth-sources' spec.
 (auth-source-backend-parse-parameters): Fill in the backend parameters.
 (auth-source-search): Main auth-source API entry point.
 (auth-source-delete): Wrapper around `auth-source-search' for deletion.
 (auth-source-search-collection): Helper function for searching.
 (auth-source-netrc-parse, auth-source-netrc-normalize)
 (auth-source-netrc-search, auth-source-netrc-create): Netrc backend.  Supports search, create, and delete.
 (auth-source-secrets-search, auth-source-secrets-create): Secrets API backend stubs.
(auth-source-user-or-password): Call `auth-source-search' but it's not ready yet.
parent e730aabe
......@@ -6,6 +6,11 @@
* url.texi: Remove duplicate @dircategory (Bug#7942).
2011-02-11 Teodor Zlatanov <tzz@lifelogs.com>
* auth.texi (Overview, Help for users, Help for developers): Update docs.
(Help for users): Talk about spaces.
2011-02-09 Paul Eggert <eggert@cs.ucla.edu>
* texinfo.tex: Update to version 2011-02-07.16.
......
......@@ -5,7 +5,7 @@
@setfilename ../../info/auth
@settitle Emacs auth-source Library @value{VERSION}
@set VERSION 0.2
@set VERSION 0.3
@copying
This file describes the Emacs auth-source library.
......@@ -78,15 +78,19 @@ It is a way for multiple applications to share a single configuration
@chapter Overview
The auth-source library is simply a way for Emacs and Gnus, among
others, to answer the old burning question ``I have a server name and
a port, what are my user name and password?''
others, to answer the old burning question ``What are my user name and
password?''
The auth-source library actually supports more than just the user name
(known as the login) or the password, but only those two are in use
today in Emacs or Gnus. Similarly, the auth-source library supports
multiple storage formats, currently either the classic ``netrc''
format, examples of which you can see later in this document, or the
Secret Service API.
(This is different from the old question about burning ``Where is the
fire extinguisher, please?''.)
The auth-source library supports more than just the user name or the
password (known as the secret).
Similarly, the auth-source library supports multiple storage backend,
currently either the classic ``netrc'' backend, examples of which you
can see later in this document, or the Secret Service API. This is
done with EIEIO-based backends and you can write your own if you want.
@node Help for users
@chapter Help for users
......@@ -96,25 +100,41 @@ Secret Service API.
machine @var{mymachine} login @var{myloginname} password @var{mypassword} port @var{myport}
@end example
The machine is the server (either a DNS name or an IP address).
The @code{machine} is the server (either a DNS name or an IP address).
It's known as @var{:host} in @code{auth-source-search} queries. You
can also use @code{host}.
The @code{port} is the connection port or protocol. It's known as
@var{:port} in @code{auth-source-search} queries. You can also use
@code{protocol}.
The @code{user} is the user name. It's known as @var{:user} in
@code{auth-source-search} queries. You can also use @code{login} and
@code{account}.
Spaces are always OK as far as auth-source is concerned (but other
programs may not like them). Just put the data in quotes, escaping
quotes as you'd expect with @code{\}.
All these are optional. You could just say (but we don't recommend
it, we're just showing that it's possible)
The port is optional. If it's missing, auth-source will assume any
port is OK. Actually the port is a protocol name or a port number so
you can have separate entries for port @var{143} and for protocol
@var{imap} if you fancy that. Anyway, you can just omit the port if
you don't need it.
@example
password @var{mypassword}
@end example
The login and password are simply your login credentials to the server.
to use the same password everywhere. Again, @emph{DO NOT DO THIS} or
you will be pwned as the kids say.
``Netrc'' files are usually called @code{.authinfo} or @code{.netrc};
nowadays @code{.authinfo} seems to be more popular and the auth-source
library encourages this confusion by making it the default, as you'll
see later.
If you have problems with the port, set @code{auth-source-debug} to
@code{t} and see what port the library is checking in the
@code{*Messages*} buffer. Ditto for any other problems, your first
step is always to see what's being checked. The second step, of
If you have problems with the search, set @code{auth-source-debug} to
@code{t} and see what host, port, and user the library is checking in
the @code{*Messages*} buffer. Ditto for any other problems, your
first step is always to see what's being checked. The second step, of
course, is to write a blog entry about it and wait for the answer in
the comments.
......@@ -139,56 +159,36 @@ and simplest configuration is:
(setq auth-sources '((:source "~/.authinfo.gpg" :host t :protocol t)))
;;; mostly equivalent (see below about fallbacks) but shorter:
(setq auth-sources '((:source "~/.authinfo.gpg")))
;;; even shorter and the @emph{default}:
(setq auth-sources '("~/.authinfo.gpg" "~/.authinfo"))
;;; use the Secrets API @var{login} collection (@pxref{Secret Service API})
(setq auth-sources '("secrets:login"))
@end lisp
This says ``for any host and any protocol, use just that one file.''
Sweet simplicity. In fact, the latter is already the default, so
unless you want to move your netrc file, it will just work if you have
that file. Make sure it exists.
By adding multiple entries to @code{auth-sources} with a particular
host or protocol, you can have specific netrc files for that host or
protocol. Usually this is unnecessary but may make sense if you have
shared netrc files or some other unusual setup (90% of Emacs users
have unusual setups and the remaining 10% are @emph{really} unusual).
Here's an example that uses the Secret Service API for all lookups,
using the default collection:
@lisp
(setq auth-sources '((:source (:secrets default))))
@end lisp
And here's a mixed example, using two sources:
Here's a mixed example using two sources:
@lisp
(setq auth-sources '((:source (:secrets default) :host "myserver" :user "joe")
(:source "~/.authinfo.gpg")))
"~/.authinfo.gpg"))
@end lisp
The best match is determined by order (starts from the bottom) only
for the first pass, where things are checked exactly. In the example
above, the first pass would find a single match for host
@code{myserver}. The netrc choice would fail because it matches any
host and protocol implicitly (as a @emph{fallback}). A specified
value of @code{:host t} in @code{auth-sources} is considered a match
on the first pass, unlike a missing @code{:host}.
Now if you look for host @code{missing}, it won't match either source
explicitly. The second pass (the @emph{fallback} pass) will look at
all the implicit matches and collect them. They will be scored and
returned sorted by score. The score is based on the number of
explicit parameters that matched. See the @code{auth-pick} function
for details.
@end defvar
If you don't customize @code{auth-sources}, you'll have to live with
the defaults: any host and any port are looked up in the netrc
file @code{~/.authinfo.gpg}, which is a GnuPG encrypted file
(@pxref{GnuPG and EasyPG Assistant Configuration}).
(@pxref{GnuPG and EasyPG Assistant Configuration}).
If that fails, the unencrypted netrc file @code{~/.authinfo} will
be used.
The simplest working netrc line example is one without a port.
The typical netrc line example is without a port.
@example
machine YOURMACHINE login YOU password YOURPASSWORD
......@@ -233,42 +233,29 @@ TODO: how does it work generally, how does secrets.el work, some examples.
@node Help for developers
@chapter Help for developers
The auth-source library only has one function for external use.
The auth-source library only has a few functions for external use.
@defun auth-source-user-or-password mode host port &optional username
@defun auth-source-search SPEC
Retrieve appropriate authentication tokens, determined by @var{mode},
for host @var{host} and @var{port}. If @var{username} is provided it
will also be checked. If @code{auth-source-debug} is t, debugging
messages will be printed. Set @code{auth-source-debug} to a function
to use that function for logging. The parameters passed will be the
same that the @code{message} function takes, that is, a string
formatting spec and optional parameters.
TODO: how to include docstring?
If @var{mode} is a list of strings, the function will return a list of
strings or @code{nil} objects (thus you can avoid parsing the netrc
file or checking the Secret Service API more than once). If it's a
string, the function will return a string or a @code{nil} object.
Currently only the modes ``login'' and ``password'' are recognized but
more may be added in the future.
@end defun
@var{host} is a string containing the host name.
@defun auth-source-delete SPEC
@var{port} contains the protocol name (e.g. ``imap'') or
a port number. It must be a string, corresponding to the port in the
users' netrc files.
TODO: how to include docstring?
@var{username} contains the user name (e.g. ``joe'') as a string.
@end defun
@example
;; IMAP example
(setq auth (auth-source-user-or-password
'("login" "password")
"anyhostnamehere"
"imap"))
(nth 0 auth) ; the login name
(nth 1 auth) ; the password
@end example
@defun auth-source-forget SPEC
TODO: how to include docstring?
@end defun
@defun auth-source-forget+ SPEC
TODO: how to include docstring?
@end defun
......
......@@ -191,6 +191,11 @@
(allout-after-copy-or-kill-hook): No arguments - hook implementers
should concentrate on the kill ring.
2011-02-09 Teodor Zlatanov <tzz@lifelogs.com>
* password-cache.el (password-cache-remove): Accept secrets that are
not strings.
2011-02-09 Stefan Monnier <monnier@iro.umontreal.ca>
* progmodes/sh-script.el (sh-font-lock-open-heredoc): Fix case
......
......@@ -7,6 +7,30 @@
* gnus-sum.el (gnus-summary-save-parts): Use read-directory-name.
2011-02-10 Teodor Zlatanov <tzz@lifelogs.com>
* sieve-manage.el: Autoload `auth-source-search'.
(sieve-sasl-auth): Use it.
2011-02-09 Teodor Zlatanov <tzz@lifelogs.com>
* nnimap.el: Autoload `auth-source-forget+'.
(nnimap-open-connection-1): Use it if the connection fails.
* auth-source.el: Require `password-cache'.
(auth-source-hide-passwords, auth-source-cache): Remove and mark
obsolete.
(auth-source-magic): Marker for `password-cache' keys.
(auth-source-do-cache): Update docstring.
(auth-source-search): Use and check cache.
(auth-source-forget-all-cached, auth-source-remember)
(auth-source-recall, auth-source-forget, auth-source-forget+)
(auth-source-specmatchp): Caching support functions.
(auth-source-forget-user-or-password, auth-source-forget-all-cached):
Remove and obsolete.
(auth-source-user-or-password): Remove caching to further discourage
using it. Always hide passwords.
2011-02-09 Lars Ingebrigtsen <larsi@gnus.org>
* nntp.el (nntp-retrieve-group-data-early-disabled): Disable the async
......@@ -17,6 +41,22 @@
* message.el (message-options): Make message-options really buffer
local.
2011-02-08 Teodor Zlatanov <tzz@lifelogs.com>
* mail-source.el: Autoload `auth-source-search'.
(mail-source-keyword-map): Note order matters.
(mail-source-set-1): Get all the mail-source source values and
defaults and search auth-source on those if needed. This can all
probably be simplified.
* nnimap.el: Autoload `auth-source-search'.
(nnimap-credentials): Use it.
(nnimap-open-connection-1): Ask for the virtual server and physical
address in one shot.
* nntp.el: Autoload `auth-source-search'.
(nntp-send-authinfo): Use it. Note TODO.
2011-02-08 Julien Danjou <julien@danjou.info>
* shr.el (shr-tag-body): Add support for text attribute in body
......@@ -24,6 +64,13 @@
* message.el (message-options): Make message-options a local variable.
2011-02-07 Teodor Zlatanov <tzz@lifelogs.com>
* auth-source.el (auth-source-secrets-search)
(auth-source-user-or-password): Use `append' instead of `nconc'.
(auth-source-user-or-password): Build return list better and protect
against nil :secret.
2011-02-07 Lars Ingebrigtsen <larsi@gnus.org>
* nnimap.el (nnimap-update-info): Refactor slightly.
......@@ -35,6 +82,13 @@
(nnimap-update-info): Fix macrology bug-out.
(nnimap-update-info): Simplify split history test.
2011-02-06 Michael Albinus <michael.albinus@gmx.de>
* auth-source.el (top): Require 'eieio unconditionally. Autoload
`secrets-get-attributes' instead of `secrets-get-attribute'.
(auth-source-secrets-search): Limit search when `max' is greater than
number of results.
2011-02-06 Lars Ingebrigtsen <larsi@gnus.org>
* nntp.el (nntp-finish-retrieve-group-infos): Protect against the first
......@@ -42,11 +96,58 @@
* proto-stream.el (open-protocol-stream): Document the return value.
2011-02-06 Teodor Zlatanov <tzz@lifelogs.com>
* auth-source.el (auth-source-secrets-search): Add examples.
2011-02-06 Julien Danjou <julien@danjou.info>
* message.el (message-setup-1): Handle message-generate-headers-first
set to t.
2011-02-06 Teodor Zlatanov <tzz@lifelogs.com>
* auth-source.el (auth-sources): Allow for simpler defaults for Secrets
API with a string "secrets:collection-name" and with 'default.
(auth-source-backend-parse): Parse "secrets:collection-name" and
'default. Recurse on parses instead of repeating code. Use the
Secrets API is the source is not nil and 'ignore otherwise. Emit a
message when ignoring a source.
(auth-source-search): List ignored search keys at the top level.
(auth-source-netrc-create): Use `case' instead of `cond'.
(auth-source-secrets-search): Created with TODOs.
(auth-source-secrets-create): Created with TODOs.
(auth-source-retrieve, auth-source-create, auth-source-delete)
(auth-source-protocol-defaults, auth-source-user-or-password-imap)
(auth-source-user-or-password-pop3, auth-source-user-or-password-ssh)
(auth-source-user-or-password-sftp)
(auth-source-user-or-password-smtp): Removed.
(auth-source-user-or-password): Deprecated and modified to be a wrapper
around `auth-source-search'. Not tested thoroughly.
2011-02-04 Teodor Zlatanov <tzz@lifelogs.com>
* auth-source.el: Bring in assoc and eioeio libraries.
(secrets-enabled): New variable to track the status of the Secrets API.
(auth-source-backend): New EIOEIO class to represent a backend.
(auth-source-creation-defaults): New variable to set prompt defaults
during token creation (see the `auth-source-search' docstring for
details).
(auth-sources): Simplify to allow a simple string as a netrc backend
spec.
(auth-source-backend-parse): Parse a backend from an `auth-sources' spec.
(auth-source-backend-parse-parameters): Fill in the backend parameters.
(auth-source-search): Main auth-source API entry point.
(auth-source-delete): Wrapper around `auth-source-search' for deletion.
(auth-source-search-collection): Helper function for searching.
(auth-source-netrc-parse, auth-source-netrc-normalize)
(auth-source-netrc-search, auth-source-netrc-create): Netrc backend.
Supports search, create, and delete.
(auth-source-secrets-search, auth-source-secrets-create): Secrets API
backend stubs.
(auth-source-user-or-password): Call `auth-source-search' but it's not
ready yet.
2011-02-04 Lars Ingebrigtsen <larsi@gnus.org>
* message.el (message-setup-1): Remove the read-only stuff, since it
......
......@@ -39,23 +39,64 @@
;;; Code:
(require 'password-cache)
(require 'gnus-util)
(require 'netrc)
(require 'assoc)
(eval-when-compile (require 'cl))
(require 'eieio)
(autoload 'secrets-create-item "secrets")
(autoload 'secrets-delete-item "secrets")
(autoload 'secrets-get-alias "secrets")
(autoload 'secrets-get-attribute "secrets")
(autoload 'secrets-get-attributes "secrets")
(autoload 'secrets-get-secret "secrets")
(autoload 'secrets-list-collections "secrets")
(autoload 'secrets-search-items "secrets")
(defvar secrets-enabled)
(defgroup auth-source nil
"Authentication sources."
:version "23.1" ;; No Gnus
:group 'gnus)
(defclass auth-source-backend ()
((type :initarg :type
:initform 'netrc
:type symbol
:custom symbol
:documentation "The backend type.")
(source :initarg :source
:type string
:custom string
:documentation "The backend source.")
(host :initarg :host
:initform t
:type t
:custom string
:documentation "The backend host.")
(user :initarg :user
:initform t
:type t
:custom string
:documentation "The backend user.")
(protocol :initarg :protocol
:initform t
:type t
:custom string
:documentation "The backend protocol.")
(create-function :initarg :create-function
:initform ignore
:type function
:custom function
:documentation "The create function.")
(search-function :initarg :search-function
:initform ignore
:type function
:custom function
:documentation "The search function.")))
(defcustom auth-source-protocols '((imap "imap" "imaps" "143" "993")
(pop3 "pop3" "pop" "pop3s" "110" "995")
(ssh "ssh" "22")
......@@ -81,11 +122,15 @@
p)))
auth-source-protocols))
(defvar auth-source-cache (make-hash-table :test 'equal)
"Cache for auth-source data")
(defvar auth-source-creation-defaults nil
"Defaults for creating token values. Usually let-bound.")
(make-obsolete 'auth-source-hide-passwords nil "Emacs 24.1")
(defvar auth-source-magic "auth-source-magic ")
(defcustom auth-source-do-cache t
"Whether auth-source should cache information."
"Whether auth-source should cache information with `password-cache'."
:group 'auth-source
:version "23.2" ;; No Gnus
:type `boolean)
......@@ -108,65 +153,71 @@ If the value is a function, debug messages are logged by calling
(function :tag "Function that takes arguments like `message'")
(const :tag "Don't log anything" nil)))
(defcustom auth-source-hide-passwords t
"Whether auth-source should hide passwords in log messages.
Only relevant if `auth-source-debug' is not nil."
:group 'auth-source
:version "23.2" ;; No Gnus
:type `boolean)
(defcustom auth-sources '((:source "~/.authinfo.gpg")
(:source "~/.authinfo"))
(defcustom auth-sources '("~/.authinfo.gpg" "~/.authinfo")
"List of authentication sources.
The default will get login and password information from a .gpg
file, which you should set up with the EPA/EPG packages to be
encrypted. See the auth.info manual for details.
The default will get login and password information from
\"~/.authinfo.gpg\", which you should set up with the EPA/EPG
packages to be encrypted. If that file doesn't exist, it will
try the unencrypted version \"~/.authinfo\".
See the auth.info manual for details.
Each entry is the authentication type with optional properties.
It's best to customize this with `M-x customize-variable' because the choices
can get pretty complex."
:group 'auth-source
:version "23.2" ;; No Gnus
:version "24.1" ;; No Gnus
:type `(repeat :tag "Authentication Sources"
(list :tag "Source definition"
(const :format "" :value :source)
(choice :tag "Authentication backend choice"
(string :tag "Authentication Source (file)")
(list :tag "secrets.el (Secret Service API/KWallet/GNOME Keyring)"
(const :format "" :value :secrets)
(choice :tag "Collection to use"
(string :tag "Collection name")
(const :tag "Default" 'default)
(const :tag "Login" "login")
(const :tag "Temporary" "session"))))
(repeat :tag "Extra Parameters" :inline t
(choice :tag "Extra parameter"
(list :tag "Host (omit to match as a fallback)"
(const :format "" :value :host)
(choice :tag "Host (machine) choice"
(const :tag "Any" t)
(regexp :tag "Host (machine) regular expression")))
(list :tag "Protocol (omit to match as a fallback)"
(const :format "" :value :protocol)
(choice :tag "Protocol"
(const :tag "Any" t)
,@auth-source-protocols-customize))
(list :tag "User (omit to match as a fallback)" :inline t
(const :format "" :value :user)
(choice :tag "Personality or username"
(const :tag "Any" t)
(string :tag "Specific user name"))))))))
(choice
(string :tag "Just a file")
(const :tag "Default Secrets API Collection" 'default)
(const :tag "Login Secrets API Collection" "secrets:login")
(const :tag "Temp Secrets API Collection" "secrets:session")
(list :tag "Source definition"
(const :format "" :value :source)
(choice :tag "Authentication backend choice"
(string :tag "Authentication Source (file)")
(list
:tag "Secret Service API/KWallet/GNOME Keyring"
(const :format "" :value :secrets)
(choice :tag "Collection to use"
(string :tag "Collection name")
(const :tag "Default" 'default)
(const :tag "Login" "login")
(const
:tag "Temporary" "session"))))
(repeat :tag "Extra Parameters" :inline t
(choice :tag "Extra parameter"
(list
:tag "Host"
(const :format "" :value :host)
(choice :tag "Host (machine) choice"
(const :tag "Any" t)
(regexp
:tag "Regular expression")))
(list
:tag "Protocol"
(const :format "" :value :protocol)
(choice
:tag "Protocol"
(const :tag "Any" t)
,@auth-source-protocols-customize))
(list :tag "User" :inline t
(const :format "" :value :user)
(choice :tag "Personality/Username"
(const :tag "Any" t)
(string :tag "Name")))))))))
(defcustom auth-source-gpg-encrypt-to t
"List of recipient keys that `authinfo.gpg' encrypted to.
If the value is not a list, symmetric encryption will be used."
:group 'auth-source
:version "23.2" ;; No Gnus
:version "24.1" ;; No Gnus
:type '(choice (const :tag "Symmetric encryption" t)
(repeat :tag "Recipient public keys"
(string :tag "Recipient public key"))))
(repeat :tag "Recipient public keys"
(string :tag "Recipient public key"))))
;; temp for debugging
;; (unintern 'auth-source-protocols)
......@@ -211,229 +262,799 @@ If the value is not a list, symmetric encryption will be used."
;; (setq auth-sources '((:source "~/.authinfo.gpg" :host t :protocol t)))
(defun auth-get-source (entry)
"Return the source string of ENTRY, which is one entry in `auth-sources'.
If it is a Secret Service API, return the collection name, otherwise
the file name."
(let ((source (plist-get entry :source)))
(if (stringp source)
source
;; Secret Service API.
(setq source (plist-get source :secrets))
(when (eq source 'default)
(setq source (or (secrets-get-alias "default") "login")))
(or source "session"))))
(defun auth-source-pick (&rest spec)
"Parse `auth-sources' for matches of the SPEC plist.
Common keys are :host, :protocol, and :user. A value of t in
SPEC means to always succeed in the match. A string value is
matched as a regex."
(let ((keys (loop for i below (length spec) by 2 collect (nth i spec)))
choices)
(dolist (choice (copy-tree auth-sources) choices)
(let ((source (plist-get choice :source))
(match t))
(when
(and
;; Check existence of source.
(if (consp source)
;; Secret Service API.
(member (auth-get-source choice) (secrets-list-collections))
;; authinfo file.
(file-exists-p source))
;; Check keywords.
(dolist (k keys match)
(let* ((v (plist-get spec k))
(choicev (if (plist-member choice k)
(plist-get choice k) t)))
(setq match
(and match
(or
;; source always matches spec key
(eq t choicev)
;; source key gives regex to match against spec
(and (stringp choicev) (string-match choicev v))
;; source key gives symbol to match against spec
(and (symbolp choicev) (eq choicev v))))))))
(add-to-list 'choices choice 'append))))))
(defun auth-source-retrieve (mode entry &rest spec)
"Retrieve MODE credentials according to SPEC from ENTRY."
(catch 'no-password
(let ((host (plist-get spec :host))