--- emacs-24.4/lisp/emacs-lisp/package.el +++ emacs-24.4/lisp/emacs-lisp/package.el @@ -314,6 +314,11 @@ (defvar package--default-summary "No description available.") +(defvar package-hashfun 'sha256 "Function for secure hashing.") + +(defvar package-acceptable-hashfuns '(sha256) + "Past and current `package-hashfun' functions that are still secure.") + (cl-defstruct (package-desc ;; Rename the default constructor from `make-package-desc'. (:constructor package-desc-create) @@ -843,6 +848,20 @@ (epg-context-result-for context 'verify))) good-signatures)))) +(defun package--check-size (pkg-desc) + (eq (cdr (assoc :size (package-desc-extras pkg-desc))) + (pcase (package-desc-kind pkg-desc) + (`single (string-bytes (buffer-string))) + (`tar (buffer-size)) ; Because insert-file-contents mangled the literal + (kind (error "Unknown package kind: %s" kind))))) + +(defun package--check-hash (pkg-desc) + (let* ((x (cdr (assoc :hash (package-desc-extras pkg-desc)))) + (hashfun (car x)) ; Avoid Git's shortsightedness + (hash (cadr x))) + (and (memq hashfun package-acceptable-hashfuns) + (string= hash (secure-hash hashfun (current-buffer)))))) + (defun package-install-from-archive (pkg-desc) "Download and install a tar package." (let* ((location (package-archive-base pkg-desc)) @@ -859,6 +878,10 @@ (unless (eq package-check-signature 'allow-unsigned) (error "Unsigned package: `%s'" (package-desc-name pkg-desc))))) + (unless (package--check-size pkg-desc) + (error "File size not correct: %s" (package-desc-name pkg-desc))) + (unless (package--check-hash pkg-desc) + (error "Failed to verify hash: %s" (package-desc-name pkg-desc))) (package-unpack pkg-desc)) ;; Here the package has been installed successfully, mark it as ;; signed if appropriate. @@ -1172,7 +1195,10 @@ (package--prepare-dependencies (package-read-from-string requires-str))) :kind 'single - :url homepage)))) + :url homepage + :size (string-bytes (buffer-string)) + :hash (list package-hashfun + (secure-hash package-hashfun (current-buffer))))))) (declare-function tar-get-file-descriptor "tar-mode" (file)) (declare-function tar--extract "tar-mode" (descriptor)) @@ -1184,7 +1210,10 @@ (let* ((dir-name (file-name-directory (tar-header-name (car tar-parse-info)))) (desc-file (package--description-file dir-name)) - (tar-desc (tar-get-file-descriptor (concat dir-name desc-file)))) + (tar-desc (tar-get-file-descriptor (concat dir-name desc-file))) + (size (buffer-size tar-data-buffer)) + (hash (list package-hashfun + (secure-hash package-hashfun tar-data-buffer)))) (unless tar-desc (error "No package descriptor file found")) (with-current-buffer (tar--extract tar-desc) @@ -1196,7 +1225,8 @@ (error "Can't find define-package in %s" (tar-header-name tar-desc)) (apply #'package-desc-from-define - (append (cdr pkg-def-parsed)))))) + (append (cdr pkg-def-parsed) + (list :size size :hash hash)))))) (setf (package-desc-kind pkg-desc) 'tar) pkg-desc) (kill-buffer (current-buffer))))))