mml1991.el 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487
  1. ;;; mml1991.el --- Old PGP message format (RFC 1991) support for MML
  2. ;; Copyright (C) 1998-2012 Free Software Foundation, Inc.
  3. ;; Author: Sascha Lüdecke <sascha@meta-x.de>,
  4. ;; Simon Josefsson <simon@josefsson.org> (Mailcrypt interface, Gnus glue)
  5. ;; Keywords: PGP
  6. ;; This file is part of GNU Emacs.
  7. ;; GNU Emacs is free software: you can redistribute it and/or modify
  8. ;; it under the terms of the GNU General Public License as published by
  9. ;; the Free Software Foundation, either version 3 of the License, or
  10. ;; (at your option) any later version.
  11. ;; GNU Emacs is distributed in the hope that it will be useful,
  12. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. ;; GNU General Public License for more details.
  15. ;; You should have received a copy of the GNU General Public License
  16. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  17. ;;; Commentary:
  18. ;;; Code:
  19. (eval-and-compile
  20. ;; For Emacs <22.2 and XEmacs.
  21. (unless (fboundp 'declare-function) (defmacro declare-function (&rest r)))
  22. (if (locate-library "password-cache")
  23. (require 'password-cache)
  24. (require 'password)))
  25. (eval-when-compile
  26. (require 'cl)
  27. (require 'mm-util))
  28. (require 'mm-encode)
  29. (require 'mml-sec)
  30. (defvar mc-pgp-always-sign)
  31. (autoload 'quoted-printable-decode-region "qp")
  32. (autoload 'quoted-printable-encode-region "qp")
  33. (autoload 'mm-decode-content-transfer-encoding "mm-bodies")
  34. (autoload 'mm-encode-content-transfer-encoding "mm-bodies")
  35. (autoload 'message-options-get "message")
  36. (autoload 'message-options-set "message")
  37. (defvar mml1991-use mml2015-use
  38. "The package used for PGP.")
  39. (defvar mml1991-function-alist
  40. '((mailcrypt mml1991-mailcrypt-sign
  41. mml1991-mailcrypt-encrypt)
  42. (pgg mml1991-pgg-sign
  43. mml1991-pgg-encrypt)
  44. (epg mml1991-epg-sign
  45. mml1991-epg-encrypt))
  46. "Alist of PGP functions.")
  47. (defvar mml1991-cache-passphrase mml-secure-cache-passphrase
  48. "If t, cache passphrase.")
  49. (defvar mml1991-passphrase-cache-expiry mml-secure-passphrase-cache-expiry
  50. "How many seconds the passphrase is cached.
  51. Whether the passphrase is cached at all is controlled by
  52. `mml1991-cache-passphrase'.")
  53. (defvar mml1991-signers nil
  54. "A list of your own key ID which will be used to sign a message.")
  55. (defvar mml1991-encrypt-to-self nil
  56. "If t, add your own key ID to recipient list when encryption.")
  57. ;;; mailcrypt wrapper
  58. (autoload 'mc-sign-generic "mc-toplev")
  59. (defvar mml1991-decrypt-function 'mailcrypt-decrypt)
  60. (defvar mml1991-verify-function 'mailcrypt-verify)
  61. (defun mml1991-mailcrypt-sign (cont)
  62. (let ((text (current-buffer))
  63. headers signature
  64. (result-buffer (get-buffer-create "*GPG Result*")))
  65. ;; Save MIME Content[^ ]+: headers from signing
  66. (goto-char (point-min))
  67. (while (looking-at "^Content[^ ]+:") (forward-line))
  68. (unless (bobp)
  69. (setq headers (buffer-string))
  70. (delete-region (point-min) (point)))
  71. (goto-char (point-max))
  72. (unless (bolp)
  73. (insert "\n"))
  74. (quoted-printable-decode-region (point-min) (point-max))
  75. (with-temp-buffer
  76. (setq signature (current-buffer))
  77. (insert-buffer-substring text)
  78. (unless (mc-sign-generic (message-options-get 'message-sender)
  79. nil nil nil nil)
  80. (unless (> (point-max) (point-min))
  81. (pop-to-buffer result-buffer)
  82. (error "Sign error")))
  83. (goto-char (point-min))
  84. (while (re-search-forward "\r+$" nil t)
  85. (replace-match "" t t))
  86. (quoted-printable-encode-region (point-min) (point-max))
  87. (set-buffer text)
  88. (delete-region (point-min) (point-max))
  89. (if headers (insert headers))
  90. (insert "\n")
  91. (insert-buffer-substring signature)
  92. (goto-char (point-max)))))
  93. (declare-function mc-encrypt-generic "ext:mc-toplev"
  94. (&optional recipients scheme start end from sign))
  95. (defun mml1991-mailcrypt-encrypt (cont &optional sign)
  96. (let ((text (current-buffer))
  97. (mc-pgp-always-sign
  98. (or mc-pgp-always-sign
  99. sign
  100. (eq t (or (message-options-get 'message-sign-encrypt)
  101. (message-options-set
  102. 'message-sign-encrypt
  103. (or (y-or-n-p "Sign the message? ")
  104. 'not))))
  105. 'never))
  106. cipher
  107. (result-buffer (get-buffer-create "*GPG Result*")))
  108. ;; Strip MIME Content[^ ]: headers since it will be ASCII ARMORED
  109. (goto-char (point-min))
  110. (while (looking-at "^Content[^ ]+:") (forward-line))
  111. (unless (bobp)
  112. (delete-region (point-min) (point)))
  113. (with-temp-buffer
  114. (inline (mm-disable-multibyte))
  115. (setq cipher (current-buffer))
  116. (insert-buffer-substring text)
  117. (unless (mc-encrypt-generic
  118. (or
  119. (message-options-get 'message-recipients)
  120. (message-options-set 'message-recipients
  121. (read-string "Recipients: ")))
  122. nil
  123. (point-min) (point-max)
  124. (message-options-get 'message-sender)
  125. 'sign)
  126. (unless (> (point-max) (point-min))
  127. (pop-to-buffer result-buffer)
  128. (error "Encrypt error")))
  129. (goto-char (point-min))
  130. (while (re-search-forward "\r+$" nil t)
  131. (replace-match "" t t))
  132. (set-buffer text)
  133. (delete-region (point-min) (point-max))
  134. ;;(insert "Content-Type: application/pgp-encrypted\n\n")
  135. ;;(insert "Version: 1\n\n")
  136. (insert "\n")
  137. (insert-buffer-substring cipher)
  138. (goto-char (point-max)))))
  139. ;; pgg wrapper
  140. (autoload 'pgg-sign-region "pgg")
  141. (autoload 'pgg-encrypt-region "pgg")
  142. (defvar pgg-default-user-id)
  143. (defvar pgg-errors-buffer)
  144. (defvar pgg-output-buffer)
  145. (defun mml1991-pgg-sign (cont)
  146. (let ((pgg-text-mode t)
  147. (pgg-default-user-id (or (message-options-get 'mml-sender)
  148. pgg-default-user-id))
  149. headers cte)
  150. ;; Don't sign headers.
  151. (goto-char (point-min))
  152. (when (re-search-forward "^$" nil t)
  153. (setq headers (buffer-substring (point-min) (point)))
  154. (save-restriction
  155. (narrow-to-region (point-min) (point))
  156. (setq cte (mail-fetch-field "content-transfer-encoding")))
  157. (forward-line 1)
  158. (delete-region (point-min) (point))
  159. (when cte
  160. (setq cte (intern (downcase cte)))
  161. (mm-decode-content-transfer-encoding cte)))
  162. (unless (pgg-sign-region (point-min) (point-max) t)
  163. (pop-to-buffer pgg-errors-buffer)
  164. (error "Encrypt error"))
  165. (delete-region (point-min) (point-max))
  166. (mm-with-unibyte-current-buffer
  167. (insert-buffer-substring pgg-output-buffer)
  168. (goto-char (point-min))
  169. (while (re-search-forward "\r+$" nil t)
  170. (replace-match "" t t))
  171. (when cte
  172. (mm-encode-content-transfer-encoding cte))
  173. (goto-char (point-min))
  174. (when headers
  175. (insert headers))
  176. (insert "\n"))
  177. t))
  178. (defun mml1991-pgg-encrypt (cont &optional sign)
  179. (goto-char (point-min))
  180. (when (re-search-forward "^$" nil t)
  181. (let ((cte (save-restriction
  182. (narrow-to-region (point-min) (point))
  183. (mail-fetch-field "content-transfer-encoding"))))
  184. ;; Strip MIME headers since it will be ASCII armored.
  185. (forward-line 1)
  186. (delete-region (point-min) (point))
  187. (when cte
  188. (mm-decode-content-transfer-encoding (intern (downcase cte))))))
  189. (unless (let ((pgg-text-mode t))
  190. (pgg-encrypt-region
  191. (point-min) (point-max)
  192. (split-string
  193. (or
  194. (message-options-get 'message-recipients)
  195. (message-options-set 'message-recipients
  196. (read-string "Recipients: ")))
  197. "[ \f\t\n\r\v,]+")
  198. sign))
  199. (pop-to-buffer pgg-errors-buffer)
  200. (error "Encrypt error"))
  201. (delete-region (point-min) (point-max))
  202. (insert "\n")
  203. (insert-buffer-substring pgg-output-buffer)
  204. t)
  205. ;; epg wrapper
  206. (defvar epg-user-id-alist)
  207. (autoload 'epg-make-context "epg")
  208. (autoload 'epg-passphrase-callback-function "epg")
  209. (autoload 'epa-select-keys "epa")
  210. (autoload 'epg-list-keys "epg")
  211. (autoload 'epg-context-set-armor "epg")
  212. (autoload 'epg-context-set-textmode "epg")
  213. (autoload 'epg-context-set-signers "epg")
  214. (autoload 'epg-context-set-passphrase-callback "epg")
  215. (autoload 'epg-key-sub-key-list "epg")
  216. (autoload 'epg-sub-key-capability "epg")
  217. (autoload 'epg-sub-key-validity "epg")
  218. (autoload 'epg-sub-key-fingerprint "epg")
  219. (autoload 'epg-sign-string "epg")
  220. (autoload 'epg-encrypt-string "epg")
  221. (autoload 'epg-configuration "epg-config")
  222. (autoload 'epg-expand-group "epg-config")
  223. (defvar mml1991-epg-secret-key-id-list nil)
  224. (defun mml1991-epg-passphrase-callback (context key-id ignore)
  225. (if (eq key-id 'SYM)
  226. (epg-passphrase-callback-function context key-id nil)
  227. (let* ((entry (assoc key-id epg-user-id-alist))
  228. (passphrase
  229. (password-read
  230. (format "GnuPG passphrase for %s: "
  231. (if entry
  232. (cdr entry)
  233. key-id))
  234. (if (eq key-id 'PIN)
  235. "PIN"
  236. key-id))))
  237. (when passphrase
  238. (let ((password-cache-expiry mml1991-passphrase-cache-expiry))
  239. (password-cache-add key-id passphrase))
  240. (setq mml1991-epg-secret-key-id-list
  241. (cons key-id mml1991-epg-secret-key-id-list))
  242. (copy-sequence passphrase)))))
  243. (defun mml1991-epg-find-usable-key (keys usage)
  244. (catch 'found
  245. (while keys
  246. (let ((pointer (epg-key-sub-key-list (car keys))))
  247. ;; The primary key will be marked as disabled, when the entire
  248. ;; key is disabled (see 12 Field, Format of colon listings, in
  249. ;; gnupg/doc/DETAILS)
  250. (unless (memq 'disabled (epg-sub-key-capability (car pointer)))
  251. (while pointer
  252. (if (and (memq usage (epg-sub-key-capability (car pointer)))
  253. (not (memq (epg-sub-key-validity (car pointer))
  254. '(revoked expired))))
  255. (throw 'found (car keys)))
  256. (setq pointer (cdr pointer)))))
  257. (setq keys (cdr keys)))))
  258. ;; XXX: since gpg --list-secret-keys does not return validity of each
  259. ;; key, `mml1991-epg-find-usable-key' defined above is not enough for
  260. ;; secret keys. The function `mml1991-epg-find-usable-secret-key'
  261. ;; below looks at appropriate public keys to check usability.
  262. (defun mml1991-epg-find-usable-secret-key (context name usage)
  263. (let ((secret-keys (epg-list-keys context name t))
  264. secret-key)
  265. (while (and (not secret-key) secret-keys)
  266. (if (mml1991-epg-find-usable-key
  267. (epg-list-keys context (epg-sub-key-fingerprint
  268. (car (epg-key-sub-key-list
  269. (car secret-keys)))))
  270. usage)
  271. (setq secret-key (car secret-keys)
  272. secret-keys nil)
  273. (setq secret-keys (cdr secret-keys))))
  274. secret-key))
  275. (defun mml1991-epg-sign (cont)
  276. (let ((context (epg-make-context))
  277. headers cte signer-key signers signature)
  278. (if (eq mm-sign-option 'guided)
  279. (setq signers (epa-select-keys context "Select keys for signing.
  280. If no one is selected, default secret key is used. "
  281. mml1991-signers t))
  282. (if mml1991-signers
  283. (setq signers (delq nil
  284. (mapcar
  285. (lambda (name)
  286. (setq signer-key
  287. (mml1991-epg-find-usable-secret-key
  288. context name 'sign))
  289. (unless (or signer-key
  290. (y-or-n-p
  291. (format
  292. "No secret key for %s; skip it? "
  293. name)))
  294. (error "No secret key for %s" name))
  295. signer-key)
  296. mml1991-signers)))))
  297. (epg-context-set-armor context t)
  298. (epg-context-set-textmode context t)
  299. (epg-context-set-signers context signers)
  300. (if mml1991-cache-passphrase
  301. (epg-context-set-passphrase-callback
  302. context
  303. #'mml1991-epg-passphrase-callback))
  304. ;; Don't sign headers.
  305. (goto-char (point-min))
  306. (when (re-search-forward "^$" nil t)
  307. (setq headers (buffer-substring (point-min) (point)))
  308. (save-restriction
  309. (narrow-to-region (point-min) (point))
  310. (setq cte (mail-fetch-field "content-transfer-encoding")))
  311. (forward-line 1)
  312. (delete-region (point-min) (point))
  313. (when cte
  314. (setq cte (intern (downcase cte)))
  315. (mm-decode-content-transfer-encoding cte)))
  316. (condition-case error
  317. (setq signature (epg-sign-string context (buffer-string) 'clear)
  318. mml1991-epg-secret-key-id-list nil)
  319. (error
  320. (while mml1991-epg-secret-key-id-list
  321. (password-cache-remove (car mml1991-epg-secret-key-id-list))
  322. (setq mml1991-epg-secret-key-id-list
  323. (cdr mml1991-epg-secret-key-id-list)))
  324. (signal (car error) (cdr error))))
  325. (delete-region (point-min) (point-max))
  326. (mm-with-unibyte-current-buffer
  327. (insert signature)
  328. (goto-char (point-min))
  329. (while (re-search-forward "\r+$" nil t)
  330. (replace-match "" t t))
  331. (when cte
  332. (mm-encode-content-transfer-encoding cte))
  333. (goto-char (point-min))
  334. (when headers
  335. (insert headers))
  336. (insert "\n"))
  337. t))
  338. (defun mml1991-epg-encrypt (cont &optional sign)
  339. (goto-char (point-min))
  340. (when (re-search-forward "^$" nil t)
  341. (let ((cte (save-restriction
  342. (narrow-to-region (point-min) (point))
  343. (mail-fetch-field "content-transfer-encoding"))))
  344. ;; Strip MIME headers since it will be ASCII armored.
  345. (forward-line 1)
  346. (delete-region (point-min) (point))
  347. (when cte
  348. (mm-decode-content-transfer-encoding (intern (downcase cte))))))
  349. (let ((context (epg-make-context))
  350. (recipients
  351. (if (message-options-get 'message-recipients)
  352. (split-string
  353. (message-options-get 'message-recipients)
  354. "[ \f\t\n\r\v,]+")))
  355. recipient-key signer-key cipher signers config)
  356. (when mml1991-encrypt-to-self
  357. (unless mml1991-signers
  358. (error "mml1991-signers is not set"))
  359. (setq recipients (nconc recipients mml1991-signers)))
  360. ;; We should remove this check if epg-0.0.6 is released.
  361. (if (and (condition-case nil
  362. (require 'epg-config)
  363. (error))
  364. (functionp #'epg-expand-group))
  365. (setq config (epg-configuration)
  366. recipients
  367. (apply #'nconc
  368. (mapcar (lambda (recipient)
  369. (or (epg-expand-group config recipient)
  370. (list recipient)))
  371. recipients))))
  372. (if (eq mm-encrypt-option 'guided)
  373. (setq recipients
  374. (epa-select-keys context "Select recipients for encryption.
  375. If no one is selected, symmetric encryption will be performed. "
  376. recipients))
  377. (setq recipients
  378. (delq nil (mapcar
  379. (lambda (name)
  380. (setq recipient-key (mml1991-epg-find-usable-key
  381. (epg-list-keys context name)
  382. 'encrypt))
  383. (unless (or recipient-key
  384. (y-or-n-p
  385. (format "No public key for %s; skip it? "
  386. name)))
  387. (error "No public key for %s" name))
  388. recipient-key)
  389. recipients)))
  390. (unless recipients
  391. (error "No recipient specified")))
  392. (when sign
  393. (if (eq mm-sign-option 'guided)
  394. (setq signers (epa-select-keys context "Select keys for signing.
  395. If no one is selected, default secret key is used. "
  396. mml1991-signers t))
  397. (if mml1991-signers
  398. (setq signers (delq nil
  399. (mapcar
  400. (lambda (name)
  401. (mml1991-epg-find-usable-secret-key
  402. context name 'sign))
  403. mml1991-signers)))))
  404. (epg-context-set-signers context signers))
  405. (epg-context-set-armor context t)
  406. (epg-context-set-textmode context t)
  407. (if mml1991-cache-passphrase
  408. (epg-context-set-passphrase-callback
  409. context
  410. #'mml1991-epg-passphrase-callback))
  411. (condition-case error
  412. (setq cipher
  413. (epg-encrypt-string context (buffer-string) recipients sign)
  414. mml1991-epg-secret-key-id-list nil)
  415. (error
  416. (while mml1991-epg-secret-key-id-list
  417. (password-cache-remove (car mml1991-epg-secret-key-id-list))
  418. (setq mml1991-epg-secret-key-id-list
  419. (cdr mml1991-epg-secret-key-id-list)))
  420. (signal (car error) (cdr error))))
  421. (delete-region (point-min) (point-max))
  422. (insert "\n" cipher))
  423. t)
  424. ;;;###autoload
  425. (defun mml1991-encrypt (cont &optional sign)
  426. (let ((func (nth 2 (assq mml1991-use mml1991-function-alist))))
  427. (if func
  428. (funcall func cont sign)
  429. (error "Cannot find encrypt function"))))
  430. ;;;###autoload
  431. (defun mml1991-sign (cont)
  432. (let ((func (nth 1 (assq mml1991-use mml1991-function-alist))))
  433. (if func
  434. (funcall func cont)
  435. (error "Cannot find sign function"))))
  436. (provide 'mml1991)
  437. ;; Local Variables:
  438. ;; coding: iso-8859-1
  439. ;; End:
  440. ;;; mml1991.el ends here