diff options
| author | Ted Zlatanov | 2017-12-19 11:36:43 -0500 |
|---|---|---|
| committer | Ted Zlatanov | 2017-12-19 11:45:48 -0500 |
| commit | 1d0a37f845dbdebee81bed4c3c104e752c95c44c (patch) | |
| tree | 4d442eb768f1c6423e9e7112661c901e89af6e1f | |
| parent | 56274bc0bbfe144ef4af08fc86e9455dabfccf30 (diff) | |
| download | emacs-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.el | 113 |
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. | ||
| 2021 | See `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") |