diff options
| author | Artur Malabarba | 2015-12-05 16:37:01 +0000 |
|---|---|---|
| committer | Artur Malabarba | 2015-12-05 16:42:04 +0000 |
| commit | aac3c8a38f0650e3c703d430f8d606547e0bd73b (patch) | |
| tree | 63af5daea99ddc3d5e5e3d43809f0a91b7ce77de | |
| parent | 0daba4888771e29f2edf170216adaf3d33040bea (diff) | |
| download | emacs-aac3c8a38f0650e3c703d430f8d606547e0bd73b.tar.gz emacs-aac3c8a38f0650e3c703d430f8d606547e0bd73b.zip | |
* lisp/emacs-lisp/package.el: Don't install bad signatures (bug#22089)
(package--with-response-buffer): NOERROR and ERROR-FORM only
handle connection errors.
(bad-signature): New error type.
(package--check-signature-content): Use it.
(package--check-signature): Properly distinguish connection errors
from bad-signature errors. Do the check for
`package-check-signature' `allow-unsigned' here instead of forcing
the callbacks to do it. Add a new argument, UNWIND.
(package--download-one-archive, package-install-from-archive):
Update usage of `package--check-signature'.
| -rw-r--r-- | lisp/emacs-lisp/package.el | 118 |
1 files changed, 62 insertions, 56 deletions
diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index 6b5a2024958..6da3c1e4bc6 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el | |||
| @@ -1133,48 +1133,49 @@ Point is after the headers when BODY runs. | |||
| 1133 | FILE, if provided, is added to URL. | 1133 | FILE, if provided, is added to URL. |
| 1134 | URL can be a local file name, which must be absolute. | 1134 | URL can be a local file name, which must be absolute. |
| 1135 | ASYNC, if non-nil, runs the request asynchronously. | 1135 | ASYNC, if non-nil, runs the request asynchronously. |
| 1136 | ERROR-FORM is run only if an error occurs. If NOERROR is | 1136 | ERROR-FORM is run only if a connection error occurs. If NOERROR |
| 1137 | non-nil, don't propagate errors caused by the connection or by | 1137 | is non-nil, don't propagate connection errors (does not apply to |
| 1138 | BODY (does not apply to errors signaled by ERROR-FORM). | 1138 | errors signaled by ERROR-FORM or by BODY). |
| 1139 | 1139 | ||
| 1140 | \(fn URL &key ASYNC FILE ERROR-FORM NOERROR &rest BODY)" | 1140 | \(fn URL &key ASYNC FILE ERROR-FORM NOERROR &rest BODY)" |
| 1141 | (declare (indent defun) (debug t)) | 1141 | (declare (indent defun) (debug t)) |
| 1142 | (while (keywordp (car body)) | 1142 | (while (keywordp (car body)) |
| 1143 | (setq body (cdr (cdr body)))) | 1143 | (setq body (cdr (cdr body)))) |
| 1144 | (macroexp-let2* nil ((url-1 url)) | 1144 | (macroexp-let2* nil ((url-1 url) |
| 1145 | `(cl-macrolet ((wrap-errors (&rest bodyforms) | 1145 | (noerror-1 noerror)) |
| 1146 | (let ((err (make-symbol "err"))) | 1146 | `(cl-macrolet ((unless-error (body-2 &rest before-body) |
| 1147 | `(condition-case ,err | 1147 | (let ((err (make-symbol "err"))) |
| 1148 | ,(macroexp-progn bodyforms) | 1148 | `(with-temp-buffer |
| 1149 | ,(list 'error ',error-form | 1149 | (when (condition-case ,err |
| 1150 | (list 'unless ',noerror | 1150 | (progn ,@before-body t) |
| 1151 | `(signal (car ,err) (cdr ,err)))))))) | 1151 | ,(list 'error ',error-form |
| 1152 | (list 'unless ',noerror-1 | ||
| 1153 | `(signal (car ,err) (cdr ,err))))) | ||
| 1154 | ,@body-2))))) | ||
| 1152 | (if (string-match-p "\\`https?:" ,url-1) | 1155 | (if (string-match-p "\\`https?:" ,url-1) |
| 1153 | (let* ((url (concat ,url-1 ,file)) | 1156 | (let* ((url (concat ,url-1 ,file)) |
| 1154 | (callback (lambda (status) | 1157 | (callback (lambda (status) |
| 1155 | (let ((b (current-buffer))) | 1158 | (let ((b (current-buffer))) |
| 1156 | (require 'url-handlers) | 1159 | (require 'url-handlers) |
| 1157 | (unwind-protect (wrap-errors | 1160 | (unless-error ,body |
| 1158 | (when-let ((er (plist-get status :error))) | 1161 | (when-let ((er (plist-get status :error))) |
| 1159 | (error "Error retrieving: %s %S" url er)) | 1162 | (error "Error retrieving: %s %S" url er)) |
| 1160 | (goto-char (point-min)) | 1163 | (goto-char (point-min)) |
| 1161 | (unless (search-forward-regexp "^\r?\n\r?" nil 'noerror) | 1164 | (unless (search-forward-regexp "^\r?\n\r?" nil 'noerror) |
| 1162 | (error "Error retrieving: %s %S" url "incomprehensible buffer")) | 1165 | (error "Error retrieving: %s %S" url "incomprehensible buffer")) |
| 1163 | (with-temp-buffer | 1166 | (url-insert-buffer-contents b url) |
| 1164 | (url-insert-buffer-contents b url) | 1167 | (kill-buffer b) |
| 1165 | (kill-buffer b) | 1168 | (goto-char (point-min))))))) |
| 1166 | (goto-char (point-min)) | ||
| 1167 | ,@body))))))) | ||
| 1168 | (if ,async | 1169 | (if ,async |
| 1169 | (wrap-errors (url-retrieve url callback nil 'silent)) | 1170 | (unless-error nil (url-retrieve url callback nil 'silent)) |
| 1170 | (with-current-buffer (wrap-errors (url-retrieve-synchronously url 'silent)) | 1171 | (unless-error ,body (url-insert-file-contents url)))) |
| 1171 | (funcall callback nil)))) | 1172 | (unless-error ,body |
| 1172 | (wrap-errors (with-temp-buffer | 1173 | (let ((url (expand-file-name ,file ,url-1))) |
| 1173 | (let ((url (expand-file-name ,file ,url-1))) | 1174 | (unless (file-name-absolute-p url) |
| 1174 | (unless (file-name-absolute-p url) | 1175 | (error "Location %s is not a url nor an absolute file name" url)) |
| 1175 | (error "Location %s is not a url nor an absolute file name" url)) | 1176 | (insert-file-contents url))))))) |
| 1176 | (insert-file-contents url)) | 1177 | |
| 1177 | ,@body)))))) | 1178 | (define-error 'bad-signature "Failed to verify signature") |
| 1178 | 1179 | ||
| 1179 | (defun package--check-signature-content (content string &optional sig-file) | 1180 | (defun package--check-signature-content (content string &optional sig-file) |
| 1180 | "Check signature CONTENT against STRING. | 1181 | "Check signature CONTENT against STRING. |
| @@ -1186,7 +1187,7 @@ errors." | |||
| 1186 | (condition-case error | 1187 | (condition-case error |
| 1187 | (epg-verify-string context content string) | 1188 | (epg-verify-string context content string) |
| 1188 | (error (package--display-verify-error context sig-file) | 1189 | (error (package--display-verify-error context sig-file) |
| 1189 | (signal (car error) (cdr error)))) | 1190 | (signal 'bad-signature error))) |
| 1190 | (let (good-signatures had-fatal-error) | 1191 | (let (good-signatures had-fatal-error) |
| 1191 | ;; The .sig file may contain multiple signatures. Success if one | 1192 | ;; The .sig file may contain multiple signatures. Success if one |
| 1192 | ;; of the signatures is good. | 1193 | ;; of the signatures is good. |
| @@ -1202,10 +1203,10 @@ errors." | |||
| 1202 | (setq had-fatal-error t)))) | 1203 | (setq had-fatal-error t)))) |
| 1203 | (when (and (null good-signatures) had-fatal-error) | 1204 | (when (and (null good-signatures) had-fatal-error) |
| 1204 | (package--display-verify-error context sig-file) | 1205 | (package--display-verify-error context sig-file) |
| 1205 | (error "Failed to verify signature %s" sig-file)) | 1206 | (signal 'bad-signature (list sig-file))) |
| 1206 | good-signatures))) | 1207 | good-signatures))) |
| 1207 | 1208 | ||
| 1208 | (defun package--check-signature (location file &optional string async callback) | 1209 | (defun package--check-signature (location file &optional string async callback unwind) |
| 1209 | "Check signature of the current buffer. | 1210 | "Check signature of the current buffer. |
| 1210 | Download the signature file from LOCATION by appending \".sig\" | 1211 | Download the signature file from LOCATION by appending \".sig\" |
| 1211 | to FILE. | 1212 | to FILE. |
| @@ -1214,18 +1215,35 @@ STRING is the string to verify, it defaults to `buffer-string'. | |||
| 1214 | If ASYNC is non-nil, the download of the signature file is | 1215 | If ASYNC is non-nil, the download of the signature file is |
| 1215 | done asynchronously. | 1216 | done asynchronously. |
| 1216 | 1217 | ||
| 1217 | If the signature is verified and CALLBACK was provided, CALLBACK | 1218 | If the signature does not verify, signal an error. |
| 1218 | is `funcall'ed with the list of good signatures as argument (the | 1219 | If the signature is verified and CALLBACK was provided, `funcall' |
| 1219 | list can be empty). If the signatures file is not found, | 1220 | CALLBACK with the list of good signatures as argument (the list |
| 1220 | CALLBACK is called with no arguments." | 1221 | can be empty). |
| 1222 | If no signatures file is found, and `package-check-signature' is | ||
| 1223 | `allow-unsigned', call CALLBACK with a nil argument. | ||
| 1224 | Otherwise, an error is signaled. | ||
| 1225 | |||
| 1226 | UNWIND, if provided, is a function to be called after everything | ||
| 1227 | else, even if an error is signaled." | ||
| 1221 | (let ((sig-file (concat file ".sig")) | 1228 | (let ((sig-file (concat file ".sig")) |
| 1222 | (string (or string (buffer-string)))) | 1229 | (string (or string (buffer-string)))) |
| 1223 | (package--with-response-buffer location :file sig-file | 1230 | (package--with-response-buffer location :file sig-file |
| 1224 | :async async :noerror t | 1231 | :async async :noerror t |
| 1225 | :error-form (when callback (funcall callback nil)) | 1232 | ;; Connection error is assumed to mean "no sig-file". |
| 1226 | (let ((sig (package--check-signature-content (buffer-substring (point) (point-max)) string sig-file))) | 1233 | :error-form (let ((allow-unsigned (eq package-check-signature 'allow-unsigned))) |
| 1227 | (when callback (funcall callback sig)) | 1234 | (when (and callback allow-unsigned) |
| 1228 | sig)))) | 1235 | (funcall callback nil)) |
| 1236 | (when unwind (funcall unwind)) | ||
| 1237 | (unless allow-unsigned | ||
| 1238 | (error "Unsigned file `%s' at %s" file location))) | ||
| 1239 | ;; OTOH, an error here means "bad signature", which we never | ||
| 1240 | ;; suppress. (Bug#22089) | ||
| 1241 | (unwind-protect | ||
| 1242 | (let ((sig (package--check-signature-content (buffer-substring (point) (point-max)) | ||
| 1243 | string sig-file))) | ||
| 1244 | (when callback (funcall callback sig)) | ||
| 1245 | sig) | ||
| 1246 | (when unwind (funcall unwind)))))) | ||
| 1229 | 1247 | ||
| 1230 | ;;; Packages on Archives | 1248 | ;;; Packages on Archives |
| 1231 | ;; The following variables store information about packages available | 1249 | ;; The following variables store information about packages available |
| @@ -1488,19 +1506,12 @@ similar to an entry in `package-alist'. Save the cached copy to | |||
| 1488 | location file content async | 1506 | location file content async |
| 1489 | ;; This function will be called after signature checking. | 1507 | ;; This function will be called after signature checking. |
| 1490 | (lambda (&optional good-sigs) | 1508 | (lambda (&optional good-sigs) |
| 1491 | (unless (or good-sigs (eq package-check-signature 'allow-unsigned)) | ||
| 1492 | ;; Even if the sig fails, this download is done, so | ||
| 1493 | ;; remove it from the in-progress list. | ||
| 1494 | (package--update-downloads-in-progress archive) | ||
| 1495 | (error "Unsigned archive `%s'" name)) | ||
| 1496 | ;; Either everything worked or we don't mind not signing. | ||
| 1497 | ;; Write out the archives file. | ||
| 1498 | (write-region content nil local-file nil 'silent) | 1509 | (write-region content nil local-file nil 'silent) |
| 1499 | ;; Write out good signatures into archive-contents.signed file. | 1510 | ;; Write out good signatures into archive-contents.signed file. |
| 1500 | (when good-sigs | 1511 | (when good-sigs |
| 1501 | (write-region (mapconcat #'epg-signature-to-string good-sigs "\n") | 1512 | (write-region (mapconcat #'epg-signature-to-string good-sigs "\n") |
| 1502 | nil (concat local-file ".signed") nil 'silent)) | 1513 | nil (concat local-file ".signed") nil 'silent))) |
| 1503 | (package--update-downloads-in-progress archive)))))))) | 1514 | (lambda () (package--update-downloads-in-progress archive)))))))) |
| 1504 | 1515 | ||
| 1505 | (defun package--download-and-read-archives (&optional async) | 1516 | (defun package--download-and-read-archives (&optional async) |
| 1506 | "Download descriptions of all `package-archives' and read them. | 1517 | "Download descriptions of all `package-archives' and read them. |
| @@ -1782,11 +1793,6 @@ if all the in-between dependencies are also in PACKAGE-LIST." | |||
| 1782 | location file content nil | 1793 | location file content nil |
| 1783 | ;; This function will be called after signature checking. | 1794 | ;; This function will be called after signature checking. |
| 1784 | (lambda (&optional good-sigs) | 1795 | (lambda (&optional good-sigs) |
| 1785 | (unless (or good-sigs (eq package-check-signature 'allow-unsigned)) | ||
| 1786 | ;; Even if the sig fails, this download is done, so | ||
| 1787 | ;; remove it from the in-progress list. | ||
| 1788 | (error "Unsigned package: `%s'" | ||
| 1789 | (package-desc-name pkg-desc))) | ||
| 1790 | ;; Signature checked, unpack now. | 1796 | ;; Signature checked, unpack now. |
| 1791 | (with-temp-buffer (insert content) | 1797 | (with-temp-buffer (insert content) |
| 1792 | (let ((save-silently t)) | 1798 | (let ((save-silently t)) |