php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #48681 openssl signature verification for tar archives broken
Submitted: 2009-06-24 22:18 UTC Modified: 2009-06-30 14:52 UTC
From: cellog@php.net Assigned: cellog (profile)
Status: Closed Package: PHAR related
PHP Version: 5.3CVS-2009-06-24 (CVS) OS:
Private report: No CVE-ID: None
 [2009-06-24 22:18 UTC] cellog@php.net
Description:
------------
openssl signature verification is broken for tar archives, and will be broken in PHP 5.3.0.  This patch can be used for those who can't wait until PHP 5.3.1.

Alternately, HEAD of php-src/ext/phar can be used, or pecl/phar, as they are synchronized with php5/ext/phar

Reproduce code:
---------------
Index: ext/phar/tar.c
===================================================================
RCS file: /repository/php-src/ext/phar/tar.c,v
retrieving revision 1.55.2.29
diff -u -r1.55.2.29 tar.c
--- ext/phar/tar.c	4 Jun 2009 19:59:09 -0000	1.55.2.29
+++ ext/phar/tar.c	24 Jun 2009 22:14:08 -0000
@@ -255,6 +255,8 @@
 			phar_tar_number(hdr->size, sizeof(hdr->size));
 
 		if (((!old && hdr->prefix[0] == 0) || old) && strlen(hdr->name) == sizeof(".phar/signature.bin")-1 && !strncmp(hdr->name, ".phar/signature.bin", sizeof(".phar/signature.bin")-1)) {
+			off_t curloc;
+
 			if (size > 511) {
 				if (error) {
 					spprintf(error, 4096, "phar error: tar-based phar \"%s\" has signature that is larger than 511 bytes, cannot process", fname);
@@ -264,6 +266,7 @@
 				phar_destroy_phar_data(myphar TSRMLS_CC);
 				return FAILURE;
 			}
+			curloc = php_stream_tell(fp);
 			read = php_stream_read(fp, buf, size);
 			if (read != size) {
 				if (error) {
@@ -280,7 +283,7 @@
 #else
 # define PHAR_GET_32(buffer) (php_uint32) *(buffer)
 #endif
-			if (FAILURE == phar_verify_signature(fp, php_stream_tell(fp) - size - 512, PHAR_GET_32(buf), buf + 8, PHAR_GET_32(buf + 4), fname, &myphar->signature, &myphar->sig_len, error TSRMLS_CC)) {
+			if (FAILURE == phar_verify_signature(fp, php_stream_tell(fp) - size - 512, PHAR_GET_32(buf), buf + 8, size - 8, fname, &myphar->signature, &myphar->sig_len, error TSRMLS_CC)) {
 				if (error) {
 					char *save = *error;
 					spprintf(error, 4096, "phar error: tar-based phar \"%s\" signature cannot be verified: %s", fname, save);
@@ -288,11 +291,11 @@
 				}
 				goto bail;
 			}
+			php_stream_seek(fp, curloc + 512, SEEK_SET);
 			/* signature checked out, let's ensure this is the last file in the phar */
-			size = ((size+511)&~511) + 512;
 			if (((hdr->typeflag == '\0') || (hdr->typeflag == TAR_FILE)) && size > 0) {
 				/* this is not good enough - seek succeeds even on truncated tars */
-				php_stream_seek(fp, size, SEEK_CUR);
+				php_stream_seek(fp, 512, SEEK_CUR);
 				if ((uint)php_stream_tell(fp) > totalsize) {
 					if (error) {
 						spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (truncated)", fname);



Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2009-06-30 14:52 UTC] cellog@php.net
This bug has been fixed in CVS.

Snapshots of the sources are packaged every three hours; this change
will be in the next snapshot. You can grab the snapshot at
http://snaps.php.net/.
 
Thank you for the report, and for helping us make PHP better.

fixed in 5.3, 6.0, pecl
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 12:01:29 2024 UTC