diff options
| author | Daiki Ueno | 2013-10-03 16:11:27 +0900 |
|---|---|---|
| committer | Daiki Ueno | 2013-10-03 16:11:27 +0900 |
| commit | acbadd0046cb1643eeaf8595ede1a69cc25d3158 (patch) | |
| tree | f1b7ffc2d37226d1f20d53b879e008b400f545ae | |
| parent | 0a858ebfc57a072ae8ab65f509d8a4901a2ec073 (diff) | |
| download | emacs-acbadd0046cb1643eeaf8595ede1a69cc25d3158.tar.gz emacs-acbadd0046cb1643eeaf8595ede1a69cc25d3158.zip | |
Add support for package signature checking.
* lisp/emacs-lisp/package.el (url-http-file-exists-p)
(epg-make-context, epg-context-set-home-directory)
(epg-verify-string, epg-context-result-for)
(epg-signature-status, epg-signature-to-string)
(epg-check-configuration, epg-configuration)
(epg-import-keys-from-file): Declare.
(package-check-signature): New user option.
(package-unsigned-archives): New user option.
(package-desc): Add `signed' field.
(package-load-descriptor): Set `signed' field if .signed file exists.
(package--archive-file-exists-p): New function.
(package--check-signature): New function.
(package-install-from-archive): Check package signature.
(package--download-one-archive): Check archive signature.
(package-delete): Remove .signed file.
(package-import-keyring): New command.
(package-refresh-contents): Import default keyring.
(package-desc-status): Add "unsigned" status.
(describe-package-1, package-menu--print-info)
(package-menu-mark-delete, package-menu--find-upgrades)
(package-menu--status-predicate): Support "unsigned" status.
* test/automated/data/package/signed/archive-contents:
* test/automated/data/package/signed/archive-contents.sig:
* test/automated/data/package/signed/signed-good-1.0.el:
* test/automated/data/package/signed/signed-good-1.0.el.sig:
* test/automated/data/package/signed/signed-bad-1.0.el:
* test/automated/data/package/signed/signed-bad-1.0.el.sig:
* test/automated/data/package/key.pub:
* test/automated/data/package/key.sec: New files.
* test/automated/package-test.el (package-test-update-listing)
(package-test-update-archives, package-test-describe-package):
Adjust to package.el change.
(package-test-signed): New test.
| -rw-r--r-- | lisp/ChangeLog | 25 | ||||
| -rw-r--r-- | lisp/emacs-lisp/package.el | 196 | ||||
| -rw-r--r-- | test/ChangeLog | 16 | ||||
| -rw-r--r-- | test/automated/data/package/key.pub | 18 | ||||
| -rw-r--r-- | test/automated/data/package/key.sec | 33 | ||||
| -rw-r--r-- | test/automated/data/package/signed/archive-contents | 7 | ||||
| -rw-r--r-- | test/automated/data/package/signed/archive-contents.sig | bin | 0 -> 287 bytes | |||
| -rw-r--r-- | test/automated/data/package/signed/signed-bad-1.0.el | 33 | ||||
| -rw-r--r-- | test/automated/data/package/signed/signed-bad-1.0.el.sig | bin | 0 -> 287 bytes | |||
| -rw-r--r-- | test/automated/data/package/signed/signed-good-1.0.el | 33 | ||||
| -rw-r--r-- | test/automated/data/package/signed/signed-good-1.0.el.sig | bin | 0 -> 287 bytes | |||
| -rw-r--r-- | test/automated/package-test.el | 39 |
12 files changed, 376 insertions, 24 deletions
diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 90158b85b4d..936f2b1f8e5 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog | |||
| @@ -1,3 +1,28 @@ | |||
| 1 | 2013-10-03 Daiki Ueno <ueno@gnu.org> | ||
| 2 | |||
| 3 | Add support for package signature checking. | ||
| 4 | * emacs-lisp/package.el (url-http-file-exists-p) | ||
| 5 | (epg-make-context, epg-context-set-home-directory) | ||
| 6 | (epg-verify-string, epg-context-result-for) | ||
| 7 | (epg-signature-status, epg-signature-to-string) | ||
| 8 | (epg-check-configuration, epg-configuration) | ||
| 9 | (epg-import-keys-from-file): Declare. | ||
| 10 | (package-check-signature): New user option. | ||
| 11 | (package-unsigned-archives): New user option. | ||
| 12 | (package-desc): Add `signed' field. | ||
| 13 | (package-load-descriptor): Set `signed' field if .signed file exists. | ||
| 14 | (package--archive-file-exists-p): New function. | ||
| 15 | (package--check-signature): New function. | ||
| 16 | (package-install-from-archive): Check package signature. | ||
| 17 | (package--download-one-archive): Check archive signature. | ||
| 18 | (package-delete): Remove .signed file. | ||
| 19 | (package-import-keyring): New command. | ||
| 20 | (package-refresh-contents): Import default keyring. | ||
| 21 | (package-desc-status): Add "unsigned" status. | ||
| 22 | (describe-package-1, package-menu--print-info) | ||
| 23 | (package-menu-mark-delete, package-menu--find-upgrades) | ||
| 24 | (package-menu--status-predicate): Support "unsigned" status. | ||
| 25 | |||
| 1 | 2013-10-03 Stefan Monnier <monnier@iro.umontreal.ca> | 26 | 2013-10-03 Stefan Monnier <monnier@iro.umontreal.ca> |
| 2 | 27 | ||
| 3 | * emacs-lisp/cconv.el (cconv-convert, cconv-analyse-form): Adjust for | 28 | * emacs-lisp/cconv.el (cconv-convert, cconv-analyse-form): Adjust for |
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index ec01d16329f..cdf210498ce 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el | |||
| @@ -206,6 +206,7 @@ If VERSION is nil, the package is not loaded (it is \"disabled\")." | |||
| 206 | (defvar Info-directory-list) | 206 | (defvar Info-directory-list) |
| 207 | (declare-function info-initialize "info" ()) | 207 | (declare-function info-initialize "info" ()) |
| 208 | (declare-function url-http-parse-response "url-http" ()) | 208 | (declare-function url-http-parse-response "url-http" ()) |
| 209 | (declare-function url-http-file-exists-p "url-http" (url)) | ||
| 209 | (declare-function lm-header "lisp-mnt" (header)) | 210 | (declare-function lm-header "lisp-mnt" (header)) |
| 210 | (declare-function lm-commentary "lisp-mnt" (&optional file)) | 211 | (declare-function lm-commentary "lisp-mnt" (&optional file)) |
| 211 | (defvar url-http-end-of-headers) | 212 | (defvar url-http-end-of-headers) |
| @@ -285,6 +286,22 @@ contrast, `package-user-dir' contains packages for personal use." | |||
| 285 | :group 'package | 286 | :group 'package |
| 286 | :version "24.1") | 287 | :version "24.1") |
| 287 | 288 | ||
| 289 | (defcustom package-check-signature 'allow-unsigned | ||
| 290 | "Whether to check package signatures when installing." | ||
| 291 | :type '(choice (const nil :tag "Never") | ||
| 292 | (const allow-unsigned :tag "Allow unsigned") | ||
| 293 | (const t :tag "Check always")) | ||
| 294 | :risky t | ||
| 295 | :group 'package | ||
| 296 | :version "24.1") | ||
| 297 | |||
| 298 | (defcustom package-unsigned-archives nil | ||
| 299 | "A list of archives which do not use package signature." | ||
| 300 | :type '(repeat (string :tag "Archive name")) | ||
| 301 | :risky t | ||
| 302 | :group 'package | ||
| 303 | :version "24.1") | ||
| 304 | |||
| 288 | (defvar package--default-summary "No description available.") | 305 | (defvar package--default-summary "No description available.") |
| 289 | 306 | ||
| 290 | (cl-defstruct (package-desc | 307 | (cl-defstruct (package-desc |
| @@ -340,7 +357,9 @@ Slots: | |||
| 340 | `dir' The directory where the package is installed (if installed), | 357 | `dir' The directory where the package is installed (if installed), |
| 341 | `builtin' if it is built-in, or nil otherwise. | 358 | `builtin' if it is built-in, or nil otherwise. |
| 342 | 359 | ||
| 343 | `extras' Optional alist of additional keyword-value pairs." | 360 | `extras' Optional alist of additional keyword-value pairs. |
| 361 | |||
| 362 | `signed' Flag to indicate that the package is signed by provider." | ||
| 344 | name | 363 | name |
| 345 | version | 364 | version |
| 346 | (summary package--default-summary) | 365 | (summary package--default-summary) |
| @@ -348,7 +367,8 @@ Slots: | |||
| 348 | kind | 367 | kind |
| 349 | archive | 368 | archive |
| 350 | dir | 369 | dir |
| 351 | extras) | 370 | extras |
| 371 | signed) | ||
| 352 | 372 | ||
| 353 | ;; Pseudo fields. | 373 | ;; Pseudo fields. |
| 354 | (defun package-desc-full-name (pkg-desc) | 374 | (defun package-desc-full-name (pkg-desc) |
| @@ -428,7 +448,8 @@ This is, approximately, the inverse of `version-to-list'. | |||
| 428 | (defun package-load-descriptor (pkg-dir) | 448 | (defun package-load-descriptor (pkg-dir) |
| 429 | "Load the description file in directory PKG-DIR." | 449 | "Load the description file in directory PKG-DIR." |
| 430 | (let ((pkg-file (expand-file-name (package--description-file pkg-dir) | 450 | (let ((pkg-file (expand-file-name (package--description-file pkg-dir) |
| 431 | pkg-dir))) | 451 | pkg-dir)) |
| 452 | (signed-file (concat pkg-dir ".signed"))) | ||
| 432 | (when (file-exists-p pkg-file) | 453 | (when (file-exists-p pkg-file) |
| 433 | (with-temp-buffer | 454 | (with-temp-buffer |
| 434 | (insert-file-contents pkg-file) | 455 | (insert-file-contents pkg-file) |
| @@ -436,6 +457,8 @@ This is, approximately, the inverse of `version-to-list'. | |||
| 436 | (let ((pkg-desc (package-process-define-package | 457 | (let ((pkg-desc (package-process-define-package |
| 437 | (read (current-buffer)) pkg-file))) | 458 | (read (current-buffer)) pkg-file))) |
| 438 | (setf (package-desc-dir pkg-desc) pkg-dir) | 459 | (setf (package-desc-dir pkg-desc) pkg-dir) |
| 460 | (if (file-exists-p signed-file) | ||
| 461 | (setf (package-desc-signed pkg-desc) t)) | ||
| 439 | pkg-desc))))) | 462 | pkg-desc))))) |
| 440 | 463 | ||
| 441 | (defun package-load-all-descriptors () | 464 | (defun package-load-all-descriptors () |
| @@ -766,13 +789,87 @@ It will move point to somewhere in the headers." | |||
| 766 | (error "Error during download request:%s" | 789 | (error "Error during download request:%s" |
| 767 | (buffer-substring-no-properties (point) (line-end-position)))))) | 790 | (buffer-substring-no-properties (point) (line-end-position)))))) |
| 768 | 791 | ||
| 792 | (defun package--archive-file-exists-p (location file) | ||
| 793 | (let ((http (string-match "\\`https?:" location))) | ||
| 794 | (if http | ||
| 795 | (progn | ||
| 796 | (require 'url-http) | ||
| 797 | (url-http-file-exists-p (concat location file))) | ||
| 798 | (file-exists-p (expand-file-name file location))))) | ||
| 799 | |||
| 800 | (declare-function epg-make-context "epg" | ||
| 801 | (&optional protocol armor textmode include-certs | ||
| 802 | cipher-algorithm | ||
| 803 | digest-algorithm | ||
| 804 | compress-algorithm)) | ||
| 805 | (declare-function epg-context-set-home-directory "epg" (context directory)) | ||
| 806 | (declare-function epg-verify-string "epg" (context signature | ||
| 807 | &optional signed-text)) | ||
| 808 | (declare-function epg-context-result-for "epg" (context name)) | ||
| 809 | (declare-function epg-signature-status "epg" (signature)) | ||
| 810 | (declare-function epg-signature-to-string "epg" (signature)) | ||
| 811 | |||
| 812 | (defun package--check-signature (location file) | ||
| 813 | "Check signature of the current buffer. | ||
| 814 | GnuPG keyring is located under \"gnupg\" in `package-user-dir'." | ||
| 815 | (let ((context (epg-make-context 'OpenPGP)) | ||
| 816 | (homedir (expand-file-name "gnupg" package-user-dir)) | ||
| 817 | (sig-file (concat file ".sig")) | ||
| 818 | sig-content | ||
| 819 | good-signatures) | ||
| 820 | (condition-case-unless-debug error | ||
| 821 | (setq sig-content (package--with-work-buffer location sig-file | ||
| 822 | (buffer-string))) | ||
| 823 | (error "Failed to download %s: %S" sig-file (cdr error))) | ||
| 824 | (epg-context-set-home-directory context homedir) | ||
| 825 | (epg-verify-string context sig-content (buffer-string)) | ||
| 826 | ;; The .sig file may contain multiple signatures. Success if one | ||
| 827 | ;; of the signatures is good. | ||
| 828 | (setq good-signatures | ||
| 829 | (delq nil (mapcar (lambda (sig) | ||
| 830 | (if (eq (epg-signature-status sig) 'good) | ||
| 831 | sig)) | ||
| 832 | (epg-context-result-for context 'verify)))) | ||
| 833 | (if (null good-signatures) | ||
| 834 | (error "Failed to verify signature %s: %S" | ||
| 835 | sig-file | ||
| 836 | (mapcar #'epg-signature-to-string | ||
| 837 | (epg-context-result-for context 'verify))) | ||
| 838 | good-signatures))) | ||
| 839 | |||
| 769 | (defun package-install-from-archive (pkg-desc) | 840 | (defun package-install-from-archive (pkg-desc) |
| 770 | "Download and install a tar package." | 841 | "Download and install a tar package." |
| 771 | (let ((location (package-archive-base pkg-desc)) | 842 | (let* ((location (package-archive-base pkg-desc)) |
| 772 | (file (concat (package-desc-full-name pkg-desc) | 843 | (file (concat (package-desc-full-name pkg-desc) |
| 773 | (package-desc-suffix pkg-desc)))) | 844 | (package-desc-suffix pkg-desc))) |
| 845 | (sig-file (concat file ".sig")) | ||
| 846 | good-signatures pkg-descs) | ||
| 774 | (package--with-work-buffer location file | 847 | (package--with-work-buffer location file |
| 775 | (package-unpack pkg-desc)))) | 848 | (if (and package-check-signature |
| 849 | (not (member (package-desc-archive pkg-desc) | ||
| 850 | package-unsigned-archives))) | ||
| 851 | (if (package--archive-file-exists-p location sig-file) | ||
| 852 | (setq good-signatures (package--check-signature location file)) | ||
| 853 | (unless (eq package-check-signature 'allow-unsigned) | ||
| 854 | (error "Unsigned package: `%s'" | ||
| 855 | (package-desc-name pkg-desc))))) | ||
| 856 | (package-unpack pkg-desc)) | ||
| 857 | ;; Here the package has been installed successfully, mark it as | ||
| 858 | ;; signed if appropriate. | ||
| 859 | (when good-signatures | ||
| 860 | ;; Write out good signatures into NAME-VERSION.signed file. | ||
| 861 | (write-region (mapconcat #'epg-signature-to-string good-signatures "\n") | ||
| 862 | nil | ||
| 863 | (expand-file-name | ||
| 864 | (concat (package-desc-full-name pkg-desc) | ||
| 865 | ".signed") | ||
| 866 | package-user-dir)) | ||
| 867 | ;; Update the old pkg-desc which will be shown on the description buffer. | ||
| 868 | (setf (package-desc-signed pkg-desc) t) | ||
| 869 | ;; Update the new (activated) pkg-desc as well. | ||
| 870 | (setq pkg-descs (cdr (assq (package-desc-name pkg-desc) package-alist))) | ||
| 871 | (if pkg-descs | ||
| 872 | (setf (package-desc-signed (car pkg-descs)) t))))) | ||
| 776 | 873 | ||
| 777 | (defvar package--initialized nil) | 874 | (defvar package--initialized nil) |
| 778 | 875 | ||
| @@ -1104,6 +1201,10 @@ The file can either be a tar file or an Emacs Lisp file." | |||
| 1104 | (error "Package `%s' is a system package, not deleting" | 1201 | (error "Package `%s' is a system package, not deleting" |
| 1105 | (package-desc-full-name pkg-desc)) | 1202 | (package-desc-full-name pkg-desc)) |
| 1106 | (delete-directory dir t t) | 1203 | (delete-directory dir t t) |
| 1204 | ;; Remove NAME-VERSION.signed file. | ||
| 1205 | (let ((signed-file (concat dir ".signed"))) | ||
| 1206 | (if (file-exists-p signed-file) | ||
| 1207 | (delete-file signed-file))) | ||
| 1107 | ;; Update package-alist. | 1208 | ;; Update package-alist. |
| 1108 | (let* ((name (package-desc-name pkg-desc))) | 1209 | (let* ((name (package-desc-name pkg-desc))) |
| 1109 | (delete pkg-desc (assq name package-alist))) | 1210 | (delete pkg-desc (assq name package-alist))) |
| @@ -1118,16 +1219,50 @@ The file can either be a tar file or an Emacs Lisp file." | |||
| 1118 | ARCHIVE should be a cons cell of the form (NAME . LOCATION), | 1219 | ARCHIVE should be a cons cell of the form (NAME . LOCATION), |
| 1119 | similar to an entry in `package-alist'. Save the cached copy to | 1220 | similar to an entry in `package-alist'. Save the cached copy to |
| 1120 | \"archives/NAME/archive-contents\" in `package-user-dir'." | 1221 | \"archives/NAME/archive-contents\" in `package-user-dir'." |
| 1121 | (let* ((dir (expand-file-name (format "archives/%s" (car archive)) | 1222 | (let ((dir (expand-file-name (format "archives/%s" (car archive)) |
| 1122 | package-user-dir))) | 1223 | package-user-dir)) |
| 1224 | (sig-file (concat file ".sig")) | ||
| 1225 | good-signatures) | ||
| 1123 | (package--with-work-buffer (cdr archive) file | 1226 | (package--with-work-buffer (cdr archive) file |
| 1227 | ;; Check signature of archive-contents, if desired. | ||
| 1228 | (if (and package-check-signature | ||
| 1229 | (not (member archive package-unsigned-archives))) | ||
| 1230 | (if (package--archive-file-exists-p (cdr archive) sig-file) | ||
| 1231 | (setq good-signatures (package--check-signature (cdr archive) | ||
| 1232 | file)) | ||
| 1233 | (unless (eq package-check-signature 'allow-unsigned) | ||
| 1234 | (error "Unsigned archive `%s'" | ||
| 1235 | (car archive))))) | ||
| 1124 | ;; Read the retrieved buffer to make sure it is valid (e.g. it | 1236 | ;; Read the retrieved buffer to make sure it is valid (e.g. it |
| 1125 | ;; may fetch a URL redirect page). | 1237 | ;; may fetch a URL redirect page). |
| 1126 | (when (listp (read buffer)) | 1238 | (when (listp (read buffer)) |
| 1127 | (make-directory dir t) | 1239 | (make-directory dir t) |
| 1128 | (setq buffer-file-name (expand-file-name file dir)) | 1240 | (setq buffer-file-name (expand-file-name file dir)) |
| 1129 | (let ((version-control 'never)) | 1241 | (let ((version-control 'never)) |
| 1130 | (save-buffer)))))) | 1242 | (save-buffer)))) |
| 1243 | (when good-signatures | ||
| 1244 | ;; Write out good signatures into archive-contents.signed file. | ||
| 1245 | (write-region (mapconcat #'epg-signature-to-string good-signatures "\n") | ||
| 1246 | nil | ||
| 1247 | (expand-file-name (concat file ".signed") dir))))) | ||
| 1248 | |||
| 1249 | (declare-function epg-check-configuration "epg-config" | ||
| 1250 | (config &optional minimum-version)) | ||
| 1251 | (declare-function epg-configuration "epg-config" ()) | ||
| 1252 | (declare-function epg-import-keys-from-file "epg" (context keys)) | ||
| 1253 | |||
| 1254 | ;;;###autoload | ||
| 1255 | (defun package-import-keyring (&optional file) | ||
| 1256 | "Import keys from FILE." | ||
| 1257 | (interactive "fFile: ") | ||
| 1258 | (setq file (expand-file-name file)) | ||
| 1259 | (let ((context (epg-make-context 'OpenPGP)) | ||
| 1260 | (homedir (expand-file-name "gnupg" package-user-dir))) | ||
| 1261 | (make-directory homedir t) | ||
| 1262 | (epg-context-set-home-directory context homedir) | ||
| 1263 | (message "Importing %s..." (file-name-nondirectory file)) | ||
| 1264 | (epg-import-keys-from-file context file) | ||
| 1265 | (message "Importing %s...done" (file-name-nondirectory file)))) | ||
| 1131 | 1266 | ||
| 1132 | ;;;###autoload | 1267 | ;;;###autoload |
| 1133 | (defun package-refresh-contents () | 1268 | (defun package-refresh-contents () |
| @@ -1138,6 +1273,14 @@ makes them available for download." | |||
| 1138 | ;; FIXME: Do it asynchronously. | 1273 | ;; FIXME: Do it asynchronously. |
| 1139 | (unless (file-exists-p package-user-dir) | 1274 | (unless (file-exists-p package-user-dir) |
| 1140 | (make-directory package-user-dir t)) | 1275 | (make-directory package-user-dir t)) |
| 1276 | (let ((default-keyring (expand-file-name "package-keyring.gpg" | ||
| 1277 | data-directory))) | ||
| 1278 | (if (file-exists-p default-keyring) | ||
| 1279 | (condition-case-unless-debug error | ||
| 1280 | (progn | ||
| 1281 | (epg-check-configuration (epg-configuration)) | ||
| 1282 | (package-import-keyring default-keyring)) | ||
| 1283 | (error (message "Cannot import default keyring: %S" (cdr error)))))) | ||
| 1141 | (dolist (archive package-archives) | 1284 | (dolist (archive package-archives) |
| 1142 | (condition-case-unless-debug nil | 1285 | (condition-case-unless-debug nil |
| 1143 | (package--download-one-archive archive "archive-contents") | 1286 | (package--download-one-archive archive "archive-contents") |
| @@ -1209,7 +1352,8 @@ If optional arg NO-ACTIVATE is non-nil, don't activate packages." | |||
| 1209 | (homepage (if desc (cdr (assoc :url (package-desc-extras desc))))) | 1352 | (homepage (if desc (cdr (assoc :url (package-desc-extras desc))))) |
| 1210 | (built-in (eq pkg-dir 'builtin)) | 1353 | (built-in (eq pkg-dir 'builtin)) |
| 1211 | (installable (and archive (not built-in))) | 1354 | (installable (and archive (not built-in))) |
| 1212 | (status (if desc (package-desc-status desc) "orphan"))) | 1355 | (status (if desc (package-desc-status desc) "orphan")) |
| 1356 | (signed (if desc (package-desc-signed desc)))) | ||
| 1213 | (prin1 name) | 1357 | (prin1 name) |
| 1214 | (princ " is ") | 1358 | (princ " is ") |
| 1215 | (princ (if (memq (aref status 0) '(?a ?e ?i ?o ?u)) "an " "a ")) | 1359 | (princ (if (memq (aref status 0) '(?a ?e ?i ?o ?u)) "an " "a ")) |
| @@ -1222,7 +1366,9 @@ If optional arg NO-ACTIVATE is non-nil, don't activate packages." | |||
| 1222 | 'font-lock-face 'font-lock-builtin-face) | 1366 | 'font-lock-face 'font-lock-builtin-face) |
| 1223 | ".")) | 1367 | ".")) |
| 1224 | (pkg-dir | 1368 | (pkg-dir |
| 1225 | (insert (propertize (capitalize status) ;FIXME: Why comment-face? | 1369 | (insert (propertize (if (equal status "unsigned") |
| 1370 | "Installed" | ||
| 1371 | (capitalize status)) ;FIXME: Why comment-face? | ||
| 1226 | 'font-lock-face 'font-lock-comment-face)) | 1372 | 'font-lock-face 'font-lock-comment-face)) |
| 1227 | (insert " in `") | 1373 | (insert " in `") |
| 1228 | ;; Todo: Add button for uninstalling. | 1374 | ;; Todo: Add button for uninstalling. |
| @@ -1233,9 +1379,11 @@ If optional arg NO-ACTIVATE is non-nil, don't activate packages." | |||
| 1233 | (not (package-built-in-p name version))) | 1379 | (not (package-built-in-p name version))) |
| 1234 | (insert "',\n shadowing a " | 1380 | (insert "',\n shadowing a " |
| 1235 | (propertize "built-in package" | 1381 | (propertize "built-in package" |
| 1236 | 'font-lock-face 'font-lock-builtin-face) | 1382 | 'font-lock-face 'font-lock-builtin-face)) |
| 1237 | ".") | 1383 | (insert "'")) |
| 1238 | (insert "'."))) | 1384 | (if signed |
| 1385 | (insert ".") | ||
| 1386 | (insert " (unsigned)."))) | ||
| 1239 | (installable | 1387 | (installable |
| 1240 | (insert (capitalize status)) | 1388 | (insert (capitalize status)) |
| 1241 | (insert " from " (format "%s" archive)) | 1389 | (insert " from " (format "%s" archive)) |
| @@ -1449,7 +1597,8 @@ package PKG-DESC, add one. The alist is keyed with PKG-DESC." | |||
| 1449 | (dir (package-desc-dir pkg-desc)) | 1597 | (dir (package-desc-dir pkg-desc)) |
| 1450 | (lle (assq name package-load-list)) | 1598 | (lle (assq name package-load-list)) |
| 1451 | (held (cadr lle)) | 1599 | (held (cadr lle)) |
| 1452 | (version (package-desc-version pkg-desc))) | 1600 | (version (package-desc-version pkg-desc)) |
| 1601 | (signed (package-desc-signed pkg-desc))) | ||
| 1453 | (cond | 1602 | (cond |
| 1454 | ((eq dir 'builtin) "built-in") | 1603 | ((eq dir 'builtin) "built-in") |
| 1455 | ((and lle (null held)) "disabled") | 1604 | ((and lle (null held)) "disabled") |
| @@ -1463,7 +1612,9 @@ package PKG-DESC, add one. The alist is keyed with PKG-DESC." | |||
| 1463 | (dir ;One of the installed packages. | 1612 | (dir ;One of the installed packages. |
| 1464 | (cond | 1613 | (cond |
| 1465 | ((not (file-exists-p (package-desc-dir pkg-desc))) "deleted") | 1614 | ((not (file-exists-p (package-desc-dir pkg-desc))) "deleted") |
| 1466 | ((eq pkg-desc (cadr (assq name package-alist))) "installed") | 1615 | ((eq pkg-desc (cadr (assq name package-alist))) (if signed |
| 1616 | "installed" | ||
| 1617 | "unsigned")) | ||
| 1467 | (t "obsolete"))) | 1618 | (t "obsolete"))) |
| 1468 | (t | 1619 | (t |
| 1469 | (let* ((ins (cadr (assq name package-alist))) | 1620 | (let* ((ins (cadr (assq name package-alist))) |
| @@ -1473,7 +1624,9 @@ package PKG-DESC, add one. The alist is keyed with PKG-DESC." | |||
| 1473 | (if (memq name package-menu--new-package-list) | 1624 | (if (memq name package-menu--new-package-list) |
| 1474 | "new" "available")) | 1625 | "new" "available")) |
| 1475 | ((version-list-< version ins-v) "obsolete") | 1626 | ((version-list-< version ins-v) "obsolete") |
| 1476 | ((version-list-= version ins-v) "installed"))))))) | 1627 | ((version-list-= version ins-v) (if signed |
| 1628 | "installed" | ||
| 1629 | "unsigned")))))))) | ||
| 1477 | 1630 | ||
| 1478 | (defun package-menu--refresh (&optional packages) | 1631 | (defun package-menu--refresh (&optional packages) |
| 1479 | "Re-populate the `tabulated-list-entries'. | 1632 | "Re-populate the `tabulated-list-entries'. |
| @@ -1532,6 +1685,7 @@ Return (PKG-DESC [NAME VERSION STATUS DOC])." | |||
| 1532 | (`"held" 'font-lock-constant-face) | 1685 | (`"held" 'font-lock-constant-face) |
| 1533 | (`"disabled" 'font-lock-warning-face) | 1686 | (`"disabled" 'font-lock-warning-face) |
| 1534 | (`"installed" 'font-lock-comment-face) | 1687 | (`"installed" 'font-lock-comment-face) |
| 1688 | (`"unsigned" 'font-lock-warning-face) | ||
| 1535 | (_ 'font-lock-warning-face)))) ; obsolete. | 1689 | (_ 'font-lock-warning-face)))) ; obsolete. |
| 1536 | (list pkg-desc | 1690 | (list pkg-desc |
| 1537 | (vector (list (symbol-name (package-desc-name pkg-desc)) | 1691 | (vector (list (symbol-name (package-desc-name pkg-desc)) |
| @@ -1570,7 +1724,7 @@ If optional arg BUTTON is non-nil, describe its associated package." | |||
| 1570 | (defun package-menu-mark-delete (&optional _num) | 1724 | (defun package-menu-mark-delete (&optional _num) |
| 1571 | "Mark a package for deletion and move to the next line." | 1725 | "Mark a package for deletion and move to the next line." |
| 1572 | (interactive "p") | 1726 | (interactive "p") |
| 1573 | (if (member (package-menu-get-status) '("installed" "obsolete")) | 1727 | (if (member (package-menu-get-status) '("installed" "obsolete" "unsigned")) |
| 1574 | (tabulated-list-put-tag "D" t) | 1728 | (tabulated-list-put-tag "D" t) |
| 1575 | (forward-line))) | 1729 | (forward-line))) |
| 1576 | 1730 | ||
| @@ -1624,7 +1778,7 @@ If optional arg BUTTON is non-nil, describe its associated package." | |||
| 1624 | ;; ENTRY is (PKG-DESC [NAME VERSION STATUS DOC]) | 1778 | ;; ENTRY is (PKG-DESC [NAME VERSION STATUS DOC]) |
| 1625 | (let ((pkg-desc (car entry)) | 1779 | (let ((pkg-desc (car entry)) |
| 1626 | (status (aref (cadr entry) 2))) | 1780 | (status (aref (cadr entry) 2))) |
| 1627 | (cond ((equal status "installed") | 1781 | (cond ((member status '("installed" "unsigned")) |
| 1628 | (push pkg-desc installed)) | 1782 | (push pkg-desc installed)) |
| 1629 | ((member status '("available" "new")) | 1783 | ((member status '("available" "new")) |
| 1630 | (push (cons (package-desc-name pkg-desc) pkg-desc) | 1784 | (push (cons (package-desc-name pkg-desc) pkg-desc) |
| @@ -1738,6 +1892,8 @@ Optional argument NOQUERY non-nil means do not ask the user to confirm." | |||
| 1738 | ((string= sB "available") nil) | 1892 | ((string= sB "available") nil) |
| 1739 | ((string= sA "installed") t) | 1893 | ((string= sA "installed") t) |
| 1740 | ((string= sB "installed") nil) | 1894 | ((string= sB "installed") nil) |
| 1895 | ((string= sA "unsigned") t) | ||
| 1896 | ((string= sB "unsigned") nil) | ||
| 1741 | ((string= sA "held") t) | 1897 | ((string= sA "held") t) |
| 1742 | ((string= sB "held") nil) | 1898 | ((string= sB "held") nil) |
| 1743 | ((string= sA "built-in") t) | 1899 | ((string= sA "built-in") t) |
diff --git a/test/ChangeLog b/test/ChangeLog index bf8ecbcb9eb..00a49eea936 100644 --- a/test/ChangeLog +++ b/test/ChangeLog | |||
| @@ -1,3 +1,19 @@ | |||
| 1 | 2013-10-03 Daiki Ueno <ueno@gnu.org> | ||
| 2 | |||
| 3 | * automated/data/package/signed/archive-contents: | ||
| 4 | * automated/data/package/signed/archive-contents.sig: | ||
| 5 | * automated/data/package/signed/signed-good-1.0.el: | ||
| 6 | * automated/data/package/signed/signed-good-1.0.el.sig: | ||
| 7 | * automated/data/package/signed/signed-bad-1.0.el: | ||
| 8 | * automated/data/package/signed/signed-bad-1.0.el.sig: | ||
| 9 | * automated/data/package/key.pub: | ||
| 10 | * automated/data/package/key.sec: New files. | ||
| 11 | |||
| 12 | * automated/package-test.el (package-test-update-listing) | ||
| 13 | (package-test-update-archives, package-test-describe-package): | ||
| 14 | Adjust to package.el change. | ||
| 15 | (package-test-signed): New test. | ||
| 16 | |||
| 1 | 2013-10-01 Dmitry Gutov <dgutov@yandex.ru> | 17 | 2013-10-01 Dmitry Gutov <dgutov@yandex.ru> |
| 2 | 18 | ||
| 3 | * automated/package-test.el: Update all cases to use :url instead | 19 | * automated/package-test.el: Update all cases to use :url instead |
diff --git a/test/automated/data/package/key.pub b/test/automated/data/package/key.pub new file mode 100644 index 00000000000..a326d34e54f --- /dev/null +++ b/test/automated/data/package/key.pub | |||
| @@ -0,0 +1,18 @@ | |||
| 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- | ||
| 2 | Version: GnuPG v1.4.14 (GNU/Linux) | ||
| 3 | |||
| 4 | mQENBFJNB8gBCACfbtpvYrM8V1HM0KFlIwatcEJugHqwOHpr/Z9mrCW0fxyQAW/d | ||
| 5 | 2L+3QVNsN9Tz/K9lLcBUgeR7rhVEzHNqhmhNj/HnikwGqXbIofhp+QbZmBKnAlCz | ||
| 6 | d77kg8K9lozHtfTkm1gX/7DdPzQKmgi7WOzzi2395wGubeqJLvYaEcqVbI0Eob+E | ||
| 7 | 3CzRjNy/e/Tf3TJRW5etTcdZN6LVuIY7tNCHqlQZTwyycON/hfLTX6cLCnzDsqm/ | ||
| 8 | NxCuwn9aqP9aGRGfIu7Y+If3zTymvrXEPUN98OEID814bOKdx0uVTZRiSMbvuTGI | ||
| 9 | 8uMa/kpGX/78rqI61gbZV51RFoU7pT2tzwY/ABEBAAG0HkouIFIuIEhhY2tlciA8 | ||
| 10 | anJoQGV4YW1wbGUuY29tPokBOAQTAQIAIgUCUk0HyAIbAwYLCQgHAwIGFQgCCQoL | ||
| 11 | BBYCAwECHgECF4AACgkQtpVAhgkYletuhQf+JAyHYhTZNxjq0UYlikuLX8EtYbXX | ||
| 12 | PB+03J0B73SMzEai5XsiTU2ADxqxwr7pveVK1INf+IGLiiXBlQq+4DSOvQY4xLfp | ||
| 13 | 58jTOYRV1ECvlXK/JtvVOwufXREADaydf9l/MUxA5G2PPBWIuQknh3ysPSsx68OJ | ||
| 14 | SzNHFwklLn0DKc4WloE/GLDpTzimnCg7QGzuUo3Iilpjdy8EvTdI5d3jx/mGJIwI | ||
| 15 | goB+YZgyxSPM+GjDwh5DEwD7OexNqqa7RynnmU0epmlYyi9UufCHLwgiiEIzjpWi | ||
| 16 | 6+iF+CQ45ZAKncovByenIUv73J3ImOudrsskeAHBmahljv1he6uV9Egj2Q== | ||
| 17 | =b5Kg | ||
| 18 | -----END PGP PUBLIC KEY BLOCK----- | ||
diff --git a/test/automated/data/package/key.sec b/test/automated/data/package/key.sec new file mode 100644 index 00000000000..d21e6ae9a45 --- /dev/null +++ b/test/automated/data/package/key.sec | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | -----BEGIN PGP PRIVATE KEY BLOCK----- | ||
| 2 | Version: GnuPG v1.4.14 (GNU/Linux) | ||
| 3 | |||
| 4 | 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 | ||
| 31 | qGWO/WF7q5X0SCPZ | ||
| 32 | =5FZK | ||
| 33 | -----END PGP PRIVATE KEY BLOCK----- | ||
diff --git a/test/automated/data/package/signed/archive-contents b/test/automated/data/package/signed/archive-contents new file mode 100644 index 00000000000..2a773ecba6a --- /dev/null +++ b/test/automated/data/package/signed/archive-contents | |||
| @@ -0,0 +1,7 @@ | |||
| 1 | (1 | ||
| 2 | (signed-good . | ||
| 3 | [(1 0) | ||
| 4 | nil "A package with good signature" single]) | ||
| 5 | (signed-bad . | ||
| 6 | [(1 0) | ||
| 7 | nil "A package with bad signature" single])) | ||
diff --git a/test/automated/data/package/signed/archive-contents.sig b/test/automated/data/package/signed/archive-contents.sig new file mode 100644 index 00000000000..658edd3f60e --- /dev/null +++ b/test/automated/data/package/signed/archive-contents.sig | |||
| Binary files differ | |||
diff --git a/test/automated/data/package/signed/signed-bad-1.0.el b/test/automated/data/package/signed/signed-bad-1.0.el new file mode 100644 index 00000000000..3734823876e --- /dev/null +++ b/test/automated/data/package/signed/signed-bad-1.0.el | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | ;;; signed-bad.el --- A single-file package with bad signature | ||
| 2 | |||
| 3 | ;; Author: J. R. Hacker <jrh@example.com> | ||
| 4 | ;; Version: 1.0 | ||
| 5 | ;; Keywords: frobnicate | ||
| 6 | ;; URL: http://doodles.au | ||
| 7 | |||
| 8 | ;;; Commentary: | ||
| 9 | |||
| 10 | ;; This package provides a minor mode to frobnicate and/or bifurcate | ||
| 11 | ;; any flanges you desire. To activate it, type "C-M-r M-3 butterfly" | ||
| 12 | ;; and all your dreams will come true. | ||
| 13 | |||
| 14 | ;;; Code: | ||
| 15 | |||
| 16 | (defgroup signed-bad nil "Simply a file" | ||
| 17 | :group 'lisp) | ||
| 18 | |||
| 19 | (defcustom signed-bad-super-sunday t | ||
| 20 | "How great is this?" | ||
| 21 | :type 'boolean | ||
| 22 | :group 'signed-bad) | ||
| 23 | |||
| 24 | (defvar signed-bad-sudo-sandwich nil | ||
| 25 | "Make a sandwich?") | ||
| 26 | |||
| 27 | ;;;###autoload | ||
| 28 | (define-minor-mode signed-bad-mode | ||
| 29 | "It does good things to stuff") | ||
| 30 | |||
| 31 | (provide 'signed-bad) | ||
| 32 | |||
| 33 | ;;; signed-bad.el ends here | ||
diff --git a/test/automated/data/package/signed/signed-bad-1.0.el.sig b/test/automated/data/package/signed/signed-bad-1.0.el.sig new file mode 100644 index 00000000000..747918794ca --- /dev/null +++ b/test/automated/data/package/signed/signed-bad-1.0.el.sig | |||
| Binary files differ | |||
diff --git a/test/automated/data/package/signed/signed-good-1.0.el b/test/automated/data/package/signed/signed-good-1.0.el new file mode 100644 index 00000000000..22718df2763 --- /dev/null +++ b/test/automated/data/package/signed/signed-good-1.0.el | |||
| @@ -0,0 +1,33 @@ | |||
| 1 | ;;; signed-good.el --- A single-file package with good signature | ||
| 2 | |||
| 3 | ;; Author: J. R. Hacker <jrh@example.com> | ||
| 4 | ;; Version: 1.0 | ||
| 5 | ;; Keywords: frobnicate | ||
| 6 | ;; URL: http://doodles.au | ||
| 7 | |||
| 8 | ;;; Commentary: | ||
| 9 | |||
| 10 | ;; This package provides a minor mode to frobnicate and/or bifurcate | ||
| 11 | ;; any flanges you desire. To activate it, type "C-M-r M-3 butterfly" | ||
| 12 | ;; and all your dreams will come true. | ||
| 13 | |||
| 14 | ;;; Code: | ||
| 15 | |||
| 16 | (defgroup signed-good nil "Simply a file" | ||
| 17 | :group 'lisp) | ||
| 18 | |||
| 19 | (defcustom signed-good-super-sunday t | ||
| 20 | "How great is this?" | ||
| 21 | :type 'boolean | ||
| 22 | :group 'signed-good) | ||
| 23 | |||
| 24 | (defvar signed-good-sudo-sandwich nil | ||
| 25 | "Make a sandwich?") | ||
| 26 | |||
| 27 | ;;;###autoload | ||
| 28 | (define-minor-mode signed-good-mode | ||
| 29 | "It does good things to stuff") | ||
| 30 | |||
| 31 | (provide 'signed-good) | ||
| 32 | |||
| 33 | ;;; signed-good.el ends here | ||
diff --git a/test/automated/data/package/signed/signed-good-1.0.el.sig b/test/automated/data/package/signed/signed-good-1.0.el.sig new file mode 100644 index 00000000000..747918794ca --- /dev/null +++ b/test/automated/data/package/signed/signed-good-1.0.el.sig | |||
| Binary files differ | |||
diff --git a/test/automated/package-test.el b/test/automated/package-test.el index 84f520df9bc..ec85432b637 100644 --- a/test/automated/package-test.el +++ b/test/automated/package-test.el | |||
| @@ -254,7 +254,7 @@ Must called from within a `tar-mode' buffer." | |||
| 254 | (should (package-installed-p 'simple-single)) | 254 | (should (package-installed-p 'simple-single)) |
| 255 | (switch-to-buffer "*Packages*") | 255 | (switch-to-buffer "*Packages*") |
| 256 | (goto-char (point-min)) | 256 | (goto-char (point-min)) |
| 257 | (should (re-search-forward "^\\s-+simple-single\\s-+1.3\\s-+installed" nil t)) | 257 | (should (re-search-forward "^\\s-+simple-single\\s-+1.3\\s-+unsigned" nil t)) |
| 258 | (goto-char (point-min)) | 258 | (goto-char (point-min)) |
| 259 | (should-not (re-search-forward "^\\s-+simple-single\\s-+1.3\\s-+\\(available\\|new\\)" nil t)) | 259 | (should-not (re-search-forward "^\\s-+simple-single\\s-+1.3\\s-+\\(available\\|new\\)" nil t)) |
| 260 | (kill-buffer buf)))) | 260 | (kill-buffer buf)))) |
| @@ -276,7 +276,7 @@ Must called from within a `tar-mode' buffer." | |||
| 276 | ;; New version should be available and old version should be installed | 276 | ;; New version should be available and old version should be installed |
| 277 | (goto-char (point-min)) | 277 | (goto-char (point-min)) |
| 278 | (should (re-search-forward "^\\s-+simple-single\\s-+1.4\\s-+new" nil t)) | 278 | (should (re-search-forward "^\\s-+simple-single\\s-+1.4\\s-+new" nil t)) |
| 279 | (should (re-search-forward "^\\s-+simple-single\\s-+1.3\\s-+installed" nil t)) | 279 | (should (re-search-forward "^\\s-+simple-single\\s-+1.3\\s-+unsigned" nil t)) |
| 280 | 280 | ||
| 281 | (goto-char (point-min)) | 281 | (goto-char (point-min)) |
| 282 | (should (re-search-forward "^\\s-+new-pkg\\s-+1.0\\s-+\\(available\\|new\\)" nil t)) | 282 | (should (re-search-forward "^\\s-+new-pkg\\s-+1.0\\s-+\\(available\\|new\\)" nil t)) |
| @@ -307,9 +307,9 @@ Must called from within a `tar-mode' buffer." | |||
| 307 | (with-fake-help-buffer | 307 | (with-fake-help-buffer |
| 308 | (describe-package 'simple-single) | 308 | (describe-package 'simple-single) |
| 309 | (goto-char (point-min)) | 309 | (goto-char (point-min)) |
| 310 | (should (search-forward "simple-single is an installed package." nil t)) | 310 | (should (search-forward "simple-single is an unsigned package." nil t)) |
| 311 | (should (search-forward | 311 | (should (search-forward |
| 312 | (format "Status: Installed in `%s/'." | 312 | (format "Status: Installed in `%s/' (unsigned)." |
| 313 | (expand-file-name "simple-single-1.3" package-user-dir)) | 313 | (expand-file-name "simple-single-1.3" package-user-dir)) |
| 314 | nil t)) | 314 | nil t)) |
| 315 | (should (search-forward "Version: 1.3" nil t)) | 315 | (should (search-forward "Version: 1.3" nil t)) |
| @@ -347,6 +347,37 @@ Must called from within a `tar-mode' buffer." | |||
| 347 | (should (search-forward "This is a bare-bones readme file for the multi-file" | 347 | (should (search-forward "This is a bare-bones readme file for the multi-file" |
| 348 | nil t))))) | 348 | nil t))))) |
| 349 | 349 | ||
| 350 | (ert-deftest package-test-signed () | ||
| 351 | "Test verifying package signature." | ||
| 352 | :expected-result (condition-case nil | ||
| 353 | (progn | ||
| 354 | (epg-check-configuration (epg-configuration)) | ||
| 355 | :passed) | ||
| 356 | (error :failed)) | ||
| 357 | (let* ((keyring (expand-file-name "key.pub" package-test-data-dir)) | ||
| 358 | (package-test-data-dir | ||
| 359 | (expand-file-name "data/package/signed" package-test-file-dir))) | ||
| 360 | (with-package-test () | ||
| 361 | (package-initialize) | ||
| 362 | (package-import-keyring keyring) | ||
| 363 | (package-refresh-contents) | ||
| 364 | (should (package-install 'signed-good)) | ||
| 365 | (should-error (package-install 'signed-bad)) | ||
| 366 | ;; Check if the installed package status is updated. | ||
| 367 | (let ((buf (package-list-packages))) | ||
| 368 | (package-menu-refresh) | ||
| 369 | (should (re-search-forward "^\\s-+signed-good\\s-+1\\.0\\s-+installed" | ||
| 370 | nil t))) | ||
| 371 | ;; Check if the package description is updated. | ||
| 372 | (with-fake-help-buffer | ||
| 373 | (describe-package 'signed-good) | ||
| 374 | (goto-char (point-min)) | ||
| 375 | (should (search-forward "signed-good is an installed package." nil t)) | ||
| 376 | (should (search-forward | ||
| 377 | (format "Status: Installed in `%s/'." | ||
| 378 | (expand-file-name "signed-good-1.0" package-user-dir)) | ||
| 379 | nil t)))))) | ||
| 380 | |||
| 350 | (provide 'package-test) | 381 | (provide 'package-test) |
| 351 | 382 | ||
| 352 | ;;; package-test.el ends here | 383 | ;;; package-test.el ends here |