Mercurial > hg > xemacs-beta
comparison lisp/mailcrypt/mc-pgp.el @ 0:376386a54a3c r19-14
Import from CVS: tag r19-14
author | cvs |
---|---|
date | Mon, 13 Aug 2007 08:45:50 +0200 |
parents | |
children | ec9a17fef872 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:376386a54a3c |
---|---|
1 ;; mc-pgp.el, PGP support for Mailcrypt | |
2 ;; Copyright (C) 1995 Jin Choi <jin@atype.com> | |
3 ;; Patrick LoPresti <patl@lcs.mit.edu> | |
4 | |
5 ;;{{{ Licensing | |
6 ;; This file is intended to be used with GNU Emacs. | |
7 | |
8 ;; This program is free software; you can redistribute it and/or modify | |
9 ;; it under the terms of the GNU General Public License as published by | |
10 ;; the Free Software Foundation; either version 2, or (at your option) | |
11 ;; any later version. | |
12 | |
13 ;; This program is distributed in the hope that it will be useful, | |
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 ;; GNU General Public License for more details. | |
17 | |
18 ;; You should have received a copy of the GNU General Public License | |
19 ;; along with GNU Emacs; see the file COPYING. If not, write to | |
20 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | |
21 ;;}}} | |
22 (require 'mailcrypt) | |
23 | |
24 (defvar mc-pgp-user-id (user-login-name) | |
25 "*PGP ID of your default identity.") | |
26 (defvar mc-pgp-always-sign nil | |
27 "*If t, always sign encrypted PGP messages, or never sign if 'never.") | |
28 (defvar mc-pgp-path "pgp" "*The PGP executable.") | |
29 (defvar mc-pgp-display-snarf-output nil | |
30 "*If t, pop up the PGP output window when snarfing keys.") | |
31 (defvar mc-pgp-alternate-keyring nil | |
32 "*Public keyring to use instead of default.") | |
33 (defvar mc-pgp-comment | |
34 (format "Processed by Mailcrypt %s, an Emacs/PGP interface" mc-version) | |
35 "*Comment field to appear in ASCII armor output. If nil, let PGP | |
36 use its default.") | |
37 | |
38 (defconst mc-pgp-msg-begin-line "-----BEGIN PGP MESSAGE-----" | |
39 "Text for start of PGP message delimiter.") | |
40 (defconst mc-pgp-msg-end-line "-----END PGP MESSAGE-----\n?" | |
41 "Text for end of PGP message delimiter.") | |
42 (defconst mc-pgp-signed-begin-line "-----BEGIN PGP SIGNED MESSAGE-----" | |
43 "Text for start of PGP signed messages.") | |
44 (defconst mc-pgp-signed-end-line "-----END PGP SIGNATURE-----" | |
45 "Text for end of PGP signed messages.") | |
46 (defconst mc-pgp-key-begin-line "^-----BEGIN PGP PUBLIC KEY BLOCK-----\r?$" | |
47 "Text for start of PGP public key.") | |
48 (defconst mc-pgp-key-end-line "^-----END PGP PUBLIC KEY BLOCK-----\r?$" | |
49 "Text for end of PGP public key.") | |
50 (defconst mc-pgp-error-re "^\\(ERROR:\\|WARNING:\\).*" | |
51 "Regular expression matching an error from PGP") | |
52 (defconst mc-pgp-sigok-re "^.*Good signature.*" | |
53 "Regular expression matching a PGP signature validation message") | |
54 (defconst mc-pgp-newkey-re "^[ \t]*\\(No\\|[0-9]+\\) +new [ku].*" | |
55 "Regular expression matching a PGP key snarf message") | |
56 (defconst mc-pgp-nokey-re | |
57 "Cannot find the public key matching userid '\\(.+\\)'$" | |
58 "Regular expression matching a PGP missing-key messsage") | |
59 (defconst mc-pgp-key-expected-re | |
60 "Key matching expected Key ID \\(\\S +\\) not found") | |
61 | |
62 (defvar mc-pgp-keydir nil | |
63 "Directory in which keyrings are stored.") | |
64 | |
65 (defun mc-get-pgp-keydir () | |
66 (if (null mc-pgp-keydir) | |
67 (let ((buffer (generate-new-buffer " *mailcrypt temp*")) | |
68 (obuf (current-buffer))) | |
69 (unwind-protect | |
70 (progn | |
71 (call-process mc-pgp-path nil buffer nil "+verbose=1" | |
72 "+language=en" "-kv" "XXXXXXXXXX") | |
73 (set-buffer buffer) | |
74 (goto-char (point-min)) | |
75 (re-search-forward "^Key ring:\\s *'\\(.*\\)'") | |
76 (setq mc-pgp-keydir | |
77 (file-name-directory | |
78 (buffer-substring-no-properties | |
79 (match-beginning 1) (match-end 1))))) | |
80 (set-buffer obuf) | |
81 (kill-buffer buffer)))) | |
82 mc-pgp-keydir) | |
83 | |
84 (defvar mc-pgp-key-cache nil | |
85 "Association list mapping PGP IDs to canonical \"keys\". A \"key\" | |
86 is a pair (USER-ID . KEY-ID) which identifies the canonical IDs of the | |
87 PGP ID.") | |
88 | |
89 (defun mc-pgp-lookup-key (str) | |
90 ;; Look up the string STR in the user's secret key ring. Return a | |
91 ;; pair of strings (USER-ID . KEY-ID) which uniquely identifies the | |
92 ;; matching key, or nil if no key matches. | |
93 (if (equal str "***** CONVENTIONAL *****") nil | |
94 (let ((keyring (concat (mc-get-pgp-keydir) "secring")) | |
95 (result (cdr-safe (assoc str mc-pgp-key-cache))) | |
96 (key-regexp | |
97 "^\\(pub\\|sec\\)\\s +[^/]+/\\(\\S *\\)\\s +\\S +\\s +\\(.*\\)$") | |
98 (obuf (current-buffer)) | |
99 buffer) | |
100 (if (null result) | |
101 (unwind-protect | |
102 (progn | |
103 (setq buffer (generate-new-buffer " *mailcrypt temp")) | |
104 (call-process mc-pgp-path nil buffer nil | |
105 "+language=en" "-kv" str keyring) | |
106 (set-buffer buffer) | |
107 (goto-char (point-min)) | |
108 (if (re-search-forward key-regexp nil t) | |
109 (progn | |
110 (setq result | |
111 (cons (buffer-substring-no-properties | |
112 (match-beginning 3) (match-end 3)) | |
113 (concat | |
114 "0x" | |
115 (buffer-substring-no-properties | |
116 (match-beginning 2) (match-end 2))))) | |
117 (setq mc-pgp-key-cache (cons (cons str result) | |
118 mc-pgp-key-cache))))) | |
119 (if buffer (kill-buffer buffer)) | |
120 (set-buffer obuf))) | |
121 (if (null result) | |
122 (error "No PGP secret key for %s" str)) | |
123 result))) | |
124 | |
125 (defun mc-pgp-generic-parser (result) | |
126 (let (start) | |
127 (goto-char (point-min)) | |
128 (cond ((not (eq result 0)) | |
129 (prog1 | |
130 nil | |
131 (if (mc-message "^\aError: +Bad pass phrase\\.$" (current-buffer)) | |
132 (mc-deactivate-passwd t) | |
133 (mc-message mc-pgp-error-re (current-buffer) | |
134 (format "PGP exited with status %d" result))))) | |
135 ((re-search-forward mc-pgp-nokey-re nil t) | |
136 nil) | |
137 (t | |
138 (and | |
139 (goto-char (point-min)) | |
140 (re-search-forward "-----BEGIN PGP.*-----$" nil t) | |
141 (setq start (match-beginning 0)) | |
142 (goto-char (point-max)) | |
143 (re-search-backward "^-----END PGP.*-----\n" nil t) | |
144 (cons start (match-end 0))))))) | |
145 | |
146 (defun mc-pgp-encrypt-region (recipients start end &optional id sign) | |
147 (let ((process-environment process-environment) | |
148 (buffer (get-buffer-create mc-buffer-name)) | |
149 ;; Crock. Rewrite someday. | |
150 (mc-pgp-always-sign mc-pgp-always-sign) | |
151 (obuf (current-buffer)) | |
152 action msg args key passwd result pgp-id) | |
153 (setq args (list "+encrypttoself=off +verbose=1" "+batchmode" | |
154 "+language=en" "-fat")) | |
155 (setq action (if recipients "Encrypting" "Armoring")) | |
156 (setq msg (format "%s..." action)) ; May get overridden below | |
157 (if recipients (setq args (cons "-e" args))) | |
158 (if mc-pgp-comment | |
159 (setq args (cons (format "+comment=%s" mc-pgp-comment) args))) | |
160 (if mc-pgp-alternate-keyring | |
161 (setq args (append args (list (format "+pubring=%s" | |
162 mc-pgp-alternate-keyring))))) | |
163 (if (and (not (eq mc-pgp-always-sign 'never)) | |
164 (or mc-pgp-always-sign sign (y-or-n-p "Sign the message? "))) | |
165 (progn | |
166 (setq mc-pgp-always-sign t) | |
167 (setq key (mc-pgp-lookup-key (or id mc-pgp-user-id))) | |
168 (setq passwd | |
169 (mc-activate-passwd | |
170 (cdr key) | |
171 (format "PGP passphrase for %s (%s): " (car key) (cdr key)))) | |
172 (setq args | |
173 (nconc args (list "-s" "-u" (cdr key)))) | |
174 (setenv "PGPPASSFD" "0") | |
175 (setq msg (format "%s+signing as %s ..." action (car key)))) | |
176 (setq mc-pgp-always-sign 'never)) | |
177 | |
178 (or key | |
179 (setq key (mc-pgp-lookup-key mc-pgp-user-id))) | |
180 | |
181 (if (and recipients mc-encrypt-for-me) | |
182 (setq recipients (cons (cdr key) recipients))) | |
183 | |
184 (setq args (append args recipients)) | |
185 | |
186 (message "%s" msg) | |
187 (setq result (mc-process-region start end passwd mc-pgp-path args | |
188 'mc-pgp-generic-parser buffer)) | |
189 (save-excursion | |
190 (set-buffer buffer) | |
191 (goto-char (point-min)) | |
192 (if (re-search-forward mc-pgp-nokey-re nil t) | |
193 (progn | |
194 (if result (error "This should never happen.")) | |
195 (setq pgp-id (buffer-substring-no-properties | |
196 (match-beginning 1) (match-end 1))) | |
197 (if (and (not (eq mc-pgp-always-fetch 'never)) | |
198 (or mc-pgp-always-fetch | |
199 (y-or-n-p | |
200 (format "Key for '%s' not found; try to fetch? " | |
201 pgp-id)))) | |
202 (progn | |
203 (mc-pgp-fetch-key (cons pgp-id nil)) | |
204 (set-buffer obuf) | |
205 (mc-pgp-encrypt-region recipients start end id)) | |
206 (mc-message mc-pgp-nokey-re buffer) | |
207 nil)) | |
208 (if (not result) | |
209 nil | |
210 (message "%s Done." msg) | |
211 t))))) | |
212 | |
213 (defun mc-pgp-decrypt-parser (result) | |
214 (goto-char (point-min)) | |
215 (cond ((eq result 0) | |
216 ;; Valid signature | |
217 (re-search-forward "^Signature made.*\n") | |
218 (if (looking-at | |
219 "\a\nWARNING: Because this public key.*\n.*\n.*\n") | |
220 (goto-char (match-end 0))) | |
221 (cons (point) (point-max))) | |
222 ((eq result 1) | |
223 (re-search-forward | |
224 "\\(\\(^File is conven.*\\)?Just a moment\\.+\\)\\|\\(^\\.\\)") | |
225 (if (eq (match-beginning 2) (match-end 2)) | |
226 (if (looking-at | |
227 "\nFile has signature.*\\(\n\a.*\n\\)*\nWARNING:.*\n") | |
228 (goto-char (match-end 0))) | |
229 (if (looking-at "Pass phrase appears good\\. \\.") | |
230 (goto-char (match-end 0)))) | |
231 (cons (point) (point-max))) | |
232 (t nil))) | |
233 | |
234 (defun mc-pgp-decrypt-region (start end &optional id) | |
235 ;; returns a pair (SUCCEEDED . VERIFIED) where SUCCEEDED is t if | |
236 ;; the decryption succeeded and verified is t if there was a valid signature | |
237 (let ((process-environment process-environment) | |
238 (buffer (get-buffer-create mc-buffer-name)) | |
239 args key new-key passwd result pgp-id) | |
240 (undo-boundary) | |
241 (setq key (mc-pgp-lookup-key (or id mc-pgp-user-id))) | |
242 (setq | |
243 passwd | |
244 (if key | |
245 (mc-activate-passwd (cdr key) | |
246 (and id | |
247 (format "PGP passphrase for %s (%s): " | |
248 (car key) (cdr key)))) | |
249 (mc-activate-passwd id "PGP passphrase for conventional decryption: "))) | |
250 (if passwd | |
251 (setenv "PGPPASSFD" "0")) | |
252 (setq args '("+verbose=1" "+batchmode" "+language=en" "-f")) | |
253 (if mc-pgp-alternate-keyring | |
254 (setq args (append args (list (format "+pubring=%s" | |
255 mc-pgp-alternate-keyring))))) | |
256 (message "Decrypting...") | |
257 (setq result | |
258 (mc-process-region | |
259 start end passwd mc-pgp-path args 'mc-pgp-decrypt-parser buffer)) | |
260 (cond | |
261 (result | |
262 (message "Decrypting... Done.") | |
263 ;; If verification failed due to missing key, offer to fetch it. | |
264 (save-excursion | |
265 (set-buffer buffer) | |
266 (goto-char (point-min)) | |
267 (if (re-search-forward mc-pgp-key-expected-re nil t) | |
268 (setq pgp-id (concat "0x" (buffer-substring-no-properties | |
269 (match-beginning 1) | |
270 (match-end 1)))))) | |
271 (if (and pgp-id | |
272 (not (eq mc-pgp-always-fetch 'never)) | |
273 (or mc-pgp-always-fetch | |
274 (y-or-n-p | |
275 (format "Key %s not found; attempt to fetch? " pgp-id))) | |
276 (mc-pgp-fetch-key (cons nil pgp-id))) | |
277 (progn | |
278 (undo-start) | |
279 (undo-more 1) | |
280 (mc-pgp-decrypt-region start end id)) | |
281 (mc-message mc-pgp-key-expected-re buffer) | |
282 (cons t (eq result 0)))) | |
283 ;; Decryption failed; maybe we need to use a different user-id | |
284 ((save-excursion | |
285 (and | |
286 (set-buffer buffer) | |
287 (goto-char (point-min)) | |
288 (re-search-forward | |
289 "^Key for user ID:.*\n.*Key ID \\([0-9A-F]+\\)" nil t) | |
290 (setq new-key | |
291 (mc-pgp-lookup-key | |
292 (concat "0x" (buffer-substring-no-properties | |
293 (match-beginning 1) | |
294 (match-end 1))))) | |
295 (not (and id (equal key new-key))))) | |
296 (mc-pgp-decrypt-region start end (cdr new-key))) | |
297 ;; Or maybe it is conventionally encrypted | |
298 ((save-excursion | |
299 (and | |
300 (set-buffer buffer) | |
301 (goto-char (point-min)) | |
302 (re-search-forward "^File is conventionally encrypted" nil t))) | |
303 (if (null key) (mc-deactivate-passwd t)) | |
304 (mc-pgp-decrypt-region start end "***** CONVENTIONAL *****")) | |
305 (t | |
306 (mc-display-buffer buffer) | |
307 (if (mc-message "^\aError: +Bad pass phrase\\.$" buffer) | |
308 (mc-deactivate-passwd t) | |
309 (mc-message mc-pgp-error-re buffer "Error decrypting buffer")) | |
310 (cons nil nil))))) | |
311 | |
312 (defun mc-pgp-sign-region (start end &optional id unclear) | |
313 (let ((process-environment process-environment) | |
314 (buffer (get-buffer-create mc-buffer-name)) | |
315 passwd args key) | |
316 (setq key (mc-pgp-lookup-key (or id mc-pgp-user-id))) | |
317 (setq passwd | |
318 (mc-activate-passwd | |
319 (cdr key) | |
320 (format "PGP passphrase for %s (%s): " (car key) (cdr key)))) | |
321 (setenv "PGPPASSFD" "0") | |
322 (setq args | |
323 (list | |
324 "-fast" "+verbose=1" "+language=en" | |
325 (format "+clearsig=%s" (if unclear "off" "on")) | |
326 "+batchmode" "-u" (cdr key))) | |
327 (if mc-pgp-comment | |
328 (setq args (cons (format "+comment=%s" mc-pgp-comment) args))) | |
329 (message "Signing as %s ..." (car key)) | |
330 (if (mc-process-region start end passwd mc-pgp-path args | |
331 'mc-pgp-generic-parser buffer) | |
332 (progn | |
333 (message "Signing as %s ... Done." (car key)) | |
334 t) | |
335 nil))) | |
336 | |
337 (defun mc-pgp-verify-parser (result) | |
338 (cond ((eq result 0) | |
339 (mc-message mc-pgp-sigok-re (current-buffer) "Good signature") | |
340 t) | |
341 ((eq result 1) | |
342 (mc-message mc-pgp-error-re (current-buffer) "Bad signature") | |
343 nil) | |
344 (t | |
345 (mc-message mc-pgp-error-re (current-buffer) | |
346 (format "PGP exited with status %d" result)) | |
347 nil))) | |
348 | |
349 (defun mc-pgp-verify-region (start end &optional no-fetch) | |
350 (let ((buffer (get-buffer-create mc-buffer-name)) | |
351 (obuf (current-buffer)) | |
352 args pgp-id) | |
353 (setq args '("+verbose=1" "+batchmode" "+language=en" "-f")) | |
354 (if mc-pgp-alternate-keyring | |
355 (setq args (append args (list (format "+pubring=%s" | |
356 mc-pgp-alternate-keyring))))) | |
357 (message "Verifying...") | |
358 (if (mc-process-region | |
359 start end nil mc-pgp-path args 'mc-pgp-verify-parser buffer) | |
360 t | |
361 (save-excursion | |
362 (set-buffer buffer) | |
363 (goto-char (point-min)) | |
364 (if (and | |
365 (not no-fetch) | |
366 (re-search-forward mc-pgp-key-expected-re nil t) | |
367 (setq pgp-id | |
368 (concat "0x" (buffer-substring-no-properties | |
369 (match-beginning 1) | |
370 (match-end 1)))) | |
371 (not (eq mc-pgp-always-fetch 'never)) | |
372 (or mc-pgp-always-fetch | |
373 (y-or-n-p | |
374 (format "Key %s not found; attempt to fetch? " pgp-id))) | |
375 (mc-pgp-fetch-key (cons nil pgp-id)) | |
376 (set-buffer obuf)) | |
377 (mc-pgp-verify-region start end t) | |
378 (mc-message mc-pgp-error-re buffer) | |
379 nil))))) | |
380 | |
381 (defun mc-pgp-insert-public-key (&optional id) | |
382 (let ((buffer (get-buffer-create mc-buffer-name)) | |
383 args) | |
384 (setq id (or id mc-pgp-user-id)) | |
385 (setq args (list "+verbose=1" "+batchmode" "+language=en" "-kxaf" id)) | |
386 (if mc-pgp-comment | |
387 (setq args (cons (format "+comment=%s" mc-pgp-comment) args))) | |
388 (if mc-pgp-alternate-keyring | |
389 (setq args (append args (list (format "+pubring=%s" | |
390 mc-pgp-alternate-keyring))))) | |
391 | |
392 (if (mc-process-region (point) (point) nil mc-pgp-path | |
393 args 'mc-pgp-generic-parser buffer) | |
394 (progn | |
395 (mc-message "Key for user ID: .*" buffer) | |
396 t)))) | |
397 | |
398 (defun mc-pgp-snarf-parser (result) | |
399 (eq result 0)) | |
400 | |
401 (defun mc-pgp-snarf-keys (start end) | |
402 ;; Returns number of keys found. | |
403 (let ((buffer (get-buffer-create mc-buffer-name)) tmpstr args) | |
404 (setq args '("+verbose=1" "+batchmode" "+language=en" "-kaf")) | |
405 (if mc-pgp-alternate-keyring | |
406 (setq args (append args (list (format "+pubring=%s" | |
407 mc-pgp-alternate-keyring))))) | |
408 (message "Snarfing...") | |
409 (if (mc-process-region start end nil mc-pgp-path args | |
410 'mc-pgp-snarf-parser buffer) | |
411 (save-excursion | |
412 (set-buffer buffer) | |
413 (goto-char (point-min)) | |
414 (if (re-search-forward mc-pgp-newkey-re nil t) | |
415 (progn | |
416 (if mc-pgp-display-snarf-output (mc-display-buffer buffer)) | |
417 (setq tmpstr (buffer-substring-no-properties | |
418 (match-beginning 1) | |
419 (match-end 1))) | |
420 (if (equal tmpstr "No") | |
421 0 | |
422 (car (read-from-string tmpstr)))))) | |
423 (mc-display-buffer buffer) | |
424 (mc-message mc-pgp-error-re buffer "Error snarfing PGP keys") | |
425 0))) | |
426 | |
427 ;;;###autoload | |
428 (defun mc-scheme-pgp () | |
429 (list | |
430 (cons 'encryption-func 'mc-pgp-encrypt-region) | |
431 (cons 'decryption-func 'mc-pgp-decrypt-region) | |
432 (cons 'signing-func 'mc-pgp-sign-region) | |
433 (cons 'verification-func 'mc-pgp-verify-region) | |
434 (cons 'key-insertion-func 'mc-pgp-insert-public-key) | |
435 (cons 'snarf-func 'mc-pgp-snarf-keys) | |
436 (cons 'msg-begin-line mc-pgp-msg-begin-line) | |
437 (cons 'msg-end-line mc-pgp-msg-end-line) | |
438 (cons 'signed-begin-line mc-pgp-signed-begin-line) | |
439 (cons 'signed-end-line mc-pgp-signed-end-line) | |
440 (cons 'key-begin-line mc-pgp-key-begin-line) | |
441 (cons 'key-end-line mc-pgp-key-end-line) | |
442 (cons 'user-id mc-pgp-user-id))) | |
443 | |
444 ;;{{{ Key fetching | |
445 | |
446 (defvar mc-pgp-always-fetch nil | |
447 "*If t, always attempt to fetch missing keys, or never fetch if | |
448 'never.") | |
449 | |
450 (defvar mc-pgp-keyserver-url-template | |
451 "/htbin/pks-extract-key.pl?op=get&search=%s" | |
452 "The URL to pass to the keyserver.") | |
453 | |
454 (defvar mc-pgp-keyserver-address "pgp.ai.mit.edu" | |
455 "Host name of keyserver.") | |
456 | |
457 (defvar mc-pgp-keyserver-port 80 | |
458 "Port on which the keyserver's HTTP daemon lives.") | |
459 | |
460 (defvar mc-pgp-fetch-timeout 20 | |
461 "*Timeout, in seconds, for any particular key fetch operation.") | |
462 | |
463 (defvar mc-pgp-fetch-keyring-list nil | |
464 "*List of strings which are filenames of public keyrings to search | |
465 when fetching keys.") | |
466 | |
467 (defsubst mc-pgp-buffer-get-key (buf) | |
468 "Return the first key block in BUF as a string, or nil if none found." | |
469 (save-excursion | |
470 (let (start) | |
471 (set-buffer buf) | |
472 (goto-char (point-min)) | |
473 (and (re-search-forward mc-pgp-key-begin-line nil t) | |
474 (setq start (match-beginning 0)) | |
475 (re-search-forward mc-pgp-key-end-line nil t) | |
476 (buffer-substring-no-properties start (match-end 0)))))) | |
477 | |
478 (defun mc-pgp-fetch-from-keyrings (id) | |
479 (let ((keyring-list mc-pgp-fetch-keyring-list) | |
480 buf proc key) | |
481 (unwind-protect | |
482 (progn | |
483 (message "Fetching %s from keyrings..." (or (cdr id) (car id))) | |
484 (while (and (not key) keyring-list) | |
485 (setq buf (generate-new-buffer " *mailcrypt temp*")) | |
486 (setq proc | |
487 (start-process "*PGP*" buf mc-pgp-path "-kxaf" | |
488 "+verbose=0" "+batchmode" | |
489 (format "+pubring=%s" (car keyring-list)) | |
490 (or (cdr id) (car id)))) | |
491 ;; Because PGPPASSFD might be set | |
492 (process-send-string proc "\r\n") | |
493 (while (eq 'run (process-status proc)) | |
494 (accept-process-output proc 5)) | |
495 (setq key (mc-pgp-buffer-get-key buf)) | |
496 (setq keyring-list (cdr keyring-list))) | |
497 key) | |
498 (if buf (kill-buffer buf)) | |
499 (if (and proc (eq 'run (process-status proc))) | |
500 (interrupt-process proc))))) | |
501 | |
502 (defun mc-pgp-fetch-from-http (id) | |
503 (let (buf connection) | |
504 (unwind-protect | |
505 (progn | |
506 (message "Fetching %s via HTTP to %s..." | |
507 (or (cdr id) (car id)) mc-pgp-keyserver-address) | |
508 (setq buf (generate-new-buffer " *mailcrypt temp*")) | |
509 (setq connection | |
510 (open-network-stream "*key fetch*" buf mc-pgp-keyserver-address | |
511 mc-pgp-keyserver-port)) | |
512 (process-send-string | |
513 connection | |
514 (concat "GET " (format mc-pgp-keyserver-url-template | |
515 (or (cdr id) (car id))) "\r\n")) | |
516 (while (and (eq 'open (process-status connection)) | |
517 (accept-process-output connection mc-pgp-fetch-timeout))) | |
518 (mc-pgp-buffer-get-key buf)) | |
519 (if buf (kill-buffer buf)) | |
520 (if connection (delete-process connection))))) | |
521 | |
522 (defun mc-pgp-fetch-from-finger (id) | |
523 (let (buf connection user host) | |
524 (unwind-protect | |
525 (and (car id) | |
526 (string-match "^\\(.+\\)@\\([^@]+\\)$" (car id)) | |
527 (progn | |
528 (message "Trying finger %s..." (car id)) | |
529 (setq user (substring (car id) | |
530 (match-beginning 1) (match-end 1))) | |
531 (setq host (substring (car id) | |
532 (match-beginning 2) (match-end 2))) | |
533 (setq buf (generate-new-buffer " *mailcrypt temp*")) | |
534 (condition-case nil | |
535 (progn | |
536 (setq connection | |
537 (open-network-stream "*key fetch*" buf host 79)) | |
538 (process-send-string connection | |
539 (concat "/W " user "\r\n")) | |
540 (while | |
541 (and (eq 'open (process-status connection)) | |
542 (accept-process-output connection | |
543 mc-pgp-fetch-timeout))) | |
544 (mc-pgp-buffer-get-key buf)) | |
545 (error nil)))) | |
546 (if buf (kill-buffer buf)) | |
547 (if connection (delete-process connection))))) | |
548 | |
549 (defvar mc-pgp-fetch-methods '(mc-pgp-fetch-from-keyrings | |
550 mc-pgp-fetch-from-finger | |
551 mc-pgp-fetch-from-http) | |
552 "List of methods to try when attempting to fetch a key. Each | |
553 element is a function to call with an ID as argument. See the | |
554 documentation for the function mc-pgp-fetch-key for a description of | |
555 the ID.") | |
556 | |
557 ;;;###autoload | |
558 (defun mc-pgp-fetch-key (&optional id) | |
559 "Attempt to fetch a key for addition to PGP keyring. Interactively, | |
560 prompt for string matching key to fetch. | |
561 | |
562 Non-interactively, ID must be a pair. The CAR must be a bare Email | |
563 address and the CDR a keyID (with \"0x\" prefix). Either, but not | |
564 both, may be nil. | |
565 | |
566 Return t if we think we were successful; nil otherwise. Note that nil | |
567 is not necessarily an error, since we may have merely fired off an Email | |
568 request for the key." | |
569 (interactive) | |
570 (let ((methods mc-pgp-fetch-methods) | |
571 (process-connection-type nil) key proc buf args) | |
572 (if (null id) | |
573 (setq id (cons (read-string "Fetch key for: ") nil))) | |
574 (while (and (not key) methods) | |
575 (setq key (funcall (car methods) id)) | |
576 (setq methods (cdr methods))) | |
577 (if (not (stringp key)) | |
578 (progn | |
579 (message "Key not found.") | |
580 nil) | |
581 ;; Maybe I'll do this right someday. | |
582 (unwind-protect | |
583 (save-window-excursion | |
584 (setq buf (generate-new-buffer " *PGP Key Info*")) | |
585 (pop-to-buffer buf) | |
586 (if (< (window-height) (/ (frame-height) 2)) | |
587 (enlarge-window (- (/ (frame-height) 2) | |
588 (window-height)))) | |
589 (setq args '("-f" "+verbose=0" "+batchmode")) | |
590 (if mc-pgp-alternate-keyring | |
591 (setq args | |
592 (append args (list (format "+pubring=%s" | |
593 mc-pgp-alternate-keyring))))) | |
594 | |
595 (setq proc (apply 'start-process "*PGP*" buf mc-pgp-path args)) | |
596 ;; Because PGPPASSFD might be set | |
597 (process-send-string proc "\r\n") | |
598 (process-send-string proc key) | |
599 (process-send-string proc "\r\n") | |
600 (process-send-eof proc) | |
601 (set-buffer buf) | |
602 (while (eq 'run (process-status proc)) | |
603 (accept-process-output proc 5) | |
604 (goto-char (point-min))) | |
605 (if (y-or-n-p "Add this key to keyring? ") | |
606 (progn | |
607 (setq args (append args '("-ka"))) | |
608 (setq proc | |
609 (apply 'start-process "*PGP*" buf mc-pgp-path args)) | |
610 ;; Because PGPPASSFD might be set | |
611 (process-send-string proc "\r\n") | |
612 (process-send-string proc key) | |
613 (process-send-string proc "\r\n") | |
614 (process-send-eof proc) | |
615 (while (eq 'run (process-status proc)) | |
616 (accept-process-output proc 5)) | |
617 t))) | |
618 (if buf (kill-buffer buf)))))) | |
619 | |
620 ;;}}} |