From 733e674af4f66ba7e9f0614b931c44484acce2b9 Mon Sep 17 00:00:00 2001 From: Stefan Kangas Date: Fri, 4 Oct 2019 10:36:14 +0200 Subject: [PATCH] Support package checksum verification Package checksum verification is the first step towards protecting users of package.el against replay attacks. Signing individual packages still allows a hostile actor to distribute an out-of-date package containing a known security defect. To avoid that, we need to distribute signed package metadata (the ELPA "archive-contents" file) and checksums for the individual packages together. (Bug#19479) A subsequent patch will add support for last-update and expiration timestamps in "archive-contents", without which the protection against replay attacks will be largely ineffective. Taken together, this feature will make signing individual packages obsolete. We will instead rely on signing the metadata, package checksums and timestamps. Note that individual package signatures should still be distributed for a long time still to support old versions of Emacs. For more on replay attacks, see: https://www2.cs.arizona.edu/stork/packagemanagersecurity/attacks-on-package-managers.html * lisp/emacs-lisp/package.el (package-verify-checksums): New defcustom. (package-desc, package--ac-desc) (package--add-to-archive-contents, package-install-from-archive): New fields 'size' and 'checksums'. (package-desc-filename): New function. (package-error): New error type. (bad-signature): Inherit from error type 'package-error'. (bad-checksum, bad-size): New error types. (package-insecure-hash-algorithms): New constant. (package--verify-package-checksum) (package--verify-package-size): New function to verify that the checksum and size of a package corresponds to the checksum and size data in the "archive-contents" file on the package archive. (package--show-verify-checksum-error): New function to show details of an error on checksum verification. * lisp/emacs-lisp/package-x.el (package-upload-buffer-internal): Update to use above new fields 'size' and 'checksums'. * test/lisp/emacs-lisp/package-tests.el (package-test-refresh-contents) (package-test-install-single-from-archive) (package-test-list-filter-by-archive) (package-test-list-filter-by-status): Update tests. (with-install-using-checksum): New macro. (package-test-install-wrong-size-single) (package-test-install-wrong-size-tar): New tests for size checking. (package-test-install-with-checksum/single-valid) (package-test-install-with-checksum/single-invalid) (package-test-install-with-checksum/tar-valid) (package-test-install-with-checksum/tar-invalid): New tests for installing packages with checksums. (package-test-verification-text) (package-tests-valid-md5-checksum) (package-tests-valid-sha256-checksum) (package-tests-valid-sha512-checksum): New variables. (package-tests--run-verify-checksums-test): New macro. (package-test-verify-package-checksums-nil/ignore-invalid) (package-test-verify-package-checksums-allow-missing) (package-test-verify-package-checksums-allow-missing/missing) (package-test-verify-package-checksums-allow-missing/ignore-unsupported) (package-test-verify-package-checksums-t) (package-test-verify-package-checksums-t/invalid-fails) (package-test-verify-package-checksums-t/missing-fails) (package-test-verify-package-checksums-all) (package-test-verify-package-checksums-all/invalid-fails) (package-test-verify-package-checksums-all/missing-fails) (package-test-verify-package-checksums-all/no-supported-hash-fails) (package-test-verify-package-checksums-all/ignore-unsupported) (package-test-verify-package-size): New tests for the checksum support. * test/lisp/emacs-lisp/package-resources/archive-contents: * test/lisp/emacs-lisp/package-resources/checksum-invalid-1.0.el: * test/lisp/emacs-lisp/package-resources/checksum-valid-123.el: * test/lisp/emacs-lisp/package-resources/checksum-valid-tar-0.99.tar: * test/lisp/emacs-lisp/package-resources/checksum-valid-tar-0.99.tar: New test data files. * doc/emacs/package.texi (Package Installation): Document package checksum checking. * etc/NEWS: Announce it. --- doc/emacs/package.texi | 45 ++-- etc/NEWS | 15 ++ lisp/emacs-lisp/package-x.el | 4 +- lisp/emacs-lisp/package.el | 166 ++++++++++++-- .../package-resources/archive-contents | 36 +++- .../package-resources/checksum-invalid-1.0.el | 17 ++ .../checksum-invalid-tar-0.1.tar | Bin 0 -> 10240 bytes .../package-resources/checksum-valid-123.el | 17 ++ .../checksum-valid-tar-0.99.tar | Bin 0 -> 10240 bytes .../wrong-size-single-1.0.el | 1 + .../package-resources/wrong-size-tar-1.0.tar | Bin 0 -> 10240 bytes test/lisp/emacs-lisp/package-tests.el | 203 +++++++++++++++++- 12 files changed, 470 insertions(+), 34 deletions(-) create mode 100644 test/lisp/emacs-lisp/package-resources/checksum-invalid-1.0.el create mode 100644 test/lisp/emacs-lisp/package-resources/checksum-invalid-tar-0.1.tar create mode 100644 test/lisp/emacs-lisp/package-resources/checksum-valid-123.el create mode 100644 test/lisp/emacs-lisp/package-resources/checksum-valid-tar-0.99.tar create mode 100644 test/lisp/emacs-lisp/package-resources/wrong-size-single-1.0.el create mode 100644 test/lisp/emacs-lisp/package-resources/wrong-size-tar-1.0.tar diff --git a/doc/emacs/package.texi b/doc/emacs/package.texi index 4981dd50c75..9a583561903 100644 --- a/doc/emacs/package.texi +++ b/doc/emacs/package.texi @@ -338,20 +338,41 @@ name of the package archive directory. You can alter this list if you wish to use third party package archives---but do so at your own risk, and use only third parties that you think you can trust! -@anchor{Package Signing} +@anchor{Package Checksums} @cindex package security +@cindex package checksums + To improve security, maintainers of package archive can add two +important measures: checksums and signatures of metadata. When used +together, they can increase your trust that a downloaded package has +not been tampered with, and is not out of date. Valid checksums and +signatures are not a cast-iron guarantee that a package is not +malicious, so you should still exercise caution. Only install +packages from package archives that you trust. + + When installing a package from an archive providing package +checksums, the package system will automatically verify that they +match the downloaded package. By default, Emacs will refuse to +install a package with an invalid checksum, but still allow installing +a package if checksums are missing. To disable installing packages +from archives without checksums, you can set user the user option +@code{package-verify-checksums} to @code{t}. This improves security, +but requires that all package archives you use distribute checksums. + +@anchor{Package Signing} @cindex package signing The maintainers of package archives can increase the trust that you -can have in their packages by @dfn{signing} them. They generate a -private/public pair of cryptographic keys, and use the private key to -create a @dfn{signature file} for each package. With the public key, you -can use the signature files to verify the package creator and make sure -the package has not been tampered with. Signature verification uses -@uref{https://www.gnupg.org/, the GnuPG package} via the EasyPG -interface (@pxref{Top,, EasyPG, epa, Emacs EasyPG Assistant Manual}). -A valid signature is not a cast-iron -guarantee that a package is not malicious, so you should still -exercise caution. Package archives should provide instructions +can have in their packages and package listings by @dfn{signing} them. +They generate a private/public pair of cryptographic keys, and use the +private key to create a @dfn{signature file} for the package listing +itself or each individual package. With the public key, you can use +the signature files to verify the files have not been tampered with. +Signature verification uses @uref{https://www.gnupg.org/, the GnuPG +package} via the EasyPG interface (@pxref{Top,, EasyPG, epa, Emacs +EasyPG Assistant Manual}). + +The public key for the GNU package archive is distributed with Emacs, +in the @file{etc/package-keyring.gpg}. Emacs uses it automatically. +Other package archives should provide instructions on how you can obtain their public key. One way is to download the key from a server such as @url{https://pgp.mit.edu/}. Use @kbd{M-x package-import-keyring} to import the key into Emacs. @@ -361,8 +382,6 @@ subdirectory of @code{package-user-dir}, which causes Emacs to invoke GnuPG with the option @samp{--homedir} when verifying signatures. If @code{package-gnupghome-dir} is @code{nil}, GnuPG's option @samp{--homedir} is omitted. -The public key for the GNU package archive is distributed with Emacs, -in the @file{etc/package-keyring.gpg}. Emacs uses it automatically. @vindex package-check-signature @vindex package-unsigned-archives diff --git a/etc/NEWS b/etc/NEWS index 9361cff3869..da18848bc4a 100644 --- a/etc/NEWS +++ b/etc/NEWS @@ -867,6 +867,21 @@ See the new user options 'package-name-column-width', 'package-version-column-width', 'package-status-column-width', and 'package-archive-column-width'. +*** Support for package checksums. +This improves the security of the Emacs package system. If the +package archives you use implements package checksums, you will +automatically benefit from this by default. + +The user option 'package-verify-checksums' controls how and when the +package system will use checksums. The default is 'allow-missing', +which will check them when they are available yet allow installation +if they are missing. + +For improved security, you might want to set this to 't' or +'all'. Make sure that the package archives you use support checksums +before setting these values, or you will be unable to install +packages. + ** gdb-mi +++ diff --git a/lisp/emacs-lisp/package-x.el b/lisp/emacs-lisp/package-x.el index c01b6efd4ef..964cf07cd6e 100644 --- a/lisp/emacs-lisp/package-x.el +++ b/lisp/emacs-lisp/package-x.el @@ -219,7 +219,9 @@ if it exists." (let ((contents (or (package--archive-contents-from-url archive-url) (package--archive-contents-from-file))) (new-desc (package-make-ac-desc - split-version requires desc file-type extras))) + split-version requires desc file-type extras + ;; FIXME: Use better values than nil nil. + nil nil))) (if (> (car contents) package-archive-version) (error "Unrecognized archive version %d" (car contents))) (let ((elt (assq pkg-name (cdr contents)))) diff --git a/lisp/emacs-lisp/package.el b/lisp/emacs-lisp/package.el index 9c37ce429a7..308f9eb3a63 100644 --- a/lisp/emacs-lisp/package.el +++ b/lisp/emacs-lisp/package.el @@ -335,6 +335,31 @@ default directory." :risky t :version "26.1") +(defcustom package-verify-checksums 'allow-missing + "Non-nil means to verify the checksum of a package before installing it. + +This can be one of: +- t Require a valid checksum; refuse to install + package if the checksum is missing or invalid. + Verify only one checksum. +- `all' Same as t, but verify all available (and supported) + checksums. +- `allow-missing' Same as t if a checksum exists, but install a + package even if there is no checksum. +- nil Ignore checksums. + +The package checksums are automatically fetched from package +archives with the package data on `package-refresh-contents'. + +Note that setting this to nil is intended for debugging, and +should normally not be used since it will decrease security." + :type '(choice (const nil :tag "Never") + (const allow-missing :tag "Allow missing") + (const t :tag "Require valid checksum") + (const t :tag "Require valid checksum, and check all")) + :risky t + :version "28.1") + (defcustom package-check-signature 'allow-unsigned "Non-nil means to check package signatures when installing. More specifically the value can be: @@ -417,6 +442,14 @@ synchronously." :type 'number :version "28.1") + +;;; Errors + +(define-error 'package-error "Unknown package error") +(define-error 'bad-size "Package size mismatch" 'package-error) +(define-error 'bad-signature "Failed to verify signature" 'package-error) +(define-error 'bad-checksum "Failed to verify checksum" 'package-error) + ;;; `package-desc' object definition ;; This is the struct used internally to represent packages. @@ -449,6 +482,8 @@ synchronously." requirements))) (kind (plist-get rest-plist :kind)) (archive (plist-get rest-plist :archive)) + (checksums (plist-get rest-plist :checksums)) + (size (plist-get rest-plist :size)) (extras (let (alist) (while rest-plist (unless (memq (car rest-plist) '(:kind :archive)) @@ -486,6 +521,13 @@ Slots: `extras' Optional alist of additional keyword-value pairs. +`size' Size of the package in bytes. + +`checksums' Checksums for the package file. Alist of ((ALGORITHM + . CHECKSUM)) where ALGORITHM is a symbol specifying a + `secure-hash' algorithm, and CHECKSUM is a string + containing the checksum. + `signed' Flag to indicate that the package is signed by provider." name version @@ -495,7 +537,9 @@ Slots: archive dir extras - signed) + signed + size + checksums) (defun package--from-builtin (bi-desc) "Create a `package-desc' object from BI-DESC. @@ -558,6 +602,13 @@ Signal an error if the kind is none of the above." ('dir "") (kind (error "Unknown package kind: %s" kind)))) +(defun package-desc-filename (pkg-desc) + "Return file-name of package-desc object PKG-DESC. +This is the concatenation of `package-desc-full-name' and +`package-desc-suffix'." + (concat (package-desc-full-name pkg-desc) + (package-desc-suffix pkg-desc))) + (defun package-desc--keywords (pkg-desc) "Return keywords of package-desc object PKG-DESC. These keywords come from the foo-pkg.el file, and in general @@ -1334,7 +1385,88 @@ errors signaled by ERROR-FORM or by BODY). url)) (insert-file-contents-literally url))))) -(define-error 'bad-signature "Failed to verify signature") +(defun package--show-verify-checksum-error (pkg-desc details) + "Show error on failed checksum verification of PKG-DESC with DETAILS. +Error is displayed in a new buffer named \"*Error*\"." + (with-output-to-temp-buffer "*Error*" + (with-current-buffer standard-output + (insert (format "Failed to verify checksum of package `%s':\n\n" + (package-desc-name pkg-desc))) + (insert details)))) + +(defconst package-insecure-hash-algorithms '(md5 sha1) + "List of hash algorithms that are not considered secure.") + +(defun package--verify-package-checksum (pkg-desc) + "Verify checksums of `package-desc' object PKG-DESC. +This assumes that the we are in a buffer containing package. + +The value of `package-verify-checksums' decides what this +function does: +- t Verify that there is at least one valid checksum. +- `all' Like t, but check all supported checksums. +- `allow-missing' Verify checksum if it exists, otherwise do + nothing. +- nil Do nothing. + +Signal an error of type `bad-checksum' if the verification." + (cl-flet* + ((supported-hashes + (lambda () + (or (seq-filter + (lambda (h) + (and (memql (car h) (secure-hash-algorithms)) + (not (memql (car h) package-insecure-hash-algorithms)))) + (package-desc-checksums pkg-desc)) + ;; Failed; signal error. + (package--show-verify-checksum-error + pkg-desc + (concat + (if (package-desc-checksums pkg-desc) + (concat + "No supported checksums found\n\n" + (format-message "Package archive had: %s\n" + (package-desc-checksums pkg-desc)) + (format-message "Emacs supports: %s\n" + (secure-hash-algorithms))) + "Package archive had no checksums for this package\n"))) + (signal 'bad-checksum "no supported checksums found")))) + (do-check + (lambda (&optional all) + (dolist (hash (seq-take (supported-hashes) + (if all most-positive-fixnum 1))) + (let* ((algorithm (car hash)) + (expected (cdr hash)) + (actual (secure-hash algorithm (current-buffer)))) + (if (equal expected actual) t + ;; Failed; signal error. + (package--show-verify-checksum-error + pkg-desc + (concat + (format-message "\nChecksum mismatch (%s)\n\n" algorithm) + (format-message "Expected: %s\n" expected) + (format-message "Result: %s\n" actual))) + (signal 'bad-checksum (list "checksum mismatch" expected actual)))))))) + (pcase package-verify-checksums + ('nil nil) + ('allow-missing (when (package-desc-checksums pkg-desc) (do-check))) + ('t (do-check)) + ('all (do-check 'all)) + (_ (user-error "Value of `package-verify-checksums' is invalid: `%s'" + package-verify-checksums))))) + +(defun package--verify-package-size (pkg-desc) + "Verify package size of `package-desc' object PKG-DESC. +This assumes that the we are in a buffer containing package." + (when-let ((expected (package-desc-size pkg-desc)) + (actual (string-bytes (buffer-string)))) + (unless (equal expected actual) + (with-output-to-temp-buffer "*Error*" + (with-current-buffer standard-output + (insert (format "Mismatch in package size for `%s':\n" + (package-desc-name pkg-desc))) + (insert (format "Expected %s bytes, but received %s" expected actual)))) + (signal 'bad-size (list "size mismatch" expected actual))))) (defun package--check-signature-content (content string &optional sig-file) "Check signature CONTENT against STRING. @@ -1461,14 +1593,19 @@ the table." (version-list-< table-version version)) (puthash name version package--compatibility-table))))) -;; Package descriptor objects used inside the "archive-contents" file. -;; Changing this defstruct implies changing the format of the -;; "archive-contents" files. (cl-defstruct (package--ac-desc - (:constructor package-make-ac-desc (version reqs summary kind extras)) + (:constructor + package-make-ac-desc (version reqs summary kind extras size checksums)) (:copier nil) (:type vector)) - version reqs summary kind extras) + "Package descriptor object used inside the \"archive-contents\" file. +Changing this defstruct implies changing the format of the +\"archive-contents\" files. + +This is mainly used in `package--add-to-archive-contents' to make +the code that parses the \"archive-contents\" file more +readable." + version reqs summary kind extras size checksums) (defun package--append-to-alist (pkg-desc alist) "Append an entry for PKG-DESC to the start of ALIST and return it. @@ -1506,10 +1643,14 @@ Also, add the originating archive to the `package-desc' structure." :summary (package--ac-desc-summary (cdr package)) :kind (package--ac-desc-kind (cdr package)) :archive archive + ;; Older "archive-contents" files might not have the + ;; below elements. :extras (and (> (length (cdr package)) 4) - ;; Older archive-contents files have only 4 - ;; elements here. - (package--ac-desc-extras (cdr package))))) + (package--ac-desc-extras (cdr package))) + :size (and (> (length (cdr package)) 5) + (package--ac-desc-size (cdr package))) + :checksums (and (> (length (cdr package)) 6) + (package--ac-desc-checksums (cdr package))))) (pinned-to-archive (assoc name package-pinned-packages))) ;; Skip entirely if pinned to another archive. (when (not (and pinned-to-archive @@ -1979,9 +2120,10 @@ if all the in-between dependencies are also in PACKAGE-LIST." (when (eq (package-desc-kind pkg-desc) 'dir) (error "Can't install directory package from archive")) (let* ((location (package-archive-base pkg-desc)) - (file (concat (package-desc-full-name pkg-desc) - (package-desc-suffix pkg-desc)))) + (file (package-desc-filename pkg-desc))) (package--with-response-buffer location :file file + (package--verify-package-size pkg-desc) + (package--verify-package-checksum pkg-desc) (if (or (not (package-check-signature)) (member (package-desc-archive pkg-desc) package-unsigned-archives)) diff --git a/test/lisp/emacs-lisp/package-resources/archive-contents b/test/lisp/emacs-lisp/package-resources/archive-contents index e2f92304f86..724972dd6b5 100644 --- a/test/lisp/emacs-lisp/package-resources/archive-contents +++ b/test/lisp/emacs-lisp/package-resources/archive-contents @@ -14,4 +14,38 @@ (multi-file . [(0 2 3) nil "Example of a multi-file tar package" tar - ((:url . "http://puddles.li"))])) + ((:url . "http://puddles.li"))]) + (checksum-valid . + [(123) + nil "A single-file package with a valid checksum." single + nil + 343 + ((sha512 . "a889917427569cc6817db5db08a88390d44ec010acdf6810c2dfaba04b9a03f00315378c3f03d5f4d531833028ad61db54c4c56106662585da6a0dde602f5c0d"))]) + (checksum-valid-tar . + [(0 99) + nil "A multi-file package with a valid checksum." tar + nil + 10240 + ((sha512 . "2be7c37a16db32a2b08fc917ed5f4241814e2665bda1bd15328c2e5a842e45b81f6f31274697248ffaabf8010796685acb3342c5920af53ddd1e75d7fd764bd1"))]) + (checksum-invalid . + [(1 0) + nil "A single-file package with an invalid checksum." single + nil + 365 + ((sha512 . "not-a-valid-checksum"))]) + (checksum-invalid-tar . + [(0 1) + nil "A multi-file package with an invalid checksum." tar + nil + 10240 + ((sha512 . "not-a-valid-checksum"))]) + (wrong-size-single . + [(1 0) + nil "A single-file package with an invalid size." single + nil + 1]) + (wrong-size-tar . + [(1 0) + nil "A multi-file package with an invalid size." tar + nil + 1])) diff --git a/test/lisp/emacs-lisp/package-resources/checksum-invalid-1.0.el b/test/lisp/emacs-lisp/package-resources/checksum-invalid-1.0.el new file mode 100644 index 00000000000..c3d47901ce5 --- /dev/null +++ b/test/lisp/emacs-lisp/package-resources/checksum-invalid-1.0.el @@ -0,0 +1,17 @@ +;;; checksum-invalid.el --- A package with an invalid checksum in archive-contents + +;; Version: 1.0 + +;;; Commentary: + +;; This package has an invalid checksum in archive-contents and is +;; just used to verify that package.el refuses to install. + +;;; Code: + +(defun p-equal-to-np-p () + (error "FIXME")) + +(provide 'checksum-invalid) + +;;; checksum-invalid.el ends here diff --git a/test/lisp/emacs-lisp/package-resources/checksum-invalid-tar-0.1.tar b/test/lisp/emacs-lisp/package-resources/checksum-invalid-tar-0.1.tar new file mode 100644 index 0000000000000000000000000000000000000000..8adc7f557bc2d294a65d5966224936f41bf65d0b GIT binary patch literal 10240 zcmeIwv2KGf5C&k+d5YUIL2a)F#SMssAk=?riMu zr|xY%gyobuf9BCOS>!pBxq1=LE19Y?Mx;emMt)w`)>=Z9MjKO=>Y#;GrqD`|dEOPa zPg+8HF_8!Z`;Nor;7|R{jeomQZ{`18Be&xtuUP{==#=Z1{OMLo8@lGNO{oe&h0;YO zNIvqhd-weF{EtU^>n+ujkJiUPQ%kXTf!?_uxUeRm1G4pDu>b%7 literal 0 HcmV?d00001 diff --git a/test/lisp/emacs-lisp/package-resources/checksum-valid-123.el b/test/lisp/emacs-lisp/package-resources/checksum-valid-123.el new file mode 100644 index 00000000000..8cfc3871c54 --- /dev/null +++ b/test/lisp/emacs-lisp/package-resources/checksum-valid-123.el @@ -0,0 +1,17 @@ +;;; checksum-valid.el --- A package with an valid checksum in archive-contents + +;; Version: 123 + +;;; Commentary: + +;; This package has an valid checksum in archive-contents and is +;; used to verify that package.el installs it. + +;;; Code: + +(defun p-equal-to-np-p () + (error "FIXME")) + +(provide 'checksum-valid) + +;;; checksum-valid.el ends here diff --git a/test/lisp/emacs-lisp/package-resources/checksum-valid-tar-0.99.tar b/test/lisp/emacs-lisp/package-resources/checksum-valid-tar-0.99.tar new file mode 100644 index 0000000000000000000000000000000000000000..e468754bb94d96a047df7a5c5926eb1d065e363f GIT binary patch literal 10240 zcmeHLU60y25aoG)#V9WYX#)vMsLEDX;_ihOX+IFKZTHb616Z5bxwZr4-`{cg=w1O^ zwc3?h)e#~P+cV>HX3iMm1;&rM$owTsdEy(U{Gk5sU8C}XS3uX>D5}scd>aK%?{>&u zmGB~JMNvC!h3!fZMnM=|A)`(nEvEGY>hut|IOf{wXgq+uvrP3 zAvFwF|33-$4=uaAygX9c#5MT7552D}%Si;}j0EB^CBU}MtqPo-k)*cE9Mn^hFJXoWjP-$Aw0edhh7nGt^suL+! z&XlnMez?7dUdCd*F}nY1)oo^j(Ayw7u$BeHOpwkcTpPuwg+bs3m`EBVcbQE1Y;9fB zGl~~C3TRMe+Iq5bXw82>fr_OtET$=s;hM)NGy=V7f1g51OyW%tu$Z1@`aTebo1Ryz(d=BwB~K9E96F%k z({+y`(Lni#uC4!&lK!5P50m3)|IZ)iuh##AX3*aEe>x0o`ak{tbLaop&nYV^T%f=0 z;&4=sJllCa@cwrk$cof(zm&2k$AFD|mVYMf+qnmVrzBFHLZ#qs6*MoBBt>0MxmR;a y^ZG65O4@M1RMem0f&G?z#;HQA@Cm&a2WFd literal 0 HcmV?d00001 diff --git a/test/lisp/emacs-lisp/package-resources/wrong-size-single-1.0.el b/test/lisp/emacs-lisp/package-resources/wrong-size-single-1.0.el new file mode 100644 index 00000000000..a4e3dafaaaf --- /dev/null +++ b/test/lisp/emacs-lisp/package-resources/wrong-size-single-1.0.el @@ -0,0 +1 @@ +;; This file just has the wrong size (i.e. not 1 as specified). diff --git a/test/lisp/emacs-lisp/package-resources/wrong-size-tar-1.0.tar b/test/lisp/emacs-lisp/package-resources/wrong-size-tar-1.0.tar new file mode 100644 index 0000000000000000000000000000000000000000..61d47c6529b855ce1dcff9df78f022aca9715814 GIT binary patch literal 10240 zcmeIy(MrQG6vpvf`xNKStJY*q+6V9ze1WiqbvjdNA_Jd($v`ML=S>m8|G5eDv}yYL z4n56N+&Ag)5t{7h#%9KFxgf~sljJeTWg?{h5n7SQDdrG!lHC+iywCFLa}INRcN>*1 x0tg_000IagfB*srAb