From 5010fec2f09b5ea4fe867b3950ee2a9435a4b756 Mon Sep 17 00:00:00 2001 From: Greg Beaver Date: Wed, 24 Jun 2009 22:19:47 +0000 Subject: [PATCH] fix Bug #48681: openssl signature verification for tar archives broken in ext/phar, merge small fixes to phar.phar generation from PHP_5_3 --- ext/phar/phar/pharcommand.inc | 28 +++++++++++++------ ext/phar/tar.c | 9 ++++-- ext/phar/tests/tar/files/P1-1.0.0.tgz | Bin 0 -> 1284 bytes ext/phar/tests/tar/files/P1-1.0.0.tgz.pubkey | 9 ++++++ ext/phar/tests/tar/tar_openssl_hash.phpt | 22 +++++++++++++++ 5 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 ext/phar/tests/tar/files/P1-1.0.0.tgz create mode 100644 ext/phar/tests/tar/files/P1-1.0.0.tgz.pubkey create mode 100644 ext/phar/tests/tar/tar_openssl_hash.phpt diff --git a/ext/phar/phar/pharcommand.inc b/ext/phar/phar/pharcommand.inc index e50637b241..bae6aae8f0 100755 --- a/ext/phar/phar/pharcommand.inc +++ b/ext/phar/phar/pharcommand.inc @@ -210,16 +210,28 @@ class PharCommand extends CLICommand */ static function cli_arg_typ_loader($arg, $cfg, $key) { - if (($arg == '0' || $arg == '1') && !file_exists($arg)) { + if (($arg == '0' || $arg == '1') && !file_exists($arg) && substr(PHP_OS, 0, 3) != 'WIN') { $found = NULL; - $apiver = `pear -q info PHP_Archive 2>/dev/null|grep 'API Version'`; - $apiver = trim(substr($apiver, strlen('API Version'))); + $apiver = false; + $path = explode(PATH_SEPARATOR, $_ENV['PATH']); + $pear = false; + foreach ($path as $component) { + if (file_exists($component . DIRECTORY_SEPARATOR . 'pear') + && is_executable($component . DIRECTORY_SEPARATOR . 'pear'))) { + $pear = true; + break; + } + } + if ($pear) { + $apiver = `pear -q info PHP_Archive 2>/dev/null|grep 'API Version'`; + $apiver = trim(substr($apiver, strlen('API Version'))); + } if ($apiver) { - self::notice("Pear package PHP_Archive: API Version: $apiver.\n"); + self::notice("PEAR package PHP_Archive: API Version: $apiver.\n"); $files = explode("\n", `pear list-files PHP_Archive`); $phpdir = `pear config-get php_dir 2>/dev/null`; $phpdir = trim($phpdir); - self::notice("Pear package PHP_Archive: $phpdir.\n"); + self::notice("PEAR package PHP_Archive: $phpdir.\n"); if (is_dir($phpdir)) { foreach($files as $ent) { $matches = NULL; @@ -234,13 +246,13 @@ class PharCommand extends CLICommand } } } else { - self::notice("Pear package PHP_Archive: corrupt or inaccessible base dir: $php_dir.\n"); + self::notice("PEAR package PHP_Archive: corrupt or inaccessible base dir: $php_dir.\n"); } } if (isset($found)) { - self::notice("Pear package PHP_Archive: $found.\n"); + self::notice("PEAR package PHP_Archive: $found.\n"); } else { - $msg = "Pear package PHP_Archive or Archive.php class file not found.\n"; + $msg = "PEAR package PHP_Archive not installed: generated phar will require PHP's phar extension be enabled.\n"; if ($arg == '0') { self::notice($msg); } else { diff --git a/ext/phar/tar.c b/ext/phar/tar.c index 85c0649900..1869e5c6ea 100644 --- a/ext/phar/tar.c +++ b/ext/phar/tar.c @@ -255,6 +255,8 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias, 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 @@ bail: 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 @@ bail: #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 @@ bail: } 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); diff --git a/ext/phar/tests/tar/files/P1-1.0.0.tgz b/ext/phar/tests/tar/files/P1-1.0.0.tgz new file mode 100644 index 0000000000000000000000000000000000000000..1d9cae43984f90a1097b5ba38d350be01974aeb6 GIT binary patch literal 1284 zcmV+f1^fCRiwFP!000001MOK`XdG1-Ua^Qx6-Dqu1(_~V)56Y~%U+swGHKQ(X=)Nu z6GaqFCo`wnA+s~%i2&iU$9^6dK@=U=mn?6!W<-Qifn#RHfJ*qNfB!E7NIVja2iZkF1qL5q>HK}%8lbwU zwXXIlVHsn%q>ja6bINm^FMa;!qVU4NM3yn9JXSgX^Yury8OJg#MRN(iv@sTV{{x7# z-~YHUAM?-uG9an@k5H=_1^zc@3`eiCZObN0d;~0l|2!}H&wu5B&;QkpIr)$3`czCm z1TD!)un_-wPMFPqk&A_W{+9t#4OF;7H55V^+6Ns)ebABb0|xgw*wk`11^K|9mA(QW zw}JxymzMLzSj_W(l#BTMF9ZDh|LR8e`!CVEOvTCAc-g-H&d2{SU-Sa;^w#i8p}8@{eTI@CP1`Os(QuRNAM{6>4zmc2WEI`~}l;pcxl*?#tc zZTEf9^WLRh4YxNOn!fnWz?mn88{Zj!;k)g>4&InLdjH!a+EpQZZvE({@cSe&HgLSQ zn%_C`qxxWT%Z2MB&z$(AN9-IN*zx4|uYCB`&*x8#y!KJTh+RAI(5DBsH*W0c{{7&Q zKXxbV3-A8P@BjGln}d}BMsC`Cs(WVt=*;-Jw##F8Umm-%c5PMS#t)-c_pYC+oX~o| z7@F9#Z_TyTTf>!|U%q_j=pA + + + +--INI-- +phar.readonly=1 +phar.require_hash=1 +--FILE-- +getMessage()."\n"; +} + +?> +===DONE=== +--EXPECT-- +===DONE=== -- 2.50.1