From c42a870b7e3dd5cc37bd74ac5be35453988a1d2b Mon Sep 17 00:00:00 2001 From: Marcus Boerger Date: Sun, 25 Mar 2007 21:43:49 +0000 Subject: [PATCH] - Add general SHA-2 support by optional pecl/hash dependency # We actually need support to select the signature type somehow --- ext/phar/TODO | 2 +- ext/phar/package.php | 1 + ext/phar/package.xml | 6 +- ext/phar/phar.c | 124 +++++++++++++++++- ext/phar/phar_internal.h | 6 + ext/phar/phar_object.c | 27 +++- ext/phar/tests/create_new_phar_c.phpt | 2 +- .../phar_get_suppoted_signatures_001.phpt | 22 ++++ .../phar_get_suppoted_signatures_002.phpt | 26 ++++ 9 files changed, 210 insertions(+), 6 deletions(-) create mode 100755 ext/phar/tests/phar_get_suppoted_signatures_001.phpt create mode 100755 ext/phar/tests/phar_get_suppoted_signatures_002.phpt diff --git a/ext/phar/TODO b/ext/phar/TODO index b07e7ad714..5ab7a3c3f8 100644 --- a/ext/phar/TODO +++ b/ext/phar/TODO @@ -39,7 +39,7 @@ Version 1.1.0 * ability to have Phar object return file class as offsetGet() result * [optional] Phar->rollback() to abort a write transaction * implement GPG signing - * add SHA-2 support + X add SHA-2 (256, 512) support [Marcus] * ability to match files containing a metadata key opendir('phar://a.phar/?mime-type=image/jpeg') or foreach ($p->match('mime-type', 'image/jpeg') as $file) * Phar::copy($from, $to); diff --git a/ext/phar/package.php b/ext/phar/package.php index 288225073c..b0419fb864 100644 --- a/ext/phar/package.php +++ b/ext/phar/package.php @@ -44,6 +44,7 @@ $package->clearDeps(); $package->setPhpDep('5.2.0'); $package->setPearInstallerDep('1.4.3'); $package->addPackageDepWithChannel('optional', 'bz2', 'pecl.php.net'); +$package->addPackageDepWithChannel('optional', 'hash', 'pecl.php.net'); $package->addExtensionDep('optional', 'spl'); $package->addExtensionDep('optional', 'zlib'); $package->addRelease(); diff --git a/ext/phar/package.xml b/ext/phar/package.xml index 0ff3450da2..f5e39e1a19 100644 --- a/ext/phar/package.xml +++ b/ext/phar/package.xml @@ -29,7 +29,7 @@ if the ini variable phar.require_hash is set to true. yes 2007-03-25 - + 1.0.0 1.0.0 @@ -173,6 +173,10 @@ Note that isBuffering() returns the opposite value to isFlushingToPhar() bz2 pecl.php.net + + hash + pecl.php.net + spl diff --git a/ext/phar/phar.c b/ext/phar/phar.c index 2f40a6df4b..a0a4135bbf 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -832,6 +832,87 @@ int phar_open_file(php_stream *fp, char *fname, int fname_len, char *alias, int } PHAR_GET_32(sig_ptr, sig_flags); switch(sig_flags) { +#if HAVE_HASH_EXT + case PHAR_SIG_SHA512: { + unsigned char digest[64], saved[64]; + PHP_SHA512_CTX context; + + php_stream_rewind(fp); + PHP_SHA512Init(&context); + read_len -= sizeof(digest); + if (read_len > sizeof(buf)) { + read_size = sizeof(buf); + } else { + read_size = (int)read_len; + } + while ((len = php_stream_read(fp, (char*)buf, read_size)) > 0) { + PHP_SHA512Update(&context, buf, len); + read_len -= (off_t)len; + if (read_len < read_size) { + read_size = (int)read_len; + } + } + PHP_SHA512Final(digest, &context); + + if (read_len > 0 + || php_stream_read(fp, (char*)saved, sizeof(saved)) != sizeof(saved) + || memcmp(digest, saved, sizeof(digest))) { + efree(savebuf); + php_stream_close(fp); + if (error) { + spprintf(error, 0, "phar \"%s\" has a broken signature", fname); + } + return FAILURE; + } + + sig_len = phar_hex_str((const char*)digest, sizeof(digest), &signature); + break; + } + case PHAR_SIG_SHA256: { + unsigned char digest[32], saved[32]; + PHP_SHA256_CTX context; + + php_stream_rewind(fp); + PHP_SHA256Init(&context); + read_len -= sizeof(digest); + if (read_len > sizeof(buf)) { + read_size = sizeof(buf); + } else { + read_size = (int)read_len; + } + while ((len = php_stream_read(fp, (char*)buf, read_size)) > 0) { + PHP_SHA256Update(&context, buf, len); + read_len -= (off_t)len; + if (read_len < read_size) { + read_size = (int)read_len; + } + } + PHP_SHA256Final(digest, &context); + + if (read_len > 0 + || php_stream_read(fp, (char*)saved, sizeof(saved)) != sizeof(saved) + || memcmp(digest, saved, sizeof(digest))) { + efree(savebuf); + php_stream_close(fp); + if (error) { + spprintf(error, 0, "phar \"%s\" has a broken signature", fname); + } + return FAILURE; + } + + sig_len = phar_hex_str((const char*)digest, sizeof(digest), &signature); + break; + } +#else + case PHAR_SIG_SHA512: + case PHAR_SIG_SHA256: + efree(savebuf); + php_stream_close(fp); + if (error) { + spprintf(error, 0, "phar \"%s\" has a unsupported signature", fname); + } + return FAILURE; +#endif case PHAR_SIG_SHA1: { unsigned char digest[20], saved[20]; PHP_SHA1_CTX context; @@ -906,7 +987,7 @@ int phar_open_file(php_stream *fp, char *fname, int fname_len, char *alias, int efree(savebuf); php_stream_close(fp); if (error) { - spprintf(error, 0, "phar \"%s\" has a broken signature", fname); + spprintf(error, 0, "phar \"%s\" has a broken or unsupported signature", fname); } return FAILURE; } @@ -2445,6 +2526,47 @@ int phar_flush(phar_archive_data *archive, char *user_stub, long len, char **err case PHAR_SIG_PGP: /* TODO: currently fall back to sha1,later do both */ default: +#if HAVE_HASH_EXT + case PHAR_SIG_SHA512: { + unsigned char digest[64]; + PHP_SHA512_CTX context; + + PHP_SHA512Init(&context); + while ((sig_len = php_stream_read(newfile, (char*)buf, sizeof(buf))) > 0) { + PHP_SHA512Update(&context, buf, sig_len); + } + PHP_SHA512Final(digest, &context); + php_stream_write(newfile, (char *) digest, sizeof(digest)); + sig_flags |= PHAR_SIG_SHA512; + archive->sig_len = phar_hex_str((const char*)digest, sizeof(digest), &archive->signature); + break; + } + case PHAR_SIG_SHA256: { + unsigned char digest[32]; + PHP_SHA256_CTX context; + + PHP_SHA256Init(&context); + while ((sig_len = php_stream_read(newfile, (char*)buf, sizeof(buf))) > 0) { + PHP_SHA256Update(&context, buf, sig_len); + } + PHP_SHA256Final(digest, &context); + php_stream_write(newfile, (char *) digest, sizeof(digest)); + sig_flags |= PHAR_SIG_SHA256; + archive->sig_len = phar_hex_str((const char*)digest, sizeof(digest), &archive->signature); + break; + } +#else + case PHAR_SIG_SHA512: + case PHAR_SIG_SHA256: + if (closeoldfile) { + php_stream_close(oldfile); + } + php_stream_close(newfile); + if (error) { + spprintf(error, 0, "unable to write contents of file \"%s\" to new phar \"%s\" with requested hash type", entry->filename, archive->fname); + } + return EOF; +#endif case PHAR_SIG_SHA1: { unsigned char digest[20]; PHP_SHA1_CTX context; diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index c27137775f..6bb532c92a 100755 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -53,6 +53,10 @@ #ifdef HAVE_STDINT_H #include #endif +#if HAVE_HASH_EXT +#include "ext/hash/php_hash.h" +#include "ext/hash/php_hash_sha.h" +#endif #ifndef E_RECOVERABLE_ERROR #define E_RECOVERABLE_ERROR E_ERROR @@ -75,6 +79,8 @@ #define PHAR_SIG_MD5 0x0001 #define PHAR_SIG_SHA1 0x0002 +#define PHAR_SIG_SHA256 0x0003 +#define PHAR_SIG_SHA512 0x0004 #define PHAR_SIG_PGP 0x0010 #define PHAR_SIG_USE PHAR_SIG_SHA1 diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 707c22b198..746de8f24d 100755 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -350,6 +350,22 @@ PHP_METHOD(Phar, setStub) } /* }}} */ +/* {{{ proto array Phar::getSupportedSignatures() + * Return array of supported signature types + */ +PHP_METHOD(Phar, getSupportedSignatures) +{ + array_init(return_value); + + add_next_index_stringl(return_value, "MD5", 3, 1); + add_next_index_stringl(return_value, "SHA-1", 5, 1); +#if HAVE_HASH_EXT + add_next_index_stringl(return_value, "SHA-256", 7, 1); + add_next_index_stringl(return_value, "SHA-512", 7, 1); +#endif +} +/* }}} */ + /* {{{ proto array|false Phar::getSignature() * Return signature or false */ @@ -362,10 +378,16 @@ PHP_METHOD(Phar, getSignature) add_assoc_stringl(return_value, "hash", phar_obj->arc.archive->signature, phar_obj->arc.archive->sig_len, 1); switch(phar_obj->arc.archive->sig_flags) { case PHAR_SIG_MD5: - add_assoc_stringl(return_value, "hash_type", "md5", 3, 1); + add_assoc_stringl(return_value, "hash_type", "MD5", 3, 1); break; case PHAR_SIG_SHA1: - add_assoc_stringl(return_value, "hash_type", "sha1", 4, 1); + add_assoc_stringl(return_value, "hash_type", "SHA-1", 5, 1); + break; + case PHAR_SIG_SHA256: + add_assoc_stringl(return_value, "hash_type", "SHA-256", 7, 1); + break; + case PHAR_SIG_SHA512: + add_assoc_stringl(return_value, "hash_type", "SHA-512", 7, 1); break; } } else { @@ -1199,6 +1221,7 @@ zend_function_entry php_archive_methods[] = { PHP_ME(Phar, loadPhar, arginfo_phar_loadPhar, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL) PHP_ME(Phar, mapPhar, arginfo_phar_mapPhar, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL) PHP_ME(Phar, getExtractList, NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL) + PHP_ME(Phar, getSupportedSignatures,NULL, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL) {NULL, NULL, NULL} }; diff --git a/ext/phar/tests/create_new_phar_c.phpt b/ext/phar/tests/create_new_phar_c.phpt index ddf9bef2a2..48702ecec4 100755 --- a/ext/phar/tests/create_new_phar_c.phpt +++ b/ext/phar/tests/create_new_phar_c.phpt @@ -24,6 +24,6 @@ array(2) { ["hash"]=> string(40) "%s" ["hash_type"]=> - string(4) "sha1" + string(5) "SHA-1" } ===DONE=== diff --git a/ext/phar/tests/phar_get_suppoted_signatures_001.phpt b/ext/phar/tests/phar_get_suppoted_signatures_001.phpt new file mode 100755 index 0000000000..16a0f6df84 --- /dev/null +++ b/ext/phar/tests/phar_get_suppoted_signatures_001.phpt @@ -0,0 +1,22 @@ +--TEST-- +Phar::setSupportedSignatures() +--SKIPIF-- + + +--INI-- +phar.require_hash=0 +phar.readonly=0 +--FILE-- + +===DONE=== +?> +--EXPECT-- +array(2) { + [0]=> + string(3) "MD5" + [1]=> + string(5) "SHA-1" +} +===DONE=== diff --git a/ext/phar/tests/phar_get_suppoted_signatures_002.phpt b/ext/phar/tests/phar_get_suppoted_signatures_002.phpt new file mode 100755 index 0000000000..db5ac138c5 --- /dev/null +++ b/ext/phar/tests/phar_get_suppoted_signatures_002.phpt @@ -0,0 +1,26 @@ +--TEST-- +Phar::setSupportedSignatures() +--SKIPIF-- + + +--INI-- +phar.require_hash=0 +phar.readonly=0 +--FILE-- + +===DONE=== +?> +--EXPECT-- +array(4) { + [0]=> + string(3) "MD5" + [1]=> + string(5) "SHA-1" + [2]=> + string(7) "SHA-256" + [3]=> + string(7) "SHA-512" +} +===DONE=== -- 2.50.1