1 ;;; mew-pgp.el --- PGP/MIME for Mew
3 ;; Author: Kazu Yamamoto <Kazu@Mew.org>
4 ;; Created: Aug 17, 1994
5 ;; Revised: Aug 30, 1999
9 (defconst mew-pgp-version "mew-pgp.el version 0.48")
13 (if (mew-which-el "timer" load-path)
17 ;;; PGP 2.6.x is supported.
18 ;;; PGP 5.x is supported. But very ad-hoc.
19 ;;; GNUPG 0.9.x is supported. But very ad-hoc.
22 (defvar mew-pgp-ver nil
23 "Automatically set 0 if PGP version is 2. Set 1 if 5. Set 2 if GNUPG.")
25 (defconst mew-pgp-ver2 0)
26 (defconst mew-pgp-ver5 1)
27 (defconst mew-pgp-verg 2)
28 (defconst mew-pgp-list '("PGPv2" "PGPv5" "GNUPG"))
29 (defconst mew-pgp-keys '(pgpv2 pgpv5 gnupg)) ;; use symbols, cases are string
31 ;; mew-prog-pgp is used only for version check
32 (defvar mew-prog-pgp2 "pgp") ;; "pgp263i", PGP selection
33 (defvar mew-prog-pgp5 "pgp") ;; PGP selection
34 (defvar mew-prog-pgp5e "pgpe")
35 (defvar mew-prog-pgp5s "pgps")
36 (defvar mew-prog-pgp5v "pgpv")
37 (defvar mew-prog-pgp5k "pgpk")
38 (defvar mew-prog-gpg "gpg") ;; PGP selection
40 (defvar mew-prog-pgpe (list mew-prog-pgp2 mew-prog-pgp5e mew-prog-gpg))
41 (defvar mew-prog-pgps (list mew-prog-pgp2 mew-prog-pgp5s mew-prog-gpg))
42 (defvar mew-prog-pgpv (list mew-prog-pgp2 mew-prog-pgp5v mew-prog-gpg))
43 (defvar mew-prog-pgpd (list mew-prog-pgp2 mew-prog-pgp5v mew-prog-gpg))
44 (defvar mew-prog-pgpk (list mew-prog-pgp2 mew-prog-pgp5k mew-prog-gpg))
46 (defconst mew-prog-pgpe-arg
47 '(("-ea" "+language=en" "+batchmode=on" "+armorlines=0")
48 ("-a" "+language=en" "+batchmode=on" "+armorlines=0")
49 ("--encrypt" "--armor" "--batch")))
50 (defconst mew-prog-pgpd-arg
51 '(("+language=en" "+batchmode=off")
52 ("+language=en" "+batchmode=off")
54 (defconst mew-prog-pgps-arg
55 '(("-sba" "+language=en" "+batchmode=off")
56 ("-ba" "+language=en" "+batchmode=off")
57 ("--detach-sign" "--armor")))
58 (defconst mew-prog-pgpv-arg
59 '(("+batchmode=on" "+language=en")
60 ("+batchmode=on" "+language=en" "+force=on")
61 ("--verify" "--batch")))
63 (defconst mew-prog-arg-output '("-o" "-o" "--output"))
64 (defconst mew-prog-arg-input '(nil "-o" nil))
65 (defconst mew-prog-arg-luserid '("-u" "-u" "--local-user"))
66 (defconst mew-prog-arg-ruserid '(nil "-r" "--remote-user"))
68 (defconst mew-prog-pgpk-add-arg
69 '(("-ka" "+batchmode=on") ("-a" "+batchmode=on") ("--import" "--batch")))
70 (defconst mew-prog-pgpk-ext-arg
71 '(("-kxfa") ("-xa") ("--export" "--armor" "--batch")))
73 (defconst mew-pgp-msg-signature
74 '("\n\\(.*\\) signature from user \\(.*\\)\\."
75 "\n\\(.*\\) signature made"
76 " \\(.*\\) signature from \"\\(.*\\)\""))
78 (defconst mew-pgp-msg-key-id
79 '("Key ID \\(\\S +\\) not found"
80 ": \\(0x[0-9A-Za-z]+\\)"
82 (defconst mew-pgp-msg-bad-pass
83 '("No passphrase" "Cannot unlock private key\\|It can only be decrypted" "bad passphrase"))
84 (defconst mew-pgp-msg-enter
85 '("Enter" "Enter" "xxx"))
86 (defconst mew-pgp-msg-enter-pass
87 '("Enter pass phrase: " "Enter pass phrase: " "Enter passphrase: "))
88 (defconst mew-pgp-msg-reenter-pass
89 '("Enter pass phrase: " "Enter pass phrase: " "Enter passphrase: "))
90 (defconst mew-pgp-msg-no-enckey
91 '("Key matching" "No encryption keys" "public key not found"))
92 (defconst mew-pgp-msg-no-validkey
93 '("DUMMY" "^WARNING:[ -9;-~\n]+belongs? to:" "no info to calculate a trust probability")) ;;xxx
94 (defconst mew-pgp-msg-no-vrfkey
95 '("Key matching" "unknown keyid" "public key not found"))
96 (defconst mew-pgp-msg-no-keyring
97 '("Keyring file" "Keyring file" "public key not found"))
98 (defconst mew-pgp-msg-no-seckey-or-secring
99 '("You do not have the secret key"
100 "Cannot find a private key"
101 ": decryption failed: secret key not available"))
102 (defconst mew-pgp-msg-unsupported
103 '("Unsupported packet format" ;; including algorithms and packets
104 "Unsupported packet format\\|None of the signatures were understood"
106 (defconst mew-pgp-verify-addr
107 '(".* \\(signature from user\\) " "\\( \\)" "gpg: .* \\(from\\|aka\\) "))
109 ;; 2: ASCII armor corrupted
113 ;; 2: ERROR: or Error:
115 (defconst mew-pgp-msg-no-export-key
116 '("Key not found" "No keys" "nothing exported"))
118 (defvar mew-pgp-micalg '("pgp-md5" "pgp-sha1" "pgp-sha1"))
123 (defvar mew-pgp-string nil)
124 (defvar mew-pgp-running nil)
125 (defvar mew-pgp-failure nil)
127 (defvar mew-pgp-decrypt-msg nil)
128 (defvar mew-pgp-sign-msg nil)
130 (defconst mew-pgp-encryption-begin "-----BEGIN PGP MESSAGE-----")
131 (defconst mew-pgp-signature-begin "-----BEGIN PGP SIGNED MESSAGE-----")
132 (defconst mew-pgp-key-begin "-----BEGIN PGP PUBLIC KEY BLOCK-----")
133 (defconst mew-pgp-key-end "-----END PGP PUBLIC KEY BLOCK-----")
135 (defconst mew-pgp-err-pass 'mew-err-pass)
136 (defconst mew-pgp-err-pubring 'mew-err-pubring)
137 (defconst mew-pgp-err-secring 'mew-err-secring)
138 (defconst mew-pgp-err-pubkey 'mew-err-pubkey)
139 (defconst mew-pgp-err-seckey 'mew-err-seckey)
140 (defconst mew-pgp-err-seckey-or-secring 'mew-err-seckey-or-secring)
141 (defconst mew-pgp-err-other 'mew-err-other)
143 (defvar mew-pgp-result-pass "Pass phrase is wrong.")
144 (defvar mew-pgp-result-pubring "No public keyring.")
145 (defvar mew-pgp-result-secring "No secret keyring.")
146 (defvar mew-pgp-result-pubkey "No his/her public key.")
147 (defvar mew-pgp-result-invalid
148 "His/her public key is invalid. Sign the key by yourself, first.")
149 (defvar mew-pgp-result-seckey "No your secret key.")
150 (defvar mew-pgp-result-seckey-or-secring
151 "PGP NOT decrypted due to no secret keyring or no your secret key.")
152 (defvar mew-pgp-result-other "PGP failed for some reasons.")
153 (defvar mew-pgp-result-sec-succ "PGP decrypted. ")
154 (defvar mew-pgp-result-dec-fail "PGP NOT decrypted for some reasons.")
155 (defvar mew-pgp-result-unsup "PGP unsupported signature.")
157 (defvar mew-pgp-prompt-enter-pass "Enter pass phrase (%s): ")
158 (defvar mew-pgp-prompt-reenter-pass "Re-enter pass phrase (%s): ")
160 (defmacro mew-pgp-get (list-or-vec)
161 (` (elt (, list-or-vec) mew-pgp-ver)))
162 (defmacro mew-pgp-set (vec val)
163 (` (aset (, vec) mew-pgp-ver (, val))))
165 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
170 (defun mew-pgp-set-version ()
171 (if (not (mew-which mew-prog-pgp exec-path))
172 (setq mew-pgp-ver nil)
175 (call-process mew-prog-pgp nil t nil)
176 (goto-char (point-min))
177 (if (search-forward "PGP is now invoked" nil t)
178 (setq mew-pgp-ver mew-pgp-ver5)
179 (goto-char (point-min))
180 (if (search-forward "Pretty Good Privacy(tm) 2" nil t)
181 (setq mew-pgp-ver mew-pgp-ver2)
182 (goto-char (point-min))
183 (if (search-forward "gpg" nil t)
184 (setq mew-pgp-ver mew-pgp-verg)
185 (setq mew-pgp-ver nil)))))))
187 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
192 (defun mew-pgp-select ()
193 "Select PGP version and set up environment for selected PGP."
198 (mapcar (function (lambda (x) (cons x x)))
199 (list mew-prog-pgp2 mew-prog-pgp5 mew-prog-gpg))
201 (mew-pgp-set-version))
203 (defun mew-pgp-passphrase (&optional again)
204 (let ((prompt (if again
205 mew-pgp-prompt-reenter-pass
206 mew-pgp-prompt-enter-pass)))
207 (setq prompt (format prompt (mew-pgp-get mew-pgp-list)))
208 (if mew-use-pgp-cached-passphrase
209 (mew-input-passwd prompt (mew-pgp-get mew-pgp-keys))
210 (mew-input-passwd prompt))))
212 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
217 (defun mew-pgp-verify-check ()
219 (goto-char (point-min))
220 (if (not (re-search-forward (mew-pgp-get mew-pgp-msg-signature) nil t))
221 ;; this is verification, so the error is about public key
223 (goto-char (point-min))
224 (if (search-forward (mew-pgp-get mew-pgp-msg-no-vrfkey) nil t)
226 (goto-char (point-min))
227 (if (not (re-search-forward (mew-pgp-get mew-pgp-msg-key-id) nil t))
228 (setq keyid "not found")
229 (setq keyid (mew-buffer-substring
230 (match-beginning 1) (match-end 1)))
231 (if (equal mew-pgp-ver mew-pgp-ver2) ;; xxx
232 (setq keyid (concat "0x" keyid))))
233 (setq ret (concat mew-pgp-result-pubkey " ID = " keyid)))
234 (goto-char (point-min))
235 (if (search-forward (mew-pgp-get mew-pgp-msg-no-keyring) nil t)
236 (setq ret mew-pgp-result-pubring)
237 (goto-char (point-min))
238 (if (re-search-forward (mew-pgp-get mew-pgp-msg-unsupported) nil t)
239 (setq ret mew-pgp-result-unsup)
240 ;; this line must be nil since this function is used
241 ;; by the decryption function, too, for signed-then-encrypted
242 ;; messages. We can't tell whether or not signatures exist
243 ;; from the outside of the cipher.
245 ;; Signature result is found.
246 (setq ret (concat (mew-match 1) " PGP sign "))
247 (goto-char (point-max))
248 (if (and (boundp 'mew-inherit-from) mew-inherit-from
249 (re-search-backward (concat (concat (mew-pgp-get mew-pgp-verify-addr) ".*") mew-inherit-from) nil t))
252 (looking-at (concat (mew-pgp-get mew-pgp-verify-addr) "\\(.*\\)"))
253 (setq ret (concat ret (mew-match 2))))
254 (goto-char (point-max))
255 (re-search-backward (concat (mew-pgp-get mew-pgp-verify-addr) "\\(.*\\)") nil t)
256 (setq ret (concat ret (mew-match 2))))
258 (goto-char (point-min))
259 (if (search-forward "not certified with enough" nil t)
260 (setq ret (concat ret " MARGINAL"))
261 (goto-char (point-min))
262 (if (search-forward "not trusted" nil t)
263 (setq ret (concat ret " UNTRUSTED"))
264 (goto-char (point-min))
265 (if (search-forward "not certified with a" nil t)
266 ;; PGP uses "unknown" for validity internally, but
267 ;; prints "undefined" instead of "unknown".
268 (setq ret (concat ret " UNDEFINED"))
269 (setq ret (concat ret " COMPLETE"))))))
272 (defun mew-pgp-verify (file1 file2)
273 (message "PGP verifying ... ")
274 (let ((ioption (mew-pgp-get mew-prog-arg-input)))
278 (apply (function call-process)
279 (mew-pgp-get mew-prog-pgpv)
281 (append (mew-pgp-get mew-prog-pgpv-arg)
282 (list ioption file1 file2)))
283 (apply (function call-process)
284 (mew-pgp-get mew-prog-pgpv)
286 (append (mew-pgp-get mew-prog-pgpv-arg)
287 (list file2 file1))))
288 (message "PGP verifying ... done")
289 (mew-pgp-verify-check))))
291 (defun mew-pgp-verify-old (file)
292 (message "PGP verifying ... ")
295 (let ((file1 (mew-make-temp-name)))
296 (apply (function call-process)
297 (mew-pgp-get mew-prog-pgpv)
299 (append (mew-pgp-get mew-prog-pgpv-arg)
300 (list (mew-pgp-get mew-prog-arg-output) file1 file)))
301 (message "PGP verifying ... done")
302 (list file1 (mew-pgp-verify-check)))))
304 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
309 (defun mew-pgp-encrypt-check ()
310 (let (ret) ;; this should be nil
311 (goto-char (point-min))
312 (if (search-forward (mew-pgp-get mew-pgp-msg-no-enckey) nil t)
313 (setq ret mew-pgp-result-pubkey)
314 (goto-char (point-min))
315 (if (search-forward (mew-pgp-get mew-pgp-msg-no-keyring) nil t)
316 (setq ret mew-pgp-result-pubring)
317 (goto-char (point-min))
318 (if (re-search-forward (mew-pgp-get mew-pgp-msg-no-validkey) nil t)
319 (setq ret mew-pgp-result-invalid))))
322 (defun mew-pgp-encrypt (file1 decrypters)
323 (message "PGP encrypting ... ")
324 (let ((roption (mew-pgp-get mew-prog-arg-ruserid))
325 file2 file3) ;; not unique if makes temp here
326 (setq file2 (mew-make-temp-name))
329 (insert "Version: 1\n")
330 (write-region (point-min) (point-max) file2 nil 'no-msg)
331 (setq file3 (concat (mew-make-temp-name) mew-pgp-ascii-suffix))
336 (setq decs (cons (car decrypters) (cons roption decs)))
337 ;; nreverse later, take care.
338 (setq decrypters (cdr decrypters)))
339 (setq decrypters (nreverse decs))
341 (function call-process)
342 (mew-pgp-get mew-prog-pgpe)
344 (append (mew-pgp-get mew-prog-pgpe-arg)
346 (list (mew-pgp-get mew-prog-arg-output) file3 file1))))
347 (apply (function call-process)
348 (mew-pgp-get mew-prog-pgpe)
350 (mew-pgp-get mew-prog-arg-output) file3 file1
351 (append (mew-pgp-get mew-prog-pgpe-arg) decrypters)))
352 (message "PGP encrypting ... done")
353 (list file2 nil file3 nil (mew-pgp-encrypt-check)) ;; both ctes are 7bit
356 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
361 (defun mew-pgp-decrypt (file1 file2)
362 ;; file1 is a key file. just ignore.
363 ;; file2 is an encrypted file with PGP.
364 (message "PGP decrypting ... ")
365 (setq mew-pgp-running 'decrypting)
366 (setq mew-pgp-string nil)
367 (setq mew-pgp-decrypt-msg nil)
368 (setq mew-pgp-failure nil)
369 (let ((process-connection-type mew-connection-type2)
370 file3 process verify)
371 (setq file3 (mew-make-temp-name))
374 (function start-process)
377 (mew-pgp-get mew-prog-pgpd)
378 (append (mew-pgp-get mew-prog-pgpd-arg)
379 (list (mew-pgp-get mew-prog-arg-output) file3 file2))))
380 (mew-set-process-cs process mew-cs-autoconv mew-cs-dummy)
381 (set-process-filter process 'mew-pgp-process-filter1)
382 (set-process-sentinel process 'mew-pgp-process-sentinel)
383 ;; Wait for the termination of PGP.
384 ;; Emacs doesn't provide synchronize mechanism with
385 ;; an asynchronous process. So, take this way.
386 (while mew-pgp-running
388 (accept-process-output)
390 ;; accept-process-output or sleep-for is not enough
392 (message "PGP decrypting ... done")
393 (if (file-exists-p file3)
397 (insert mew-pgp-string)
398 (setq verify (mew-pgp-verify-check)))
400 (setq mew-pgp-decrypt-msg
401 (concat mew-pgp-decrypt-msg "\n\t" verify))))
402 ;; unpredictable error
403 (mew-passwd-set-passwd (mew-pgp-get mew-pgp-keys) nil)
404 (if (equal mew-pgp-decrypt-msg mew-pgp-result-sec-succ)
405 (setq mew-pgp-decrypt-msg mew-pgp-result-dec-fail)))
406 (list file3 mew-pgp-decrypt-msg)))
408 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
413 (defun mew-pgp-sign (file1)
414 (message "PGP signing ... ")
415 (setq mew-pgp-running 'signing)
416 (setq mew-pgp-string nil)
417 (setq mew-pgp-sign-msg nil)
418 (setq mew-pgp-failure nil)
419 (let ((process-connection-type mew-connection-type2)
421 (setq file2 (concat (mew-make-temp-name) mew-pgp-ascii-suffix))
422 ;; not perfectly unique but OK
425 (function start-process)
428 (mew-pgp-get mew-prog-pgps)
429 (append (mew-pgp-get mew-prog-pgps-arg)
430 (list (mew-pgp-get mew-prog-arg-luserid) mew-inherit-signer
431 (mew-pgp-get mew-prog-arg-output) file2 file1))))
432 (mew-set-process-cs process mew-cs-autoconv mew-cs-dummy)
433 (set-process-filter process 'mew-pgp-process-filter1)
434 (set-process-sentinel process 'mew-pgp-process-sentinel)
435 ;; Wait for the termination of PGP.
436 ;; Emacs doesn't provide synchronize mechanism with
437 ;; an asynchronous process. So, take this way.
438 (while mew-pgp-running
440 (accept-process-output)
442 ;; accept-process-output or sleep-for is not enough
444 (message "PGP signing ... done")
445 (if (not (file-exists-p file2)) ;; for unpredictable error
446 (mew-passwd-set-passwd (mew-pgp-get mew-pgp-keys) nil))
447 (list file2 nil (mew-pgp-get mew-pgp-micalg) mew-pgp-sign-msg))) ;; return
449 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
451 ;; PGP process functions
454 (defun mew-pgp-process-sentinel (process event)
455 (let ((decrypted mew-pgp-result-sec-succ)
457 (if (not mew-pgp-failure)
459 ((equal mew-pgp-running 'decrypting)
460 (setq mew-pgp-decrypt-msg decrypted))
461 ((equal mew-pgp-running 'signing)
462 (setq mew-pgp-sign-msg nil)))
465 ((equal mew-pgp-failure mew-pgp-err-pass)
466 (setq msg mew-pgp-result-pass))
467 ;; decrypt-then-verify
468 ((equal mew-pgp-failure mew-pgp-err-pubring)
469 (setq msg decrypted))
470 ;; decrypt-then-vrify
471 ((equal mew-pgp-failure mew-pgp-err-pubkey)
472 (setq msg decrypted))
474 ((equal mew-pgp-failure mew-pgp-err-secring)
475 (setq msg mew-pgp-result-secring))
477 ((equal mew-pgp-failure mew-pgp-err-seckey)
478 (setq msg mew-pgp-result-seckey))
480 ((equal mew-pgp-failure mew-pgp-err-seckey-or-secring)
481 (setq msg mew-pgp-result-seckey-or-secring))
483 (t ;; mew-pgp-err-other or nil
484 (setq msg mew-pgp-result-other)))
486 ((equal mew-pgp-running 'decrypting)
487 (setq mew-pgp-decrypt-msg msg))
488 ((equal mew-pgp-running 'signing)
489 (setq mew-pgp-sign-msg msg))))
490 (setq mew-pgp-running nil)))
492 (defun mew-pgp-process-filter1 (process string)
493 ;; sign or decrypt, not verify
494 (setq mew-pgp-string (concat mew-pgp-string string))
496 ;; no secret key or no secring for decrypt
497 ((string-match (mew-pgp-get mew-pgp-msg-no-seckey-or-secring) string)
498 (setq mew-pgp-failure mew-pgp-err-seckey-or-secring)
499 (set-process-filter process 'mew-pgp-process-filter3))
501 ;; no secring for sign
502 ((string-match (mew-pgp-get mew-pgp-msg-no-keyring) string)
503 (setq mew-pgp-failure mew-pgp-err-secring)
504 ;; Enter secret key filename:
505 (process-send-string process "\n")
506 (set-process-filter process 'mew-pgp-process-filter3))
508 ;; no secret key for sign
509 ((string-match (mew-pgp-get mew-pgp-msg-no-enckey) string)
510 (setq mew-pgp-failure mew-pgp-err-seckey)
511 ;; Enter secret key filename:
512 (process-send-string process "\n")
513 (set-process-filter process 'mew-pgp-process-filter3))
515 ;; pass phrase for sign or decrypt
516 ((string-match (mew-pgp-get mew-pgp-msg-enter-pass) string)
517 (process-send-string process (format "%s\n" (mew-pgp-passphrase)))
518 (set-process-filter process 'mew-pgp-process-filter2))
521 ((string-match (mew-pgp-get mew-pgp-msg-enter) string)
522 (setq mew-pgp-failure mew-pgp-err-other)
524 (process-send-string process "\n")
525 (set-process-filter process 'mew-pgp-process-filter3))))
527 (defun mew-pgp-process-filter2 (process string)
528 (setq mew-pgp-string (concat mew-pgp-string string))
530 ;; re-enter pass phrase
531 ((string-match (mew-pgp-get mew-pgp-msg-reenter-pass) string)
532 (setq mew-pgp-string nil)
533 (mew-passwd-set-passwd (mew-pgp-get mew-pgp-keys) nil) ;; cancel anyway
534 (process-send-string process (format "%s\n" (mew-pgp-passphrase 'again)))
535 (set-process-filter process 'mew-pgp-process-filter2))
537 ;; pass phrases were wrong three times
538 ((string-match (mew-pgp-get mew-pgp-msg-bad-pass) string)
539 (setq mew-pgp-failure mew-pgp-err-pass)
540 (mew-passwd-set-passwd (mew-pgp-get mew-pgp-keys) nil) ;; cancel anyway
541 (set-process-filter process 'mew-pgp-process-filter3))
543 ;; no pubring for verify
544 ((string-match (mew-pgp-get mew-pgp-msg-no-keyring) string)
545 (setq mew-pgp-failure mew-pgp-err-pubring)
546 ;; Enter public key filename:
547 (process-send-string process "\n")
548 (set-process-filter process 'mew-pgp-process-filter3))
550 ;; no public key for verify
551 ((string-match (mew-pgp-get mew-pgp-msg-no-vrfkey) string)
552 (setq mew-pgp-failure mew-pgp-err-pubkey)
553 ;; Enter public key filename:
554 (process-send-string process "\n")
555 (set-process-filter process 'mew-pgp-process-filter3))
557 ;; after decrypted secret key, symmetric key is not uknown...
558 ;; gpg: unknown cipher algorithm
559 ;; no secret key or no secring for decrypt
560 ((string-match (mew-pgp-get mew-pgp-msg-no-seckey-or-secring) string)
561 (setq mew-pgp-failure mew-pgp-err-seckey-or-secring)
562 (set-process-filter process 'mew-pgp-process-filter3))
565 ((string-match (mew-pgp-get mew-pgp-msg-enter) string)
566 (setq mew-pgp-failure mew-pgp-err-other)
568 (process-send-string process "\n")
569 (set-process-filter process 'mew-pgp-process-filter3))))
571 (defun mew-pgp-process-filter3 (process string)
573 (setq mew-pgp-string (concat mew-pgp-string string))
574 ;; string may contain old "Enter"
577 ((string-match (mew-pgp-get mew-pgp-msg-enter) string)
578 ;; (setq mew-pgp-failure mew-pgp-err-other) ;; this is wrong
580 (process-send-string process "\n")
581 (set-process-filter process 'mew-pgp-process-filter3))))
583 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
588 (defun mew-pgp-sign-letter ()
589 "Sign the entire draft with PGP. Input your passphrase."
591 (mew-pgp-encode-letter 'pgp-signature))
593 (defun mew-pgp-encrypt-letter ()
594 "Encrypt the entire draft with PGP."
596 (mew-pgp-encode-letter 'pgp-encryption))
598 (defun mew-pgp-sign-encrypt-letter ()
599 "Sign then encrypt the entire draft with PGP. Input your passphrase."
601 (mew-pgp-encode-letter 'pgp-signature-encryption))
603 (defun mew-pgp-encrypt-sign-letter ()
604 "Encrypt then sign the entire draft with PGP. Input your passphrase."
606 (mew-pgp-encode-letter 'pgp-encryption-signature))
608 (defmacro mew-pgp-encode-letter (type)
609 (` (if (null mew-pgp-ver)
610 (message "%s doesn't exist" mew-prog-pgp)
611 (mew-draft-make-message (, type)))))
613 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
618 (defun mew-pgp-check-old-pgp ()
619 (goto-char (point-min))
620 (if (re-search-forward (concat "^" mew-pgp-encryption-begin) nil t)
622 (goto-char (point-min))
623 (if (re-search-forward (concat "^" mew-pgp-signature-begin) nil t)
628 (defun mew-summary-decode-pgp ()
629 "Decrypting/verifying old-fashioned PGP messages."
631 (if (null mew-pgp-ver)
632 (message "%s doesn't exist" mew-prog-pgp)
634 (let* ((fld (mew-summary-folder-name))
635 (msg (mew-summary-message-number))
636 (file (mew-expand-folder-get-msg fld msg))
637 file1 type result win start
640 (set-buffer (mew-buffer-message))
643 (setq win (get-buffer-window (current-buffer)))
644 (setq start (window-start win))
645 (setq type (mew-pgp-check-old-pgp))
649 (insert-file-contents file)
650 (setq type (mew-pgp-check-old-pgp))))
652 (message "No PGP message was found")
653 (setq mew-inherit-from
654 (mew-addrstr-parse-address
655 (mew-header-get-value mew-from:)))
656 (goto-char (mew-header-end))
658 (delete-region (point) (point-max))
660 ((equal type 'pgp-encryption)
661 (setq result (mew-pgp-decrypt 'dummy file)))
662 ((equal type 'pgp-signature)
663 (setq result (mew-pgp-verify-old file))))
664 (setq file1 (nth 0 result))
665 (setq mew-syntax-privacy-result
666 (concat mew-x-mew: " <body> " (nth 1 result) "\n"))
668 (goto-char (mew-header-end))
669 (mew-decode-syntax-insert-privacy))
670 (if (not (file-exists-p file1))
673 mew-cs-text-for-read mew-cs-dummy
674 (insert-file-contents file1))
677 (mew-cs-decode-region (point) (point-max) mew-cs-rfc822-trans))
678 (mew-message-set-end-of)
679 (set-window-start win start)
680 (set-buffer-modified-p nil))))))))
682 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
687 (defun mew-attach-pgp-public-key ()
688 "Extract the PGP key for the inputed user on '.'. in attachments"
690 (if (not (mew-attach-not-line012-1))
691 (message "Can't link here.")
693 (nums (mew-syntax-nums))
694 (subdir (mew-attach-expand-path mew-encode-syntax nums))
695 (attachdir (mew-attachdir))
696 user file filepath begin end)
697 ;; attachdir / {subdir/} dir
698 (if (not (equal subdir ""))
699 (setq attachdir (expand-file-name subdir attachdir)))
701 (setq filepath (mew-random-filename attachdir mew-pgp-key-suffix))
703 (message "Could not make a file for pgp key, sorry.")
704 (setq file (file-name-nondirectory filepath))
705 (setq user (car (mew-input-address "Who's key? (%s): " (mew-get-my-address))))
708 (apply (function call-process)
709 (mew-pgp-get mew-prog-pgpk)
712 (mew-pgp-get mew-prog-pgpk-ext-arg)
714 (goto-char (point-min))
715 (if (search-forward (mew-pgp-get mew-pgp-msg-no-export-key) nil t)
717 (goto-char (point-min))
718 (if (not (search-forward mew-pgp-key-begin nil t))
722 (if (not (search-forward mew-pgp-key-end nil t))
727 (write-region begin end filepath nil 'no-msg))))
729 (message "can't extract pgp key for %s" user)
730 (setq mew-encode-syntax
731 (mew-syntax-insert-entry
734 (mew-encode-syntax-single file mew-type-apk nil user)))
735 (mew-encode-syntax-print mew-encode-syntax))))))
737 (defvar mew-pgp-tmp-file nil)
739 (defun mew-mime-pgp-keys (begin end &optional params execute)
740 "A function to add PGP keys in Application/PGP-Keys to your
743 (insert " ###### ##### ###### # # ####### # #\n"
744 " # # # # # # # # # # #\n"
745 " # # # # # # # # # #\n"
746 " ###### # #### ###### #### ####### #\n"
749 " # ##### # # # ####### #\n"
752 (mew-pgp-add-keys begin end (mew-current-get 'cache)
753 (mew-buffer-message))
754 (insert "\nTo add this key to your pubring, type "
755 (substitute-command-keys
756 "'\\<mew-summary-mode-map>\\[mew-summary-execute-external]'."))))
758 (defun mew-pgp-add-keys (begin end key-buf mes-buf)
759 "A function to add PGP keys to your public keyring."
761 (if (not mew-pgp-ver)
762 (message "PGP is not found")
763 (if (not (y-or-n-p "Add this PGP key onto your public keyring? "))
765 (setq mew-pgp-tmp-file (mew-make-temp-name))
769 mew-cs-dummy mew-cs-autoconv
770 (write-region begin end mew-pgp-tmp-file nil 'no-msg))
773 (message "Adding PGP keys ... ")
774 (apply (function call-process)
775 (mew-pgp-get mew-prog-pgpk)
777 (append (mew-pgp-get mew-prog-pgpk-add-arg)
778 (list mew-pgp-tmp-file)))
779 (message "Adding PGP keys ... done")
781 "**************** IMPORTANT NOTE ****************\n"
782 "When Mew adds PGP keys onto your public keyring,\n"
783 "it is careless about both TRUST and VALIDITY.\n"
784 "It is YOU who set these values. Please use\n")
786 ((equal mew-pgp-ver mew-pgp-ver2)
787 (insert "\"pgp -ke\" and \"pgp -ks\" to change them.\n"))
788 ((equal mew-pgp-ver mew-pgp-ver5)
789 (insert "\"pgpk -e\" and \"pgpk -s\" to change them.\n"))
790 ((equal mew-pgp-ver mew-pgp-verg)
791 (insert "\"gpg --edit-key\" to change them.\n")))
792 (insert "If you don't know what TRUST and VALIDITY is,\n"
793 "you should learn the web of trust system BEFORE\n"
794 "using PGP to protect your privacy.\n"
795 "**************** IMPORTANT NOTE ****************\n")
796 (if (equal mes-buf (mew-buffer-message))
798 (let ((inhibit-quit t)) (read-char-exclusive)))))
799 (if (file-exists-p mew-pgp-tmp-file)
800 (delete-file mew-pgp-tmp-file)))))
802 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
807 (defun mew-pgp-fetch-key (arg)
808 "Fetch PGP public key."
810 (if (null (processp mew-pgp-fetch-key-process))
811 (let (key key-list buf keyid xurl xurl-list xmew uri userid)
813 (set-buffer (mew-buffer-message))
814 (setq userid (mew-header-parse-address mew-from:))
817 (setq key-list mew-x-pgp-key-list)
818 (setq key (car key-list))
821 (setq xurl (mew-header-get-value key))
822 (if (and xurl (string-match "http:[^ \t\n]*" xurl))
824 (setq xurl (substring xurl (match-beginning 0) (match-end 0)))
825 (setq xurl-list (append xurl-list (list xurl)))))
826 (setq key-list (cdr key-list))
827 (setq key (car key-list)))))
828 (t (setq xmew (mew-header-get-value mew-x-mew:)))))
831 (setq xurl (car xurl-list))
832 (while (and xurl (not uri))
834 (if (y-or-n-p (format "fetch from %s? " xurl))
836 (setq xurl-list (cdr xurl-list))
837 (setq xurl (car xurl-list)))))
839 (string-match "key. ID = \\(0x[0-9a-fA-F]+\\)" xmew nil)
840 (setq keyid (substring xmew (match-beginning 1) (match-end 1))))
841 (if (y-or-n-p (format "Fetch Key ID=%s? " keyid))
842 (setq uri (format mew-pgp-keyserver-url-template keyid))))
844 (y-or-n-p (format "fetch User ID=%s? " userid)))
845 (setq uri (format mew-pgp-keyserver-url-template userid))
848 (message "can't find PGP public key's information.")
849 (setq buf (generate-new-buffer mew-buffer-pgpkey))
850 (message "key fetching...%s." uri)
852 mew-cs-autoconv mew-cs-autoconv
853 (setq mew-pgp-fetch-key-process
854 (start-process "Get PGP Key" buf mew-prog-imcat uri)))
855 (set-process-sentinel mew-pgp-fetch-key-process
856 'mew-pgp-fetch-process-done)))
857 (if (y-or-n-p "Fetching process is running. Continue fetching process? ")
859 (mew-pgp-fetch-process-kill))))
861 (defun mew-pgp-fetch-process-kill ()
862 "Kill the current process fetching PGP keys."
865 (if (processp mew-pgp-fetch-key-process)
866 (kill-process mew-pgp-fetch-key-process))
867 (setq mew-pgp-fetch-key-process nil)))
869 (defun mew-pgp-fetch-process-done (proc str)
870 (let* ((buf (process-buffer proc))
871 (wconf (current-window-configuration)))
873 (mew-pop-to-buffer buf)
874 (delete-other-windows)
875 (goto-char (point-min))
876 (if (and (search-forward mew-pgp-key-begin nil t)
877 (search-forward mew-pgp-key-end nil t))
879 (goto-char (point-max))
881 (mew-pgp-add-keys (point-min) (point-max)
882 (current-buffer) (current-buffer)))
884 (goto-char (point-max))
885 (insert "\n\n** PGP Key fetch failure. **\n\n")
886 (let ((inhibit-quit t)) (read-char-exclusive))))
888 (setq mew-pgp-fetch-key-process nil)
889 (set-window-configuration wconf))))
891 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
892 ;; <Decrypt> or <Decrypt-then-Verify>
894 ;; no seckey no secring:: <1>
895 ;; You do not have the secret key needed to decrypt this file.
898 ;; Keyring file 'pubring.pgp' does not exist.
899 ;; Enter public key filename:
901 ;; Key matching expected Key ID 1B8BF431 not found in file 'pubring.pgp'.
902 ;; Enter public key filename:
906 ;; A secret key is required to make a signature.
907 ;; Keyring file 'secring.pgp' does not exist.
908 ;; Enter secret key filename:
910 ;; A secret key is required to make a signature.
911 ;; Key matching userid 'hoge' not found in file 'secring.pgp'.
912 ;; Enter secret key filename:
916 ;; Keyring file 'pubring.pgp' does not exist.
918 ;; Key matching userid 'hoge' not found in file 'pubring.pgp'.
921 ;; Keyring file 'pubring.pgp' does not exist.
923 ;; Key matching expected Key ID 1B8BF431 not found in file 'pubring.pgp'.
927 ;;; Copyright Notice:
929 ;; Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999 Mew developing team.
930 ;; All rights reserved.
932 ;; Redistribution and use in source and binary forms, with or without
933 ;; modification, are permitted provided that the following conditions
936 ;; 1. Redistributions of source code must retain the above copyright
937 ;; notice, this list of conditions and the following disclaimer.
938 ;; 2. Redistributions in binary form must reproduce the above copyright
939 ;; notice, this list of conditions and the following disclaimer in the
940 ;; documentation and/or other materials provided with the distribution.
941 ;; 3. Neither the name of the team nor the names of its contributors
942 ;; may be used to endorse or promote products derived from this software
943 ;; without specific prior written permission.
945 ;; THIS SOFTWARE IS PROVIDED BY THE TEAM AND CONTRIBUTORS ``AS IS'' AND
946 ;; ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
947 ;; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
948 ;; PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE TEAM OR CONTRIBUTORS BE
949 ;; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
950 ;; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
951 ;; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
952 ;; BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
953 ;; WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
954 ;; OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
955 ;; IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
957 ;;; mew-pgp.el ends here