aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGnus developers2011-06-30 14:25:27 +0000
committerKatsumi Yamaoka2011-06-30 14:25:27 +0000
commit936d08bba7cdc8c3a28d7ad716e82a00555fccef (patch)
treefd0a4c24c8e1fc2a3dea444871522ee6a10b5aa7
parent9851bfc58dcf38d05e469112790c514c3fd6fbf7 (diff)
downloademacs-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/ChangeLog16
-rw-r--r--lisp/gnus/auth-source.el193
-rw-r--r--lisp/gnus/gnus-art.el11
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 @@
12011-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
62011-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
12011-06-30 Lars Magne Ingebrigtsen <larsi@gnus.org> 172011-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)) 990extra SYM-DETAIL parameter which will be printed at the end of
988 (,(if (boundp 'find-file-hook) 'find-file-hook 'find-file-hooks) 991the symmetric passphrase prompt, and assumes symmetric
989 ',(remove 992encryption."
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.
1029FILE 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))