aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTed Zlatanov2017-12-19 11:36:43 -0500
committerTed Zlatanov2017-12-19 11:45:48 -0500
commit1d0a37f845dbdebee81bed4c3c104e752c95c44c (patch)
tree4d442eb768f1c6423e9e7112661c901e89af6e1f
parent56274bc0bbfe144ef4af08fc86e9455dabfccf30 (diff)
downloademacs-1d0a37f845dbdebee81bed4c3c104e752c95c44c.tar.gz
emacs-1d0a37f845dbdebee81bed4c3c104e752c95c44c.zip
auth-source: support JSON backend with .json extension
* lisp/auth-source.el (auth-source-backends-parser-file): Look for .gpg extension and make backend decision without it. Add JSON case to backends. (auth-source-json-check): Parse JSON data.
-rw-r--r--lisp/auth-source.el113
1 files changed, 99 insertions, 14 deletions
diff --git a/lisp/auth-source.el b/lisp/auth-source.el
index 1cb7f5d57ef..152c5af59ae 100644
--- a/lisp/auth-source.el
+++ b/lisp/auth-source.el
@@ -379,24 +379,38 @@ soon as a function returns non-nil.")
379 ;; take just a file name use it as a netrc/plist file 379 ;; take just a file name use it as a netrc/plist file
380 ;; matching any user, host, and protocol 380 ;; matching any user, host, and protocol
381 (when (stringp entry) 381 (when (stringp entry)
382 (setq entry `(:source ,entry))) 382 (setq entry (list :source entry)))
383 (cond 383 (let* ((source (plist-get entry :source))
384 ;; a file name with parameters 384 (source-without-gpg
385 ((stringp (plist-get entry :source)) 385 (if (and (stringp source)
386 (if (equal (file-name-extension (plist-get entry :source)) "plist") 386 (equal (file-name-extension source) "gpg"))
387 (file-name-sans-extension source)
388 (or source "")))
389 (extension (or (file-name-extension source-without-gpg)
390 "")))
391 (when (stringp source)
392 (cond
393 ((equal extension "plist")
387 (auth-source-backend 394 (auth-source-backend
388 (plist-get entry :source) 395 source
389 :source (plist-get entry :source) 396 :source source
390 :type 'plstore 397 :type 'plstore
391 :search-function #'auth-source-plstore-search 398 :search-function #'auth-source-plstore-search
392 :create-function #'auth-source-plstore-create 399 :create-function #'auth-source-plstore-create
393 :data (plstore-open (plist-get entry :source))) 400 :data (plstore-open source)))
394 (auth-source-backend 401 ((member-ignore-case extension '("json"))
395 (plist-get entry :source) 402 (auth-source-backend
396 :source (plist-get entry :source) 403 source
397 :type 'netrc 404 :source source
398 :search-function #'auth-source-netrc-search 405 :type 'json
399 :create-function #'auth-source-netrc-create))))) 406 :search-function #'auth-source-json-search))
407 (t
408 (auth-source-backend
409 source
410 :source source
411 :type 'netrc
412 :search-function #'auth-source-netrc-search
413 :create-function #'auth-source-netrc-create))))))
400 414
401;; Note this function should be last in the parser functions, so we add it first 415;; Note this function should be last in the parser functions, so we add it first
402(add-hook 'auth-source-backend-parser-functions 'auth-source-backends-parser-file) 416(add-hook 'auth-source-backend-parser-functions 'auth-source-backends-parser-file)
@@ -1967,6 +1981,77 @@ entries for git.gnus.org:
1967 (plstore-get-file (oref backend data)))) 1981 (plstore-get-file (oref backend data))))
1968 (plstore-save (oref backend data))))) 1982 (plstore-save (oref backend data)))))
1969 1983
1984;;; Backend specific parsing: JSON backend
1985;;; (auth-source-search :max 1 :machine "imap.gmail.com")
1986;;; (auth-source-search :max 1 :host '("my-gmail" "imap.gmail.com") :port '(993 "imaps" "imap" "993" "143") :user nil :require '(:user :secret))
1987
1988(defun auth-source-json-check (host user port require item)
1989 (and item
1990 (auth-source-search-collection
1991 (or host t)
1992 (or
1993 (plist-get item :machine)
1994 (plist-get item :host)
1995 t))
1996 (auth-source-search-collection
1997 (or user t)
1998 (or
1999 (plist-get item :login)
2000 (plist-get item :account)
2001 (plist-get item :user)
2002 t))
2003 (auth-source-search-collection
2004 (or port t)
2005 (or
2006 (plist-get item :port)
2007 (plist-get item :protocol)
2008 t))
2009 (or
2010 ;; the required list of keys is nil, or
2011 (null require)
2012 ;; every element of require is in
2013 (cl-loop for req in require
2014 always (plist-get item req)))))
2015
2016(cl-defun auth-source-json-search (&rest spec
2017 &key backend require create
2018 type max host user port
2019 &allow-other-keys)
2020 "Given a property list SPEC, return search matches from the :backend.
2021See `auth-source-search' for details on SPEC."
2022 ;; just in case, check that the type is correct (null or same as the backend)
2023 (cl-assert (or (null type) (eq type (oref backend type)))
2024 t "Invalid JSON search: %s %s")
2025
2026 ;; Hide the secrets early to avoid accidental exposure.
2027 (let* ((jdata
2028 (mapcar (lambda (entry)
2029 (let (ret)
2030 (while entry
2031 (let* ((item (pop entry))
2032 (k (auth-source--symbol-keyword (car item)))
2033 (v (cdr item)))
2034 (setq k (cond ((memq k '(:machine)) :host)
2035 ((memq k '(:login :account)) :user)
2036 ((memq k '(:protocol)) :port)
2037 ((memq k '(:password)) :secret)
2038 (t k)))
2039 ;; send back the secret in a function (lexical binding)
2040 (when (eq k :secret)
2041 (setq v (let ((lexv v))
2042 (lambda () lexv))))
2043 (setq ret (plist-put ret k v))))
2044 ret))
2045 (json-read-file (oref backend source))))
2046 (max (or max 5000)) ; sanity check: default to stop at 5K
2047 all)
2048 (dolist (item jdata)
2049 (when (and item
2050 (> max (length all))
2051 (auth-source-json-check host user port require item))
2052 (push item all)))
2053 (nreverse all)))
2054
1970;;; older API 2055;;; older API
1971 2056
1972;; (auth-source-user-or-password '("login" "password") "imap.myhost.com" t "tzz") 2057;; (auth-source-user-or-password '("login" "password") "imap.myhost.com" t "tzz")