The major problem so far is that secrets-search-items on a nil (matching
any) collection doesn't tell me what collection matched. So then I
can't say
(secrets-get-attributes nil (car (secrets-search-items nil :user "joe")))
to find the attributes of that item (although
(secrets-get-secret nil "my item")
does work, so this only fails when I need attributes).
When I do know the session, things work. Attached is a patch to show
how auth-source-pick and auth-source-user-or-password would change, on
top of the recent check-ins to Gnus. Basically auth-source-pick bakes a
list of results that includes the found collection in :search and the
found item in :item. Then auth-source-user-or-password looks up the
:user attribute for the "login" attribute and the secret for the
"password" attribute.
The default session is looked up as the "default" alias and if that
fails, as the "default" session (with a message). Otherwise most of the
code converts between the nil "match all" session parameter in
secrets.el and the t "match all" in auth-source.el and massages the
results.
I also redid the auth-sources customization a little bit.
If you can follow this, great. Otherwise if you think it's too
complicated, it's time to redo auth-source.el to be more flexible about
taking extra parameters. As the author it's hard for me to say if that
time is now :)
Ted
Index: auth-source.el
===================================================================
RCS file: /usr/local/cvsroot/gnus/lisp/auth-source.el,v
retrieving revision 7.20
diff -u -r7.20 auth-source.el
--- auth-source.el 23 Mar 2010 02:54:14 -0000 7.20
+++ auth-source.el 23 Mar 2010 18:52:52 -0000
@@ -124,7 +124,6 @@
(const :tag "Default" 'default)
(const :tag "Any" t)
(const :tag "Temporary" "session")
- (string :tag "Specific session name")
(const :tag "Fallback" nil))))
(const :format "" :value :host)
(choice :tag "Host (machine) choice"
@@ -139,7 +138,7 @@
(repeat :tag "Extra Parameters" :inline t
(choice :tag "Extra parameter"
(list :tag "Preferred username" :inline t
- (const :format "" :value :preferred-username)
+ (const :format "" :value :user)
(choice :tag "Personality or username"
(const :tag "Any" t)
(const :tag "Fallback" nil)
@@ -154,7 +153,7 @@
;; (customize-variable 'auth-source-protocols)
;; (setq auth-source-protocols nil)
;; (format "%S" auth-source-protocols)
-;; (auth-source-pick "a" 'imap)
+;; (auth-source-pick "a" 'imap '())
;; (auth-source-user-or-password "login" "imap.myhost.com" 'imap)
;; (auth-source-user-or-password "password" "imap.myhost.com" 'imap)
;; (auth-source-user-or-password-imap "login" "imap.myhost.com")
@@ -174,25 +173,74 @@
'message)))
(apply logger msg))))
-(defun auth-source-pick (host protocol &optional fallback)
- "Parse `auth-sources' for HOST, and PROTOCOL matches.
+(defun auth-source-pick (host protocol extras &optional fallback)
+ "Parse `auth-sources' for HOST and PROTOCOL (+EXTRAS) matches.
+
+Only :user is checked currently in the plist EXTRAS.
Returns fallback choices (where PROTOCOL or HOST are nil) with FALLBACK t."
(interactive "sHost: \nsProtocol: \n") ;for testing
(let (choices)
(dolist (choice auth-sources)
- (let ((h (plist-get choice :host))
- (p (plist-get choice :protocol)))
- (when (and
- (or (equal t h)
- (and (stringp h) (string-match h host))
- (and fallback (equal h nil)))
- (or (equal t p)
- (and (symbolp p) (equal p protocol))
- (and fallback (equal p nil))))
- (push choice choices))))
+ (let* ((h (plist-get choice :host))
+ (p (plist-get choice :protocol))
+ (s (plist-get choice :source))
+ (u (or (plist-get choice :user) t)) ; the user spec in this choice, defaults to t
+ (user (plist-get extras :user)) ; the passed user
+ ;; this is only set for Secret Service API specs (through secrets.el)
+ (coll (plist-get s :secrets)))
+ (cond
+ (coll ; use secrets.el here
+ (when (eq coll 'default)
+ (setq coll (secrets-get-alias "default"))
+ (unless coll
+ (auth-source-do-debug
+ "Default alias: no '%s' alias. Trying collection '%s'."
+ "default" "default")
+ (setq coll "default")))
+ (let* ((coll-search (cond
+ ((stringp coll) coll)
+ ((eq coll t) nil) ; t = any collection
+
+ ;; when the collection is nil:
+ ;; in fallback mode, accept it as any
+ ;; otherwise, hope to fail
+ ((null coll) (if fallback
+ nil
+ " *fallback-fail*"))))
+ ;; this will have the other secrets-search-items parameters
+ (other-search (append
+ (when (stringp h) `(:host ,h))
+ (when (stringp u) `(:user ,u))
+ (when (stringp p) `(:port ,p))))
+ (results (apply 'secrets-search-items
+ coll-search
+ other-search)))
+ (auth-source-do-debug
+ "auth-source-pick: got items %s in collection search %s + %s"
+ results coll-search other-search)
+ (dolist (result results)
+ (push `(:source secrets
+ :item ,result
+ :collection ,coll
+ :search ,coll-search
+ ,@other-search)
+ choices))))
+ (t ; this is any non-secrets spec
+ (when (and
+ (or (equal t h)
+ (and (stringp h) (string-match h host))
+ (and fallback (equal h nil)))
+ (or (equal t p)
+ (and (symbolp p) (equal p protocol))
+ (and fallback (equal p nil)))
+ (or (equal t u) ; note that u defaults to t
+ (and (stringp u) (string-match u user))))
+ (push choice choices))))))
(if choices
choices
+ ;; when there were no matches, do a second pass but this time
+ ;; fallbacks (nil values) are acceptable
(unless fallback
(auth-source-pick host protocol t)))))
@@ -205,44 +253,58 @@
(interactive)
(setq auth-source-cache (make-hash-table :test 'equal)))
-(defun auth-source-user-or-password (mode host protocol)
+(defun auth-source-user-or-password (mode host protocol &optional username)
"Find MODE (string or list of strings) matching HOST and PROTOCOL.
MODE can be \"login\" or \"password\" for example."
(auth-source-do-debug
- "auth-source-user-or-password: get %s for %s (%s)"
- mode host protocol)
+ "auth-source-user-or-password: get %s for %s (%s) + user=%s"
+ mode host protocol username)
(let* ((listy (listp mode))
(mode (if listy mode (list mode)))
- (cname (format "%s %s:%s" mode host protocol))
+ (extras (when username `(:user ,username)))
+ (cname (format "%s %s:%s %s" mode host protocol extras))
(found (gethash cname auth-source-cache)))
(if found
(progn
(auth-source-do-debug
- "auth-source-user-or-password: cached %s=%s for %s (%s)"
+ "auth-source-user-or-password: cached %s=%s for %s (%s) + %s"
mode
;; don't show the password
- (if (and (member "password" mode) auth-source-hide-passwords) "SECRET" found)
- host protocol)
- found)
- (dolist (choice (auth-source-pick host protocol))
- (setq found (netrc-machine-user-or-password
- mode
- (plist-get choice :source)
- (list host)
- (list (format "%s" protocol))
- (auth-source-protocol-defaults protocol)))
+ (if (and (member "password" mode) auth-source-hide-passwords)
+ "SECRET"
+ found)
+ host protocol extras)
+ found) ; return the found data
+ (dolist (choice (auth-source-pick host protocol extras))
+ (setq found (cond
+ ;; the secrets.el spec
+ ((eq (plist-get choice :source) 'secrets)
+ (let ((coll (plist-get choice :search))
+ (item (plist-get choice :item)))
+ (mapcar (lambda (m)
+ (if (equal "password" m)
+ (secrets-get-secret coll item)
+ (secrets-get-attribute coll item :user)))
+ mode)))
+ (t ; anything else is netrc
+ (netrc-machine-user-or-password
+ mode
+ (plist-get choice :source)
+ (list host)
+ (list (format "%s" protocol))
+ (auth-source-protocol-defaults protocol)))))
(when found
(auth-source-do-debug
- "auth-source-user-or-password: found %s=%s for %s (%s)"
+ "auth-source-user-or-password: found %s=%s for %s (%s) + %s"
mode
;; don't show the password
(if (and (member "password" mode) auth-source-hide-passwords) "SECRET" found)
- host protocol)
+ host protocol extras)
(setq found (if listy found (car-safe found)))
(when auth-source-do-cache
(puthash cname found auth-source-cache)))
(return found)))))
-
+
(defun auth-source-protocol-defaults (protocol)
"Return a list of default ports and names for PROTOCOL."
(cdr-safe (assoc protocol auth-source-protocols)))
_______________________________________________
Tramp-devel mailing list
[email protected]
http://lists.gnu.org/mailman/listinfo/tramp-devel