X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/0d26e0b62b7d01e3cb6eb57943269b8f25e53cd6..9e4ce6976d594b65c7b925fdff12a1adadb3b688:/lisp/epg.el diff --git a/lisp/epg.el b/lisp/epg.el index 00c00f9c9d..3f04aa2e07 100644 --- a/lisp/epg.el +++ b/lisp/epg.el @@ -1,5 +1,5 @@ ;;; epg.el --- the EasyPG Library -*- lexical-binding: t -*- -;; Copyright (C) 1999-2000, 2002-2011 Free Software Foundation, Inc. +;; Copyright (C) 1999-2000, 2002-2013 Free Software Foundation, Inc. ;; Author: Daiki Ueno ;; Keywords: PGP, GnuPG @@ -37,6 +37,8 @@ (defvar epg-key-id nil) (defvar epg-context nil) (defvar epg-debug-buffer nil) +(defvar epg-agent-file nil) +(defvar epg-agent-mtime nil) ;; from gnupg/include/cipher.h (defconst epg-cipher-algorithm-alist @@ -82,7 +84,7 @@ (defconst epg-invalid-recipients-reason-alist '((0 . "No specific reason given") (1 . "Not Found") - (2 . "Ambigious specification") + (2 . "Ambiguous specification") (3 . "Wrong key usage") (4 . "Key revoked") (5 . "Key expired") @@ -95,7 +97,7 @@ (defconst epg-delete-problem-reason-alist '((1 . "No such key") (2 . "Must delete secret key first") - (3 . "Ambigious specification"))) + (3 . "Ambiguous specification"))) (defconst epg-import-ok-reason-alist '((0 . "Not actually changed") @@ -161,6 +163,7 @@ (defvar epg-prompt-alist nil) (put 'epg-error 'error-conditions '(epg-error error)) +(put 'epg-error 'error-message "GPG error") (defun epg-make-data-from-file (file) "Make a data object from FILE." @@ -970,7 +973,8 @@ This function is for internal use only." "Convert SIGNATURE to a human readable string." (let* ((user-id (cdr (assoc (epg-signature-key-id signature) epg-user-id-alist))) - (pubkey-algorithm (epg-signature-pubkey-algorithm signature))) + (pubkey-algorithm (epg-signature-pubkey-algorithm signature)) + (key-id (epg-signature-key-id signature))) (concat (cond ((eq (epg-signature-status signature) 'good) "Good signature from ") @@ -984,7 +988,7 @@ This function is for internal use only." "Signature made by revoked key ") ((eq (epg-signature-status signature) 'no-pubkey) "No public key for ")) - (epg-signature-key-id signature) + key-id (if user-id (concat " " (if (stringp user-id) @@ -1130,12 +1134,12 @@ This function is for internal use only." (if (eq (epg-context-protocol context) 'CMS) epg-gpgsm-program epg-gpg-program))) - (let* ((args (append (list "--no-tty" + (let* ((agent-info (getenv "GPG_AGENT_INFO")) + (args (append (list "--no-tty" "--status-fd" "1" "--yes") (if (and (not (eq (epg-context-protocol context) 'CMS)) - (string-match ":" (or (getenv "GPG_AGENT_INFO") - ""))) + (string-match ":" (or agent-info ""))) '("--use-agent")) (if (and (not (eq (epg-context-protocol context) 'CMS)) (epg-context-progress-callback context)) @@ -1152,16 +1156,45 @@ This function is for internal use only." (coding-system-for-write 'binary) (coding-system-for-read 'binary) process-connection-type + (process-environment process-environment) (orig-mode (default-file-modes)) (buffer (generate-new-buffer " *epg*")) - process) + process + terminal-name + agent-file + (agent-mtime '(0 0 0 0))) + ;; Set GPG_TTY and TERM for pinentry-curses. Note that we can't + ;; use `terminal-name' here to get the real pty name for the child + ;; process, though /dev/fd/0" is not portable. + (unless (memq system-type '(ms-dos windows-nt)) + (with-temp-buffer + (condition-case nil + (when (= (call-process "tty" "/dev/fd/0" t) 0) + (delete-char -1) + (setq terminal-name (buffer-string))) + (file-error)))) + (when terminal-name + (setq process-environment + (cons (concat "GPG_TTY=" terminal-name) + (cons "TERM=xterm" process-environment)))) + ;; Record modified time of gpg-agent socket to restore the Emacs + ;; frame on text terminal in `epg-wait-for-completion'. + ;; See + ;; + ;; for more details. + (when (and agent-info (string-match "\\(.*\\):[0-9]+:[0-9]+" agent-info)) + (setq agent-file (match-string 1 agent-info) + agent-mtime (or (nth 5 (file-attributes agent-file)) '(0 0 0 0)))) (if epg-debug (save-excursion (unless epg-debug-buffer (setq epg-debug-buffer (generate-new-buffer " *epg-debug*"))) (set-buffer epg-debug-buffer) (goto-char (point-max)) - (insert (format "%s %s\n" + (insert (if agent-info + (format "GPG_AGENT_INFO=%s\n" agent-info) + "GPG_AGENT_INFO is not set\n") + (format "%s %s\n" (if (eq (epg-context-protocol context) 'CMS) epg-gpgsm-program epg-gpg-program) @@ -1180,7 +1213,11 @@ This function is for internal use only." (make-local-variable 'epg-key-id) (setq epg-key-id nil) (make-local-variable 'epg-context) - (setq epg-context context)) + (setq epg-context context) + (make-local-variable 'epg-agent-file) + (setq epg-agent-file agent-file) + (make-local-variable 'epg-agent-mtime) + (setq epg-agent-mtime agent-mtime)) (unwind-protect (progn (set-default-file-modes 448) @@ -1257,6 +1294,13 @@ This function is for internal use only." (accept-process-output (epg-context-process context) 1)) ;; This line is needed to run the process-filter right now. (sleep-for 0.1) + ;; Restore Emacs frame on text terminal, when pinentry-curses has terminated. + (if (with-current-buffer (process-buffer (epg-context-process context)) + (and epg-agent-file + (> (float-time (or (nth 5 (file-attributes epg-agent-file)) + '(0 0 0 0))) + (float-time epg-agent-mtime)))) + (redraw-frame (selected-frame))) (epg-context-set-result-for context 'error (nreverse (epg-context-result-for context 'error)))) @@ -1779,6 +1823,7 @@ This function is for internal use only." (epg-context-set-result-for context 'import-status nil))) (defun epg-passphrase-callback-function (context key-id _handback) + (declare (obsolete epa-passphrase-callback-function "23.1")) (if (eq key-id 'SYM) (read-passwd "Passphrase for symmetric encryption: " (eq (epg-context-operation context) 'encrypt)) @@ -1790,9 +1835,6 @@ This function is for internal use only." (format "Passphrase for %s %s: " key-id (cdr entry)) (format "Passphrase for %s: " key-id))))))) -(make-obsolete 'epg-passphrase-callback-function - 'epa-passphrase-callback-function "23.1") - (defun epg--list-keys-1 (context name mode) (let ((args (append (if epg-gpg-home-directory (list "--homedir" epg-gpg-home-directory)) @@ -1951,7 +1993,8 @@ The returned file name (created by appending some random characters at the end of PREFIX, and expanding against `temporary-file-directory' if necessary), is guaranteed to point to a newly created empty file. You can then use `write-region' to write new data into the file." - (let (tempdir tempfile) + (let ((orig-modes (default-file-modes)) + tempdir tempfile) (setq prefix (expand-file-name prefix (if (featurep 'xemacs) (temp-directory) @@ -1959,6 +2002,7 @@ You can then use `write-region' to write new data into the file." (unwind-protect (let (file) ;; First, create a temporary directory. + (set-default-file-modes #o700) (while (condition-case () (progn (setq tempdir (make-temp-name @@ -1969,14 +2013,12 @@ You can then use `write-region' to write new data into the file." (make-directory tempdir)) ;; let's try again. (file-already-exists t))) - (set-file-modes tempdir 448) ;; Second, create a temporary file in the tempdir. ;; There *is* a race condition between `make-temp-name' ;; and `write-region', but we don't care it since we are ;; in a private directory now. (setq tempfile (make-temp-name (concat tempdir "/EMU"))) (write-region "" nil tempfile nil 'silent) - (set-file-modes tempfile 384) ;; Finally, make a hard-link from the tempfile. (while (condition-case () (progn @@ -1986,6 +2028,7 @@ You can then use `write-region' to write new data into the file." ;; let's try again. (file-already-exists t))) file) + (set-default-file-modes orig-modes) ;; Cleanup the tempfile. (and tempfile (file-exists-p tempfile) @@ -2561,6 +2604,7 @@ If you use this function, you will need to wait for the completion of `epg-reset' to clear a temporary output file. If you are unsure, use synchronous version of this function `epg-sign-keys' instead." + (declare (obsolete nil "23.1")) (epg-context-set-operation context 'sign-keys) (epg-context-set-result context nil) (epg--start context (cons (if local @@ -2571,10 +2615,10 @@ If you are unsure, use synchronous version of this function (epg-sub-key-id (car (epg-key-sub-key-list key)))) keys)))) -(make-obsolete 'epg-start-sign-keys "do not use." "23.1") (defun epg-sign-keys (context keys &optional local) "Sign KEYS from the key ring." + (declare (obsolete nil "23.1")) (unwind-protect (progn (epg-start-sign-keys context keys local) @@ -2585,7 +2629,6 @@ If you are unsure, use synchronous version of this function (list "Sign keys failed" (epg-errors-to-string errors)))))) (epg-reset context))) -(make-obsolete 'epg-sign-keys "do not use." "23.1") (defun epg-start-generate-key (context parameters) "Initiate a key generation.