Function: auth-source-macos-keychain-search
auth-source-macos-keychain-search is a byte-compiled function defined
in auth-source.el.gz.
Signature
(auth-source-macos-keychain-search &rest SPEC &key BACKEND CREATE DELETE TYPE MAX &allow-other-keys)
Documentation
Search the macOS Keychain; spec is like auth-source.
All search keys must match exactly. If you need substring matching, do a wider search and narrow it down yourself.
You'll get back all the properties of the token as a plist.
The :type key is either macos-keychain-internet or
macos-keychain-generic.
For the internet keychain type, the :label key searches the
item's labels ("-l LABEL" passed to "/usr/bin/security").
Similarly, :host maps to "-s HOST", :user maps to "-a USER",
and :port maps to "-P PORT" or "-r PROT"
(note PROT has to be a 4-character string).
For the generic keychain type, the :label key searches the item's labels ("-l LABEL" passed to "/usr/bin/security"). Similarly, :host maps to "-c HOST" (the "creator" keychain field), :user maps to "-a USER", and :port maps to "-s PORT".
Here's an example that looks for the first item in the default generic macOS Keychain:
(let ((auth-sources '(macos-keychain-generic)))
(auth-source-search :max 1)
Here's another that looks for the first item in the internet
macOS Keychain collection whose label is gnus:
(let ((auth-sources '(macos-keychain-internet)))
(auth-source-search :max 1 :label "gnus")
And this one looks for the first item in the internet keychain entries for git.gnus.org:
(let ((auth-sources '(macos-keychain-internet")))
(auth-source-search :max 1 :host "git.gnus.org"))
Source Code
;; Defined in /usr/src/emacs/lisp/auth-source.el.gz
;;; Backend specific parsing: Mac OS Keychain (using /usr/bin/security) backend
(cl-defun auth-source-macos-keychain-search (&rest spec
&key backend create delete type max
&allow-other-keys)
"Search the macOS Keychain; spec is like `auth-source'.
All search keys must match exactly. If you need substring
matching, do a wider search and narrow it down yourself.
You'll get back all the properties of the token as a plist.
The :type key is either `macos-keychain-internet' or
`macos-keychain-generic'.
For the internet keychain type, the :label key searches the
item's labels (\"-l LABEL\" passed to \"/usr/bin/security\").
Similarly, :host maps to \"-s HOST\", :user maps to \"-a USER\",
and :port maps to \"-P PORT\" or \"-r PROT\"
\(note PROT has to be a 4-character string).
For the generic keychain type, the :label key searches the item's
labels (\"-l LABEL\" passed to \"/usr/bin/security\").
Similarly, :host maps to \"-c HOST\" (the \"creator\" keychain
field), :user maps to \"-a USER\", and :port maps to \"-s PORT\".
Here's an example that looks for the first item in the default
generic macOS Keychain:
(let ((auth-sources \\='(macos-keychain-generic)))
(auth-source-search :max 1)
Here's another that looks for the first item in the internet
macOS Keychain collection whose label is `gnus':
(let ((auth-sources \\='(macos-keychain-internet)))
(auth-source-search :max 1 :label \"gnus\")
And this one looks for the first item in the internet keychain
entries for git.gnus.org:
(let ((auth-sources \\='(macos-keychain-internet\")))
(auth-source-search :max 1 :host \"git.gnus.org\"))"
;; TODO
(cl-assert (not create) nil
"The macOS Keychain auth-source backend doesn't support creation yet")
;; TODO
;; (macos-keychain-delete-item coll elt)
(cl-assert (not delete) nil
"The macOS Keychain auth-source backend doesn't support deletion yet")
(let* ((coll (oref backend source))
(max (or max 5000)) ; sanity check: default to stop at 5K
;; Filter out ignored keys from the spec
(ignored-keys '(:create :delete :max :backend :label :host :port))
;; Build a search spec without the ignored keys
;; FIXME make this loop a function? it's used in at least 3 places
(search-keys (cl-loop for i below (length spec) by 2
unless (memq (nth i spec) ignored-keys)
collect (nth i spec)))
;; If a search key value is nil or t (match anything), we skip it
(search-spec (apply #'append (mapcar
(lambda (k)
(if (or (null (plist-get spec k))
(eq t (plist-get spec k)))
nil
(list k (plist-get spec k))))
search-keys)))
;; needed keys (always including host, login, port, and secret)
(returned-keys (delete-dups (append
'(:host :login :port :secret)
search-keys)))
;; Extract host, port and user from spec
(hosts (plist-get spec :host))
(hosts (if (consp hosts) hosts `(,hosts)))
(ports (plist-get spec :port))
(ports (if (consp ports) ports `(,ports)))
(users (plist-get spec :user))
(users (if (consp users) users `(,users)))
;; Loop through all combinations of host/port and pass each of these to
;; auth-source-macos-keychain-search-items. Convert numeric port to
;; string (bug#68376).
(items (catch 'match
(dolist (host hosts)
(dolist (port ports)
(when (numberp port) (setq port (number-to-string port)))
(dolist (user users)
(let ((items (apply
#'auth-source-macos-keychain-search-items
coll
type
max
host port user
search-spec)))
(when items
(throw 'match items))))))))
;; ensure each item has each key in `returned-keys'
(items (mapcar (lambda (plist)
(append
(apply #'append
(mapcar (lambda (req)
(if (plist-get plist req)
nil
(list req nil)))
returned-keys))
plist))
items)))
items))