cellog          Fri Jun 13 06:34:41 2008 UTC

  Modified files:              (Branch: PHP_5_3)
    /php-src/ext/phar   phar.c phar.phar phar_internal.h util.c 
  Log:
  partial refactor - move signature verification into its own function, in 
preparation for tar/zip signature support.
  next is signature creation
  
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/phar.c?r1=1.370.2.12&r2=1.370.2.13&diff_format=u
Index: php-src/ext/phar/phar.c
diff -u php-src/ext/phar/phar.c:1.370.2.12 php-src/ext/phar/phar.c:1.370.2.13
--- php-src/ext/phar/phar.c:1.370.2.12  Thu Jun 12 18:56:23 2008
+++ php-src/ext/phar/phar.c     Fri Jun 13 06:34:41 2008
@@ -17,7 +17,7 @@
   +----------------------------------------------------------------------+
 */
 
-/* $Id: phar.c,v 1.370.2.12 2008/06/12 18:56:23 cellog Exp $ */
+/* $Id: phar.c,v 1.370.2.13 2008/06/13 06:34:41 cellog Exp $ */
 
 #define PHAR_MAIN 1
 #include "phar_internal.h"
@@ -726,8 +726,6 @@
        /* The lowest nibble contains the phar wide flags. The compression 
flags can */
        /* be ignored on reading because it is being generated anyways. */
        if (manifest_flags & PHAR_HDR_SIGNATURE) {
-               unsigned char buf[1024];
-               int read_size, len;
                char sig_buf[8], *sig_ptr = sig_buf;
                off_t read_len;
                size_t end_of_phar;
@@ -746,27 +744,10 @@
                PHAR_GET_32(sig_ptr, sig_flags);
                switch(sig_flags) {
                case PHAR_SIG_OPENSSL: {
-#ifdef PHAR_HAVE_OPENSSL
-                       BIO *in;
-                       EVP_PKEY *key;
-                       EVP_MD *mdtype = (EVP_MD *) EVP_sha1();
-                       EVP_MD_CTX md_ctx;
-#else
-                       int tempsig;
-#endif
-                       php_uint32 signature_len, pubkey_len;
-                       char *sig, *pubkey = NULL, *pfile;
+                       php_uint32 signature_len;
+                       char *sig;
                        off_t whence;
-                       php_stream *pfp;
 
-                       if (!zend_hash_exists(&module_registry, "openssl", 
sizeof("openssl"))) {
-                               efree(savebuf);
-                               php_stream_close(fp);
-                               if (error) {
-                                       spprintf(error, 0, "phar \"%s\" openssl 
signature cannot be verified, openssl not loaded", fname);
-                               }
-                               return FAILURE;
-                       }
                        /* we store the signature followed by the signature 
length */
                        if (-1 == php_stream_seek(fp, -12, SEEK_CUR)
                        || 4 != php_stream_read(fp, sig_buf, 4)) {
@@ -781,7 +762,7 @@
                        sig_ptr = sig_buf;
                        PHAR_GET_32(sig_ptr, signature_len);
 
-                       sig = (char *)emalloc(signature_len);
+                       sig = (char *) emalloc(signature_len);
 
                        whence = signature_len + 4;
                        whence = -whence;
@@ -796,125 +777,54 @@
                                }
                                return FAILURE;
                        }
-
-                       /* use __FILE__ . '.pubkey' for public key file */
-                       spprintf(&pfile, 0, "%s.pubkey", fname);
-                       pfp = php_stream_open_wrapper(pfile, "rb", 0, NULL);
-                       efree(pfile);
-                       if (!pfp || !(pubkey_len = php_stream_copy_to_mem(pfp, 
&pubkey, PHP_STREAM_COPY_ALL, 0)) || !pubkey) {
-                               efree(savebuf);
-                               efree(sig);
-                               if (pubkey) {
-                                       efree(pubkey);
-                               }
-                               php_stream_close(fp);
-                               if (error) {
-                                       spprintf(error, 0, "phar \"%s\" openssl 
public key could not be read", fname);
-                               }
-                               return FAILURE;
-                       }
-                       php_stream_close(pfp);
-#ifndef PHAR_HAVE_OPENSSL
-                       tempsig = signature_len;
-                       if (FAILURE == phar_call_openssl_signverify(0, fp, 
end_of_phar, pubkey, pubkey_len, &sig, &tempsig TSRMLS_CC)) {
-                               efree(savebuf);
-                               efree(sig);
-                               if (pubkey) {
-                                       efree(pubkey);
-                               }
-                               php_stream_close(fp);
-                               if (error) {
-                                       spprintf(error, 0, "phar \"%s\" openssl 
signature could not be verified", fname);
-                               }
-                               return FAILURE;
-                       }
-                       if (pubkey) {
-                               efree(pubkey);
-                       }
-                       signature_len = tempsig;
-#else
-                       in = BIO_new_mem_buf(pubkey, pubkey_len);
-                       if (NULL == in) {
+                       if (FAILURE == phar_verify_signature(fp, end_of_phar, 
PHAR_SIG_OPENSSL, sig, signature_len, fname, &signature, &sig_len, error 
TSRMLS_CC)) {
                                efree(savebuf);
                                efree(sig);
-                               efree(pubkey);
                                php_stream_close(fp);
                                if (error) {
-                                       spprintf(error, 0, "phar \"%s\" openssl 
signature could not be processed", fname);
+                                       char *save = *error;
+                                       spprintf(error, 0, "phar \"%s\" openssl 
signature could not be verified: %s", fname, *error);
+                                       efree(save);
                                }
                                return FAILURE;
                        }
-                       key = PEM_read_bio_PUBKEY(in, NULL,NULL, NULL);
-                       BIO_free(in);
-                       efree(pubkey);
-                       if (NULL == key) {
+                       efree(sig);
+               }
+               break;
+#if HAVE_HASH_EXT
+               case PHAR_SIG_SHA512: {
+                       unsigned char digest[64];
+
+                       php_stream_seek(fp, -(8 + 64), SEEK_END);
+                       read_len = php_stream_tell(fp);
+                       if (php_stream_read(fp, (char*)digest, sizeof(digest)) 
!= sizeof(digest)) {
                                efree(savebuf);
-                               efree(sig);
                                php_stream_close(fp);
                                if (error) {
-                                       spprintf(error, 0, "phar \"%s\" openssl 
signature could not be processed", fname);
+                                       spprintf(error, 0, "phar \"%s\" has a 
broken signature", fname);
                                }
                                return FAILURE;
                        }
 
-                       EVP_VerifyInit(&md_ctx, mdtype);
-
-                       read_len -= signature_len + 4;
-                       if (read_len > sizeof(buf)) {
-                               read_size = sizeof(buf);
-                       } else {
-                               read_size = (int)read_len;
-                       }
-                       php_stream_seek(fp, 0, SEEK_SET);
-                       while (read_size && (len = php_stream_read(fp, 
(char*)buf, read_size)) > 0) {
-                               EVP_VerifyUpdate (&md_ctx, buf, len);
-                               read_len -= (off_t)len;
-                               if (read_len < read_size) {
-                                       read_size = (int)read_len;
-                               }
-                       }
-                       if (!EVP_VerifyFinal (&md_ctx, (unsigned char *)sig, 
signature_len, key)) {
-                               EVP_MD_CTX_cleanup(&md_ctx);
-                               efree(sig);
+                       if (FAILURE == phar_verify_signature(fp, read_len, 
PHAR_SIG_SHA512, (char *)digest, 64, fname, &signature, &sig_len, error 
TSRMLS_CC)) {
                                efree(savebuf);
                                php_stream_close(fp);
                                if (error) {
-                                       spprintf(error, 0, "phar \"%s\" has a 
broken signature", fname);
+                                       char *save = *error;
+                                       spprintf(error, 0, "phar \"%s\" SHA512 
signature could not be verified: %s", fname, *error);
+                                       efree(save);
                                }
                                return FAILURE;
                        }
-                       EVP_MD_CTX_cleanup(&md_ctx);
-#endif
-                       
-                       sig_len = phar_hex_str((const char*)sig, signature_len, 
&signature);
-                       efree(sig);
+                       break;
                }
-               break;
-#if HAVE_HASH_EXT
-               case PHAR_SIG_SHA512: {
-                       unsigned char digest[64], saved[64];
-                       PHP_SHA512_CTX  context;
+               case PHAR_SIG_SHA256: {
+                       unsigned char digest[32];
 
-                       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);
+                       php_stream_seek(fp, -(8 + 32), SEEK_END);
+                       read_len = php_stream_tell(fp);
 
-                       if (read_len > 0
-                       || php_stream_read(fp, (char*)saved, sizeof(saved)) != 
sizeof(saved)
-                       || memcmp(digest, saved, sizeof(digest))) {
+                       if (php_stream_read(fp, (char*)digest, sizeof(digest)) 
!= sizeof(digest)) {
                                efree(savebuf);
                                php_stream_close(fp);
                                if (error) {
@@ -923,42 +833,16 @@
                                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))) {
+                       if (FAILURE == phar_verify_signature(fp, read_len, 
PHAR_SIG_SHA256, (char *)digest, 32, fname, &signature, &sig_len, error 
TSRMLS_CC)) {
                                efree(savebuf);
                                php_stream_close(fp);
                                if (error) {
-                                       spprintf(error, 0, "phar \"%s\" has a 
broken signature", fname);
+                                       char *save = *error;
+                                       spprintf(error, 0, "phar \"%s\" SHA256 
signature could not be verified: %s", fname, *error);
+                                       efree(save);
                                }
                                return FAILURE;
                        }
-
-                       sig_len = phar_hex_str((const char*)digest, 
sizeof(digest), &signature);
                        break;
                }
 #else
@@ -972,29 +856,12 @@
                        return FAILURE;
 #endif
                case PHAR_SIG_SHA1: {
-                       unsigned char digest[20], saved[20];
-                       PHP_SHA1_CTX  context;
+                       unsigned char digest[20];
 
-                       php_stream_rewind(fp);
-                       PHP_SHA1Init(&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_SHA1Update(&context, buf, len);
-                               read_len -= (off_t)len;
-                               if (read_len < read_size) {
-                                       read_size = (int)read_len;
-                               }
-                       }
-                       PHP_SHA1Final(digest, &context);
+                       php_stream_seek(fp, -(8 + 20), SEEK_END);
+                       read_len = php_stream_tell(fp);
 
-                       if (read_len > 0
-                       || php_stream_read(fp, (char*)saved, sizeof(saved)) != 
sizeof(saved)
-                       || memcmp(digest, saved, sizeof(digest))) {
+                       if (php_stream_read(fp, (char*)digest, sizeof(digest)) 
!= sizeof(digest)) {
                                efree(savebuf);
                                php_stream_close(fp);
                                if (error) {
@@ -1003,33 +870,25 @@
                                return FAILURE;
                        }
 
-                       sig_len = phar_hex_str((const char*)digest, 
sizeof(digest), &signature);
+                       if (FAILURE == phar_verify_signature(fp, read_len, 
PHAR_SIG_SHA1, (char *)digest, 20, fname, &signature, &sig_len, error 
TSRMLS_CC)) {
+                               efree(savebuf);
+                               php_stream_close(fp);
+                               if (error) {
+                                       char *save = *error;
+                                       spprintf(error, 0, "phar \"%s\" SHA1 
signature could not be verified: %s", fname, *error);
+                                       efree(save);
+                               }
+                               return FAILURE;
+                       }
                        break;
                }
                case PHAR_SIG_MD5: {
-                       unsigned char digest[16], saved[16];
-                       PHP_MD5_CTX   context;
+                       unsigned char digest[16];
 
-                       php_stream_rewind(fp);
-                       PHP_MD5Init(&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_MD5Update(&context, buf, len);
-                               read_len -= (off_t)len;
-                               if (read_len < read_size) {
-                                       read_size = (int)read_len;
-                               }
-                       }
-                       PHP_MD5Final(digest, &context);
+                       php_stream_seek(fp, -(8 + 16), SEEK_END);
+                       read_len = php_stream_tell(fp);
 
-                       if (read_len > 0
-                       || php_stream_read(fp, (char*)saved, sizeof(saved)) != 
sizeof(saved)
-                       || memcmp(digest, saved, sizeof(digest))) {
+                       if (php_stream_read(fp, (char*)digest, sizeof(digest)) 
!= sizeof(digest)) {
                                efree(savebuf);
                                php_stream_close(fp);
                                if (error) {
@@ -1038,7 +897,16 @@
                                return FAILURE;
                        }
 
-                       sig_len = phar_hex_str((const char*)digest, 
sizeof(digest), &signature);
+                       if (FAILURE == phar_verify_signature(fp, read_len, 
PHAR_SIG_MD5, (char *)digest, 16, fname, &signature, &sig_len, error 
TSRMLS_CC)) {
+                               efree(savebuf);
+                               php_stream_close(fp);
+                               if (error) {
+                                       char *save = *error;
+                                       spprintf(error, 0, "phar \"%s\" MD5 
signature could not be verified: %s", fname, *error);
+                                       efree(save);
+                               }
+                               return FAILURE;
+                       }
                        break;
                }
                default:
@@ -3665,7 +3533,7 @@
        php_info_print_table_header(2, "Phar: PHP Archive support", "enabled");
        php_info_print_table_row(2, "Phar EXT version", PHP_PHAR_VERSION);
        php_info_print_table_row(2, "Phar API version", PHP_PHAR_API_VERSION);
-       php_info_print_table_row(2, "CVS revision", "$Revision: 1.370.2.12 $");
+       php_info_print_table_row(2, "CVS revision", "$Revision: 1.370.2.13 $");
        php_info_print_table_row(2, "Phar-based phar archives", "enabled");
        php_info_print_table_row(2, "Tar-based phar archives", "enabled");
        php_info_print_table_row(2, "ZIP-based phar archives", "enabled");
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/phar.phar?r1=1.7.2.11&r2=1.7.2.12&diff_format=u
Index: php-src/ext/phar/phar.phar
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/phar_internal.h?r1=1.109.2.7&r2=1.109.2.8&diff_format=u
Index: php-src/ext/phar/phar_internal.h
diff -u php-src/ext/phar/phar_internal.h:1.109.2.7 
php-src/ext/phar/phar_internal.h:1.109.2.8
--- php-src/ext/phar/phar_internal.h:1.109.2.7  Thu Jun 12 18:56:23 2008
+++ php-src/ext/phar/phar_internal.h    Fri Jun 13 06:34:41 2008
@@ -17,7 +17,7 @@
   +----------------------------------------------------------------------+
 */
 
-/* $Id: phar_internal.h,v 1.109.2.7 2008/06/12 18:56:23 cellog Exp $ */
+/* $Id: phar_internal.h,v 1.109.2.8 2008/06/13 06:34:41 cellog Exp $ */
 
 #ifdef HAVE_CONFIG_H
 #include "config.h"
@@ -416,6 +416,7 @@
 int phar_free_alias(phar_archive_data *phar, char *alias, int alias_len 
TSRMLS_DC);
 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);
 
 /* utility functions */
 char *phar_create_default_stub(const char *index_php, const char *web_index, 
size_t *len, char **error TSRMLS_DC);
http://cvs.php.net/viewvc.cgi/php-src/ext/phar/util.c?r1=1.55.2.4&r2=1.55.2.5&diff_format=u
Index: php-src/ext/phar/util.c
diff -u php-src/ext/phar/util.c:1.55.2.4 php-src/ext/phar/util.c:1.55.2.5
--- php-src/ext/phar/util.c:1.55.2.4    Tue Jun 10 17:58:09 2008
+++ php-src/ext/phar/util.c     Fri Jun 13 06:34:41 2008
@@ -18,9 +18,27 @@
   +----------------------------------------------------------------------+
 */
 
-/* $Id: util.c,v 1.55.2.4 2008/06/10 17:58:09 cellog Exp $ */
+/* $Id: util.c,v 1.55.2.5 2008/06/13 06:34:41 cellog Exp $ */
 
 #include "phar_internal.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
 #if !defined(PHP_VERSION_ID) || PHP_VERSION_ID < 50300
 extern php_stream_wrapper php_stream_phar_wrapper;
 #endif
@@ -1319,3 +1337,373 @@
        return NULL;
 }
 /* }}} */
+
+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;
+
+       *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;
+}
+#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)
+{
+       zend_fcall_info fci;
+       zend_fcall_info_cache fcc;
+       zval *zdata, *zsig, *zkey, *retval_ptr, **zp[3], *openssl;
+
+       MAKE_STD_ZVAL(zdata);
+       MAKE_STD_ZVAL(openssl);
+       ZVAL_STRINGL(openssl, is_sign ? "openssl_sign" : "openssl_verify", 
is_sign ? sizeof("openssl_sign")-1 : sizeof("openssl_verify")-1, 1);
+       MAKE_STD_ZVAL(zsig);
+       ZVAL_STRINGL(zsig, *signature, *signature_len, 1);
+       MAKE_STD_ZVAL(zkey);
+       ZVAL_STRINGL(zkey, key, key_len, 1);
+       zp[0] = &zdata;
+       zp[1] = &zsig;
+       zp[2] = &zkey;
+
+       php_stream_rewind(fp);
+       Z_TYPE_P(zdata) = IS_STRING;
+       Z_STRLEN_P(zdata) = end;
+       if (end != (off_t) php_stream_copy_to_mem(fp, &(Z_STRVAL_P(zdata)), 
(size_t) end, 0)) {
+               zval_dtor(zdata);
+               zval_dtor(zsig);
+               zval_dtor(zkey);
+               return FAILURE;
+       }
+
+#if PHP_VERSION_ID < 50300
+       if (FAILURE == zend_fcall_info_init(openssl, &fci, &fcc TSRMLS_CC)) {
+#else
+       if (FAILURE == zend_fcall_info_init(openssl, 0, &fci, &fcc, NULL, NULL 
TSRMLS_CC)) {
+#endif
+               zval_dtor(zdata);
+               zval_dtor(zsig);
+               zval_dtor(zkey);
+               zval_dtor(openssl);
+               return FAILURE;
+       }
+       zval_dtor(openssl);
+       efree(openssl);
+
+       fci.param_count = 3;
+       fci.params = zp;
+#if PHP_VERSION_ID < 50300
+       ++(zdata->refcount);
+       ++(zsig->refcount);
+       ++(zkey->refcount);
+#else
+       Z_ADDREF_P(zdata);
+       if (is_sign) {
+               Z_SET_ISREF_P(zsig);
+       } else {
+               Z_ADDREF_P(zsig);
+       }
+       Z_ADDREF_P(zkey);
+#endif
+       fci.retval_ptr_ptr = &retval_ptr;
+
+       if (FAILURE == zend_call_function(&fci, &fcc TSRMLS_CC)) {
+               zval_dtor(zdata);
+               zval_dtor(zsig);
+               zval_dtor(zkey);
+               efree(zdata);
+               efree(zkey);
+               efree(zsig);
+               return FAILURE;
+       }
+#if PHP_VERSION_ID < 50300
+       --(zdata->refcount);
+       --(zsig->refcount);
+       --(zkey->refcount);
+#else
+       Z_DELREF_P(zdata);
+       if (is_sign) {
+               Z_UNSET_ISREF_P(zsig);
+       } else {
+               Z_DELREF_P(zsig);
+       }
+       Z_DELREF_P(zkey);
+#endif
+       zval_dtor(zdata);
+       efree(zdata);
+       zval_dtor(zkey);
+       efree(zkey);
+       switch (Z_TYPE_P(retval_ptr)) {
+               default:
+               case IS_LONG :
+                       zval_dtor(zsig);
+                       efree(zsig);
+                       if (1 == Z_LVAL_P(retval_ptr)) {
+                               efree(retval_ptr);
+                               return SUCCESS;
+                       }
+                       efree(retval_ptr);
+                       return FAILURE;
+               case IS_BOOL :
+                       efree(retval_ptr);
+                       if (Z_BVAL_P(retval_ptr)) {
+                               *signature = estrndup(Z_STRVAL_P(zsig), 
Z_STRLEN_P(zsig));
+                               *signature_len = Z_STRLEN_P(zsig);
+                               zval_dtor(zsig);
+                               efree(zsig);
+                               return SUCCESS;
+                       }
+                       zval_dtor(zsig);
+                       efree(zsig);
+                       return FAILURE;
+       }
+}
+#endif /* #ifndef PHAR_HAVE_OPENSSL */
+
+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 read_size, len;
+       off_t read_len;
+       unsigned char buf[1024];
+
+       php_stream_rewind(fp);
+
+       switch (sig_type) {
+               case PHAR_SIG_OPENSSL: {
+#ifdef PHAR_HAVE_OPENSSL
+                       BIO *in;
+                       EVP_PKEY *key;
+                       EVP_MD *mdtype = (EVP_MD *) EVP_sha1();
+                       EVP_MD_CTX md_ctx;
+#else
+                       int tempsig;
+#endif
+                       php_uint32 pubkey_len;
+                       char *pubkey = NULL, *pfile;
+                       php_stream *pfp;
+
+                       if (!zend_hash_exists(&module_registry, "openssl", 
sizeof("openssl"))) {
+                               if (error) {
+                                       spprintf(error, 0, "openssl not 
loaded");
+                               }
+                               return FAILURE;
+                       }
+
+                       /* use __FILE__ . '.pubkey' for public key file */
+                       spprintf(&pfile, 0, "%s.pubkey", fname);
+                       pfp = php_stream_open_wrapper(pfile, "rb", 0, NULL);
+                       efree(pfile);
+                       if (!pfp || !(pubkey_len = php_stream_copy_to_mem(pfp, 
&pubkey, PHP_STREAM_COPY_ALL, 0)) || !pubkey) {
+                               if (error) {
+                                       spprintf(error, 0, "openssl public key 
could not be read");
+                               }
+                               return FAILURE;
+                       }
+                       php_stream_close(pfp);
+#ifndef PHAR_HAVE_OPENSSL
+                       tempsig = sig_len;
+                       if (FAILURE == phar_call_openssl_signverify(0, fp, 
end_of_phar, pubkey, pubkey_len, &sig, &tempsig TSRMLS_CC)) {
+                               if (pubkey) {
+                                       efree(pubkey);
+                               }
+                               if (error) {
+                                       spprintf(error, 0, "openssl signature 
could not be verified");
+                               }
+                               return FAILURE;
+                       }
+                       if (pubkey) {
+                               efree(pubkey);
+                       }
+                       sig_len = tempsig;
+#else
+                       in = BIO_new_mem_buf(pubkey, pubkey_len);
+                       if (NULL == in) {
+                               efree(pubkey);
+                               if (error) {
+                                       spprintf(error, 0, "openssl signature 
could not be processed");
+                               }
+                               return FAILURE;
+                       }
+                       key = PEM_read_bio_PUBKEY(in, NULL,NULL, NULL);
+                       BIO_free(in);
+                       efree(pubkey);
+                       if (NULL == key) {
+                               if (error) {
+                                       spprintf(error, 0, "openssl signature 
could not be processed");
+                               }
+                               return FAILURE;
+                       }
+
+                       EVP_VerifyInit(&md_ctx, mdtype);
+
+                       read_len = end_of_phar;
+                       if (read_len > sizeof(buf)) {
+                               read_size = sizeof(buf);
+                       } else {
+                               read_size = (int)read_len;
+                       }
+                       php_stream_seek(fp, 0, SEEK_SET);
+                       while (read_size && (len = php_stream_read(fp, 
(char*)buf, read_size)) > 0) {
+                               EVP_VerifyUpdate (&md_ctx, buf, len);
+                               read_len -= (off_t)len;
+                               if (read_len < read_size) {
+                                       read_size = (int)read_len;
+                               }
+                       }
+                       if (!EVP_VerifyFinal (&md_ctx, (unsigned char *)sig, 
sig_len, key)) {
+                               EVP_MD_CTX_cleanup(&md_ctx);
+                               if (error) {
+                                       spprintf(error, 0, "broken openssl 
signature");
+                               }
+                               return FAILURE;
+                       }
+                       EVP_MD_CTX_cleanup(&md_ctx);
+#endif
+                       
+                       *signature_len = phar_hex_str((const char*)sig, 
sig_len, signature);
+               }
+               break;
+#if HAVE_HASH_EXT
+               case PHAR_SIG_SHA512: {
+                       unsigned char digest[64];
+                       PHP_SHA512_CTX  context;
+
+                       PHP_SHA512Init(&context);
+                       read_len = end_of_phar;
+                       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 (memcmp(digest, sig, sizeof(digest))) {
+                               if (error) {
+                                       spprintf(error, 0, "broken signature");
+                               }
+                               return FAILURE;
+                       }
+
+                       *signature_len = phar_hex_str((const char*)digest, 
sizeof(digest), signature);
+                       break;
+               }
+               case PHAR_SIG_SHA256: {
+                       unsigned char digest[32];
+                       PHP_SHA256_CTX  context;
+
+                       PHP_SHA256Init(&context);
+                       read_len = end_of_phar;
+                       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 (memcmp(digest, sig, sizeof(digest))) {
+                               if (error) {
+                                       spprintf(error, 0, "broken signature");
+                               }
+                               return FAILURE;
+                       }
+
+                       *signature_len = phar_hex_str((const char*)digest, 
sizeof(digest), signature);
+                       break;
+               }
+#else
+               case PHAR_SIG_SHA512:
+               case PHAR_SIG_SHA256:
+                       if (error) {
+                               spprintf(error, 0, "unsupported signature");
+                       }
+                       return FAILURE;
+#endif
+               case PHAR_SIG_SHA1: {
+                       unsigned char digest[20];
+                       PHP_SHA1_CTX  context;
+
+                       PHP_SHA1Init(&context);
+                       read_len = end_of_phar;
+                       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_SHA1Update(&context, buf, len);
+                               read_len -= (off_t)len;
+                               if (read_len < read_size) {
+                                       read_size = (int)read_len;
+                               }
+                       }
+                       PHP_SHA1Final(digest, &context);
+
+                       if (memcmp(digest, sig, sizeof(digest))) {
+                               if (error) {
+                                       spprintf(error, 0, "broken signature");
+                               }
+                               return FAILURE;
+                       }
+
+                       *signature_len = phar_hex_str((const char*)digest, 
sizeof(digest), signature);
+                       break;
+               }
+               case PHAR_SIG_MD5: {
+                       unsigned char digest[16];
+                       PHP_MD5_CTX   context;
+
+                       PHP_MD5Init(&context);
+                       read_len = end_of_phar;
+                       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_MD5Update(&context, buf, len);
+                               read_len -= (off_t)len;
+                               if (read_len < read_size) {
+                                       read_size = (int)read_len;
+                               }
+                       }
+                       PHP_MD5Final(digest, &context);
+
+                       if (memcmp(digest, sig, sizeof(digest))) {
+                               if (error) {
+                                       spprintf(error, 0, "broken signature");
+                               }
+                               return FAILURE;
+                       }
+
+                       *signature_len = phar_hex_str((const char*)digest, 
sizeof(digest), signature);
+                       break;
+               }
+               default:
+                       if (error) {
+                               spprintf(error, 0, "broken or unsupported 
signature");
+                       }
+                       return FAILURE;
+       }
+       return SUCCESS;
+}
+/* }}} */

-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to