cellog Fri, 24 Jul 2009 19:40:41 +0000 Revision: http://svn.php.net/viewvc?view=revision&revision=284716
Log: fix --CLEAN-- of all.phpt, remove unnecessary check in phar_convert_again.phpt, and fix signature generation and checking for zip to also include central directory up to the signature, implement better check for end-of-zip at signature verification Changed paths: U pecl/phar/trunk/tests/phar_convert_again.phpt U pecl/phar/trunk/tests/zip/all.phpt U pecl/phar/trunk/zip.c U php/php-src/branches/PHP_5_3/ext/phar/tests/phar_convert_again.phpt U php/php-src/branches/PHP_5_3/ext/phar/tests/zip/all.phpt U php/php-src/branches/PHP_5_3/ext/phar/zip.c U php/php-src/trunk/ext/phar/tests/phar_convert_again.phpt U php/php-src/trunk/ext/phar/tests/zip/all.phpt U php/php-src/trunk/ext/phar/zip.c
Modified: pecl/phar/trunk/tests/phar_convert_again.phpt =================================================================== --- pecl/phar/trunk/tests/phar_convert_again.phpt 2009-07-24 19:21:10 UTC (rev 284715) +++ pecl/phar/trunk/tests/phar_convert_again.phpt 2009-07-24 19:40:41 UTC (rev 284716) @@ -62,11 +62,6 @@ } catch (Exception $e) { echo $e->getMessage() . "\n"; } -try { -$data->setSignatureAlgorithm(Phar::MD5); -} catch (Exception $e) { -echo $e->getMessage() . "\n"; -} $tar = $phar->convertToExecutable(Phar::TAR); echo $tar->getPath() . "\n"; $data = $tar->convertToData(); @@ -188,7 +183,6 @@ A Phar stub cannot be set in a plain zip archive A Phar stub cannot be set in a plain zip archive A Phar alias cannot be set in a plain zip archive -Cannot set signature algorithm, not possible with zip-based phar archives %sphar_convert_again2.phar.tar %sphar_convert_again2.tar %sphar_convert_again2.phar.tar.gz Modified: pecl/phar/trunk/tests/zip/all.phpt =================================================================== --- pecl/phar/trunk/tests/zip/all.phpt 2009-07-24 19:21:10 UTC (rev 284715) +++ pecl/phar/trunk/tests/zip/all.phpt 2009-07-24 19:40:41 UTC (rev 284716) @@ -46,6 +46,7 @@ ?> ===DONE=== --CLEAN-- +<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.zip.php'); ?> <?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.2.phar.zip.php'); ?> --EXPECT-- bool(false) Modified: pecl/phar/trunk/zip.c =================================================================== --- pecl/phar/trunk/zip.c 2009-07-24 19:21:10 UTC (rev 284715) +++ pecl/phar/trunk/zip.c 2009-07-24 19:40:41 UTC (rev 284716) @@ -350,6 +350,7 @@ /* add each central directory item to the manifest */ for (i = 0; i < PHAR_GET_16(locator.count); ++i) { phar_zip_central_dir_file zipentry; + off_t beforeus = php_stream_tell(fp); if (sizeof(zipentry) != php_stream_read(fp, (char *) &zipentry, sizeof(zipentry))) { PHAR_ZIP_FAIL("unable to read central directory entry, truncated"); @@ -404,24 +405,34 @@ if (entry.filename_len == sizeof(".phar/signature.bin")-1 && !strncmp(entry.filename, ".phar/signature.bin", sizeof(".phar/signature.bin")-1)) { size_t read; php_stream *sigfile; + off_t now; + char *sig; + now = php_stream_tell(fp); pefree(entry.filename, entry.is_persistent); sigfile = php_stream_fopen_tmpfile(); php_stream_seek(fp, 0, SEEK_SET); /* copy file contents + local headers and zip comment, if any, to be hashed for signature */ phar_stream_copy_to_stream(fp, sigfile, entry.header_offset, NULL); + /* seek to central directory */ + php_stream_seek(fp, PHAR_GET_32(locator.cdir_offset), SEEK_SET); + /* copy central directory header */ + phar_stream_copy_to_stream(fp, sigfile, beforeus - PHAR_GET_32(locator.cdir_offset), NULL); if (metadata) { php_stream_write(sigfile, metadata, PHAR_GET_16(locator.comment_len)); } php_stream_seek(fp, sizeof(phar_zip_file_header) + entry.header_offset + entry.filename_len + PHAR_GET_16(zipentry.extra_len), SEEK_SET); - read = php_stream_read(fp, buf, entry.uncompressed_filesize); + sig = (char *) emalloc(entry.uncompressed_filesize); + read = php_stream_read(fp, sig, entry.uncompressed_filesize); if (read != entry.uncompressed_filesize) { php_stream_close(sigfile); + efree(sig); PHAR_ZIP_FAIL("signature cannot be read"); } - mydata->sig_flags = PHAR_GET_32(buf); - if (FAILURE == phar_verify_signature(sigfile, php_stream_tell(sigfile), mydata->sig_flags, buf + 8, entry.uncompressed_filesize - 8, fname, &mydata->signature, &mydata->sig_len, error TSRMLS_CC)) { + mydata->sig_flags = PHAR_GET_32(sig); + if (FAILURE == phar_verify_signature(sigfile, php_stream_tell(sigfile), mydata->sig_flags, sig + 8, entry.uncompressed_filesize - 8, fname, &mydata->signature, &mydata->sig_len, error TSRMLS_CC)) { + efree(sig); if (error) { char *save; php_stream_close(sigfile); @@ -434,14 +445,9 @@ } } php_stream_close(sigfile); + efree(sig); /* signature checked out, let's ensure this is the last file in the phar */ - read = php_stream_read(fp, buf, 4); - - if (read != 4) { - PHAR_ZIP_FAIL("corrupted zip file (truncated)"); - } - - if (!memcmp(buf, "PK\5\6", 4)) { + if (i != PHAR_GET_16(locator.count) - 1) { PHAR_ZIP_FAIL("entries exist after signature, invalid phar"); } @@ -1083,15 +1089,18 @@ char *signature, sigbuf[8]; phar_entry_info entry = {0}; php_stream *newfile; - off_t tell; + off_t tell, st; newfile = php_stream_fopen_tmpfile(); - tell = php_stream_tell(pass->filefp); - /* copy the local files and the zip comment to generate the hash */ + st = tell = php_stream_tell(pass->filefp); + /* copy the local files, central directory, and the zip comment to generate the hash */ php_stream_seek(pass->filefp, 0, SEEK_SET); phar_stream_copy_to_stream(pass->filefp, newfile, tell, NULL); + tell = php_stream_tell(pass->centralfp); + php_stream_seek(pass->centralfp, 0, SEEK_SET); + phar_stream_copy_to_stream(pass->centralfp, newfile, tell, NULL); if (metadata->c) { - php_stream_write(pass->filefp, metadata->c, metadata->len); + php_stream_write(newfile, metadata->c, metadata->len); } if (FAILURE == phar_create_signature(phar, newfile, &signature, &signature_length, pass->error TSRMLS_CC)) { @@ -1355,6 +1364,9 @@ memset(&eocd, 0, sizeof(eocd)); strncpy(eocd.signature, "PK\5\6", 4); + if (!phar->is_data && !phar->sig_flags) { + phar->sig_flags = PHAR_SIG_SHA1; + } if (phar->sig_flags) { PHAR_SET_16(eocd.counthere, zend_hash_num_elements(&phar->manifest) + 1); PHAR_SET_16(eocd.count, zend_hash_num_elements(&phar->manifest) + 1); Modified: php/php-src/branches/PHP_5_3/ext/phar/tests/phar_convert_again.phpt =================================================================== --- php/php-src/branches/PHP_5_3/ext/phar/tests/phar_convert_again.phpt 2009-07-24 19:21:10 UTC (rev 284715) +++ php/php-src/branches/PHP_5_3/ext/phar/tests/phar_convert_again.phpt 2009-07-24 19:40:41 UTC (rev 284716) @@ -62,11 +62,6 @@ } catch (Exception $e) { echo $e->getMessage() . "\n"; } -try { -$data->setSignatureAlgorithm(Phar::MD5); -} catch (Exception $e) { -echo $e->getMessage() . "\n"; -} $tar = $phar->convertToExecutable(Phar::TAR); echo $tar->getPath() . "\n"; $data = $tar->convertToData(); @@ -188,7 +183,6 @@ A Phar stub cannot be set in a plain zip archive A Phar stub cannot be set in a plain zip archive A Phar alias cannot be set in a plain zip archive -Cannot set signature algorithm, not possible with zip-based phar archives %sphar_convert_again2.phar.tar %sphar_convert_again2.tar %sphar_convert_again2.phar.tar.gz Modified: php/php-src/branches/PHP_5_3/ext/phar/tests/zip/all.phpt =================================================================== --- php/php-src/branches/PHP_5_3/ext/phar/tests/zip/all.phpt 2009-07-24 19:21:10 UTC (rev 284715) +++ php/php-src/branches/PHP_5_3/ext/phar/tests/zip/all.phpt 2009-07-24 19:40:41 UTC (rev 284716) @@ -46,6 +46,7 @@ ?> ===DONE=== --CLEAN-- +<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.zip.php'); ?> <?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.2.phar.zip.php'); ?> --EXPECT-- bool(false) Modified: php/php-src/branches/PHP_5_3/ext/phar/zip.c =================================================================== --- php/php-src/branches/PHP_5_3/ext/phar/zip.c 2009-07-24 19:21:10 UTC (rev 284715) +++ php/php-src/branches/PHP_5_3/ext/phar/zip.c 2009-07-24 19:40:41 UTC (rev 284716) @@ -350,6 +350,7 @@ /* add each central directory item to the manifest */ for (i = 0; i < PHAR_GET_16(locator.count); ++i) { phar_zip_central_dir_file zipentry; + off_t beforeus = php_stream_tell(fp); if (sizeof(zipentry) != php_stream_read(fp, (char *) &zipentry, sizeof(zipentry))) { PHAR_ZIP_FAIL("unable to read central directory entry, truncated"); @@ -404,24 +405,34 @@ if (entry.filename_len == sizeof(".phar/signature.bin")-1 && !strncmp(entry.filename, ".phar/signature.bin", sizeof(".phar/signature.bin")-1)) { size_t read; php_stream *sigfile; + off_t now; + char *sig; + now = php_stream_tell(fp); pefree(entry.filename, entry.is_persistent); sigfile = php_stream_fopen_tmpfile(); php_stream_seek(fp, 0, SEEK_SET); /* copy file contents + local headers and zip comment, if any, to be hashed for signature */ phar_stream_copy_to_stream(fp, sigfile, entry.header_offset, NULL); + /* seek to central directory */ + php_stream_seek(fp, PHAR_GET_32(locator.cdir_offset), SEEK_SET); + /* copy central directory header */ + phar_stream_copy_to_stream(fp, sigfile, beforeus - PHAR_GET_32(locator.cdir_offset), NULL); if (metadata) { php_stream_write(sigfile, metadata, PHAR_GET_16(locator.comment_len)); } php_stream_seek(fp, sizeof(phar_zip_file_header) + entry.header_offset + entry.filename_len + PHAR_GET_16(zipentry.extra_len), SEEK_SET); - read = php_stream_read(fp, buf, entry.uncompressed_filesize); + sig = (char *) emalloc(entry.uncompressed_filesize); + read = php_stream_read(fp, sig, entry.uncompressed_filesize); if (read != entry.uncompressed_filesize) { php_stream_close(sigfile); + efree(sig); PHAR_ZIP_FAIL("signature cannot be read"); } - mydata->sig_flags = PHAR_GET_32(buf); - if (FAILURE == phar_verify_signature(sigfile, php_stream_tell(sigfile), mydata->sig_flags, buf + 8, entry.uncompressed_filesize - 8, fname, &mydata->signature, &mydata->sig_len, error TSRMLS_CC)) { + mydata->sig_flags = PHAR_GET_32(sig); + if (FAILURE == phar_verify_signature(sigfile, php_stream_tell(sigfile), mydata->sig_flags, sig + 8, entry.uncompressed_filesize - 8, fname, &mydata->signature, &mydata->sig_len, error TSRMLS_CC)) { + efree(sig); if (error) { char *save; php_stream_close(sigfile); @@ -434,14 +445,9 @@ } } php_stream_close(sigfile); + efree(sig); /* signature checked out, let's ensure this is the last file in the phar */ - read = php_stream_read(fp, buf, 4); - - if (read != 4) { - PHAR_ZIP_FAIL("corrupted zip file (truncated)"); - } - - if (!memcmp(buf, "PK\5\6", 4)) { + if (i != PHAR_GET_16(locator.count) - 1) { PHAR_ZIP_FAIL("entries exist after signature, invalid phar"); } @@ -1083,15 +1089,18 @@ char *signature, sigbuf[8]; phar_entry_info entry = {0}; php_stream *newfile; - off_t tell; + off_t tell, st; newfile = php_stream_fopen_tmpfile(); - tell = php_stream_tell(pass->filefp); - /* copy the local files and the zip comment to generate the hash */ + st = tell = php_stream_tell(pass->filefp); + /* copy the local files, central directory, and the zip comment to generate the hash */ php_stream_seek(pass->filefp, 0, SEEK_SET); phar_stream_copy_to_stream(pass->filefp, newfile, tell, NULL); + tell = php_stream_tell(pass->centralfp); + php_stream_seek(pass->centralfp, 0, SEEK_SET); + phar_stream_copy_to_stream(pass->centralfp, newfile, tell, NULL); if (metadata->c) { - php_stream_write(pass->filefp, metadata->c, metadata->len); + php_stream_write(newfile, metadata->c, metadata->len); } if (FAILURE == phar_create_signature(phar, newfile, &signature, &signature_length, pass->error TSRMLS_CC)) { @@ -1355,6 +1364,9 @@ memset(&eocd, 0, sizeof(eocd)); strncpy(eocd.signature, "PK\5\6", 4); + if (!phar->is_data && !phar->sig_flags) { + phar->sig_flags = PHAR_SIG_SHA1; + } if (phar->sig_flags) { PHAR_SET_16(eocd.counthere, zend_hash_num_elements(&phar->manifest) + 1); PHAR_SET_16(eocd.count, zend_hash_num_elements(&phar->manifest) + 1); Modified: php/php-src/trunk/ext/phar/tests/phar_convert_again.phpt =================================================================== --- php/php-src/trunk/ext/phar/tests/phar_convert_again.phpt 2009-07-24 19:21:10 UTC (rev 284715) +++ php/php-src/trunk/ext/phar/tests/phar_convert_again.phpt 2009-07-24 19:40:41 UTC (rev 284716) @@ -62,11 +62,6 @@ } catch (Exception $e) { echo $e->getMessage() . "\n"; } -try { -$data->setSignatureAlgorithm(Phar::MD5); -} catch (Exception $e) { -echo $e->getMessage() . "\n"; -} $tar = $phar->convertToExecutable(Phar::TAR); echo $tar->getPath() . "\n"; $data = $tar->convertToData(); @@ -188,7 +183,6 @@ A Phar stub cannot be set in a plain zip archive A Phar stub cannot be set in a plain zip archive A Phar alias cannot be set in a plain zip archive -Cannot set signature algorithm, not possible with zip-based phar archives %sphar_convert_again2.phar.tar %sphar_convert_again2.tar %sphar_convert_again2.phar.tar.gz Modified: php/php-src/trunk/ext/phar/tests/zip/all.phpt =================================================================== --- php/php-src/trunk/ext/phar/tests/zip/all.phpt 2009-07-24 19:21:10 UTC (rev 284715) +++ php/php-src/trunk/ext/phar/tests/zip/all.phpt 2009-07-24 19:40:41 UTC (rev 284716) @@ -46,6 +46,7 @@ ?> ===DONE=== --CLEAN-- +<?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.phar.zip.php'); ?> <?php unlink(dirname(__FILE__) . '/' . basename(__FILE__, '.clean.php') . '.2.phar.zip.php'); ?> --EXPECT-- bool(false) Modified: php/php-src/trunk/ext/phar/zip.c =================================================================== --- php/php-src/trunk/ext/phar/zip.c 2009-07-24 19:21:10 UTC (rev 284715) +++ php/php-src/trunk/ext/phar/zip.c 2009-07-24 19:40:41 UTC (rev 284716) @@ -350,6 +350,7 @@ /* add each central directory item to the manifest */ for (i = 0; i < PHAR_GET_16(locator.count); ++i) { phar_zip_central_dir_file zipentry; + off_t beforeus = php_stream_tell(fp); if (sizeof(zipentry) != php_stream_read(fp, (char *) &zipentry, sizeof(zipentry))) { PHAR_ZIP_FAIL("unable to read central directory entry, truncated"); @@ -404,24 +405,34 @@ if (entry.filename_len == sizeof(".phar/signature.bin")-1 && !strncmp(entry.filename, ".phar/signature.bin", sizeof(".phar/signature.bin")-1)) { size_t read; php_stream *sigfile; + off_t now; + char *sig; + now = php_stream_tell(fp); pefree(entry.filename, entry.is_persistent); sigfile = php_stream_fopen_tmpfile(); php_stream_seek(fp, 0, SEEK_SET); /* copy file contents + local headers and zip comment, if any, to be hashed for signature */ phar_stream_copy_to_stream(fp, sigfile, entry.header_offset, NULL); + /* seek to central directory */ + php_stream_seek(fp, PHAR_GET_32(locator.cdir_offset), SEEK_SET); + /* copy central directory header */ + phar_stream_copy_to_stream(fp, sigfile, beforeus - PHAR_GET_32(locator.cdir_offset), NULL); if (metadata) { php_stream_write(sigfile, metadata, PHAR_GET_16(locator.comment_len)); } php_stream_seek(fp, sizeof(phar_zip_file_header) + entry.header_offset + entry.filename_len + PHAR_GET_16(zipentry.extra_len), SEEK_SET); - read = php_stream_read(fp, buf, entry.uncompressed_filesize); + sig = (char *) emalloc(entry.uncompressed_filesize); + read = php_stream_read(fp, sig, entry.uncompressed_filesize); if (read != entry.uncompressed_filesize) { php_stream_close(sigfile); + efree(sig); PHAR_ZIP_FAIL("signature cannot be read"); } - mydata->sig_flags = PHAR_GET_32(buf); - if (FAILURE == phar_verify_signature(sigfile, php_stream_tell(sigfile), mydata->sig_flags, buf + 8, entry.uncompressed_filesize - 8, fname, &mydata->signature, &mydata->sig_len, error TSRMLS_CC)) { + mydata->sig_flags = PHAR_GET_32(sig); + if (FAILURE == phar_verify_signature(sigfile, php_stream_tell(sigfile), mydata->sig_flags, sig + 8, entry.uncompressed_filesize - 8, fname, &mydata->signature, &mydata->sig_len, error TSRMLS_CC)) { + efree(sig); if (error) { char *save; php_stream_close(sigfile); @@ -434,14 +445,9 @@ } } php_stream_close(sigfile); + efree(sig); /* signature checked out, let's ensure this is the last file in the phar */ - read = php_stream_read(fp, buf, 4); - - if (read != 4) { - PHAR_ZIP_FAIL("corrupted zip file (truncated)"); - } - - if (!memcmp(buf, "PK\5\6", 4)) { + if (i != PHAR_GET_16(locator.count) - 1) { PHAR_ZIP_FAIL("entries exist after signature, invalid phar"); } @@ -1083,15 +1089,18 @@ char *signature, sigbuf[8]; phar_entry_info entry = {0}; php_stream *newfile; - off_t tell; + off_t tell, st; newfile = php_stream_fopen_tmpfile(); - tell = php_stream_tell(pass->filefp); - /* copy the local files and the zip comment to generate the hash */ + st = tell = php_stream_tell(pass->filefp); + /* copy the local files, central directory, and the zip comment to generate the hash */ php_stream_seek(pass->filefp, 0, SEEK_SET); phar_stream_copy_to_stream(pass->filefp, newfile, tell, NULL); + tell = php_stream_tell(pass->centralfp); + php_stream_seek(pass->centralfp, 0, SEEK_SET); + phar_stream_copy_to_stream(pass->centralfp, newfile, tell, NULL); if (metadata->c) { - php_stream_write(pass->filefp, metadata->c, metadata->len); + php_stream_write(newfile, metadata->c, metadata->len); } if (FAILURE == phar_create_signature(phar, newfile, &signature, &signature_length, pass->error TSRMLS_CC)) { @@ -1355,6 +1364,9 @@ memset(&eocd, 0, sizeof(eocd)); strncpy(eocd.signature, "PK\5\6", 4); + if (!phar->is_data && !phar->sig_flags) { + phar->sig_flags = PHAR_SIG_SHA1; + } if (phar->sig_flags) { PHAR_SET_16(eocd.counthere, zend_hash_num_elements(&phar->manifest) + 1); PHAR_SET_16(eocd.count, zend_hash_num_elements(&phar->manifest) + 1);
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php