aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtur Malabarba2015-12-05 16:37:01 +0000
committerArtur Malabarba2015-12-05 16:42:04 +0000
commitaac3c8a38f0650e3c703d430f8d606547e0bd73b (patch)
tree63af5daea99ddc3d5e5e3d43809f0a91b7ce77de
parent0daba4888771e29f2edf170216adaf3d33040bea (diff)
downloademacs-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.el118
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.
1133FILE, if provided, is added to URL. 1133FILE, if provided, is added to URL.
1134URL can be a local file name, which must be absolute. 1134URL can be a local file name, which must be absolute.
1135ASYNC, if non-nil, runs the request asynchronously. 1135ASYNC, if non-nil, runs the request asynchronously.
1136ERROR-FORM is run only if an error occurs. If NOERROR is 1136ERROR-FORM is run only if a connection error occurs. If NOERROR
1137non-nil, don't propagate errors caused by the connection or by 1137is non-nil, don't propagate connection errors (does not apply to
1138BODY (does not apply to errors signaled by ERROR-FORM). 1138errors 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.
1210Download the signature file from LOCATION by appending \".sig\" 1211Download the signature file from LOCATION by appending \".sig\"
1211to FILE. 1212to FILE.
@@ -1214,18 +1215,35 @@ STRING is the string to verify, it defaults to `buffer-string'.
1214If ASYNC is non-nil, the download of the signature file is 1215If ASYNC is non-nil, the download of the signature file is
1215done asynchronously. 1216done asynchronously.
1216 1217
1217If the signature is verified and CALLBACK was provided, CALLBACK 1218If the signature does not verify, signal an error.
1218is `funcall'ed with the list of good signatures as argument (the 1219If the signature is verified and CALLBACK was provided, `funcall'
1219list can be empty). If the signatures file is not found, 1220CALLBACK with the list of good signatures as argument (the list
1220CALLBACK is called with no arguments." 1221can be empty).
1222If no signatures file is found, and `package-check-signature' is
1223`allow-unsigned', call CALLBACK with a nil argument.
1224Otherwise, an error is signaled.
1225
1226UNWIND, if provided, is a function to be called after everything
1227else, 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))