]> granicus.if.org Git - php/commitdiff
full refactor of signatures complete - now to implement them for tar as a starting...
authorGreg Beaver <cellog@php.net>
Fri, 13 Jun 2008 20:15:19 +0000 (20:15 +0000)
committerGreg Beaver <cellog@php.net>
Fri, 13 Jun 2008 20:15:19 +0000 (20:15 +0000)
ext/phar/phar.c
ext/phar/phar.phar
ext/phar/phar_internal.h
ext/phar/phar_object.c
ext/phar/util.c

index 9884a8d2aa53417c2e4f587151c3c2cf788dee27..a7dc72d0fbf186939c265fdf35c54bced002be8d 100644 (file)
 #include "SAPI.h"
 #include "func_interceptors.h"
 
-#ifdef PHAR_HAVE_OPENSSL
-
-/* OpenSSL includes */
-#include <openssl/evp.h>
-#include <openssl/x509.h>
-#include <openssl/x509v3.h>
-#include <openssl/crypto.h>
-#include <openssl/pem.h>
-#include <openssl/err.h>
-#include <openssl/conf.h>
-#include <openssl/rand.h>
-#include <openssl/ssl.h>
-#include <openssl/pkcs12.h>
-
-#endif
-
-#ifndef PHAR_HAVE_OPENSSL
-static int phar_call_openssl_signverify(int is_sign, php_stream *fp, off_t end, char *key, int key_len, char **signature, int *signature_len TSRMLS_DC);
-#endif
 static void destroy_phar_data(void *pDest);
 
 ZEND_DECLARE_MODULE_GLOBALS(phar)
@@ -604,25 +585,6 @@ int phar_parse_metadata(char **buffer, zval **metadata, int zip_metadata_len TSR
 }
 /* }}}*/
 
