]> granicus.if.org Git - php/commitdiff
fix Bug #48681: openssl signature verification for tar archives broken in ext/phar...
authorGreg Beaver <cellog@php.net>
Wed, 24 Jun 2009 22:19:47 +0000 (22:19 +0000)
committerGreg Beaver <cellog@php.net>
Wed, 24 Jun 2009 22:19:47 +0000 (22:19 +0000)
ext/phar/phar/pharcommand.inc
ext/phar/tar.c
ext/phar/tests/tar/files/P1-1.0.0.tgz [new file with mode: 0644]
ext/phar/tests/tar/files/P1-1.0.0.tgz.pubkey [new file with mode: 0644]
ext/phar/tests/tar/tar_openssl_hash.phpt [new file with mode: 0644]

index e50637b24124b4774e94f45fc2e65b9996df5718..bae6aae8f0d958ebaa724940bdf812f1855f7e3e 100755 (executable)
@@ -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 {
index 85c06499006ca30607a0e047f5beb756f1d9d389..1869e5c6ea63eee758be59aa3787b92ba4698723 100644 (file)
@@ -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 (file)
index 0000000..1d9cae4
Binary files /dev/null and b/ext/phar/tests/tar/files/P1-1.0.0.tgz differ
diff --git a/ext/phar/tests/tar/files/P1-1.0.0.tgz.pubkey b/ext/phar/tests/tar/files/P1-1.0.0.tgz.pubkey
new file mode 100644 (file)
index 0000000..eb59bdd
--- /dev/null
@@ -0,0 +1,9 @@
+-----BEGIN PUBLIC KEY-----
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4drcwddPs6LmIbdT1ifT
+Ev8HXh1Fk1yNusCDoCX6mYkgqvCmx02F/9k5q7n6CPblTcF5mdDI8kcRrUHmyXtD
+9X0d7RN7BakZMPH5KPaNkXiXsI9YGSb39AnZgYw01n6u0W6Ohha+KwOsrxkKCF4u
+LjPLQAlM+3uD8y9Tz2fF+pAE901kHrd3ue7a5i5EtW0bzl5QfxnwFZXAO0StQ9dF
+slzibRH+1pFjMRxDnlgYmLQF6jMWm9Ty6x9UH9HZ3E3F9QZEQVXWT9y/pe30HcAX
+YxAGZjPIx19UNPF5C+Nps6MjxNRht0pGXTL9sptYoiNjRiXAS0y4FM+8K6xvBIOF
+ZQIDAQAB
+-----END PUBLIC KEY-----
diff --git a/ext/phar/tests/tar/tar_openssl_hash.phpt b/ext/phar/tests/tar/tar_openssl_hash.phpt
new file mode 100644 (file)
index 0000000..49ef77a
--- /dev/null
@@ -0,0 +1,22 @@
+--TEST--
+Phar: tar archive, require_hash=1, OpenSSL hash
+--SKIPIF--
+<?php if (!extension_loaded('phar')) die('skip'); ?>
+<?php if (!extension_loaded("spl")) die("skip SPL not available"); ?>
+<?php if (!extension_loaded("zlib")) die("skip zlib not available"); ?>
+<?php if (!extension_loaded("openssl")) die("skip openssl not available"); ?>
+--INI--
+phar.readonly=1
+phar.require_hash=1
+--FILE--
+<?php
+try {
+       $phar = new PharData(dirname(__FILE__) . '/files/P1-1.0.0.tgz');
+} catch (Exception $e) {
+       echo $e->getMessage()."\n";
+}
+
+?>
+===DONE===
+--EXPECT--
+===DONE===