diff options
| author | Gnus developers | 2011-06-30 14:25:27 +0000 |
|---|---|---|
| committer | Katsumi Yamaoka | 2011-06-30 14:25:27 +0000 |
| commit | 936d08bba7cdc8c3a28d7ad716e82a00555fccef (patch) | |
| tree | fd0a4c24c8e1fc2a3dea444871522ee6a10b5aa7 | |
| parent | 9851bfc58dcf38d05e469112790c514c3fd6fbf7 (diff) | |
| download | emacs-936d08bba7cdc8c3a28d7ad716e82a00555fccef.tar.gz emacs-936d08bba7cdc8c3a28d7ad716e82a00555fccef.zip | |
Merge changes made in Gnus trunk.
gnus-art.el (gnus-request-article-this-buffer): Use existing function `gnus-refer-article-methods'.
auth-source.el: Require EPA and EPG.
(auth-source-passphrase-alist): New variable.
(auth-source-passphrase-callback-function, auth-source-token-passphrase-callback-function): Callbacks for the netrc field encryption (GPG tokens).
(auth-source-epa-extract-gpg-token, auth-source-epa-make-gpg-token): Symmetric encryption and decryption of the netrc GPG tokens.
(auth-source-netrc-normalize): Use them, simplifying the closure.
| -rw-r--r-- | lisp/gnus/ChangeLog | 16 | ||||
| -rw-r--r-- | lisp/gnus/auth-source.el | 193 | ||||
| -rw-r--r-- | lisp/gnus/gnus-art.el | 11 |
3 files changed, 108 insertions, 112 deletions
diff --git a/lisp/gnus/ChangeLog b/lisp/gnus/ChangeLog index ea7aedc3e6a..8133964dd41 100644 --- a/lisp/gnus/ChangeLog +++ b/lisp/gnus/ChangeLog | |||
| @@ -1,3 +1,19 @@ | |||
| 1 | 2011-06-30 Andrew Cohen <cohen@andy.bu.edu> | ||
| 2 | |||
| 3 | * gnus-art.el (gnus-request-article-this-buffer): Use existing function | ||
| 4 | `gnus-refer-article-methods'. | ||
| 5 | |||
| 6 | 2011-06-30 Teodor Zlatanov <tzz@lifelogs.com> | ||
| 7 | |||
| 8 | * auth-source.el: Require EPA and EPG. | ||
| 9 | (auth-source-passphrase-alist): New variable. | ||
| 10 | (auth-source-passphrase-callback-function) | ||
| 11 | (auth-source-token-passphrase-callback-function): Callbacks for the | ||
| 12 | netrc field encryption (GPG tokens). | ||
| 13 | (auth-source-epa-extract-gpg-token, auth-source-epa-make-gpg-token): | ||
| 14 | Symmetric encryption and decryption of the netrc GPG tokens. | ||
| 15 | (auth-source-netrc-normalize): Use them, simplifying the closure. | ||
| 16 | |||
| 1 | 2011-06-30 Lars Magne Ingebrigtsen <larsi@gnus.org> | 17 | 2011-06-30 Lars Magne Ingebrigtsen <larsi@gnus.org> |
| 2 | 18 | ||
| 3 | * nnimap.el (nnimap-split-incoming-mail): If `nnimap-split-fancy' is | 19 | * nnimap.el (nnimap-split-incoming-mail): If `nnimap-split-fancy' is |
diff --git a/lisp/gnus/auth-source.el b/lisp/gnus/auth-source.el index d62b79b6484..25c6b924305 100644 --- a/lisp/gnus/auth-source.el +++ b/lisp/gnus/auth-source.el | |||
| @@ -43,6 +43,9 @@ | |||
| 43 | (require 'mm-util) | 43 | (require 'mm-util) |
| 44 | (require 'gnus-util) | 44 | (require 'gnus-util) |
| 45 | (require 'assoc) | 45 | (require 'assoc) |
| 46 | (require 'epa) | ||
| 47 | (require 'epg) | ||
| 48 | |||
| 46 | (eval-when-compile (require 'cl)) | 49 | (eval-when-compile (require 'cl)) |
| 47 | (require 'eieio) | 50 | (require 'eieio) |
| 48 | 51 | ||
| @@ -979,56 +982,78 @@ Note that the MAX parameter is used so we can exit the parse early." | |||
| 979 | 982 | ||
| 980 | (nreverse result)))))) | 983 | (nreverse result)))))) |
| 981 | 984 | ||
| 982 | (defmacro with-auth-source-epa-overrides (&rest body) | 985 | (defvar auth-source-passphrase-alist nil) |
| 983 | `(let ((file-name-handler-alist | 986 | |
| 984 | ',(if (boundp 'epa-file-handler) | 987 | (defun auth-source-passphrase-callback-function (context key-id handback |
| 985 | (remove (symbol-value 'epa-file-handler) | 988 | &optional sym-detail) |
| 986 | file-name-handler-alist) | 989 | "Exactly like `epa-passphrase-callback-function' but takes an |
| 987 | file-name-handler-alist)) | 990 | extra SYM-DETAIL parameter which will be printed at the end of |
| 988 | (,(if (boundp 'find-file-hook) 'find-file-hook 'find-file-hooks) | 991 | the symmetric passphrase prompt, and assumes symmetric |
| 989 | ',(remove | 992 | encryption." |
| 990 | 'epa-file-find-file-hook | 993 | (read-passwd |
| 991 | (if (boundp 'find-file-hook) | 994 | (format "Passphrase for symmetric encryption%s%s: " |
| 992 | (symbol-value 'find-file-hook) | 995 | ;; Add the file name to the prompt, if any. |
| 993 | (symbol-value 'find-file-hooks)))) | 996 | (if (stringp handback) |
| 994 | (auto-mode-alist | 997 | (format " for %s" handback) |
| 995 | ',(if (boundp 'epa-file-auto-mode-alist-entry) | 998 | "") |
| 996 | (remove (symbol-value 'epa-file-auto-mode-alist-entry) | 999 | (if (stringp sym-detail) |
| 997 | auto-mode-alist) | 1000 | sym-detail |
| 998 | auto-mode-alist))) | 1001 | "")) |
| 999 | ,@body)) | 1002 | (eq (epg-context-operation context) 'encrypt))) |
| 1000 | 1003 | ||
| 1004 | (defun auth-source-token-passphrase-callback-function (context key-id file) | ||
| 1005 | (if (eq key-id 'SYM) | ||
| 1006 | (let* ((file (file-truename file)) | ||
| 1007 | (entry (assoc file auth-source-passphrase-alist)) | ||
| 1008 | passphrase) | ||
| 1009 | ;; return the saved passphrase, calling a function if needed | ||
| 1010 | (or (copy-sequence (if (functionp (cdr entry)) | ||
| 1011 | (funcall (cdr entry)) | ||
| 1012 | (cdr entry))) | ||
| 1013 | (progn | ||
| 1014 | (unless entry | ||
| 1015 | (setq entry (list file)) | ||
| 1016 | (push entry auth-source-passphrase-alist)) | ||
| 1017 | (setq passphrase (auth-source-passphrase-callback-function context | ||
| 1018 | key-id | ||
| 1019 | file | ||
| 1020 | " tokens")) | ||
| 1021 | (setcdr entry (lexical-let ((p (copy-sequence passphrase))) | ||
| 1022 | (lambda () p))) | ||
| 1023 | passphrase))) | ||
| 1024 | (epa-passphrase-callback-function context key-id file))) | ||
| 1025 | |||
| 1026 | ;; (auth-source-epa-extract-gpg-token "gpg:LS0tLS1CRUdJTiBQR1AgTUVTU0FHRS0tLS0tClZlcnNpb246IEdudVBHIHYxLjQuMTEgKEdOVS9MaW51eCkKCmpBMEVBd01DT25qMjB1ak9rZnRneVI3K21iNm9aZWhuLzRad3cySkdlbnVaKzRpeEswWDY5di9icDI1U1dsQT0KPS9yc2wKLS0tLS1FTkQgUEdQIE1FU1NBR0UtLS0tLQo=" "~/.netrc") | ||
| 1027 | (defun auth-source-epa-extract-gpg-token (secret file) | ||
| 1028 | "Pass either the decoded SECRET or the gpg:BASE64DATA version. | ||
| 1029 | FILE is the file from which we obtained this token." | ||
| 1030 | (when (string-match "^gpg:\\(.+\\)" secret) | ||
| 1031 | (setq secret (base64-decode-string (match-string 1 secret)))) | ||
| 1032 | (let ((context (epg-make-context 'OpenPGP)) | ||
| 1033 | plain) | ||
| 1034 | (epg-context-set-passphrase-callback | ||
| 1035 | context | ||
| 1036 | (cons #'auth-source-token-passphrase-callback-function | ||
| 1037 | file)) | ||
| 1038 | (epg-decrypt-string context secret))) | ||
| 1039 | |||
| 1040 | ;; (insert (auth-source-epa-make-gpg-token "mysecret" "~/.netrc")) | ||
| 1001 | (defun auth-source-epa-make-gpg-token (secret file) | 1041 | (defun auth-source-epa-make-gpg-token (secret file) |
| 1002 | (require 'epa nil t) | 1042 | (let ((context (epg-make-context 'OpenPGP)) |
| 1003 | (unless (featurep 'epa) | 1043 | (pp-escape-newlines nil) |
| 1004 | (error "EPA could not be loaded.")) | 1044 | cipher) |
| 1005 | (let* ((base (file-name-sans-extension file)) | 1045 | (epg-context-set-armor context t) |
| 1006 | (passkey (format "gpg:-%s" base)) | 1046 | (epg-context-set-passphrase-callback |
| 1007 | (stash (concat base ".gpg")) | 1047 | context |
| 1008 | ;; temporarily disable EPA | 1048 | (cons #'auth-source-token-passphrase-callback-function |
| 1009 | (stashfile | 1049 | file)) |
| 1010 | (with-auth-source-epa-overrides | 1050 | (setq cipher (epg-encrypt-string context secret nil)) |
| 1011 | (make-temp-file "gpg-token" nil | 1051 | (with-temp-buffer |
| 1012 | stash))) | 1052 | (insert cipher) |
| 1013 | (epa-file-passphrase-alist | 1053 | (base64-encode-region (point-min) (point-max) t) |
| 1014 | `((,stashfile | 1054 | (concat "gpg:" (buffer-substring-no-properties |
| 1015 | . ,(password-read | 1055 | (point-min) |
| 1016 | (format | 1056 | (point-max)))))) |
| 1017 | "token pass for %s? " | ||
| 1018 | file) | ||
| 1019 | passkey))))) | ||
| 1020 | (write-region secret nil stashfile) | ||
| 1021 | ;; temporarily disable EPA | ||
| 1022 | (unwind-protect | ||
| 1023 | (with-auth-source-epa-overrides | ||
| 1024 | (with-temp-buffer | ||
| 1025 | (insert-file-contents stashfile) | ||
| 1026 | (base64-encode-region (point-min) (point-max) t) | ||
| 1027 | (concat "gpg:" | ||
| 1028 | (buffer-substring-no-properties | ||
| 1029 | (point-min) | ||
| 1030 | (point-max))))) | ||
| 1031 | (delete-file stashfile)))) | ||
| 1032 | 1057 | ||
| 1033 | (defun auth-source-netrc-normalize (alist filename) | 1058 | (defun auth-source-netrc-normalize (alist filename) |
| 1034 | (mapcar (lambda (entry) | 1059 | (mapcar (lambda (entry) |
| @@ -1046,60 +1071,22 @@ Note that the MAX parameter is used so we can exit the parse early." | |||
| 1046 | 1071 | ||
| 1047 | ;; send back the secret in a function (lexical binding) | 1072 | ;; send back the secret in a function (lexical binding) |
| 1048 | (when (equal k "secret") | 1073 | (when (equal k "secret") |
| 1049 | (setq v (lexical-let ((v v) | 1074 | (setq v (lexical-let ((lexv v) |
| 1050 | (filename filename) | 1075 | (token-decoder nil)) |
| 1051 | (base (file-name-nondirectory | 1076 | (when (string-match "^gpg:" lexv) |
| 1052 | filename)) | 1077 | ;; it's a GPG token: create a token decoder |
| 1053 | (token-decoder nil) | 1078 | ;; which unsets itself once |
| 1054 | (gpgdata nil) | 1079 | (setq token-decoder |
| 1055 | (stash nil)) | 1080 | (lambda (val) |
| 1056 | (setq stash (concat base ".gpg")) | 1081 | (prog1 |
| 1057 | (when (string-match "gpg:\\(.+\\)" v) | 1082 | (auth-source-epa-extract-gpg-token |
| 1058 | (require 'epa nil t) | 1083 | val |
| 1059 | (unless (featurep 'epa) | 1084 | filename) |
| 1060 | (error "EPA could not be loaded.")) | 1085 | (setq token-decoder nil))))) |
| 1061 | (setq gpgdata (base64-decode-string | 1086 | (lambda () |
| 1062 | (match-string 1 v))) | 1087 | (when token-decoder |
| 1063 | ;; it's a GPG token | 1088 | (setq lexv (funcall token-decoder lexv))) |
| 1064 | (setq | 1089 | lexv)))) |
| 1065 | token-decoder | ||
| 1066 | (lambda (gpgdata) | ||
| 1067 | ;;; FIXME: this relies on .gpg files being handled by EPA/EPG | ||
| 1068 | (let* ((passkey (format "gpg:-%s" base)) | ||
| 1069 | ;; temporarily disable EPA | ||
| 1070 | (stashfile | ||
| 1071 | (with-auth-source-epa-overrides | ||
| 1072 | (make-temp-file "gpg-token" nil | ||
| 1073 | stash))) | ||
| 1074 | (epa-file-passphrase-alist | ||
| 1075 | `((,stashfile | ||
| 1076 | . ,(password-read | ||
| 1077 | (format | ||
| 1078 | "token pass for %s? " | ||
| 1079 | filename) | ||
| 1080 | passkey))))) | ||
| 1081 | (unwind-protect | ||
| 1082 | (progn | ||
| 1083 | ;; temporarily disable EPA | ||
| 1084 | (with-auth-source-epa-overrides | ||
| 1085 | (write-region gpgdata | ||
| 1086 | nil | ||
| 1087 | stashfile)) | ||
| 1088 | (setq | ||
| 1089 | v | ||
| 1090 | (with-temp-buffer | ||
| 1091 | (insert-file-contents stashfile) | ||
| 1092 | (buffer-substring-no-properties | ||
| 1093 | (point-min) | ||
| 1094 | (point-max))))) | ||
| 1095 | (delete-file stashfile))) | ||
| 1096 | ;; clear out the decoder at end | ||
| 1097 | (setq token-decoder nil | ||
| 1098 | gpgdata nil)))) | ||
| 1099 | (lambda () | ||
| 1100 | (when token-decoder | ||
| 1101 | (funcall token-decoder gpgdata)) | ||
| 1102 | v)))) | ||
| 1103 | (setq ret (plist-put ret | 1090 | (setq ret (plist-put ret |
| 1104 | (intern (concat ":" k)) | 1091 | (intern (concat ":" k)) |
| 1105 | v)))) | 1092 | v)))) |
diff --git a/lisp/gnus/gnus-art.el b/lisp/gnus/gnus-art.el index 6c3ad01eabf..7e2d213d20c 100644 --- a/lisp/gnus/gnus-art.el +++ b/lisp/gnus/gnus-art.el | |||
| @@ -6832,23 +6832,16 @@ If given a prefix, show the hidden text instead." | |||
| 6832 | (numberp article)) | 6832 | (numberp article)) |
| 6833 | (let ((gnus-override-method gnus-override-method) | 6833 | (let ((gnus-override-method gnus-override-method) |
| 6834 | (methods (and (stringp article) | 6834 | (methods (and (stringp article) |
| 6835 | gnus-refer-article-method)) | 6835 | (with-current-buffer gnus-summary-buffer |
| 6836 | (gnus-refer-article-methods)))) | ||
| 6836 | (backend (car (gnus-find-method-for-group | 6837 | (backend (car (gnus-find-method-for-group |
| 6837 | gnus-newsgroup-name))) | 6838 | gnus-newsgroup-name))) |
| 6838 | result | 6839 | result |
| 6839 | (inhibit-read-only t)) | 6840 | (inhibit-read-only t)) |
| 6840 | (if (or (not (listp methods)) | ||
| 6841 | (and (symbolp (car methods)) | ||
| 6842 | (assq (car methods) nnoo-definition-alist))) | ||
| 6843 | (setq methods (list methods))) | ||
| 6844 | (when (and (null gnus-override-method) | 6841 | (when (and (null gnus-override-method) |
| 6845 | methods) | 6842 | methods) |
| 6846 | (setq gnus-override-method (pop methods))) | 6843 | (setq gnus-override-method (pop methods))) |
| 6847 | (while (not result) | 6844 | (while (not result) |
| 6848 | (when (eq gnus-override-method 'current) | ||
| 6849 | (setq gnus-override-method | ||
| 6850 | (with-current-buffer gnus-summary-buffer | ||
| 6851 | gnus-current-select-method))) | ||
| 6852 | (erase-buffer) | 6845 | (erase-buffer) |
| 6853 | (gnus-kill-all-overlays) | 6846 | (gnus-kill-all-overlays) |
| 6854 | (let ((gnus-newsgroup-name group)) | 6847 | (let ((gnus-newsgroup-name group)) |