pgg-pgp5.el 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. ;;; pgg-pgp5.el --- PGP 5.* support for PGG.
  2. ;; Copyright (C) 1999-2000, 2002-2012 Free Software Foundation, Inc.
  3. ;; Author: Daiki Ueno <ueno@unixuser.org>
  4. ;; Created: 1999/11/02
  5. ;; Keywords: PGP, OpenPGP
  6. ;; Package: pgg
  7. ;; Obsolete-since: 24.1
  8. ;; This file is part of GNU Emacs.
  9. ;; GNU Emacs is free software: you can redistribute it and/or modify
  10. ;; it under the terms of the GNU General Public License as published by
  11. ;; the Free Software Foundation, either version 3 of the License, or
  12. ;; (at your option) any later version.
  13. ;; GNU Emacs 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. ;; You should have received a copy of the GNU General Public License
  18. ;; along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>.
  19. ;;; Code:
  20. (eval-when-compile
  21. (require 'cl) ; for pgg macros
  22. (require 'pgg))
  23. (defgroup pgg-pgp5 ()
  24. "PGP 5.* interface."
  25. :group 'pgg)
  26. (defcustom pgg-pgp5-pgpe-program "pgpe"
  27. "PGP 5.* 'pgpe' executable."
  28. :group 'pgg-pgp5
  29. :type 'string)
  30. (defcustom pgg-pgp5-pgps-program "pgps"
  31. "PGP 5.* 'pgps' executable."
  32. :group 'pgg-pgp5
  33. :type 'string)
  34. (defcustom pgg-pgp5-pgpk-program "pgpk"
  35. "PGP 5.* 'pgpk' executable."
  36. :group 'pgg-pgp5
  37. :type 'string)
  38. (defcustom pgg-pgp5-pgpv-program "pgpv"
  39. "PGP 5.* 'pgpv' executable."
  40. :group 'pgg-pgp5
  41. :type 'string)
  42. (defcustom pgg-pgp5-shell-file-name "/bin/sh"
  43. "File name to load inferior shells from.
  44. Bourne shell or its equivalent \(not tcsh) is needed for \"2>\"."
  45. :group 'pgg-pgp5
  46. :type 'string)
  47. (defcustom pgg-pgp5-shell-command-switch "-c"
  48. "Switch used to have the shell execute its command line argument."
  49. :group 'pgg-pgp5
  50. :type 'string)
  51. (defcustom pgg-pgp5-extra-args nil
  52. "Extra arguments for every PGP 5.* invocation."
  53. :group 'pgg-pgp5
  54. :type '(choice
  55. (const :tag "None" nil)
  56. (string :tag "Arguments")))
  57. (defvar pgg-pgp5-user-id nil
  58. "PGP 5.* ID of your default identity.")
  59. (defun pgg-pgp5-process-region (start end passphrase program args)
  60. (let* ((errors-file-name (pgg-make-temp-file "pgg-errors"))
  61. (args
  62. (append args
  63. pgg-pgp5-extra-args
  64. (list (concat "2>" errors-file-name))))
  65. (shell-file-name pgg-pgp5-shell-file-name)
  66. (shell-command-switch pgg-pgp5-shell-command-switch)
  67. (process-environment process-environment)
  68. (output-buffer pgg-output-buffer)
  69. (errors-buffer pgg-errors-buffer)
  70. (process-connection-type nil)
  71. process status exit-status)
  72. (with-current-buffer (get-buffer-create output-buffer)
  73. (buffer-disable-undo)
  74. (erase-buffer))
  75. (when passphrase
  76. (setenv "PGPPASSFD" "0"))
  77. (unwind-protect
  78. (progn
  79. (let ((coding-system-for-read 'binary)
  80. (coding-system-for-write 'binary))
  81. (setq process
  82. (apply #'funcall
  83. #'start-process-shell-command "*PGP*" output-buffer
  84. program args)))
  85. (set-process-sentinel process #'ignore)
  86. (when passphrase
  87. (process-send-string process (concat passphrase "\n")))
  88. (process-send-region process start end)
  89. (process-send-eof process)
  90. (while (eq 'run (process-status process))
  91. (accept-process-output process 5))
  92. (setq status (process-status process)
  93. exit-status (process-exit-status process))
  94. (delete-process process)
  95. (with-current-buffer output-buffer
  96. (pgg-convert-lbt-region (point-min)(point-max) 'LF)
  97. (if (memq status '(stop signal))
  98. (error "%s exited abnormally: '%s'" program exit-status))
  99. (if (= 127 exit-status)
  100. (error "%s could not be found" program))
  101. (set-buffer (get-buffer-create errors-buffer))
  102. (buffer-disable-undo)
  103. (erase-buffer)
  104. (insert-file-contents errors-file-name)))
  105. (if (and process (eq 'run (process-status process)))
  106. (interrupt-process process))
  107. (condition-case nil
  108. (delete-file errors-file-name)
  109. (file-error nil)))))
  110. (defun pgg-pgp5-lookup-key (string &optional type)
  111. "Search keys associated with STRING."
  112. (let ((args (list "+language=en" "-l" string)))
  113. (with-current-buffer (get-buffer-create pgg-output-buffer)
  114. (buffer-disable-undo)
  115. (erase-buffer)
  116. (apply #'call-process pgg-pgp5-pgpk-program nil t nil args)
  117. (goto-char (point-min))
  118. (when (re-search-forward "^sec" nil t)
  119. (substring
  120. (nth 2 (split-string
  121. (buffer-substring (match-end 0)(progn (end-of-line)(point)))))
  122. 2)))))
  123. (defun pgg-pgp5-encrypt-region (start end recipients &optional sign passphrase)
  124. "Encrypt the current region between START and END."
  125. (let* ((pgg-pgp5-user-id (or pgg-pgp5-user-id pgg-default-user-id))
  126. (passphrase (or passphrase
  127. (when sign
  128. (pgg-read-passphrase
  129. (format "PGP passphrase for %s: "
  130. pgg-pgp5-user-id)
  131. pgg-pgp5-user-id))))
  132. (args
  133. (append
  134. `("+NoBatchInvalidKeys=off" "-fat" "+batchmode=1"
  135. ,@(if (or recipients pgg-encrypt-for-me)
  136. (apply #'append
  137. (mapcar (lambda (rcpt)
  138. (list "-r"
  139. (concat "\"" rcpt "\"")))
  140. (append recipients
  141. (if pgg-encrypt-for-me
  142. (list pgg-pgp5-user-id)))))))
  143. (if sign '("-s" "-u" pgg-pgp5-user-id)))))
  144. (pgg-pgp5-process-region start end nil pgg-pgp5-pgpe-program args)
  145. (pgg-process-when-success nil)))
  146. (defun pgg-pgp5-decrypt-region (start end &optional passphrase)
  147. "Decrypt the current region between START and END."
  148. (let* ((pgg-pgp5-user-id (or pgg-pgp5-user-id pgg-default-user-id))
  149. (passphrase
  150. (or passphrase
  151. (pgg-read-passphrase
  152. (format "PGP passphrase for %s: " pgg-pgp5-user-id)
  153. (pgg-pgp5-lookup-key pgg-pgp5-user-id 'encrypt))))
  154. (args
  155. '("+verbose=1" "+batchmode=1" "+language=us" "-f")))
  156. (pgg-pgp5-process-region start end passphrase pgg-pgp5-pgpv-program args)
  157. (pgg-process-when-success nil)))
  158. (defun pgg-pgp5-sign-region (start end &optional clearsign passphrase)
  159. "Make detached signature from text between START and END."
  160. (let* ((pgg-pgp5-user-id (or pgg-pgp5-user-id pgg-default-user-id))
  161. (passphrase
  162. (or passphrase
  163. (pgg-read-passphrase
  164. (format "PGP passphrase for %s: " pgg-pgp5-user-id)
  165. (pgg-pgp5-lookup-key pgg-pgp5-user-id 'sign))))
  166. (args
  167. (list (if clearsign "-fat" "-fbat")
  168. "+verbose=1" "+language=us" "+batchmode=1"
  169. "-u" pgg-pgp5-user-id)))
  170. (pgg-pgp5-process-region start end passphrase pgg-pgp5-pgps-program args)
  171. (pgg-process-when-success
  172. (when (re-search-forward "^-+BEGIN PGP SIGNATURE" nil t);XXX
  173. (let ((packet
  174. (cdr (assq 2 (pgg-parse-armor-region
  175. (progn (beginning-of-line 2)
  176. (point))
  177. (point-max))))))
  178. (if pgg-cache-passphrase
  179. (pgg-add-passphrase-to-cache
  180. (cdr (assq 'key-identifier packet))
  181. passphrase)))))))
  182. (defun pgg-pgp5-verify-region (start end &optional signature)
  183. "Verify region between START and END as the detached signature SIGNATURE."
  184. (let ((orig-file (pgg-make-temp-file "pgg"))
  185. (args '("+verbose=1" "+batchmode=1" "+language=us"))
  186. (orig-mode (default-file-modes)))
  187. (unwind-protect
  188. (progn
  189. (set-default-file-modes 448)
  190. (let ((coding-system-for-write 'binary)
  191. jka-compr-compression-info-list jam-zcat-filename-list)
  192. (write-region start end orig-file)))
  193. (set-default-file-modes orig-mode))
  194. (when (stringp signature)
  195. (copy-file signature (setq signature (concat orig-file ".asc")))
  196. (setq args (append args (list signature))))
  197. (pgg-pgp5-process-region (point)(point) nil pgg-pgp5-pgpv-program args)
  198. (delete-file orig-file)
  199. (if signature (delete-file signature))
  200. (with-current-buffer pgg-errors-buffer
  201. (goto-char (point-min))
  202. (if (re-search-forward "^Good signature" nil t)
  203. (progn
  204. (set-buffer pgg-output-buffer)
  205. (insert-buffer-substring pgg-errors-buffer)
  206. t)
  207. nil))))
  208. (defun pgg-pgp5-insert-key ()
  209. "Insert public key at point."
  210. (let* ((pgg-pgp5-user-id (or pgg-pgp5-user-id pgg-default-user-id))
  211. (args
  212. (list "+verbose=1" "+batchmode=1" "+language=us" "-x"
  213. (concat "\"" pgg-pgp5-user-id "\""))))
  214. (pgg-pgp5-process-region (point)(point) nil pgg-pgp5-pgpk-program args)
  215. (insert-buffer-substring pgg-output-buffer)))
  216. (defun pgg-pgp5-snarf-keys-region (start end)
  217. "Add all public keys in region between START and END to the keyring."
  218. (let* ((pgg-pgp5-user-id (or pgg-pgp5-user-id pgg-default-user-id))
  219. (key-file (pgg-make-temp-file "pgg"))
  220. (args
  221. (list "+verbose=1" "+batchmode=1" "+language=us" "-a"
  222. key-file)))
  223. (let ((coding-system-for-write 'raw-text-dos))
  224. (write-region start end key-file))
  225. (pgg-pgp5-process-region start end nil pgg-pgp5-pgpk-program args)
  226. (delete-file key-file)
  227. (pgg-process-when-success nil)))
  228. (provide 'pgg-pgp5)
  229. ;;; pgg-pgp5.el ends here