]> granicus.if.org Git - php/commitdiff
- Add general SHA-2 support by optional pecl/hash dependency
authorMarcus Boerger <helly@php.net>
Sun, 25 Mar 2007 21:43:49 +0000 (21:43 +0000)
committerMarcus Boerger <helly@php.net>
Sun, 25 Mar 2007 21:43:49 +0000 (21:43 +0000)
# We actually need support to select the signature type somehow

ext/phar/TODO
ext/phar/package.php
ext/phar/package.xml
ext/phar/phar.c
ext/phar/phar_internal.h
ext/phar/phar_object.c
ext/phar/tests/create_new_phar_c.phpt
ext/phar/tests/phar_get_suppoted_signatures_001.phpt [new file with mode: 0755]
ext/phar/tests/phar_get_suppoted_signatures_002.phpt [new file with mode: 0755]

index b07e7ad71482ef548caa2be0a8b8ae26655abcce..5ab7a3c3f83b45f7b9da986362a4a2970cdc6b9c 100644 (file)
@@ -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);
index 288225073ca6bd1b50dec93f83f36b4c201e3b75..b0419fb864a921f0f194fed74da3ebaf4b174ac8 100644 (file)
@@ -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();
index 0ff3450da24fdefa2f7c4759bef63d3167840077..f5e39e1a19d865a6920aa4b40df02d60474c1271 100644 (file)
@@ -29,7 +29,7 @@ if the ini variable phar.require_hash is set to true.</description>
   <active>yes</active>
  </lead>
  <date>2007-03-25</date>
- <time>22:34:16</time>
+ <time>23:41:57</time>
  <version>
   <release>1.0.0</release>
   <api>1.0.0</api>
@@ -173,6 +173,10 @@ Note that isBuffering() returns the opposite value to isFlushingToPhar()
     <name>bz2</name>
     <channel>pecl.php.net</channel>
    </package>
+   <package>
+    <name>hash</name>
+    <channel>pecl.php.net</channel>
+   </package>
    <extension>
     <name>spl</name>
    </extension>
index 2f40a6df4bb2e9775aa8450cf116773c2d4ed1fc..a0a4135bbf26762a5bc0787aac8de980c6d1e081 100644 (file)
@@ -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;
index c27137775f036550bc92ce0e49326cd85074aabe..6bb532c92af23307b64dea44dcd361e26c9cdef1 100755 (executable)
 #ifdef HAVE_STDINT_H
 #include <stdint.h>
 #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
index 707c22b198c63b9609e10fa3ae990f76e7e04bd9..746de8f24db6bea1a5f3a447fd9ed1190565b353 100755 (executable)
@@ -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}
 };
 
index ddf9bef2a2dd13f3c05463f4341d3d4d5c8d2e21..48702ecec461ced81307a70976bd336dfd41e071 100755 (executable)
@@ -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 (executable)
index 0000000..16a0f6d
--- /dev/null
@@ -0,0 +1,22 @@
+--TEST--
+Phar::setSupportedSignatures()
+--SKIPIF--
+<?php if (!extension_loaded("phar")) print "skip"; ?>
+<?php if ( extension_loaded("hash")) print "skip extension hash conflicts"; ?>
+--INI--
+phar.require_hash=0
+phar.readonly=0
+--FILE--
+<?php
+var_dump(Phar::getSupportedSignatures());
+?>
+===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 (executable)
index 0000000..db5ac13
--- /dev/null
@@ -0,0 +1,26 @@
+--TEST--
+Phar::setSupportedSignatures()
+--SKIPIF--
+<?php if (!extension_loaded("phar")) print "skip"; ?>
+<?php if (!extension_loaded("hash")) print "skip extension hash required"; ?>
+--INI--
+phar.require_hash=0
+phar.readonly=0
+--FILE--
+<?php
+var_dump(Phar::getSupportedSignatures());
+?>
+===DONE===
+?>
+--EXPECT--
+array(4) {
+  [0]=>
+  string(3) "MD5"
+  [1]=>
+  string(5) "SHA-1"
+  [2]=>
+  string(7) "SHA-256"
+  [3]=>
+  string(7) "SHA-512"
+}
+===DONE===