From cb9193e2f68b09e50433291a14580d5158fa874c Mon Sep 17 00:00:00 2001 From: ueno Date: Wed, 12 Apr 2006 22:59:42 +0000 Subject: [PATCH] * epf.el: Renamed from epg-file.el. --- COMPILE | 2 +- ChangeLog | 4 ++ Makefile.am | 2 +- README | 31 +++++---- epf.el | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ epg-file.el | 202 ----------------------------------------------------------- 6 files changed, 224 insertions(+), 217 deletions(-) create mode 100644 epf.el delete mode 100644 epg-file.el diff --git a/COMPILE b/COMPILE index 7f19076..4d18562 100644 --- a/COMPILE +++ b/COMPILE @@ -1,7 +1,7 @@ ;;; -*- Emacs-Lisp -*- (defvar epg-modules - '(epg epg-file)) + '(epg epf)) (defun epg-compile-modules (modules) (let ((load-path (cons nil load-path)) diff --git a/ChangeLog b/ChangeLog index 9261463..74068e2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ 2006-04-12 Daiki Ueno + * epf.el: Renamed from epg-file.el. + +2006-04-12 Daiki Ueno + * epg.el (epg-status-GET_BOOL): New function. (epg-status-GET_LINE): New function. (epg-prompt-alist): New variable, to be filled. diff --git a/Makefile.am b/Makefile.am index 09cb909..ef8f1bb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ AUTOMAKE_OPTIONS = no-dependencies -EXTRA_DIST = epg.el epg-file.el pgg-epg.el +EXTRA_DIST = epg.el epf.el pgg-epg.el CLEANFILES = auto-autoloads.el custom-load.el *.elc FLAGS ?= -batch -q -no-site-file diff --git a/README b/README index e231330..7084cb5 100644 --- a/README +++ b/README @@ -27,7 +27,7 @@ EasyPG provides transparent file encryption utility similar to crypt++, alpaca.el, hedgehog. To try this, add the following line to your ~/.emacs and C-x C-f ~/test.txt.gpg. -(require 'epg-file) +(require 'epf) ** Gnus/PGG backend @@ -44,13 +44,25 @@ gpg.el, etc. EasyPG has some advantages over them. ** EasyPG avoides potential security flaws of Emacs -*** `call-process-region' writes data in region to temporary files +See "Security consideration" section. -`call-process-region' writes data in region to temporary files. -EasyPG do _not_ use `call-process-region' to communicate with a gpg +** GnuPG features are directly accessible from Emacs + +Other competitors provide only specific features of GnuPG since they +still support PGP 2.*, 5.*, 6.*. As the name indicates, EasyPG is +inspired by GPGME (GnuPG Made Easy), and the library interface is +close to GPGME. With EasyPG you can benefit from a lot of features of +GnuPG. + +* Security consideration + +** `call-process-region' writes data in region to a temporary file + +`call-process-region' writes data in region to a temporary file. +EasyPG does *not* use `call-process-region' to communicate with a gpg subprocess. -*** `(fillarray string 0)' is not enough to clear passphrases +** `(fillarray string 0)' is not enough to clear passphrases If Emacs crashed and dumps core, passphrase strings in memory are also dumped within the core file. `read-passwd' function clears passphrase @@ -59,13 +71,6 @@ in gc_sweep phase. If GC happens before `fillarray', passphrase strings may be moved elsewhere in memory. Fortunately, there is gpg-agent to cache passphrases in more secure -way, so EasyPG dares _not_ to cache passphrase. Elisp programs can +way, so EasyPG dares *not* to cache passphrase. Elisp programs can set `epg-context-passphrase-callback' to cache user's passphrases. -** GnuPG features are directly accessible from Emacs - -Other competitors provide only specific features of GnuPG since they -still support PGP 2.*, 5.*, 6.*. As the name indicates, EasyPG is -inspired by GPGME (GnuPG Made Easy), and the library interface is -close to GPGME. With EasyPG you can benefit from a lot of features of -GnuPG. diff --git a/epf.el b/epf.el new file mode 100644 index 0000000..7205353 --- /dev/null +++ b/epf.el @@ -0,0 +1,200 @@ +;;; epf.el --- transparent file encryption utility +;; Copyright (C) 1999, 2000, 2002, 2003, 2004, +;; 2005, 2006 Free Software Foundation, Inc. +;; Copyright (C) 2006 Daiki Ueno + +;; Author: Daiki Ueno +;; Naoto Morishima +;; Keywords: PGP, GnuPG + +;; This file is part of EasyPG. + +;; This program is free software; you can redistribute it and/or modify +;; it under the terms of the GNU General Public License as published by +;; the Free Software Foundation; either version 2, or (at your option) +;; any later version. + +;; This program is distributed in the hope that it will be useful, +;; but WITHOUT ANY WARRANTY; without even the implied warranty of +;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;; GNU General Public License for more details. + +;; You should have received a copy of the GNU General Public License +;; along with GNU Emacs; see the file COPYING. If not, write to the +;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, +;; Boston, MA 02110-1301, USA. + +;;; Commentary: + +;; epf.el is based on hedgehog.el by Naoto Morishima. +;; http://www.morishima.net/~naoto/software/hedgehog/index.php.ja + +;;; Code: + +(require 'epg) + +(defgroup epf () + "Transparent file encryption utility of EasyPG." + :group 'epg) + +(defcustom epf-name-regexp "\\.gpg\\'" + "Regexp that matches filenames that are assumed to be encrypted +with GnuPG." + :type 'regexp + :group 'epf) + +(defun epf-handler (operation &rest args) + (let ((epf-operation (get operation 'epf))) + (if epf-operation + (apply epf-operation args) + (epf-run-real-handler operation args)))) + +(defun epf-run-real-handler (operation args) + (let ((inhibit-file-name-handlers + (cons 'epf-handler + (and (eq inhibit-file-name-operation operation) + inhibit-file-name-handlers))) + (inhibit-file-name-operation operation)) + (apply operation args))) + +(defvar buffer-file-type) +(defvar last-coding-system-used) +(defun epf-write-region (start end filename &optional append visit + lockname mustbenew) + (let* ((visit-file (if (stringp visit) + (expand-file-name visit) + (expand-file-name filename))) + ;; XXX: Obtain the value returned by choose_write_coding_system + (coding-system (condition-case nil + (epf-run-real-handler + 'write-region (list start end "/")) + (file-error (if (boundp 'last-coding-system-used) + last-coding-system-used + buffer-file-coding-system)))) + ;; start and end are normally buffer positions + ;; specifying the part of the buffer to write. + ;; If start is nil, that means to use the entire buffer contents. + ;; If start is a string, then output that string to the file + ;; instead of any buffer contents; end is ignored. + (string (encode-coding-string (cond + ((stringp start) + start) + ((null start) + (buffer-string)) + (t + (buffer-substring start end))) + coding-system))) + (with-temp-buffer + (if (fboundp 'set-buffer-multibyte) + (set-buffer-multibyte nil)) + ;; Optional fourth argument append if non-nil means + ;; append to existing file contents (if any). If it is an integer, + ;; seek to that offset in the file before writing. + (if (and append (file-exists-p filename)) + ;; Enable passphrase cache on this temp buffer + (let ((coding-system-for-read 'binary)) + ;; set visit to t so that passphrase is cached + (insert-file-contents filename t) + (setq buffer-file-name nil))) + ;; Insert data to encrypt + (goto-char (if (integerp append) (1+ append) (point-max))) + (delete-region (point) (min (+ (point) (length string)) (point-max))) + (insert string) + + (let ((coding-system-for-write 'binary) + (coding-system-for-read 'binary) + (context (epg-make-context)) + recipients + string + cipher) + (while (not (equal (setq string + (read-string "To (end with an empty line): ")) + "")) + (setq recipients (cons string recipients))) + (when (setq cipher (epg-encrypt-string context (buffer-string) + recipients)) + (if (and (memq system-type '(ms-dos windows-nt)) + (boundp 'buffer-file-type)) + (setq buffer-file-type t)) + (epf-run-real-handler + 'write-region + (list cipher nil filename nil 'not-visit lockname mustbenew))))) + ;; Optional fifth argument visit, if t or a string, means + ;; set the last-save-file-modtime of buffer to this file's modtime + ;; and mark buffer not modified. + ;; If visit is a string, it is a second file name; + ;; the output goes to filename, but the buffer is marked as visiting visit. + ;; visit is also the file name to lock and unlock for clash detection. + ;; If visit is neither t nor nil nor a string, + ;; that means do not display the "Wrote file" message. + (when (or (eq visit t) (stringp visit)) + (setq buffer-file-name filename) + (set-visited-file-modtime)) + (if (stringp visit) + (setq buffer-file-name visit)) + (when (or (eq visit t) (eq visit nil) (stringp visit)) + (message "Wrote %s" visit-file)) + (if (boundp 'last-coding-system-used) + (setq last-coding-system-used coding-system)) + nil)) + +(defun epf-insert-file-contents (filename &optional visit beg end replace) + (barf-if-buffer-read-only) + (setq filename (expand-file-name filename)) + (let ((filename (expand-file-name filename)) + (length 0)) + (if (file-exists-p filename) + (let ((local-file + (let ((inhibit-file-name-operation + (when (eq inhibit-file-name-operation + 'insert-file-contents) + 'file-local-copy))) + (file-local-copy filename))) + (coding-system-for-read 'binary) + (context (epg-make-context)) + string) + (unwind-protect + (progn + (setq string (epg-decrypt-file context (or local-file + filename)) + length (length string)) + (if replace + (goto-char (point-min))) + (save-excursion + (let ((buffer-file-name (if visit nil buffer-file-name))) + (save-restriction + (narrow-to-region (point) (point)) + (insert (decode-coding-string string 'undecided))) + (if replace + (delete-region (point) (point-max)))))) + (when (and local-file (file-exists-p local-file)) + (delete-file local-file))))) + ;; If second argument visit is non-nil, the buffer's visited filename + ;; and last save file modtime are set, and it is marked unmodified. + (when visit + (unlock-buffer) + (setq buffer-file-name filename) + (set-visited-file-modtime)) + + ;; If visiting and the file does not exist, visiting is completed + ;; before the error is signaled. + (if (and visit (not (file-exists-p filename))) + (signal 'file-error (list "Opening input file" filename))) + + ;; Returns list of absolute file name and number of characters inserted. + (list filename length))) + +(put 'write-region 'epf 'epf-write-region) +(put 'insert-file-contents 'epf 'epf-insert-file-contents) + +(unless (rassq 'epf-handler file-name-handler-alist) + (setq file-name-handler-alist + (cons (cons epf-name-regexp 'epf-handler) + file-name-handler-alist) + auto-mode-alist + (cons (list epf-name-regexp nil 'strip-suffix) + auto-mode-alist))) + +(provide 'epf) + +;;; epf.el ends here diff --git a/epg-file.el b/epg-file.el deleted file mode 100644 index cd6f6a0..0000000 --- a/epg-file.el +++ /dev/null @@ -1,202 +0,0 @@ -;;; epg-file.el --- transparent file encryption utility -;; Copyright (C) 1999, 2000, 2002, 2003, 2004, -;; 2005, 2006 Free Software Foundation, Inc. -;; Copyright (C) 2006 Daiki Ueno - -;; Author: Daiki Ueno -;; Naoto Morishima -;; Keywords: PGP, GnuPG - -;; This file is part of EasyPG. - -;; This program is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -;; Boston, MA 02110-1301, USA. - -;;; Commentary: - -;; epg-file.el is based on hedgehog.el by Naoto Morishima. -;; http://www.morishima.net/~naoto/software/hedgehog/index.php.ja - -;;; Code: - -(require 'epg) - -(defgroup epg-file () - "Transparent file encryption utility of EasyPG." - :group 'epg) - -(defcustom epg-file-name-regexp "\\.gpg\\'" - "Regexp that matches filenames that are assumed to be encrypted -with GnuPG." - :type 'regexp - :group 'epg-file) - -(defun epg-file-handler (operation &rest args) - (let ((epg-file-operation (get operation 'epg-file))) - (if epg-file-operation - (apply epg-file-operation args) - (epg-file-run-real-handler operation args)))) - -(defun epg-file-run-real-handler (operation args) - (let ((inhibit-file-name-handlers - (cons 'epg-file-handler - (and (eq inhibit-file-name-operation operation) - inhibit-file-name-handlers))) - (inhibit-file-name-operation operation)) - (apply operation args))) - -(defvar buffer-file-type) -(defvar last-coding-system-used) -(defun epg-file-write-region (start end filename &optional append visit - lockname mustbenew) - (let* ((visit-file (if (stringp visit) - (expand-file-name visit) - (expand-file-name filename))) - ;; XXX: Obtain the value returned by choose_write_coding_system - (coding-system (condition-case nil - (epg-file-run-real-handler - 'write-region (list start end "/")) - (file-error (if (boundp 'last-coding-system-used) - last-coding-system-used - buffer-file-coding-system)))) - ;; start and end are normally buffer positions - ;; specifying the part of the buffer to write. - ;; If start is nil, that means to use the entire buffer contents. - ;; If start is a string, then output that string to the file - ;; instead of any buffer contents; end is ignored. - (string (encode-coding-string (cond - ((stringp start) - start) - ((null start) - (buffer-string)) - (t - (buffer-substring start end))) - coding-system))) - (with-temp-buffer - (if (fboundp 'set-buffer-multibyte) - (set-buffer-multibyte nil)) - ;; Optional fourth argument append if non-nil means - ;; append to existing file contents (if any). If it is an integer, - ;; seek to that offset in the file before writing. - (if (and append (file-exists-p filename)) - ;; Enable passphrase cache on this temp buffer - (let ((coding-system-for-read 'binary)) - ;; set visit to t so that passphrase is cached - (insert-file-contents filename t) - (setq buffer-file-name nil))) - ;; Insert data to encrypt - (goto-char (if (integerp append) (1+ append) (point-max))) - (delete-region (point) (min (+ (point) (length string)) (point-max))) - (insert string) - - (let ((coding-system-for-write 'binary) - (coding-system-for-read 'binary) - (context (epg-make-context)) - recipients - string - cipher) - (while (not (equal (setq string - (read-string "To (end with an empty line): ")) - "")) - (setq recipients (cons string recipients))) - (when (setq cipher (epg-encrypt-string context (buffer-string) - recipients)) - (if (and (memq system-type '(ms-dos windows-nt)) - (boundp 'buffer-file-type)) - (setq buffer-file-type t)) - (epg-file-run-real-handler - 'write-region - (list cipher nil filename nil 'not-visit lockname mustbenew))))) - ;; Optional fifth argument visit, if t or a string, means - ;; set the last-save-file-modtime of buffer to this file's modtime - ;; and mark buffer not modified. - ;; If visit is a string, it is a second file name; - ;; the output goes to filename, but the buffer is marked as visiting visit. - ;; visit is also the file name to lock and unlock for clash detection. - ;; If visit is neither t nor nil nor a string, - ;; that means do not display the "Wrote file" message. - (when (or (eq visit t) (stringp visit)) - (setq buffer-file-name filename) - (set-visited-file-modtime)) - (if (stringp visit) - (setq buffer-file-name visit)) - (when (or (eq visit t) (eq visit nil) (stringp visit)) - (message "Wrote %s" visit-file)) - (if (boundp 'last-coding-system-used) - (setq last-coding-system-used coding-system)) - nil)) - -(defun epg-file-insert-file-contents (filename &optional visit beg end replace) - (barf-if-buffer-read-only) - (setq filename (expand-file-name filename)) - (let ((filename (expand-file-name filename)) - (length 0)) - (if (file-exists-p filename) - (let ((local-file - (let ((inhibit-file-name-operation - (when (eq inhibit-file-name-operation - 'insert-file-contents) - 'file-local-copy))) - (file-local-copy filename))) - (coding-system-for-read 'binary) - (context (epg-make-context)) - string) - (unwind-protect - (progn - (setq string (epg-decrypt-file context (or local-file - filename)) - length (length string)) - (if replace - (goto-char (point-min))) - (save-excursion - (let ((buffer-file-name (if visit nil buffer-file-name))) - (save-restriction - (narrow-to-region (point) (point)) - (insert (decode-coding-string string 'undecided))) - (if replace - (delete-region (point) (point-max)))))) - (when (and local-file (file-exists-p local-file)) - (delete-file local-file))))) - ;; If second argument visit is non-nil, the buffer's visited filename - ;; and last save file modtime are set, and it is marked unmodified. - (when visit - (unlock-buffer) - (setq buffer-file-name filename) - (set-visited-file-modtime)) - - ;; If visiting and the file does not exist, visiting is completed - ;; before the error is signaled. - (if (and visit (not (file-exists-p filename))) - (signal 'file-error (list "Opening input file" filename))) - - ;; Returns list of absolute file name and number of characters inserted. - (list filename length))) - -(put 'write-region 'epg-file 'epg-file-write-region) -(put 'insert-file-contents 'epg-file 'epg-file-insert-file-contents) - -(unless (assoc epg-file-name-regexp file-name-handler-alist) - (setq file-name-handler-alist - (cons (cons epg-file-name-regexp 'epg-file-handler) - file-name-handler-alist))) - -(unless (assoc epg-file-name-regexp auto-mode-alist) - (setq auto-mode-alist - (cons (list epg-file-name-regexp nil 'strip-suffix) - auto-mode-alist))) - -(provide 'epg-file) - -;;; epg-file.el ends here -- 1.7.10.4