-static const char hexChars[] = "0123456789ABCDEF";
-
-static int phar_hex_str(const char *digest, size_t digest_len, char ** signature)
-{
-       int pos = -1;
-       size_t len = 0;
-       
-       TSRMLS_FETCH();
-
-       *signature = (char*)safe_pemalloc(digest_len, 2, 1, PHAR_G(persist));
-
-       for (; len < digest_len; ++len) {
-               (*signature)[++pos] = hexChars[((const unsigned char *)digest)[len] >> 4];
-               (*signature)[++pos] = hexChars[((const unsigned char *)digest)[len] & 0x0F];
-       }
-       (*signature)[++pos] = '\0';
-       return pos;
-}
-
 /**
  * Does not check for a previously opened phar in the cache.
  *
@@ -2917,169 +2879,57 @@ int phar_flush(phar_archive_data *phar, char *user_stub, long len, int convert,
 
        /* append signature */
        if (global_flags & PHAR_HDR_SIGNATURE) {
-               unsigned char buf[1024];
-               int  sig_flags = 0, sig_len;
                char sig_buf[4];
+
                php_stream_rewind(newfile);
-               
                if (phar->signature) {
                        efree(phar->signature);
                        phar->signature = NULL;
                }
                
                switch(phar->sig_flags) {
-#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;
-                       phar->sig_len = phar_hex_str((const char*)digest, sizeof(digest), &phar->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;
-                       phar->sig_len = phar_hex_str((const char*)digest, sizeof(digest), &phar->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, phar->fname);
-                       }
-                       return EOF;
-#endif
-               case PHAR_SIG_OPENSSL: {
-                       int siglen;
-                       unsigned char *sigbuf;
-#ifdef PHAR_HAVE_OPENSSL
-                       BIO *in;
-                       EVP_PKEY *key;
-                       EVP_MD *mdtype = (EVP_MD *) EVP_sha1();
-                       EVP_MD_CTX md_ctx;
-                       
-                       if (!zend_hash_exists(&module_registry, "openssl", sizeof("openssl"))) {
+#if !HAVE_HASH_EXT
+                       case PHAR_SIG_SHA512:
+                       case PHAR_SIG_SHA256:
                                if (closeoldfile) {
                                        php_stream_close(oldfile);
                                }
                                php_stream_close(newfile);
                                if (error) {
-                                       spprintf(error, 0, "phar \"%s\" openssl signature cannot be created, openssl not loaded", phar->fname);
+                                       spprintf(error, 0, "unable to write contents of file \"%s\" to new phar \"%s\" with requested hash type", entry->filename, phar->fname);
                                }
                                return EOF;
-                       }
-                       in = BIO_new_mem_buf(PHAR_G(openssl_privatekey), PHAR_G(openssl_privatekey_len));
+#endif
+                       default: {
+                               char *digest;
+                               int digest_len;
 
-                       if (in == NULL) {
-                               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 openssl signature", entry->filename, phar->fname);
+                               if (FAILURE == phar_create_signature(phar, newfile, &digest, &digest_len, error TSRMLS_CC)) {
+                                       if (error) {
+                                               char *save = *error;
+                                               spprintf(error, 0, "phar error: unable to write signature: %s", save);
+                                               efree(save);
+                                       }
+                                       efree(digest);
+                                       if (closeoldfile) {
+                                               php_stream_close(oldfile);
+                                       }
+                                       php_stream_close(newfile);
+                                       return EOF;
                                }
-                               return EOF;
-                       }
-                       key = PEM_read_bio_PrivateKey(in, NULL,NULL, "");
 
-                       BIO_free(in);
-                       siglen = EVP_PKEY_size(key);
-                       sigbuf = emalloc(siglen + 1);
-               
-                       EVP_SignInit(&md_ctx, mdtype);
-                       while ((sig_len = php_stream_read(newfile, (char*)buf, sizeof(buf))) > 0) {
-                               EVP_SignUpdate(&md_ctx, buf, sig_len);
-                       }
-                       if (!EVP_SignFinal (&md_ctx, sigbuf,(unsigned int *)&siglen, key)) {
-                               efree(sigbuf);
-                               if (closeoldfile) {
-                                       php_stream_close(oldfile);
-                               }
-                               php_stream_close(newfile);
-                               if (error) {
-                                       spprintf(error, 0, "unable to write phar \"%s\" with requested openssl signature", phar->fname);
+                               php_stream_write(newfile, digest, digest_len);
+                               efree(digest);
+                               if (phar->sig_flags == PHAR_SIG_OPENSSL) {
+                                       phar_set_32(sig_buf, digest_len);
+                                       php_stream_write(newfile, sig_buf, 4);
                                }
-                               return EOF;
+                               break;
                        }
-                       sigbuf[siglen] = '\0';
-                       EVP_MD_CTX_cleanup(&md_ctx);
-#else
-                       sigbuf = NULL;
-                       siglen = 0;
-                       php_stream_seek(newfile, 0, SEEK_END);
-                       if (FAILURE == phar_call_openssl_signverify(1, newfile, php_stream_tell(newfile), PHAR_G(openssl_privatekey), PHAR_G(openssl_privatekey_len), (char **)&sigbuf, &siglen TSRMLS_CC)) {
-                               if (closeoldfile) {
-                                       php_stream_close(oldfile);
-                               }
-                               php_stream_close(newfile);
-                               if (error) {
-                                       spprintf(error, 0, "unable to write phar \"%s\" with requested openssl signature", phar->fname);
-                               }
-                               return EOF;
-                       }
-#endif
-                       sig_flags |= PHAR_SIG_OPENSSL;
-                       phar->sig_len = phar_hex_str((const char *)sigbuf, siglen, &phar->signature);
-                       php_stream_write(newfile, (char *) sigbuf, siglen);
-                       efree(sigbuf);
-                       phar_set_32(sig_buf, siglen);
-                       php_stream_write(newfile, sig_buf, 4);
-               }
-               break;
-               default:
-               case PHAR_SIG_SHA1: {
-                       unsigned char digest[20];
-                       PHP_SHA1_CTX  context;
-
-                       PHP_SHA1Init(&context);
-                       while ((sig_len = php_stream_read(newfile, (char*)buf, sizeof(buf))) > 0) {
-                               PHP_SHA1Update(&context, buf, sig_len);
-                       }
-                       PHP_SHA1Final(digest, &context);
-                       php_stream_write(newfile, (char *) digest, sizeof(digest));
-                       sig_flags |= PHAR_SIG_SHA1;
-                       phar->sig_len = phar_hex_str((const char*)digest, sizeof(digest), &phar->signature);
-                       break;
-               }
-               case PHAR_SIG_MD5: {
-                       unsigned char digest[16];
-                       PHP_MD5_CTX   context;
-
-                       PHP_MD5Init(&context);
-                       while ((sig_len = php_stream_read(newfile, (char*)buf, sizeof(buf))) > 0) {
-                               PHP_MD5Update(&context, buf, sig_len);
-                       }
-                       PHP_MD5Final(digest, &context);
-                       php_stream_write(newfile, (char *) digest, sizeof(digest));
-                       sig_flags |= PHAR_SIG_MD5;
-                       phar->sig_len = phar_hex_str((const char*)digest, sizeof(digest), &phar->signature);
-                       break;
-               }
                }
-               phar_set_32(sig_buf, sig_flags);
+               phar_set_32(sig_buf, phar->sig_flags);
                php_stream_write(newfile, sig_buf, 4);
                php_stream_write(newfile, "GBMB", 4);
-               phar->sig_flags = sig_flags;
        }
 
        /* finally, close the temp file, rename the original phar,
index a6edd5c9d3e985f3016900f34ccc0cb1a65d029d..06432e05798d05ddf8d1c336a0f9a1092d05d695 100755 (executable)
Binary files a/ext/phar/phar.phar and b/ext/phar/phar.phar differ
index e8d384ce7cec91701bae4a308a9cfc0842df3dcc..cb7a20419bcdd9a5efaa0e625835b0eade3874a2 100755 (executable)
@@ -421,6 +421,7 @@ int phar_free_alias(phar_archive_data *phar, char *alias, int alias_len TSRMLS_D
 int phar_get_archive(phar_archive_data **archive, char *fname, int fname_len, char *alias, int alias_len, char **error TSRMLS_DC);
 int phar_open_parsed_phar(char *fname, int fname_len, char *alias, int alias_len, int is_data, int options, phar_archive_data** pphar, char **error TSRMLS_DC);
 int phar_verify_signature(php_stream *fp, size_t end_of_phar, int sig_type, char *sig, int sig_len, char *fname, char **signature, int *signature_len, char **error TSRMLS_DC);
+int phar_create_signature(phar_archive_data *phar, php_stream *fp, char **signature, int *signature_length, char **error TSRMLS_DC);
 
 /* utility functions */
 char *phar_create_default_stub(const char *index_php, const char *web_index, size_t *len, char **error TSRMLS_DC);
index 7d1d652820083478e5254413315988734a61831f..c7801542c9ec01e955328e1b38cab44759b9d857 100755 (executable)
@@ -2759,6 +2759,9 @@ PHP_METHOD(Phar, getSignature)
        PHAR_ARCHIVE_OBJECT();
 
        if (phar_obj->arc.archive->signature) {
+               char *unknown;
+               int unknown_len;
+
                array_init(return_value);
                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) {
@@ -2777,6 +2780,10 @@ PHP_METHOD(Phar, getSignature)
                case PHAR_SIG_OPENSSL:
                        add_assoc_stringl(return_value, "hash_type", "OpenSSL", 7, 1);
                        break;
+               default:
+                       unknown_len = spprintf(&unknown, 0, "Unknown (%d)", phar_obj->arc.archive->sig_flags);
+                       add_assoc_stringl(return_value, "hash_type", unknown, unknown_len, 0);
+                       break;
                }
        } else {
                RETURN_FALSE;
index b811906ef4ea00cf5aa5d545c1d750a032c57f2e..8103bf307d00fe0cde65d2977c5bfcae5ae0c0a9 100644 (file)
@@ -1340,12 +1340,10 @@ phar_entry_info *phar_get_entry_info_dir(phar_archive_data *phar, char *path, in
 
 static const char hexChars[] = "0123456789ABCDEF";
 
-static int phar_hex_str(const char *digest, size_t digest_len, char ** signature)
+static int phar_hex_str(const char *digest, size_t digest_len, char **signature TSRMLS_DC)
 {
        int pos = -1;
        size_t len = 0;
-       
-       TSRMLS_FETCH();
 
        *signature = (char*)safe_pemalloc(digest_len, 2, 1, PHAR_G(persist));
 
@@ -1568,7 +1566,7 @@ int phar_verify_signature(php_stream *fp, size_t end_of_phar, int sig_type, char
                        EVP_MD_CTX_cleanup(&md_ctx);
 #endif
                        
-                       *signature_len = phar_hex_str((const char*)sig, sig_len, signature);
+                       *signature_len = phar_hex_str((const char*)sig, sig_len, signature TSRMLS_CC);
                }
                break;
 #if HAVE_HASH_EXT
@@ -1599,7 +1597,7 @@ int phar_verify_signature(php_stream *fp, size_t end_of_phar, int sig_type, char
                                return FAILURE;
                        }
 
-                       *signature_len = phar_hex_str((const char*)digest, sizeof(digest), signature);
+                       *signature_len = phar_hex_str((const char*)digest, sizeof(digest), signature TSRMLS_CC);
                        break;
                }
                case PHAR_SIG_SHA256: {
@@ -1629,7 +1627,7 @@ int phar_verify_signature(php_stream *fp, size_t end_of_phar, int sig_type, char
                                return FAILURE;
                        }
 
-                       *signature_len = phar_hex_str((const char*)digest, sizeof(digest), signature);
+                       *signature_len = phar_hex_str((const char*)digest, sizeof(digest), signature TSRMLS_CC);
                        break;
                }
 #else
@@ -1667,7 +1665,7 @@ int phar_verify_signature(php_stream *fp, size_t end_of_phar, int sig_type, char
                                return FAILURE;
                        }
 
-                       *signature_len = phar_hex_str((const char*)digest, sizeof(digest), signature);
+                       *signature_len = phar_hex_str((const char*)digest, sizeof(digest), signature TSRMLS_CC);
                        break;
                }
                case PHAR_SIG_MD5: {
@@ -1697,7 +1695,7 @@ int phar_verify_signature(php_stream *fp, size_t end_of_phar, int sig_type, char
                                return FAILURE;
                        }
 
-                       *signature_len = phar_hex_str((const char*)digest, sizeof(digest), signature);
+                       *signature_len = phar_hex_str((const char*)digest, sizeof(digest), signature TSRMLS_CC);
                        break;
                }
                default:
@@ -1709,3 +1707,142 @@ int phar_verify_signature(php_stream *fp, size_t end_of_phar, int sig_type, char
        return SUCCESS;
 }
 /* }}} */
+
+int phar_create_signature(phar_archive_data *phar, php_stream *fp, char **signature, int *signature_length, char **error TSRMLS_DC) /* {{{ */
+{
+       unsigned char buf[1024];
+       int sig_len;
+
+       php_stream_rewind(fp);
+
+       if (phar->signature) {
+               efree(phar->signature);
+               phar->signature = NULL;
+       }
+
+       switch(phar->sig_flags) {
+#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(fp, (char*)buf, sizeof(buf))) > 0) {
+                               PHP_SHA512Update(&context, buf, sig_len);
+                       }
+                       PHP_SHA512Final(digest, &context);
+                       *signature = estrndup((char *) digest, 64);
+                       *signature_length = 64;
+                       break;
+               }
+               case PHAR_SIG_SHA256: {
+                       unsigned char digest[32];
+                       PHP_SHA256_CTX  context;
+       
+                       PHP_SHA256Init(&context);
+                       while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
+                               PHP_SHA256Update(&context, buf, sig_len);
+                       }
+                       PHP_SHA256Final(digest, &context);
+                       *signature = estrndup((char *) digest, 32);
+                       *signature_length = 32;
+                       break;
+               }
+#else
+               case PHAR_SIG_SHA512:
+               case PHAR_SIG_SHA256:
+                       if (error) {
+                               spprintf(error, 0, "unable to write to phar \"%s\" with requested hash type", phar->fname);
+                       }
+                       return FAILURE;
+#endif
+               case PHAR_SIG_OPENSSL: {
+                       int siglen;
+                       unsigned char *sigbuf;
+#ifdef PHAR_HAVE_OPENSSL
+                       BIO *in;
+                       EVP_PKEY *key;
+                       EVP_MD *mdtype = (EVP_MD *) EVP_sha1();
+                       EVP_MD_CTX md_ctx;
+
+                       if (!zend_hash_exists(&module_registry, "openssl", sizeof("openssl"))) {
+                               if (error) {
+                                       spprintf(error, 0, "phar \"%s\" openssl signature cannot be created, openssl not loaded", phar->fname);
+                               }
+                               return FAILURE;
+                       }
+                       in = BIO_new_mem_buf(PHAR_G(openssl_privatekey), PHAR_G(openssl_privatekey_len));
+
+                       if (in == NULL) {
+                               if (error) {
+                                       spprintf(error, 0, "unable to write to phar \"%s\" with requested openssl signature", phar->fname);
+                               }
+                               return FAILURE;
+                       }
+                       key = PEM_read_bio_PrivateKey(in, NULL,NULL, "");
+
+                       BIO_free(in);
+                       siglen = EVP_PKEY_size(key);
+                       sigbuf = emalloc(siglen + 1);
+
+                       EVP_SignInit(&md_ctx, mdtype);
+                       while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
+                               EVP_SignUpdate(&md_ctx, buf, sig_len);
+                       }
+                       if (!EVP_SignFinal (&md_ctx, sigbuf,(unsigned int *)&siglen, key)) {
+                               efree(sigbuf);
+                               if (error) {
+                                       spprintf(error, 0, "unable to write phar \"%s\" with requested openssl signature", phar->fname);
+                               }
+                               return FAILURE;
+                       }
+                       sigbuf[siglen] = '\0';
+                       EVP_MD_CTX_cleanup(&md_ctx);
+#else
+                       sigbuf = NULL;
+                       siglen = 0;
+                       php_stream_seek(fp, 0, SEEK_END);
+                       if (FAILURE == phar_call_openssl_signverify(1, fp, php_stream_tell(fp), PHAR_G(openssl_privatekey), PHAR_G(openssl_privatekey_len), (char **)&sigbuf, &siglen TSRMLS_CC)) {
+                               if (error) {
+                                       spprintf(error, 0, "unable to write phar \"%s\" with requested openssl signature", phar->fname);
+                               }
+                               return FAILURE;
+                       }
+#endif
+                       *signature = (char *) sigbuf;
+                       *signature_length = siglen;
+               }
+               break;
+               default:
+                       phar->sig_flags = PHAR_SIG_SHA1;
+               case PHAR_SIG_SHA1: {
+                       unsigned char digest[20];
+                       PHP_SHA1_CTX  context;
+
+                       PHP_SHA1Init(&context);
+                       while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
+                               PHP_SHA1Update(&context, buf, sig_len);
+                       }
+                       PHP_SHA1Final(digest, &context);
+                       *signature = estrndup((char *) digest, 20);
+                       *signature_length = 20;
+                       break;
+               }
+               case PHAR_SIG_MD5: {
+                       unsigned char digest[16];
+                       PHP_MD5_CTX   context;
+
+                       PHP_MD5Init(&context);
+                       while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) {
+                               PHP_MD5Update(&context, buf, sig_len);
+                       }
+                       PHP_MD5Final(digest, &context);
+                       *signature = estrndup((char *) digest, 16);
+                       *signature_length = 16;
+                       break;
+               }
+       }
+       phar->sig_len = phar_hex_str((const char *)*signature, *signature_length, &phar->signature TSRMLS_CC);
+       return SUCCESS;
+}
+/* }}} */