]> granicus.if.org Git - php/commitdiff
Added support for ext/openssl
authorDmitry Stogov <dmitry@zend.com>
Tue, 6 May 2014 21:09:42 +0000 (01:09 +0400)
committerDmitry Stogov <dmitry@zend.com>
Tue, 6 May 2014 21:09:42 +0000 (01:09 +0400)
ext/openssl/openssl.c
ext/openssl/xp_ssl.c

index 42f8196aa0b92f1a6c5fe532dc0253bf884df07b..94056ce04b551cd5ba6c6cd9e31c125efbe4b583 100755 (executable)
@@ -542,7 +542,7 @@ int php_openssl_get_x509_list_id(void) /* {{{ */
 /* }}} */
 
 /* {{{ resource destructors */
-static void php_pkey_free(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+static void php_pkey_free(zend_resource *rsrc TSRMLS_DC)
 {
        EVP_PKEY *pkey = (EVP_PKEY *)rsrc->ptr;
 
@@ -551,13 +551,13 @@ static void php_pkey_free(zend_rsrc_list_entry *rsrc TSRMLS_DC)
        EVP_PKEY_free(pkey);
 }
 
-static void php_x509_free(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+static void php_x509_free(zend_resource *rsrc TSRMLS_DC)
 {
        X509 *x509 = (X509 *)rsrc->ptr;
        X509_free(x509);
 }
 
-static void php_csr_free(zend_rsrc_list_entry *rsrc TSRMLS_DC)
+static void php_csr_free(zend_resource *rsrc TSRMLS_DC)
 {
        X509_REQ * csr = (X509_REQ*)rsrc->ptr;
        X509_REQ_free(csr);
@@ -615,18 +615,18 @@ struct php_x509_request { /* {{{ */
 };
 /* }}} */
 
-static X509 * php_openssl_x509_from_zval(zval ** val, int makeresource, long * resourceval TSRMLS_DC);
-static EVP_PKEY * php_openssl_evp_from_zval(zval ** val, int public_key, char * passphrase, int makeresource, long * resourceval TSRMLS_DC);
+static X509 * php_openssl_x509_from_zval(zval * val, int makeresource, zend_resource **resourceval TSRMLS_DC);
+static EVP_PKEY * php_openssl_evp_from_zval(zval * val, int public_key, char * passphrase, int makeresource, zend_resource **resourceval TSRMLS_DC);
 static int php_openssl_is_private_key(EVP_PKEY* pkey TSRMLS_DC);
 static X509_STORE * setup_verify(zval * calist TSRMLS_DC);
 static STACK_OF(X509) * load_all_certs_from_file(char *certfile);
-static X509_REQ * php_openssl_csr_from_zval(zval ** val, int makeresource, long * resourceval TSRMLS_DC);
+static X509_REQ * php_openssl_csr_from_zval(zval * val, int makeresource, zend_resource ** resourceval TSRMLS_DC);
 static EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req TSRMLS_DC);
 
 static void add_assoc_name_entry(zval * val, char * key, X509_NAME * name, int shortname TSRMLS_DC) /* {{{ */
 {
-       zval **data;
-       zval *subitem, *subentries;
+       zval *data;
+       zval subitem, tmp;
        int i;
        char *sname;
        int nid;
@@ -635,10 +635,9 @@ static void add_assoc_name_entry(zval * val, char * key, X509_NAME * name, int s
        ASN1_OBJECT * obj;
 
        if (key != NULL) {
-               MAKE_STD_ZVAL(subitem);
-               array_init(subitem);
+               array_init(&subitem);
        } else {
-               subitem = val;
+               ZVAL_COPY_VALUE(&subitem, val);
        }
        
        for (i = 0; i < X509_NAME_entry_count(name); i++) {
@@ -665,24 +664,22 @@ static void add_assoc_name_entry(zval * val, char * key, X509_NAME * name, int s
                }
 
                if (to_add_len != -1) {
-                       if (zend_hash_find(Z_ARRVAL_P(subitem), sname, strlen(sname)+1, (void**)&data) == SUCCESS) {
-                               if (Z_TYPE_PP(data) == IS_ARRAY) {
-                                       subentries = *data;
-                                       add_next_index_stringl(subentries, (char *)to_add, to_add_len);
-                               } else if (Z_TYPE_PP(data) == IS_STRING) {
-                                       MAKE_STD_ZVAL(subentries);
-                                       array_init(subentries);
-                                       add_next_index_stringl(subentries, Z_STRVAL_PP(data), Z_STRLEN_PP(data));
-                                       add_next_index_stringl(subentries, (char *)to_add, to_add_len);
-                                       zend_hash_update(Z_ARRVAL_P(subitem), sname, strlen(sname)+1, &subentries, sizeof(zval*), NULL);
+                       if ((data = zend_hash_str_find(Z_ARRVAL(subitem), sname, strlen(sname))) != NULL) {
+                               if (Z_TYPE_P(data) == IS_ARRAY) {
+                                       add_next_index_stringl(data, (char *)to_add, to_add_len);
+                               } else if (Z_TYPE_P(data) == IS_STRING) {                                       
+                                       array_init(&tmp);
+                                       add_next_index_str(&tmp, STR_COPY(Z_STR_P(data)));
+                                       add_next_index_stringl(&tmp, (char *)to_add, to_add_len);
+                                       zend_hash_str_update(Z_ARRVAL(subitem), sname, strlen(sname), &tmp);
                                }
                        } else {
-                               add_assoc_stringl(subitem, sname, (char *)to_add, to_add_len);
+                               add_assoc_stringl(&subitem, sname, (char *)to_add, to_add_len);
                        }
                }
        }
        if (key != NULL) {
-               zend_hash_update(HASH_OF(val), key, strlen(key) + 1, (void *)&subitem, sizeof(subitem), NULL);
+               zend_hash_str_update(HASH_OF(val), key, strlen(key), &subitem);
        }
 }
 /* }}} */
@@ -829,14 +826,14 @@ static int add_oid_section(struct php_x509_request * req TSRMLS_DC) /* {{{ */
                        req->config_filename, req->var, req->req_config TSRMLS_CC) == FAILURE) return FAILURE
 
 #define SET_OPTIONAL_STRING_ARG(key, varname, defval)  \
-       if (optional_args && zend_hash_find(Z_ARRVAL_P(optional_args), key, sizeof(key), (void**)&item) == SUCCESS) \
-               varname = Z_STRVAL_PP(item); \
+               if (optional_args && (item = zend_hash_str_find(Z_ARRVAL_P(optional_args), key, sizeof(key)-1)) != NULL) \
+               varname = Z_STRVAL_P(item); \
        else \
                varname = defval
 
 #define SET_OPTIONAL_LONG_ARG(key, varname, defval)    \
-       if (optional_args && zend_hash_find(Z_ARRVAL_P(optional_args), key, sizeof(key), (void**)&item) == SUCCESS) \
-               varname = Z_LVAL_PP(item); \
+       if (optional_args && (item = zend_hash_str_find(Z_ARRVAL_P(optional_args), key, sizeof(key)-1)) != NULL) \
+               varname = Z_LVAL_P(item); \
        else \
                varname = defval
 
@@ -847,7 +844,7 @@ int openssl_spki_cleanup(const char *src, char *dest);
 static int php_openssl_parse_config(struct php_x509_request * req, zval * optional_args TSRMLS_DC) /* {{{ */
 {
        char * str;
-       zval ** item;
+       zval * item;
 
        SET_OPTIONAL_STRING_ARG("config", req->config_filename, default_ssl_conf_filename);
        SET_OPTIONAL_STRING_ARG("config_section_name", req->section_name, "req");
@@ -881,8 +878,8 @@ static int php_openssl_parse_config(struct php_x509_request * req, zval * option
 
        SET_OPTIONAL_LONG_ARG("private_key_type", req->priv_key_type, OPENSSL_KEYTYPE_DEFAULT);
 
-       if (optional_args && zend_hash_find(Z_ARRVAL_P(optional_args), "encrypt_key", sizeof("encrypt_key"), (void**)&item) == SUCCESS) {
-               req->priv_key_encrypt = Z_BVAL_PP(item);
+       if (optional_args && (item = zend_hash_str_find(Z_ARRVAL_P(optional_args), "encrypt_key", sizeof("encrypt_key")-1)) != NULL) {
+               req->priv_key_encrypt = Z_TYPE_P(item) == IS_TRUE ? 1 : 0;
        } else {
                str = CONF_get_string(req->req_config, req->section_name, "encrypt_rsa_key");
                if (str == NULL) {
@@ -895,8 +892,8 @@ static int php_openssl_parse_config(struct php_x509_request * req, zval * option
                }
        }
 
-       if (req->priv_key_encrypt && optional_args && zend_hash_find(Z_ARRVAL_P(optional_args), "encrypt_key_cipher", sizeof("encrypt_key_cipher"), (void**)&item) == SUCCESS) {
-               long cipher_algo = Z_LVAL_PP(item);
+       if (req->priv_key_encrypt && optional_args && (item = zend_hash_str_find(Z_ARRVAL_P(optional_args), "encrypt_key_cipher", sizeof("encrypt_key_cipher")-1)) != NULL) {
+               long cipher_algo = Z_LVAL_P(item);
                const EVP_CIPHER* cipher = php_openssl_get_evp_cipher_from_algo(cipher_algo);
                if (cipher == NULL) {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown cipher algorithm for private key.");
@@ -1292,16 +1289,16 @@ PHP_FUNCTION(openssl_get_cert_locations)
 {
        array_init(return_value);
 
-       add_assoc_string(return_value, "default_cert_file", (char *) X509_get_default_cert_file(), 1);
-       add_assoc_string(return_value, "default_cert_file_env", (char *) X509_get_default_cert_file_env(), 1);
-       add_assoc_string(return_value, "default_cert_dir", (char *) X509_get_default_cert_dir(), 1);
-       add_assoc_string(return_value, "default_cert_dir_env", (char *) X509_get_default_cert_dir_env(), 1);
-       add_assoc_string(return_value, "default_private_dir", (char *) X509_get_default_private_dir(), 1);
-       add_assoc_string(return_value, "default_default_cert_area", (char *) X509_get_default_cert_area(), 1);
+       add_assoc_string(return_value, "default_cert_file", (char *) X509_get_default_cert_file());
+       add_assoc_string(return_value, "default_cert_file_env", (char *) X509_get_default_cert_file_env());
+       add_assoc_string(return_value, "default_cert_dir", (char *) X509_get_default_cert_dir());
+       add_assoc_string(return_value, "default_cert_dir_env", (char *) X509_get_default_cert_dir_env());
+       add_assoc_string(return_value, "default_private_dir", (char *) X509_get_default_private_dir());
+       add_assoc_string(return_value, "default_default_cert_area", (char *) X509_get_default_cert_area());
        add_assoc_string(return_value, "ini_cafile",
-               zend_ini_string("openssl.cafile", sizeof("openssl.cafile"), 0), 1);
+               zend_ini_string("openssl.cafile", sizeof("openssl.cafile")-1, 0));
        add_assoc_string(return_value, "ini_capath",
-               zend_ini_string("openssl.capath", sizeof("openssl.capath"), 0), 1);
+               zend_ini_string("openssl.capath", sizeof("openssl.capath")-1, 0));
 }
 /* }}} */
 
@@ -1315,14 +1312,14 @@ PHP_FUNCTION(openssl_get_cert_locations)
        If you supply makeresource, the result will be registered as an x509 resource and
        it's value returned in makeresource.
 */
-static X509 * php_openssl_x509_from_zval(zval ** val, int makeresource, long * resourceval TSRMLS_DC)
+static X509 * php_openssl_x509_from_zval(zval * val, int makeresource, zend_resource **resourceval TSRMLS_DC)
 {
        X509 *cert = NULL;
 
        if (resourceval) {
-               *resourceval = -1;
+               *resourceval = NULL;
        }
-       if (Z_TYPE_PP(val) == IS_RESOURCE) {
+       if (Z_TYPE_P(val) == IS_RESOURCE) {
                /* is it an x509 resource ? */
                void * what;
                int type;
@@ -1333,7 +1330,8 @@ static X509 * php_openssl_x509_from_zval(zval ** val, int makeresource, long * r
                }
                /* this is so callers can decide if they should free the X509 */
                if (resourceval) {
-                       *resourceval = Z_LVAL_PP(val);
+                       *resourceval = Z_RES_P(val);
+                       Z_ADDREF_P(val);
                }
                if (type == le_x509) {
                        return (X509*)what;
@@ -1343,22 +1341,22 @@ static X509 * php_openssl_x509_from_zval(zval ** val, int makeresource, long * r
                return NULL;
        }
 
-       if (!(Z_TYPE_PP(val) == IS_STRING || Z_TYPE_PP(val) == IS_OBJECT)) {
+       if (!(Z_TYPE_P(val) == IS_STRING || Z_TYPE_P(val) == IS_OBJECT)) {
                return NULL;
        }
 
        /* force it to be a string and check if it refers to a file */
        convert_to_string_ex(val);
 
-       if (Z_STRLEN_PP(val) > 7 && memcmp(Z_STRVAL_PP(val), "file://", sizeof("file://") - 1) == 0) {
+       if (Z_STRLEN_P(val) > 7 && memcmp(Z_STRVAL_P(val), "file://", sizeof("file://") - 1) == 0) {
                /* read cert from the named file */
                BIO *in;
 
-               if (php_openssl_open_base_dir_chk(Z_STRVAL_PP(val) + (sizeof("file://") - 1) TSRMLS_CC)) {
+               if (php_openssl_open_base_dir_chk(Z_STRVAL_P(val) + (sizeof("file://") - 1) TSRMLS_CC)) {
                        return NULL;
                }
 
-               in = BIO_new_file(Z_STRVAL_PP(val) + (sizeof("file://") - 1), "r");
+               in = BIO_new_file(Z_STRVAL_P(val) + (sizeof("file://") - 1), "r");
                if (in == NULL) {
                        return NULL;
                }
@@ -1367,7 +1365,7 @@ static X509 * php_openssl_x509_from_zval(zval ** val, int makeresource, long * r
        } else {
                BIO *in;
 
-               in = BIO_new_mem_buf(Z_STRVAL_PP(val), Z_STRLEN_PP(val));
+               in = BIO_new_mem_buf(Z_STRVAL_P(val), Z_STRLEN_P(val));
                if (in == NULL) {
                        return NULL;
                }
@@ -1380,7 +1378,7 @@ static X509 * php_openssl_x509_from_zval(zval ** val, int makeresource, long * r
        }
 
        if (cert && makeresource && resourceval) {
-               *resourceval = zend_list_insert(cert, le_x509 TSRMLS_CC);
+               *resourceval = zend_register_resource(NULL, cert, le_x509 TSRMLS_CC);
        }
        return cert;
 }
@@ -1392,14 +1390,14 @@ static X509 * php_openssl_x509_from_zval(zval ** val, int makeresource, long * r
 PHP_FUNCTION(openssl_x509_export_to_file)
 {
        X509 * cert;
-       zval ** zcert;
+       zval * zcert;
        zend_bool notext = 1;
        BIO * bio_out;
-       long certresource;
+       zend_resource *certresource;
        char * filename;
        int filename_len;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zp|b", &zcert, &filename, &filename_len, &notext) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zp|b", &zcert, &filename, &filename_len, &notext) == FAILURE) {
                return;
        }
        RETVAL_FALSE;
@@ -1425,7 +1423,7 @@ PHP_FUNCTION(openssl_x509_export_to_file)
        } else {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "error opening file %s", filename);
        }
-       if (certresource == -1 && cert) {
+       if (certresource == NULL && cert) {
                X509_free(cert);
        }
        BIO_free(bio_out);
@@ -1438,8 +1436,9 @@ PHP_FUNCTION(openssl_x509_export_to_file)
 PHP_FUNCTION(openssl_spki_new)
 {
        int challenge_len;
-       char * challenge = NULL, * spkstr = NULL, * s = NULL;
-       long keyresource = -1;
+       char * challenge = NULL, * spkstr = NULL;
+       zend_string * s = NULL;
+       zend_resource *keyresource = NULL;
        const char *spkac = "SPKAC=";
        long algo = OPENSSL_ALGO_MD5;
 
@@ -1454,7 +1453,7 @@ PHP_FUNCTION(openssl_spki_new)
        }
        RETVAL_FALSE;
 
-       pkey = php_openssl_evp_from_zval(&zpkey, 0, challenge, 1, &keyresource TSRMLS_CC);
+       pkey = php_openssl_evp_from_zval(zpkey, 0, challenge, 1, &keyresource TSRMLS_CC);
 
        if (pkey == NULL) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to use supplied private key");
@@ -1501,30 +1500,31 @@ PHP_FUNCTION(openssl_spki_new)
                goto cleanup;
        }
 
-       s = emalloc(strlen(spkac) + strlen(spkstr) + 1);
-       sprintf(s, "%s%s", spkac, spkstr);
+       s = STR_ALLOC(strlen(spkac) + strlen(spkstr), 0);
+       sprintf(s->val, "%s%s", spkac, spkstr);
+       s->len = strlen(s->val);
 
-       RETVAL_STRINGL(s, strlen(s), 0);
+       RETVAL_STR(s);
        goto cleanup;
 
 cleanup:
 
-       if (keyresource == -1 && spki != NULL) {
+       if (keyresource == NULL && spki != NULL) {
                NETSCAPE_SPKI_free(spki);
        }
-       if (keyresource == -1 && pkey != NULL) {
+       if (keyresource == NULL && pkey != NULL) {
                EVP_PKEY_free(pkey);
        }
-       if (keyresource == -1 && spkstr != NULL) {
+       if (keyresource == NULL && spkstr != NULL) {
                efree(spkstr);
        }
 
-       if (strlen(s) <= 0) {
+       if (s->len <= 0) {
                RETVAL_FALSE;
        }
 
-       if (keyresource == -1 && s != NULL) {
-               efree(s);
+       if (keyresource == NULL && s != NULL) {
+               STR_RELEASE(s);
        }
 }
 /* }}} */
@@ -1677,7 +1677,7 @@ PHP_FUNCTION(openssl_spki_export_challenge)
                goto cleanup;
        }
 
-       RETVAL_STRING((char *) ASN1_STRING_data(spki->spkac->challenge), 1);
+       RETVAL_STRING((char *) ASN1_STRING_data(spki->spkac->challenge));
        goto cleanup;
 
 cleanup:
@@ -1710,14 +1710,15 @@ int openssl_spki_cleanup(const char *src, char *dest)
 PHP_FUNCTION(openssl_x509_export)
 {
        X509 * cert;
-       zval ** zcert, *zout;
+       zval * zcert, *zout;
        zend_bool notext = 1;
        BIO * bio_out;
-       long certresource;
+       zend_resource *certresource;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zz|b", &zcert, &zout, &notext) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|b", &zcert, &zout, &notext) == FAILURE) {
                return;
        }
+       ZVAL_DEREF(zout);
        RETVAL_FALSE;
 
        cert = php_openssl_x509_from_zval(zcert, 0, &certresource TSRMLS_CC);
@@ -1735,12 +1736,12 @@ PHP_FUNCTION(openssl_x509_export)
 
                zval_dtor(zout);
                BIO_get_mem_ptr(bio_out, &bio_buf);
-               ZVAL_STRINGL(zout, bio_buf->data, bio_buf->length, 1);
+               ZVAL_STRINGL(zout, bio_buf->data, bio_buf->length);
 
                RETVAL_TRUE;
        }
 
-       if (certresource == -1 && cert) {
+       if (certresource == NULL && cert) {
                X509_free(cert);
        }
        BIO_free(bio_out);
@@ -1805,25 +1806,16 @@ zend_bool php_x509_fingerprint_match(X509 *peer, zval *val TSRMLS_DC)
 
                return method && php_x509_fingerprint_cmp(peer, method, Z_STRVAL_P(val) TSRMLS_CC) == 0;
        } else if (Z_TYPE_P(val) == IS_ARRAY) {
-               HashPosition pos;
-               zval **current;
-               char *key;
-               uint key_len;
-               ulong key_index;
-
-               for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(val), &pos);
-                       zend_hash_get_current_data_ex(Z_ARRVAL_P(val), (void **)&current, &pos) == SUCCESS;
-                       zend_hash_move_forward_ex(Z_ARRVAL_P(val), &pos)
-               ) {
-                       int key_type = zend_hash_get_current_key_ex(Z_ARRVAL_P(val), &key, &key_len, &key_index, 0, &pos);
-
-                       if (key_type == HASH_KEY_IS_STRING 
-                               && Z_TYPE_PP(current) == IS_STRING
-                               && php_x509_fingerprint_cmp(peer, key, Z_STRVAL_PP(current) TSRMLS_CC) != 0
+               zval *current;
+               zend_string *key;
+
+               ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(val), key, current) {
+                       if (Z_TYPE_P(current) == IS_STRING
+                               && php_x509_fingerprint_cmp(peer, key->val, Z_STRVAL_P(current) TSRMLS_CC) != 0
                        ) {
                                return 0;
                        }
-               }
+               } ZEND_HASH_FOREACH_END();
                return 1;
        }
        return 0;
@@ -1832,8 +1824,8 @@ zend_bool php_x509_fingerprint_match(X509 *peer, zval *val TSRMLS_DC)
 PHP_FUNCTION(openssl_x509_fingerprint)
 {
        X509 *cert;
-       zval **zcert;
-       long certresource;
+       zval *zcert;
+       zend_resource *certresource;
        zend_bool raw_output = 0;
        char *method = "sha1";
        int method_len;
@@ -1841,7 +1833,7 @@ PHP_FUNCTION(openssl_x509_fingerprint)
        char *fingerprint;
        int fingerprint_len;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|sb", &zcert, &method, &method_len, &raw_output) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|sb", &zcert, &method, &method_len, &raw_output) == FAILURE) {
                return;
        }
 
@@ -1852,12 +1844,14 @@ PHP_FUNCTION(openssl_x509_fingerprint)
        }
 
        if (php_openssl_x509_fingerprint(cert, method, raw_output, &fingerprint, &fingerprint_len TSRMLS_CC) == SUCCESS) {
-               RETVAL_STRINGL(fingerprint, fingerprint_len, 0);
+               // TODO: avoid reallocation ???
+               RETVAL_STRINGL(fingerprint, fingerprint_len);
+               efree(fingerprint);
        } else {
                RETVAL_FALSE;
        }
 
-       if (certresource == -1 && cert) {
+       if (certresource == NULL && cert) {
                X509_free(cert);
        }
 }
@@ -1866,14 +1860,14 @@ PHP_FUNCTION(openssl_x509_fingerprint)
    Checks if a private key corresponds to a CERT */
 PHP_FUNCTION(openssl_x509_check_private_key)
 {
-       zval ** zcert, **zkey;
+       zval * zcert, *zkey;
        X509 * cert = NULL;
        EVP_PKEY * key = NULL;
-       long certresource = -1, keyresource = -1;
+       zend_resource *certresource = NULL, *keyresource = NULL;
 
        RETVAL_FALSE;
        
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ", &zcert, &zkey) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz", &zcert, &zkey) == FAILURE) {
                return;
        }
        cert = php_openssl_x509_from_zval(zcert, 0, &certresource TSRMLS_CC);
@@ -1885,10 +1879,10 @@ PHP_FUNCTION(openssl_x509_check_private_key)
                RETVAL_BOOL(X509_check_private_key(cert, key));
        }
 
-       if (keyresource == -1 && key) {
+       if (keyresource == NULL && key) {
                EVP_PKEY_free(key);
        }
-       if (certresource == -1 && cert) {
+       if (certresource == NULL && cert) {
                X509_free(cert);
        }
 }
@@ -1966,20 +1960,20 @@ static int openssl_x509v3_subjectAltName(BIO *bio, X509_EXTENSION *extension)
    Returns an array of the fields/values of the CERT */
 PHP_FUNCTION(openssl_x509_parse)
 {
-       zval ** zcert;
+       zval * zcert;
        X509 * cert = NULL;
-       long certresource = -1;
+       zend_resource *certresource = NULL;
        int i;
        zend_bool useshortnames = 1;
        char * tmpstr;
-       zval subitem;
+       zval subitem;
        X509_EXTENSION *extension;
        char *extname;
        BIO  *bio_out;
        BUF_MEM *bio_buf;
        char buf[256];
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|b", &zcert, &useshortnames) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &zcert, &useshortnames) == FAILURE) {
                return;
        }
        cert = php_openssl_x509_from_zval(zcert, 0, &certresource TSRMLS_CC);
@@ -2021,8 +2015,7 @@ PHP_FUNCTION(openssl_x509_parse)
        add_assoc_string(return_value, "signaturetype", OBJ_nid2sn(X509_get_signature_type(cert)));
        add_assoc_string(return_value, "signaturetypeLN", OBJ_nid2ln(X509_get_signature_type(cert)));
 */
-       MAKE_STD_ZVAL(subitem);
-       array_init(subitem);
+       array_init(&subitem);
 
        /* NOTE: the purposes are added as integer keys - the keys match up to the X509_PURPOSE_SSL_XXX defines
           in x509v3.h */
@@ -2030,31 +2023,29 @@ PHP_FUNCTION(openssl_x509_parse)
                int id, purpset;
                char * pname;
                X509_PURPOSE * purp;
-               zval subsub;
+               zval subsub;
 
-               MAKE_STD_ZVAL(subsub);
-               array_init(subsub);
+               array_init(&subsub);
 
                purp = X509_PURPOSE_get0(i);
                id = X509_PURPOSE_get_id(purp);
 
                purpset = X509_check_purpose(cert, id, 0);
-               add_index_bool(subsub, 0, purpset);
+               add_index_bool(&subsub, 0, purpset);
 
                purpset = X509_check_purpose(cert, id, 1);
-               add_index_bool(subsub, 1, purpset);
+               add_index_bool(&subsub, 1, purpset);
 
                pname = useshortnames ? X509_PURPOSE_get0_sname(purp) : X509_PURPOSE_get0_name(purp);
-               add_index_string(subsub, 2, pname);
+               add_index_string(&subsub, 2, pname);
 
                /* NOTE: if purpset > 1 then it's a warning - we should mention it ? */
 
-               add_index_zval(subitem, id, subsub);
+               add_index_zval(&subitem, id, &subsub);
        }
-       add_assoc_zval(return_value, "purposes", subitem);
+       add_assoc_zval(return_value, "purposes", &subitem);
 
-       MAKE_STD_ZVAL(subitem);
-       array_init(subitem);
+       array_init(&subitem);
 
 
        for (i = 0; i < X509_get_ext_count(cert); i++) {
@@ -2071,10 +2062,10 @@ PHP_FUNCTION(openssl_x509_parse)
                if (nid == NID_subject_alt_name) {
                        if (openssl_x509v3_subjectAltName(bio_out, extension) == 0) {
                                BIO_get_mem_ptr(bio_out, &bio_buf);
-                               add_assoc_stringl(subitem, extname, bio_buf->data, bio_buf->length);
+                               add_assoc_stringl(&subitem, extname, bio_buf->data, bio_buf->length);
                        } else {
                                zval_dtor(return_value);
-                               if (certresource == -1 && cert) {
+                               if (certresource == NULL && cert) {
                                        X509_free(cert);
                                }
                                BIO_free(bio_out);
@@ -2083,15 +2074,15 @@ PHP_FUNCTION(openssl_x509_parse)
                }
                else if (X509V3_EXT_print(bio_out, extension, 0, 0)) {
                        BIO_get_mem_ptr(bio_out, &bio_buf);
-                       add_assoc_stringl(subitem, extname, bio_buf->data, bio_buf->length);
+                       add_assoc_stringl(&subitem, extname, bio_buf->data, bio_buf->length);
                } else {
-                       add_assoc_asn1_string(subitem, extname, X509_EXTENSION_get_data(extension));
+                       add_assoc_asn1_string(&subitem, extname, X509_EXTENSION_get_data(extension));
                }
                BIO_free(bio_out);
        }
-       add_assoc_zval(return_value, "extensions", subitem);
+       add_assoc_zval(return_value, "extensions", &subitem);
 
-       if (certresource == -1 && cert) {
+       if (certresource == NULL && cert) {
                X509_free(cert);
        }
 }
@@ -2179,16 +2170,16 @@ static int check_cert(X509_STORE *ctx, X509 *x, STACK_OF(X509) *untrustedchain,
    Checks the CERT to see if it can be used for the purpose in purpose. cainfo holds information about trusted CAs */
 PHP_FUNCTION(openssl_x509_checkpurpose)
 {
-       zval ** zcert, * zcainfo = NULL;
+       zval * zcert, * zcainfo = NULL;
        X509_STORE * cainfo = NULL;
        X509 * cert = NULL;
-       long certresource = -1;
+       zend_resource *certresource = NULL;
        STACK_OF(X509) * untrustedchain = NULL;
        long purpose;
        char * untrusted = NULL;
        int untrusted_len = 0, ret;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zl|a!s", &zcert, &purpose, &zcainfo, &untrusted, &untrusted_len) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zl|a!s", &zcert, &purpose, &zcainfo, &untrusted, &untrusted_len) == FAILURE) {
                return;
        }
 
@@ -2218,7 +2209,7 @@ PHP_FUNCTION(openssl_x509_checkpurpose)
        }
 
 clean_exit:
-       if (certresource == 1 && cert) {
+       if (certresource == NULL && cert) {
                X509_free(cert);
        }
        if (cainfo) { 
@@ -2238,8 +2229,9 @@ static X509_STORE * setup_verify(zval * calist TSRMLS_DC)
 {
        X509_STORE *store;
        X509_LOOKUP * dir_lookup, * file_lookup;
-       HashPosition pos;
        int ndirs = 0, nfiles = 0;
+       zval * item;
+       struct stat sb;
 
        store = X509_STORE_new();
 
@@ -2248,39 +2240,32 @@ static X509_STORE * setup_verify(zval * calist TSRMLS_DC)
        }
 
        if (calist && (Z_TYPE_P(calist) == IS_ARRAY)) {
-               zend_hash_internal_pointer_reset_ex(HASH_OF(calist), &pos);
-               for (;; zend_hash_move_forward_ex(HASH_OF(calist), &pos)) {
-                       zval ** item;
-                       struct stat sb;
-
-                       if (zend_hash_get_current_data_ex(HASH_OF(calist), (void**)&item, &pos) == FAILURE) {
-                               break;
-                       }
+               ZEND_HASH_FOREACH_VAL(HASH_OF(calist), item) {
                        convert_to_string_ex(item);
 
-                       if (VCWD_STAT(Z_STRVAL_PP(item), &sb) == -1) {
-                               php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to stat %s", Z_STRVAL_PP(item));
+                       if (VCWD_STAT(Z_STRVAL_P(item), &sb) == -1) {
+                               php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to stat %s", Z_STRVAL_P(item));
                                continue;
                        }
 
                        if ((sb.st_mode & S_IFREG) == S_IFREG) {
                                file_lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
-                               if (file_lookup == NULL || !X509_LOOKUP_load_file(file_lookup, Z_STRVAL_PP(item), X509_FILETYPE_PEM)) {
-                                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "error loading file %s", Z_STRVAL_PP(item));
+                               if (file_lookup == NULL || !X509_LOOKUP_load_file(file_lookup, Z_STRVAL_P(item), X509_FILETYPE_PEM)) {
+                                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "error loading file %s", Z_STRVAL_P(item));
                                } else {
                                        nfiles++;
                                }
                                file_lookup = NULL;
                        } else {
                                dir_lookup = X509_STORE_add_lookup(store, X509_LOOKUP_hash_dir());
-                               if (dir_lookup == NULL || !X509_LOOKUP_add_dir(dir_lookup, Z_STRVAL_PP(item), X509_FILETYPE_PEM)) {
-                                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "error loading directory %s", Z_STRVAL_PP(item));
+                               if (dir_lookup == NULL || !X509_LOOKUP_add_dir(dir_lookup, Z_STRVAL_P(item), X509_FILETYPE_PEM)) {
+                                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "error loading directory %s", Z_STRVAL_P(item));
                                } else { 
                                        ndirs++;
                                }
                                dir_lookup = NULL;
                        }
-               }
+               } ZEND_HASH_FOREACH_END();
        }
        if (nfiles == 0) {
                file_lookup = X509_STORE_add_lookup(store, X509_LOOKUP_file());
@@ -2302,14 +2287,15 @@ static X509_STORE * setup_verify(zval * calist TSRMLS_DC)
    Reads X.509 certificates */
 PHP_FUNCTION(openssl_x509_read)
 {
-       zval **cert;
+       zval *cert;
        X509 *x509;
+       zend_resource *res;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &cert) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &cert) == FAILURE) {
                return;
        }
-       Z_TYPE_P(return_value) = IS_RESOURCE;
-       x509 = php_openssl_x509_from_zval(cert, 1, &Z_LVAL_P(return_value) TSRMLS_CC);
+       x509 = php_openssl_x509_from_zval(cert, 1, &res TSRMLS_CC);
+       ZVAL_RES(return_value, res);
 
        if (x509 == NULL) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "supplied parameter cannot be coerced into an X509 certificate!");
@@ -2328,8 +2314,8 @@ PHP_FUNCTION(openssl_x509_free)
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &x509) == FAILURE) {
                return;
        }
-       ZEND_FETCH_RESOURCE(cert, X509 *, &x509, -1, "OpenSSL X.509", le_x509);
-       zend_list_delete(Z_LVAL_P(x509));
+       ZEND_FETCH_RESOURCE(cert, X509 *, x509, -1, "OpenSSL X.509", le_x509);
+       zend_list_close(Z_RES_P(x509));
 }
 /* }}} */
 
@@ -2347,27 +2333,24 @@ static void php_sk_X509_free(STACK_OF(X509) * sk) /* {{{ */
 }
 /* }}} */
 
-static STACK_OF(X509) * php_array_to_X509_sk(zval ** zcerts TSRMLS_DC) /* {{{ */
+static STACK_OF(X509) * php_array_to_X509_sk(zval * zcerts TSRMLS_DC) /* {{{ */
 {
-       HashPosition hpos;
-       zval ** zcertval;
+       zval * zcertval;
        STACK_OF(X509) * sk = NULL;
     X509 * cert;
-    long certresource;
+    zend_resource *certresource;
 
        sk = sk_X509_new_null();
 
        /* get certs */
-       if (Z_TYPE_PP(zcerts) == IS_ARRAY) {
-               zend_hash_internal_pointer_reset_ex(HASH_OF(*zcerts), &hpos);
-               while(zend_hash_get_current_data_ex(HASH_OF(*zcerts), (void**)&zcertval, &hpos) == SUCCESS) {
-
+       if (Z_TYPE_P(zcerts) == IS_ARRAY) {
+               ZEND_HASH_FOREACH_VAL(HASH_OF(zcerts), zcertval) {
                        cert = php_openssl_x509_from_zval(zcertval, 0, &certresource TSRMLS_CC);
                        if (cert == NULL) {
                                goto clean_exit;
                        }
 
-                       if (certresource != -1) {
+                       if (certresource != NULL) {
                                cert = X509_dup(cert);
                                
                                if (cert == NULL) {
@@ -2376,9 +2359,7 @@ static STACK_OF(X509) * php_array_to_X509_sk(zval ** zcerts TSRMLS_DC) /* {{{ */
                                
                        }
                        sk_X509_push(sk, cert);
-
-                       zend_hash_move_forward_ex(HASH_OF(*zcerts), &hpos);
-               }
+               } ZEND_HASH_FOREACH_END();
        } else {
                /* a single certificate */
                cert = php_openssl_x509_from_zval(zcerts, 0, &certresource TSRMLS_CC);
@@ -2387,7 +2368,7 @@ static STACK_OF(X509) * php_array_to_X509_sk(zval ** zcerts TSRMLS_DC) /* {{{ */
                        goto clean_exit;
                }
 
-               if (certresource != -1) {
+               if (certresource != NULL) {
                        cert = X509_dup(cert);
                        if (cert == NULL) {
                                goto clean_exit;
@@ -2413,13 +2394,13 @@ PHP_FUNCTION(openssl_pkcs12_export_to_file)
        int filename_len;
        char * pass;
        int pass_len;
-       zval **zcert = NULL, *zpkey = NULL, *args = NULL;
+       zval *zcert = NULL, *zpkey = NULL, *args = NULL;
        EVP_PKEY *priv_key = NULL;
-       long certresource, keyresource;
-       zval ** item;
+       zend_resource *certresource, *keyresource;
+       zval * item;
        STACK_OF(X509) *ca = NULL;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zpzs|a", &zcert, &filename, &filename_len, &zpkey, &pass, &pass_len, &args) == FAILURE)
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zpzs|a", &zcert, &filename, &filename_len, &zpkey, &pass, &pass_len, &args) == FAILURE)
                return;
 
        RETVAL_FALSE;
@@ -2429,7 +2410,7 @@ PHP_FUNCTION(openssl_pkcs12_export_to_file)
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get cert from parameter 1");
                return;
        }
-       priv_key = php_openssl_evp_from_zval(&zpkey, 0, "", 1, &keyresource TSRMLS_CC);
+       priv_key = php_openssl_evp_from_zval(zpkey, 0, "", 1, &keyresource TSRMLS_CC);
        if (priv_key == NULL) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get private key from parameter 3");
                goto cleanup;
@@ -2443,14 +2424,14 @@ PHP_FUNCTION(openssl_pkcs12_export_to_file)
        }
 
        /* parse extra config from args array, promote this to an extra function */
-       if (args && zend_hash_find(Z_ARRVAL_P(args), "friendly_name", sizeof("friendly_name"), (void**)&item) == SUCCESS)
-               friendly_name = Z_STRVAL_PP(item);
+       if (args && (item = zend_hash_str_find(Z_ARRVAL_P(args), "friendly_name", sizeof("friendly_name")-1)) != NULL)
+               friendly_name = Z_STRVAL_P(item);
        /* certpbe (default RC2-40)
           keypbe (default 3DES)
           friendly_caname
        */
 
-       if (args && zend_hash_find(Z_ARRVAL_P(args), "extracerts", sizeof("extracerts"), (void**)&item) == SUCCESS)
+       if (args && (item = zend_hash_str_find(Z_ARRVAL_P(args), "extracerts", sizeof("extracerts")-1)) != NULL)
                ca = php_array_to_X509_sk(item TSRMLS_CC);
        /* end parse extra config */
 
@@ -2475,10 +2456,10 @@ PHP_FUNCTION(openssl_pkcs12_export_to_file)
        
 cleanup:
 
-       if (keyresource == -1 && priv_key) {
+       if (keyresource == NULL && priv_key) {
                EVP_PKEY_free(priv_key);
        }
-       if (certresource == -1 && cert) { 
+       if (certresource == NULL && cert) { 
                X509_free(cert);
        }
 }
@@ -2493,24 +2474,25 @@ PHP_FUNCTION(openssl_pkcs12_export)
        PKCS12 * p12 = NULL;
        zval * zcert = NULL, *zout = NULL, *zpkey, *args = NULL;
        EVP_PKEY *priv_key = NULL;
-       long certresource, keyresource;
+       zend_resource *certresource, *keyresource;
        char * pass;
        int pass_len;
        char * friendly_name = NULL;
-       zval ** item;
+       zval * item;
        STACK_OF(X509) *ca = NULL;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zzzs|a", &zcert, &zout, &zpkey, &pass, &pass_len, &args) == FAILURE)
                return;
 
+       ZVAL_DEREF(zout);
        RETVAL_FALSE;
        
-       cert = php_openssl_x509_from_zval(&zcert, 0, &certresource TSRMLS_CC);
+       cert = php_openssl_x509_from_zval(zcert, 0, &certresource TSRMLS_CC);
        if (cert == NULL) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get cert from parameter 1");
                return;
        }
-       priv_key = php_openssl_evp_from_zval(&zpkey, 0, "", 1, &keyresource TSRMLS_CC);
+       priv_key = php_openssl_evp_from_zval(zpkey, 0, "", 1, &keyresource TSRMLS_CC);
        if (priv_key == NULL) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get private key from parameter 3");
                goto cleanup;
@@ -2521,10 +2503,10 @@ PHP_FUNCTION(openssl_pkcs12_export)
        }
 
        /* parse extra config from args array, promote this to an extra function */
-       if (args && zend_hash_find(Z_ARRVAL_P(args), "friendly_name", sizeof("friendly_name"), (void**)&item) == SUCCESS)
-               friendly_name = Z_STRVAL_PP(item);
+       if (args && (item = zend_hash_str_find(Z_ARRVAL_P(args), "friendly_name", sizeof("friendly_name")-1)) != NULL)
+               friendly_name = Z_STRVAL_P(item);
 
-       if (args && zend_hash_find(Z_ARRVAL_P(args), "extracerts", sizeof("extracerts"), (void**)&item) == SUCCESS)
+       if (args && (item = zend_hash_str_find(Z_ARRVAL_P(args), "extracerts", sizeof("extracerts")-1)) != NULL)
                ca = php_array_to_X509_sk(item TSRMLS_CC);
        /* end parse extra config */
        
@@ -2536,7 +2518,7 @@ PHP_FUNCTION(openssl_pkcs12_export)
 
                zval_dtor(zout);
                BIO_get_mem_ptr(bio_out, &bio_buf);
-               ZVAL_STRINGL(zout, bio_buf->data, bio_buf->length, 1);
+               ZVAL_STRINGL(zout, bio_buf->data, bio_buf->length);
 
                RETVAL_TRUE;
        }
@@ -2547,10 +2529,10 @@ PHP_FUNCTION(openssl_pkcs12_export)
        
 cleanup:
 
-       if (keyresource == -1 && priv_key) {
+       if (keyresource == NULL && priv_key) {
                EVP_PKEY_free(priv_key);
        }
-       if (certresource == -1 && cert) { 
+       if (certresource == NULL && cert) { 
                X509_free(cert);
        }
 }
@@ -2560,7 +2542,7 @@ cleanup:
    Parses a PKCS12 to an array */
 PHP_FUNCTION(openssl_pkcs12_read)
 {
-       zval *zout = NULL, *zextracerts, *zcert, *zpkey;
+       zval *zout = NULL, zextracerts, zcert, zpkey;
        char *pass, *zp12;
        int pass_len, zp12_len;
        PKCS12 * p12 = NULL;
@@ -2572,7 +2554,7 @@ PHP_FUNCTION(openssl_pkcs12_read)
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szs", &zp12, &zp12_len, &zout, &pass, &pass_len) == FAILURE)
                return;
-
+       ZVAL_DEREF(zout);
        RETVAL_FALSE;
        
        bio_in = BIO_new(BIO_s_mem());
@@ -2591,9 +2573,8 @@ PHP_FUNCTION(openssl_pkcs12_read)
                        if (PEM_write_bio_X509(bio_out, cert)) {
                                BUF_MEM *bio_buf;
                                BIO_get_mem_ptr(bio_out, &bio_buf);
-                               MAKE_STD_ZVAL(zcert);
-                               ZVAL_STRINGL(zcert, bio_buf->data, bio_buf->length, 1);
-                               add_assoc_zval(zout, "cert", zcert);
+                               ZVAL_STRINGL(&zcert, bio_buf->data, bio_buf->length);
+                               add_assoc_zval(zout, "cert", &zcert);
                        }
                        BIO_free(bio_out);
 
@@ -2601,17 +2582,15 @@ PHP_FUNCTION(openssl_pkcs12_read)
                        if (PEM_write_bio_PrivateKey(bio_out, pkey, NULL, NULL, 0, 0, NULL)) {
                                BUF_MEM *bio_buf;
                                BIO_get_mem_ptr(bio_out, &bio_buf);
-                               MAKE_STD_ZVAL(zpkey);
-                               ZVAL_STRINGL(zpkey, bio_buf->data, bio_buf->length, 1);
-                               add_assoc_zval(zout, "pkey", zpkey);
+                               ZVAL_STRINGL(&zpkey, bio_buf->data, bio_buf->length);
+                               add_assoc_zval(zout, "pkey", &zpkey);
                        }
                        BIO_free(bio_out);
 
-                       MAKE_STD_ZVAL(zextracerts);
-                       array_init(zextracerts);
+                       array_init(&zextracerts);
                        
                        for (i=0;;i++) {
-                               zval zextracert;
+                               zval zextracert;
                                X509* aCA = sk_X509_pop(ca);
                                if (!aCA) break;
                                
@@ -2619,9 +2598,8 @@ PHP_FUNCTION(openssl_pkcs12_read)
                                if (PEM_write_bio_X509(bio_out, aCA)) {
                                        BUF_MEM *bio_buf;
                                        BIO_get_mem_ptr(bio_out, &bio_buf);
-                                       MAKE_STD_ZVAL(zextracert);
-                                       ZVAL_STRINGL(zextracert, bio_buf->data, bio_buf->length, 1);
-                                       add_index_zval(zextracerts, i, zextracert);
+                                       ZVAL_STRINGL(&zextracert, bio_buf->data, bio_buf->length);
+                                       add_index_zval(&zextracerts, i, &zextracert);
                                        
                                }
                                BIO_free(bio_out);
@@ -2630,9 +2608,9 @@ PHP_FUNCTION(openssl_pkcs12_read)
                        }
                        if(ca) {
                                sk_X509_free(ca);
-                               add_assoc_zval(zout, "extracerts", zextracerts);
+                               add_assoc_zval(zout, "extracerts", &zextracerts);
                        } else {
-                               zval_dtor(zextracerts);
+                               zval_dtor(&zextracerts);
                        }
                        
                        RETVAL_TRUE;
@@ -2685,42 +2663,34 @@ static int php_openssl_make_REQ(struct php_x509_request * req, X509_REQ * csr, z
                char * type;
                CONF_VALUE * v;
                X509_NAME * subj;
-               HashPosition hpos;
-               zval ** item;
+               zval * item;
+               zend_string * strindex = NULL; 
                
                subj = X509_REQ_get_subject_name(csr);
                /* apply values from the dn hash */
-               zend_hash_internal_pointer_reset_ex(HASH_OF(dn), &hpos);
-               while(zend_hash_get_current_data_ex(HASH_OF(dn), (void**)&item, &hpos) == SUCCESS) {
-                       char * strindex = NULL; 
-                       uint strindexlen = 0;
-                       ulong intindex;
-                       
-                       zend_hash_get_current_key_ex(HASH_OF(dn), &strindex, &strindexlen, &intindex, 0, &hpos);
-
-                       convert_to_string_ex(item);
-
+               ZEND_HASH_FOREACH_STR_KEY_VAL(HASH_OF(dn), strindex, item) {
                        if (strindex) {
                                int nid;
 
-                               nid = OBJ_txt2nid(strindex);
+                               convert_to_string_ex(item);
+
+                               nid = OBJ_txt2nid(strindex->val);
                                if (nid != NID_undef) {
                                        if (!X509_NAME_add_entry_by_NID(subj, nid, MBSTRING_UTF8, 
-                                                               (unsigned char*)Z_STRVAL_PP(item), -1, -1, 0))
+                                                               (unsigned char*)Z_STRVAL_P(item), -1, -1, 0))
                                        {
                                                php_error_docref(NULL TSRMLS_CC, E_WARNING,
                                                        "dn: add_entry_by_NID %d -> %s (failed; check error"
                                                        " queue and value of string_mask OpenSSL option "
                                                        "if illegal characters are reported)",
-                                                       nid, Z_STRVAL_PP(item));
+                                                       nid, Z_STRVAL_P(item));
                                                return FAILURE;
                                        }
                                } else {
-                                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "dn: %s is not a recognized name", strindex);
+                                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "dn: %s is not a recognized name", strindex->val);
                                }
                        }
-                       zend_hash_move_forward_ex(HASH_OF(dn), &hpos);
-               }
+               } ZEND_HASH_FOREACH_END();
 
                /* Finally apply defaults from config file */
                for(i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) {
@@ -2771,30 +2741,21 @@ static int php_openssl_make_REQ(struct php_x509_request * req, X509_REQ * csr, z
                        }
                }
                if (attribs) {
-                       zend_hash_internal_pointer_reset_ex(HASH_OF(attribs), &hpos);
-                       while(zend_hash_get_current_data_ex(HASH_OF(attribs), (void**)&item, &hpos) == SUCCESS) {
-                               char *strindex = NULL;
-                               uint strindexlen;
-                               ulong intindex;
+                       ZEND_HASH_FOREACH_STR_KEY_VAL(HASH_OF(attribs), strindex, item) {
+                               int nid;
 
-                               zend_hash_get_current_key_ex(HASH_OF(attribs), &strindex, &strindexlen, &intindex, 0, &hpos);
                                convert_to_string_ex(item);
 
-                               if (strindex) {
-                                       int nid;
-
-                                       nid = OBJ_txt2nid(strindex);
-                                       if (nid != NID_undef) {
-                                               if (!X509_NAME_add_entry_by_NID(subj, nid, MBSTRING_UTF8, (unsigned char*)Z_STRVAL_PP(item), -1, -1, 0)) {
-                                                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "attribs: add_entry_by_NID %d -> %s (failed)", nid, Z_STRVAL_PP(item));
-                                                       return FAILURE;
-                                               }
-                                       } else {
-                                               php_error_docref(NULL TSRMLS_CC, E_WARNING, "dn: %s is not a recognized name", strindex);
+                               nid = OBJ_txt2nid(strindex->val);
+                               if (nid != NID_undef) {
+                                       if (!X509_NAME_add_entry_by_NID(subj, nid, MBSTRING_UTF8, (unsigned char*)Z_STRVAL_P(item), -1, -1, 0)) {
+                                               php_error_docref(NULL TSRMLS_CC, E_WARNING, "attribs: add_entry_by_NID %d -> %s (failed)", nid, Z_STRVAL_P(item));
+                                               return FAILURE;
                                        }
+                               } else {
+                                       php_error_docref(NULL TSRMLS_CC, E_WARNING, "dn: %s is not a recognized name", strindex->val);
                                }
-                               zend_hash_move_forward_ex(HASH_OF(attribs), &hpos);
-                       }
+                       } ZEND_HASH_FOREACH_END();
                        for (i = 0; i < sk_CONF_VALUE_num(attr_sk); i++) {
                                v = sk_CONF_VALUE_value(attr_sk, i);
                                /* if it is already set, skip this */
@@ -2820,33 +2781,34 @@ static int php_openssl_make_REQ(struct php_x509_request * req, X509_REQ * csr, z
 /* }}} */
 
 /* {{{ php_openssl_csr_from_zval */
-static X509_REQ * php_openssl_csr_from_zval(zval ** val, int makeresource, long * resourceval TSRMLS_DC)
+static X509_REQ * php_openssl_csr_from_zval(zval * val, int makeresource, zend_resource **resourceval TSRMLS_DC)
 {
        X509_REQ * csr = NULL;
        char * filename = NULL;
        BIO * in;
        
        if (resourceval) {
-               *resourceval = -1;
+               *resourceval = NULL;
        }
-       if (Z_TYPE_PP(val) == IS_RESOURCE) {
+       if (Z_TYPE_P(val) == IS_RESOURCE) {
                void * what;
                int type;
 
                what = zend_fetch_resource(val TSRMLS_CC, -1, "OpenSSL X.509 CSR", &type, 1, le_csr);
                if (what) {
                        if (resourceval) {
-                               *resourceval = Z_LVAL_PP(val);
+                               *resourceval = Z_RES_P(val);
+                               Z_ADDREF_P(val);
                        }
                        return (X509_REQ*)what;
                }
                return NULL;
-       } else if (Z_TYPE_PP(val) != IS_STRING) {
+       } else if (Z_TYPE_P(val) != IS_STRING) {
                return NULL;
        }
 
-       if (Z_STRLEN_PP(val) > 7 && memcmp(Z_STRVAL_PP(val), "file://", sizeof("file://") - 1) == 0) {
-               filename = Z_STRVAL_PP(val) + (sizeof("file://") - 1);
+       if (Z_STRLEN_P(val) > 7 && memcmp(Z_STRVAL_P(val), "file://", sizeof("file://") - 1) == 0) {
+               filename = Z_STRVAL_P(val) + (sizeof("file://") - 1);
        }
        if (filename) {
                if (php_openssl_open_base_dir_chk(filename TSRMLS_CC)) {
@@ -2854,7 +2816,7 @@ static X509_REQ * php_openssl_csr_from_zval(zval ** val, int makeresource, long
                }
                in = BIO_new_file(filename, "r");
        } else {
-               in = BIO_new_mem_buf(Z_STRVAL_PP(val), Z_STRLEN_PP(val));
+               in = BIO_new_mem_buf(Z_STRVAL_P(val), Z_STRLEN_P(val));
        }
        csr = PEM_read_bio_X509_REQ(in, NULL,NULL,NULL);
        BIO_free(in);
@@ -2872,14 +2834,14 @@ PHP_FUNCTION(openssl_csr_export_to_file)
        zend_bool notext = 1;
        char * filename = NULL; int filename_len;
        BIO * bio_out;
-       long csr_resource;
+       zend_resource *csr_resource;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rp|b", &zcsr, &filename, &filename_len, &notext) == FAILURE) {
                return;
        }
        RETVAL_FALSE;
 
-       csr = php_openssl_csr_from_zval(&zcsr, 0, &csr_resource TSRMLS_CC);
+       csr = php_openssl_csr_from_zval(zcsr, 0, &csr_resource TSRMLS_CC);
        if (csr == NULL) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get CSR from parameter 1");
                return;
@@ -2900,7 +2862,7 @@ PHP_FUNCTION(openssl_csr_export_to_file)
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "error opening file %s", filename);
        }
 
-       if (csr_resource == -1 && csr) {
+       if (csr_resource == NULL && csr) {
                X509_REQ_free(csr);
        }
        BIO_free(bio_out);
@@ -2915,15 +2877,15 @@ PHP_FUNCTION(openssl_csr_export)
        zval * zcsr = NULL, *zout=NULL;
        zend_bool notext = 1;
        BIO * bio_out;
-
-       long csr_resource;
+       zend_resource *csr_resource;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz|b", &zcsr, &zout, &notext) == FAILURE) {
                return;
        }
+       ZVAL_DEREF(zout);
        RETVAL_FALSE;
 
-       csr = php_openssl_csr_from_zval(&zcsr, 0, &csr_resource TSRMLS_CC);
+       csr = php_openssl_csr_from_zval(zcsr, 0, &csr_resource TSRMLS_CC);
        if (csr == NULL) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get CSR from parameter 1");
                return;
@@ -2941,12 +2903,12 @@ PHP_FUNCTION(openssl_csr_export)
 
                BIO_get_mem_ptr(bio_out, &bio_buf);
                zval_dtor(zout);
-               ZVAL_STRINGL(zout, bio_buf->data, bio_buf->length, 1);
+               ZVAL_STRINGL(zout, bio_buf->data, bio_buf->length);
 
                RETVAL_TRUE;
        }
 
-       if (csr_resource == -1 && csr) {
+       if (csr_resource == NULL && csr) {
                X509_REQ_free(csr);
        }
        BIO_free(bio_out);
@@ -2957,17 +2919,17 @@ PHP_FUNCTION(openssl_csr_export)
    Signs a cert with another CERT */
 PHP_FUNCTION(openssl_csr_sign)
 {
-       zval ** zcert = NULL, **zcsr, **zpkey, *args = NULL;
+       zval * zcert = NULL, *zcsr, *zpkey, *args = NULL;
        long num_days;
        long serial = 0L;
        X509 * cert = NULL, *new_cert = NULL;
        X509_REQ * csr;
        EVP_PKEY * key = NULL, *priv_key = NULL;
-       long csr_resource, certresource = 0, keyresource = -1;
+       zend_resource *csr_resource, *certresource = NULL, *keyresource = NULL;
        int i;
        struct php_x509_request req;
        
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ZZ!Zl|a!l", &zcsr, &zcert, &zpkey, &num_days, &args, &serial) == FAILURE)
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz!zl|a!l", &zcsr, &zcert, &zpkey, &num_days, &args, &serial) == FAILURE)
                return;
 
        RETVAL_FALSE;
@@ -3059,7 +3021,7 @@ PHP_FUNCTION(openssl_csr_sign)
        }
        
        /* Succeeded; lets return the cert */
-       RETVAL_RESOURCE(zend_list_insert(new_cert, le_x509 TSRMLS_CC));
+       zend_register_resource(return_value, new_cert, le_x509 TSRMLS_CC);
        new_cert = NULL;
        
 cleanup:
@@ -3069,16 +3031,16 @@ cleanup:
        }
        PHP_SSL_REQ_DISPOSE(&req);
 
-       if (keyresource == -1 && priv_key) {
+       if (keyresource == NULL && priv_key) {
                EVP_PKEY_free(priv_key);
        }
        if (key) {
                EVP_PKEY_free(key);
        }
-       if (csr_resource == -1 && csr) {
+       if (csr_resource == NULL && csr) {
                X509_REQ_free(csr);
        }
-       if (certresource == -1 && cert) { 
+       if (zcert && certresource == NULL && cert) { 
                X509_free(cert);
        }
        if (new_cert) {
@@ -3096,11 +3058,12 @@ PHP_FUNCTION(openssl_csr_new)
        zval * out_pkey;
        X509_REQ * csr = NULL;
        int we_made_the_key = 1;
-       long key_resource;
+       zend_resource *key_resource;
        
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "az|a!a!", &dn, &out_pkey, &args, &attribs) == FAILURE) {
                return;
        }
+       ZVAL_DEREF(out_pkey);
        RETVAL_FALSE;
        
        PHP_SSL_REQ_INIT(&req);
@@ -3108,7 +3071,7 @@ PHP_FUNCTION(openssl_csr_new)
        if (PHP_SSL_REQ_PARSE(&req, args) == SUCCESS) {
                /* Generate or use a private key */
                if (Z_TYPE_P(out_pkey) != IS_NULL) {
-                       req.priv_key = php_openssl_evp_from_zval(&out_pkey, 0, NULL, 0, &key_resource TSRMLS_CC);
+                       req.priv_key = php_openssl_evp_from_zval(out_pkey, 0, NULL, 0, &key_resource TSRMLS_CC);
                        if (req.priv_key != NULL) {
                                we_made_the_key = 0;
                        }
@@ -3136,7 +3099,7 @@ PHP_FUNCTION(openssl_csr_new)
                                                RETVAL_TRUE;
                                                
                                                if (X509_REQ_sign(csr, req.priv_key, req.digest)) {
-                                                       RETVAL_RESOURCE(zend_list_insert(csr, le_csr TSRMLS_CC));
+                                                       zend_register_resource(return_value, csr, le_csr TSRMLS_CC);
                                                        csr = NULL;                     
                                                } else {
                                                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Error signing request");
@@ -3145,9 +3108,9 @@ PHP_FUNCTION(openssl_csr_new)
                                                if (we_made_the_key) {
                                                        /* and a resource for the private key */
                                                        zval_dtor(out_pkey);
-                                                       ZVAL_RESOURCE(out_pkey, zend_list_insert(req.priv_key, le_key TSRMLS_CC));
+                                                       zend_register_resource(out_pkey, req.priv_key, le_key TSRMLS_CC);
                                                        req.priv_key = NULL; /* make sure the cleanup code doesn't zap it! */
-                                               } else if (key_resource != -1) {
+                                               } else if (key_resource != NULL) {
                                                        req.priv_key = NULL; /* make sure the cleanup code doesn't zap it! */
                                                }
                                        }
@@ -3172,13 +3135,13 @@ PHP_FUNCTION(openssl_csr_new)
    Returns the subject of a CERT or FALSE on error */
 PHP_FUNCTION(openssl_csr_get_subject)
 {
-       zval ** zcsr;
+       zval * zcsr;
        zend_bool use_shortnames = 1;
-       long csr_resource;
+       zend_resource *csr_resource;
        X509_NAME * subject;
        X509_REQ * csr;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|b", &zcsr, &use_shortnames) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &zcsr, &use_shortnames) == FAILURE) {
                return;
        }
 
@@ -3200,14 +3163,14 @@ PHP_FUNCTION(openssl_csr_get_subject)
        Returns the subject of a CERT or FALSE on error */
 PHP_FUNCTION(openssl_csr_get_public_key)
 {
-       zval ** zcsr;
+       zval * zcsr;
        zend_bool use_shortnames = 1;
-       long csr_resource;
+       zend_resource *csr_resource;
 
        X509_REQ * csr;
        EVP_PKEY *tpubkey;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|b", &zcsr, &use_shortnames) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|b", &zcsr, &use_shortnames) == FAILURE) {
                return;
        }
 
@@ -3218,7 +3181,7 @@ PHP_FUNCTION(openssl_csr_get_public_key)
        }
 
        tpubkey=X509_REQ_get_pubkey(csr);
-       RETVAL_RESOURCE(zend_list_insert(tpubkey, le_key TSRMLS_CC));
+       zend_register_resource(return_value, tpubkey, le_key TSRMLS_CC);
        return;
 }
 /* }}} */
@@ -3240,16 +3203,16 @@ PHP_FUNCTION(openssl_csr_get_public_key)
        empty string rather than NULL for the passphrase - NULL causes a passphrase prompt to be emitted in
        the Apache error log!
 */
-static EVP_PKEY * php_openssl_evp_from_zval(zval ** val, int public_key, char * passphrase, int makeresource, long * resourceval TSRMLS_DC)
+static EVP_PKEY * php_openssl_evp_from_zval(zval * val, int public_key, char * passphrase, int makeresource, zend_resource **resourceval TSRMLS_DC)
 {
        EVP_PKEY * key = NULL;
        X509 * cert = NULL;
        int free_cert = 0;
-       long cert_res = -1;
+       zend_resource *cert_res = NULL;
        char * filename = NULL;
        zval tmp;
 
-       Z_TYPE(tmp) = IS_NULL;
+       ZVAL_NULL(&tmp);
 
 #define TMP_CLEAN \
        if (Z_TYPE(tmp) == IS_STRING) {\
@@ -3258,35 +3221,34 @@ static EVP_PKEY * php_openssl_evp_from_zval(zval ** val, int public_key, char *
        return NULL;
 
        if (resourceval) {
-               *resourceval = -1;
+               *resourceval = NULL;
        }
-       if (Z_TYPE_PP(val) == IS_ARRAY) {
-               zval ** zphrase;
+       if (Z_TYPE_P(val) == IS_ARRAY) {
+               zval * zphrase;
                
                /* get passphrase */
 
-               if (zend_hash_index_find(HASH_OF(*val), 1, (void **)&zphrase) == FAILURE) {
+               if ((zphrase = zend_hash_index_find(HASH_OF(val), 1)) == NULL) {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "key array must be of the form array(0 => key, 1 => phrase)");
                        return NULL;
                }
                
-               if (Z_TYPE_PP(zphrase) == IS_STRING) {
-                       passphrase = Z_STRVAL_PP(zphrase);
+               if (Z_TYPE_P(zphrase) == IS_STRING) {
+                       passphrase = Z_STRVAL_P(zphrase);
                } else {
-                       tmp = **zphrase;
-                       zval_copy_ctor(&tmp);
+                       ZVAL_DUP(&tmp, zphrase);
                        convert_to_string(&tmp);
                        passphrase = Z_STRVAL(tmp);
                }
 
                /* now set val to be the key param and continue */
-               if (zend_hash_index_find(HASH_OF(*val), 0, (void **)&val) == FAILURE) {
+               if ((val = zend_hash_index_find(HASH_OF(val), 0)) == NULL) {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "key array must be of the form array(0 => key, 1 => phrase)");
                        TMP_CLEAN;
                }
        }
 
-       if (Z_TYPE_PP(val) == IS_RESOURCE) {
+       if (Z_TYPE_P(val) == IS_RESOURCE) {
                void * what;
                int type;
 
@@ -3295,7 +3257,8 @@ static EVP_PKEY * php_openssl_evp_from_zval(zval ** val, int public_key, char *
                        TMP_CLEAN;
                }
                if (resourceval) { 
-                       *resourceval = Z_LVAL_PP(val);
+                       *resourceval = Z_RES_P(val);
+                       Z_ADDREF_P(val);
                }
                if (type == le_x509) {
                        /* extract key from cert, depending on public_key param */
@@ -3331,18 +3294,18 @@ static EVP_PKEY * php_openssl_evp_from_zval(zval ** val, int public_key, char *
                /* passing non string values leaks, object uses toString, it returns NULL 
                 * See bug38255.phpt 
                 */
-               if (!(Z_TYPE_PP(val) == IS_STRING || Z_TYPE_PP(val) == IS_OBJECT)) {
+               if (!(Z_TYPE_P(val) == IS_STRING || Z_TYPE_P(val) == IS_OBJECT)) {
                        TMP_CLEAN;
                }
                convert_to_string_ex(val);
 
-               if (Z_STRLEN_PP(val) > 7 && memcmp(Z_STRVAL_PP(val), "file://", sizeof("file://") - 1) == 0) {
-                       filename = Z_STRVAL_PP(val) + (sizeof("file://") - 1);
+               if (Z_STRLEN_P(val) > 7 && memcmp(Z_STRVAL_P(val), "file://", sizeof("file://") - 1) == 0) {
+                       filename = Z_STRVAL_P(val) + (sizeof("file://") - 1);
                }
                /* it's an X509 file/cert of some kind, and we need to extract the data from that */
                if (public_key) {
                        cert = php_openssl_x509_from_zval(val, 0, &cert_res TSRMLS_CC);
-                       free_cert = (cert_res == -1);
+                       free_cert = (cert_res == NULL);
                        /* actual extraction done later */
                        if (!cert) {
                                /* not a X509 certificate, try to retrieve public key */
@@ -3350,7 +3313,7 @@ static EVP_PKEY * php_openssl_evp_from_zval(zval ** val, int public_key, char *
                                if (filename) {
                                        in = BIO_new_file(filename, "r");
                                } else {
-                                       in = BIO_new_mem_buf(Z_STRVAL_PP(val), Z_STRLEN_PP(val));
+                                       in = BIO_new_mem_buf(Z_STRVAL_P(val), Z_STRLEN_P(val));
                                }
                                if (in == NULL) {
                                        TMP_CLEAN;
@@ -3368,7 +3331,7 @@ static EVP_PKEY * php_openssl_evp_from_zval(zval ** val, int public_key, char *
                                }
                                in = BIO_new_file(filename, "r");
                        } else {
-                               in = BIO_new_mem_buf(Z_STRVAL_PP(val), Z_STRLEN_PP(val));
+                               in = BIO_new_mem_buf(Z_STRVAL_P(val), Z_STRLEN_P(val));
                        }
 
                        if (in == NULL) {
@@ -3535,18 +3498,18 @@ static int php_openssl_is_private_key(EVP_PKEY* pkey TSRMLS_DC)
                        BN_bn2bin(pkey->pkey._type->_name, (unsigned char*)str);        \
                        str[len] = 0;                                                   \
                        /* TODO: avoid reallocation ??? */                                                      \
-                       add_assoc_stringl(_type, #_name, str, len);                                     \
+                       add_assoc_stringl(&_type, #_name, str, len);                            \
                        efree(str);                                                                                                     \
                }                                                                                                                               \
        } while (0)
 
 #define OPENSSL_PKEY_SET_BN(_ht, _type, _name) do {                                            \
-               zval **bn;                                                                                                              \
-               if (zend_hash_find(_ht, #_name, sizeof(#_name), (void**)&bn) == SUCCESS && \
-                               Z_TYPE_PP(bn) == IS_STRING) {                                                   \
+               zval *bn;                                                                                                               \
+               if ((bn = zend_hash_str_find(_ht, #_name, sizeof(#_name)-1)) != NULL && \
+                               Z_TYPE_P(bn) == IS_STRING) {                                                    \
                        _type->_name = BN_bin2bn(                                                                       \
-                               (unsigned char*)Z_STRVAL_PP(bn),                                                \
-                               Z_STRLEN_PP(bn), NULL);                                                                 \
+                               (unsigned char*)Z_STRVAL_P(bn),                                                 \
+                               Z_STRLEN_P(bn), NULL);                                                                  \
            }                                                               \
        } while (0);
 
@@ -3557,7 +3520,7 @@ PHP_FUNCTION(openssl_pkey_new)
 {
        struct php_x509_request req;
        zval * args = NULL;
-       zval **data;
+       zval *data;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "|a!", &args) == FAILURE) {
                return;
@@ -3567,23 +3530,24 @@ PHP_FUNCTION(openssl_pkey_new)
        if (args && Z_TYPE_P(args) == IS_ARRAY) {
                EVP_PKEY *pkey;
 
-               if (zend_hash_find(Z_ARRVAL_P(args), "rsa", sizeof("rsa"), (void**)&data) == SUCCESS &&
-                   Z_TYPE_PP(data) == IS_ARRAY) {
+               if ((data = zend_hash_str_find(Z_ARRVAL_P(args), "rsa", sizeof("rsa")-1)) != NULL &&
+                   Z_TYPE_P(data) == IS_ARRAY) {
                    pkey = EVP_PKEY_new();
                    if (pkey) {
                                RSA *rsa = RSA_new();
                                if (rsa) {
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), rsa, n);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), rsa, e);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), rsa, d);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), rsa, p);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), rsa, q);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), rsa, dmp1);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), rsa, dmq1);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), rsa, iqmp);
+                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), rsa, n);
+                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), rsa, e);
+                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), rsa, d);
+                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), rsa, p);
+                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), rsa, q);
+                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), rsa, dmp1);
+                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), rsa, dmq1);
+                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), rsa, iqmp);
                                        if (rsa->n && rsa->d) {
                                                if (EVP_PKEY_assign_RSA(pkey, rsa)) {
-                                                       RETURN_RESOURCE(zend_list_insert(pkey, le_key TSRMLS_CC));
+                                                       zend_register_resource(return_value, pkey, le_key TSRMLS_CC);
+                                                       return;
                                                }
                                        }
                                        RSA_free(rsa);
@@ -3591,23 +3555,24 @@ PHP_FUNCTION(openssl_pkey_new)
                                EVP_PKEY_free(pkey);
                        }
                        RETURN_FALSE;
-               } else if (zend_hash_find(Z_ARRVAL_P(args), "dsa", sizeof("dsa"), (void**)&data) == SUCCESS &&
-                          Z_TYPE_PP(data) == IS_ARRAY) {
+               } else if ((data = zend_hash_str_find(Z_ARRVAL_P(args), "dsa", sizeof("dsa")-1)) != NULL &&
+                          Z_TYPE_P(data) == IS_ARRAY) {
                    pkey = EVP_PKEY_new();
                    if (pkey) {
                                DSA *dsa = DSA_new();
                                if (dsa) {
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), dsa, p);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), dsa, q);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), dsa, g);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), dsa, priv_key);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), dsa, pub_key);
+                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), dsa, p);
+                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), dsa, q);
+                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), dsa, g);
+                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), dsa, priv_key);
+                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), dsa, pub_key);
                                        if (dsa->p && dsa->q && dsa->g) {
                                                if (!dsa->priv_key && !dsa->pub_key) {
                                                        DSA_generate_key(dsa);
                                                }
                                                if (EVP_PKEY_assign_DSA(pkey, dsa)) {
-                                                       RETURN_RESOURCE(zend_list_insert(pkey, le_key TSRMLS_CC));
+                                                       zend_register_resource(return_value, pkey, le_key TSRMLS_CC);
+                                                       return;
                                                }
                                        }
                                        DSA_free(dsa);
@@ -3615,22 +3580,23 @@ PHP_FUNCTION(openssl_pkey_new)
                                EVP_PKEY_free(pkey);
                        }
                        RETURN_FALSE;
-               } else if (zend_hash_find(Z_ARRVAL_P(args), "dh", sizeof("dh"), (void**)&data) == SUCCESS &&
-                          Z_TYPE_PP(data) == IS_ARRAY) {
+               } else if ((data = zend_hash_str_find(Z_ARRVAL_P(args), "dh", sizeof("dh")-1)) != NULL &&
+                          Z_TYPE_P(data) == IS_ARRAY) {
                    pkey = EVP_PKEY_new();
                    if (pkey) {
                                DH *dh = DH_new();
                                if (dh) {
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), dh, p);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), dh, g);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), dh, priv_key);
-                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_PP(data), dh, pub_key);
+                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), dh, p);
+                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), dh, g);
+                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), dh, priv_key);
+                                       OPENSSL_PKEY_SET_BN(Z_ARRVAL_P(data), dh, pub_key);
                                        if (dh->p && dh->g) {
                                                if (!dh->pub_key) {
                                                        DH_generate_key(dh);
                                                }
                                                if (EVP_PKEY_assign_DH(pkey, dh)) {
-                                                       RETURN_RESOURCE(zend_list_insert(pkey, le_key TSRMLS_CC));
+                                                       ZVAL_COPY_VALUE(return_value, zend_list_insert(pkey, le_key TSRMLS_CC));
+                                                       return;
                                                }
                                        }
                                        DH_free(dh);
@@ -3647,7 +3613,7 @@ PHP_FUNCTION(openssl_pkey_new)
        {
                if (php_openssl_generate_private_key(&req TSRMLS_CC)) {
                        /* pass back a key resource */
-                       RETVAL_RESOURCE(zend_list_insert(req.priv_key, le_key TSRMLS_CC));
+                       zend_register_resource(return_value, req.priv_key, le_key TSRMLS_CC);
                        /* make sure the cleanup code doesn't zap it! */
                        req.priv_key = NULL;
                }
@@ -3661,15 +3627,15 @@ PHP_FUNCTION(openssl_pkey_new)
 PHP_FUNCTION(openssl_pkey_export_to_file)
 {
        struct php_x509_request req;
-       zval ** zpkey, * args = NULL;
+       zval * zpkey, * args = NULL;
        char * passphrase = NULL; int passphrase_len = 0;
        char * filename = NULL; int filename_len = 0;
-       long key_resource = -1;
+       zend_resource *key_resource = NULL;
        EVP_PKEY * key;
        BIO * bio_out = NULL;
        const EVP_CIPHER * cipher;
        
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zp|s!a!", &zpkey, &filename, &filename_len, &passphrase, &passphrase_len, &args) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zp|s!a!", &zpkey, &filename, &filename_len, &passphrase, &passphrase_len, &args) == FAILURE) {
                return;
        }
        RETVAL_FALSE;
@@ -3707,7 +3673,7 @@ PHP_FUNCTION(openssl_pkey_export_to_file)
        }
        PHP_SSL_REQ_DISPOSE(&req);
 
-       if (key_resource == -1 && key) {
+       if (key_resource == NULL && key) {
                EVP_PKEY_free(key);
        }
        if (bio_out) {
@@ -3721,16 +3687,17 @@ PHP_FUNCTION(openssl_pkey_export_to_file)
 PHP_FUNCTION(openssl_pkey_export)
 {
        struct php_x509_request req;
-       zval ** zpkey, * args = NULL, *out;
+       zval * zpkey, * args = NULL, *out;
        char * passphrase = NULL; int passphrase_len = 0;
-       long key_resource = -1;
+       zend_resource *key_resource = NULL;
        EVP_PKEY * key;
        BIO * bio_out = NULL;
        const EVP_CIPHER * cipher;
        
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zz|s!a!", &zpkey, &out, &passphrase, &passphrase_len, &args) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|s!a!", &zpkey, &out, &passphrase, &passphrase_len, &args) == FAILURE) {
                return;
        }
+       ZVAL_DEREF(out);
        RETVAL_FALSE;
 
        key = php_openssl_evp_from_zval(zpkey, 0, passphrase, 0, &key_resource TSRMLS_CC);
@@ -3764,12 +3731,12 @@ PHP_FUNCTION(openssl_pkey_export)
 
                        bio_mem_len = BIO_get_mem_data(bio_out, &bio_mem_ptr);
                        zval_dtor(out);
-                       ZVAL_STRINGL(out, bio_mem_ptr, bio_mem_len, 1);
+                       ZVAL_STRINGL(out, bio_mem_ptr, bio_mem_len);
                }
        }
        PHP_SSL_REQ_DISPOSE(&req);
 
-       if (key_resource == -1 && key) {
+       if (key_resource == NULL && key) {
                EVP_PKEY_free(key);
        }
        if (bio_out) {
@@ -3782,19 +3749,19 @@ PHP_FUNCTION(openssl_pkey_export)
    Gets public key from X.509 certificate */
 PHP_FUNCTION(openssl_pkey_get_public)
 {
-       zval **cert;
+       zval *cert;
        EVP_PKEY *pkey;
+       zend_resource *res;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z", &cert) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z", &cert) == FAILURE) {
                return;
        }
-       Z_TYPE_P(return_value) = IS_RESOURCE;
-       pkey = php_openssl_evp_from_zval(cert, 1, NULL, 1, &Z_LVAL_P(return_value) TSRMLS_CC);
-
+       pkey = php_openssl_evp_from_zval(cert, 1, NULL, 1, &res TSRMLS_CC);
        if (pkey == NULL) {
                RETURN_FALSE;
        }
-       zend_list_addref(Z_LVAL_P(return_value));
+       ZVAL_RES(return_value, res);
+       Z_ADDREF_P(return_value);
 }
 /* }}} */
 
@@ -3808,8 +3775,8 @@ PHP_FUNCTION(openssl_pkey_free)
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &key) == FAILURE) {
                return;
        }
-       ZEND_FETCH_RESOURCE(pkey, EVP_PKEY *, &key, -1, "OpenSSL key", le_key);
-       zend_list_delete(Z_LVAL_P(key));
+       ZEND_FETCH_RESOURCE(pkey, EVP_PKEY *, key, -1, "OpenSSL key", le_key);
+       zend_list_close(Z_RES_P(key));
 }
 /* }}} */
 
@@ -3817,21 +3784,22 @@ PHP_FUNCTION(openssl_pkey_free)
    Gets private keys */
 PHP_FUNCTION(openssl_pkey_get_private)
 {
-       zval **cert;
+       zval *cert;
        EVP_PKEY *pkey;
        char * passphrase = "";
        int passphrase_len = sizeof("")-1;
+       zend_resource *res;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Z|s", &cert, &passphrase, &passphrase_len) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|s", &cert, &passphrase, &passphrase_len) == FAILURE) {
                return;
        }
-       Z_TYPE_P(return_value) = IS_RESOURCE;
-       pkey = php_openssl_evp_from_zval(cert, 0, passphrase, 1, &Z_LVAL_P(return_value) TSRMLS_CC);
+       pkey = php_openssl_evp_from_zval(cert, 0, passphrase, 1, &res TSRMLS_CC);
 
        if (pkey == NULL) {
                RETURN_FALSE;
        }
-       zend_list_addref(Z_LVAL_P(return_value));
+       ZVAL_RES(return_value, res);
+       Z_ADDREF_P(return_value);
 }
 
 /* }}} */
@@ -3850,7 +3818,7 @@ PHP_FUNCTION(openssl_pkey_get_details)
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &key) == FAILURE) {
                return;
        }
-       ZEND_FETCH_RESOURCE(pkey, EVP_PKEY *, &key, -1, "OpenSSL key", le_key);
+       ZEND_FETCH_RESOURCE(pkey, EVP_PKEY *, key, -1, "OpenSSL key", le_key);
        if (!pkey) {
                RETURN_FALSE;
        }
@@ -3870,10 +3838,9 @@ PHP_FUNCTION(openssl_pkey_get_details)
                        ktype = OPENSSL_KEYTYPE_RSA;
 
                        if (pkey->pkey.rsa != NULL) {
-                               zval *rsa;
+                               zval rsa;
 
-                               ALLOC_INIT_ZVAL(rsa);
-                               array_init(rsa);
+                               array_init(&rsa);
                                OPENSSL_PKEY_GET_BN(rsa, n);
                                OPENSSL_PKEY_GET_BN(rsa, e);
                                OPENSSL_PKEY_GET_BN(rsa, d);
@@ -3882,7 +3849,7 @@ PHP_FUNCTION(openssl_pkey_get_details)
                                OPENSSL_PKEY_GET_BN(rsa, dmp1);
                                OPENSSL_PKEY_GET_BN(rsa, dmq1);
                                OPENSSL_PKEY_GET_BN(rsa, iqmp);
-                               add_assoc_zval(return_value, "rsa", rsa);
+                               add_assoc_zval(return_value, "rsa", &rsa);
                        }
 
                        break;  
@@ -3893,16 +3860,15 @@ PHP_FUNCTION(openssl_pkey_get_details)
                        ktype = OPENSSL_KEYTYPE_DSA;
 
                        if (pkey->pkey.dsa != NULL) {
-                               zval *dsa;
+                               zval dsa;
 
-                               ALLOC_INIT_ZVAL(dsa);
-                               array_init(dsa);
+                               array_init(&dsa);
                                OPENSSL_PKEY_GET_BN(dsa, p);
                                OPENSSL_PKEY_GET_BN(dsa, q);
                                OPENSSL_PKEY_GET_BN(dsa, g);
                                OPENSSL_PKEY_GET_BN(dsa, priv_key);
                                OPENSSL_PKEY_GET_BN(dsa, pub_key);
-                               add_assoc_zval(return_value, "dsa", dsa);
+                               add_assoc_zval(return_value, "dsa", &dsa);
                        }
                        break;
                case EVP_PKEY_DH:
@@ -3910,15 +3876,14 @@ PHP_FUNCTION(openssl_pkey_get_details)
                        ktype = OPENSSL_KEYTYPE_DH;
 
                        if (pkey->pkey.dh != NULL) {
-                               zval *dh;
+                               zval dh;
 
-                               ALLOC_INIT_ZVAL(dh);
-                               array_init(dh);
+                               array_init(&dh);
                                OPENSSL_PKEY_GET_BN(dh, p);
                                OPENSSL_PKEY_GET_BN(dh, g);
                                OPENSSL_PKEY_GET_BN(dh, priv_key);
                                OPENSSL_PKEY_GET_BN(dh, pub_key);
-                               add_assoc_zval(return_value, "dh", dh);
+                               add_assoc_zval(return_value, "dh", &dh);
                        }
 
                        break;
@@ -3980,7 +3945,9 @@ PHP_FUNCTION(openssl_pbkdf2)
        out_buffer[key_length] = '\0';
 
        if (PKCS5_PBKDF2_HMAC(password, password_len, (unsigned char *)salt, salt_len, iterations, digest, key_length, out_buffer) == 1) {
-               RETVAL_STRINGL((char *)out_buffer, key_length, 0);
+               // TODO: avoid reallocation ???
+               RETVAL_STRINGL((char *)out_buffer, key_length);
+               efree(out_buffer);
        } else {
                efree(out_buffer);
                RETURN_FALSE;
@@ -4105,25 +4072,22 @@ clean_exit:
    Encrypts the message in the file named infile with the certificates in recipcerts and output the result to the file named outfile */
 PHP_FUNCTION(openssl_pkcs7_encrypt)
 {
-       zval ** zrecipcerts, * zheaders = NULL;
+       zval * zrecipcerts, * zheaders = NULL;
        STACK_OF(X509) * recipcerts = NULL;
        BIO * infile = NULL, * outfile = NULL;
        long flags = 0;
        PKCS7 * p7 = NULL;
-       HashPosition hpos;
-       zval ** zcertval;
+       zval * zcertval;
        X509 * cert;
        const EVP_CIPHER *cipher = NULL;
        long cipherid = PHP_OPENSSL_CIPHER_DEFAULT;
-       uint strindexlen;
-       ulong intindex;
-       char * strindex;
+       zend_string * strindex;
        char * infilename = NULL;       int infilename_len;
        char * outfilename = NULL;      int outfilename_len;
        
        RETVAL_FALSE;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ppZa!|ll", &infilename, &infilename_len,
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ppza!|ll", &infilename, &infilename_len,
                                &outfilename, &outfilename_len, &zrecipcerts, &zheaders, &flags, &cipherid) == FAILURE)
                return;
 
@@ -4145,17 +4109,16 @@ PHP_FUNCTION(openssl_pkcs7_encrypt)
        recipcerts = sk_X509_new_null();
 
        /* get certs */
-       if (Z_TYPE_PP(zrecipcerts) == IS_ARRAY) {
-               zend_hash_internal_pointer_reset_ex(HASH_OF(*zrecipcerts), &hpos);
-               while(zend_hash_get_current_data_ex(HASH_OF(*zrecipcerts), (void**)&zcertval, &hpos) == SUCCESS) {
-                       long certresource;
+       if (Z_TYPE_P(zrecipcerts) == IS_ARRAY) {
+               ZEND_HASH_FOREACH_VAL(HASH_OF(zrecipcerts), zcertval) {
+                       zend_resource *certresource;
 
                        cert = php_openssl_x509_from_zval(zcertval, 0, &certresource TSRMLS_CC);
                        if (cert == NULL) {
                                goto clean_exit;
                        }
 
-                       if (certresource != -1) {
+                       if (certresource != NULL) {
                                /* we shouldn't free this particular cert, as it is a resource.
                                        make a copy and push that on the stack instead */
                                cert = X509_dup(cert);
@@ -4164,19 +4127,17 @@ PHP_FUNCTION(openssl_pkcs7_encrypt)
                                }
                        }
                        sk_X509_push(recipcerts, cert);
-
-                       zend_hash_move_forward_ex(HASH_OF(*zrecipcerts), &hpos);
-               }
+               } ZEND_HASH_FOREACH_END();
        } else {
                /* a single certificate */
-               long certresource;
+               zend_resource *certresource;
 
                cert = php_openssl_x509_from_zval(zrecipcerts, 0, &certresource TSRMLS_CC);
                if (cert == NULL) {
                        goto clean_exit;
                }
 
-               if (certresource != -1) {
+               if (certresource != NULL) {
                        /* we shouldn't free this particular cert, as it is a resource.
                                make a copy and push that on the stack instead */
                        cert = X509_dup(cert);
@@ -4203,21 +4164,15 @@ PHP_FUNCTION(openssl_pkcs7_encrypt)
 
        /* tack on extra headers */
        if (zheaders) {
-               zend_hash_internal_pointer_reset_ex(HASH_OF(zheaders), &hpos);
-               while(zend_hash_get_current_data_ex(HASH_OF(zheaders), (void**)&zcertval, &hpos) == SUCCESS) {
-                       strindex = NULL;
-                       zend_hash_get_current_key_ex(HASH_OF(zheaders), &strindex, &strindexlen, &intindex, 0, &hpos);
-
+               ZEND_HASH_FOREACH_STR_KEY_VAL(HASH_OF(zheaders), strindex, zcertval) {
                        convert_to_string_ex(zcertval);
 
                        if (strindex) {
-                               BIO_printf(outfile, "%s: %s\n", strindex, Z_STRVAL_PP(zcertval));
+                               BIO_printf(outfile, "%s: %s\n", strindex->val, Z_STRVAL_P(zcertval));
                        } else {
-                               BIO_printf(outfile, "%s\n", Z_STRVAL_PP(zcertval));
+                               BIO_printf(outfile, "%s\n", Z_STRVAL_P(zcertval));
                        }
-
-                       zend_hash_move_forward_ex(HASH_OF(zheaders), &hpos);
-               }
+               } ZEND_HASH_FOREACH_END();
        }
 
        (void)BIO_reset(infile);
@@ -4242,24 +4197,21 @@ clean_exit:
 
 PHP_FUNCTION(openssl_pkcs7_sign)
 {
-       zval ** zcert, ** zprivkey, * zheaders;
-       zval ** hval;
+       zval * zcert, * zprivkey, * zheaders;
+       zval * hval;
        X509 * cert = NULL;
        EVP_PKEY * privkey = NULL;
        long flags = PKCS7_DETACHED;
        PKCS7 * p7 = NULL;
        BIO * infile = NULL, * outfile = NULL;
        STACK_OF(X509) *others = NULL;
-       long certresource = -1, keyresource = -1;
-       ulong intindex;
-       uint strindexlen;
-       HashPosition hpos;
-       char * strindex;
+       zend_resource *certresource = NULL, *keyresource = NULL;
+       zend_string * strindex;
        char * infilename;      int infilename_len;
        char * outfilename;     int outfilename_len;
        char * extracertsfilename = NULL; int extracertsfilename_len;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ppZZa!|lp",
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ppzza!|lp",
                                &infilename, &infilename_len, &outfilename, &outfilename_len,
                                &zcert, &zprivkey, &zheaders, &flags, &extracertsfilename,
                                &extracertsfilename_len) == FAILURE) {
@@ -4313,20 +4265,15 @@ PHP_FUNCTION(openssl_pkcs7_sign)
 
        /* tack on extra headers */
        if (zheaders) {
-               zend_hash_internal_pointer_reset_ex(HASH_OF(zheaders), &hpos);
-               while(zend_hash_get_current_data_ex(HASH_OF(zheaders), (void**)&hval, &hpos) == SUCCESS) {
-                       strindex = NULL;
-                       zend_hash_get_current_key_ex(HASH_OF(zheaders), &strindex, &strindexlen, &intindex, 0, &hpos);
-
+               ZEND_HASH_FOREACH_STR_KEY_VAL(HASH_OF(zheaders), strindex, hval) {
                        convert_to_string_ex(hval);
 
                        if (strindex) {
-                               BIO_printf(outfile, "%s: %s\n", strindex, Z_STRVAL_PP(hval));
+                               BIO_printf(outfile, "%s: %s\n", strindex->val, Z_STRVAL_P(hval));
                        } else {
-                               BIO_printf(outfile, "%s\n", Z_STRVAL_PP(hval));
+                               BIO_printf(outfile, "%s\n", Z_STRVAL_P(hval));
                        }
-                       zend_hash_move_forward_ex(HASH_OF(zheaders), &hpos);
-               }
+               } ZEND_HASH_FOREACH_END();
        }
        /* write the signed data */
        SMIME_write_PKCS7(outfile, p7, infile, flags);
@@ -4340,10 +4287,10 @@ clean_exit:
        if (others) {
                sk_X509_pop_free(others, X509_free);
        }
-       if (privkey && keyresource == -1) {
+       if (privkey && keyresource == NULL) {
                EVP_PKEY_free(privkey);
        }
-       if (cert && certresource == -1) {
+       if (cert && certresource == NULL) {
                X509_free(cert);
        }
 }
@@ -4354,16 +4301,16 @@ clean_exit:
 
 PHP_FUNCTION(openssl_pkcs7_decrypt)
 {
-       zval ** recipcert, ** recipkey = NULL;
+       zval * recipcert, * recipkey = NULL;
        X509 * cert = NULL;
        EVP_PKEY * key = NULL;
-       long certresval, keyresval;
+       zend_resource *certresval, *keyresval;
        BIO * in = NULL, * out = NULL, * datain = NULL;
        PKCS7 * p7 = NULL;
        char * infilename;      int infilename_len;
        char * outfilename;     int outfilename_len;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ppZ|Z", &infilename, &infilename_len,
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ppz|z", &infilename, &infilename_len,
                                &outfilename, &outfilename_len, &recipcert, &recipkey) == FAILURE) {
                return;
        }
@@ -4408,10 +4355,10 @@ clean_exit:
        BIO_free(datain);
        BIO_free(in);
        BIO_free(out);
-       if (cert && certresval == -1) {
+       if (cert && certresval == NULL) {
                X509_free(cert);
        }
-       if (key && keyresval == -1) {
+       if (key && keyresval == NULL) {
                EVP_PKEY_free(key);
        }
 }
@@ -4423,19 +4370,20 @@ clean_exit:
    Encrypts data with private key */
 PHP_FUNCTION(openssl_private_encrypt)
 {
-       zval **key, *crypted;
+       zval *key, *crypted;
        EVP_PKEY *pkey;
        int cryptedlen;
        unsigned char *cryptedbuf = NULL;
        int successful = 0;
-       long keyresource = -1;
+       zend_resource *keyresource = NULL;
        char * data;
        int data_len;
        long padding = RSA_PKCS1_PADDING;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szZ|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) { 
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szz|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) { 
                return;
        }
+       ZVAL_DEREF(crypted);
        RETVAL_FALSE;
 
        pkey = php_openssl_evp_from_zval(key, 0, "", 0, &keyresource TSRMLS_CC);
@@ -4464,14 +4412,16 @@ PHP_FUNCTION(openssl_private_encrypt)
        if (successful) {
                zval_dtor(crypted);
                cryptedbuf[cryptedlen] = '\0';
-               ZVAL_STRINGL(crypted, (char *)cryptedbuf, cryptedlen, 0);
+               // TODO: avoid reallocation ???
+               ZVAL_STRINGL(crypted, (char *)cryptedbuf, cryptedlen);
+               efree(cryptedbuf);
                cryptedbuf = NULL;
                RETVAL_TRUE;
        }
        if (cryptedbuf) {
                efree(cryptedbuf);
        }
-       if (keyresource == -1) { 
+       if (keyresource == NULL) { 
                EVP_PKEY_free(pkey);
        }
 }
@@ -4481,20 +4431,21 @@ PHP_FUNCTION(openssl_private_encrypt)
    Decrypts data with private key */
 PHP_FUNCTION(openssl_private_decrypt)
 {
-       zval **key, *crypted;
+       zval *key, *crypted;
        EVP_PKEY *pkey;
        int cryptedlen;
        unsigned char *cryptedbuf = NULL;
        unsigned char *crypttemp;
        int successful = 0;
        long padding = RSA_PKCS1_PADDING;
-       long keyresource = -1;
+       zend_resource *keyresource = NULL;
        char * data;
        int data_len;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szZ|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szz|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) {
                return;
        }
+       ZVAL_DEREF(crypted);
        RETVAL_FALSE;
 
        pkey = php_openssl_evp_from_zval(key, 0, "", 0, &keyresource TSRMLS_CC);
@@ -4529,12 +4480,14 @@ PHP_FUNCTION(openssl_private_decrypt)
        if (successful) {
                zval_dtor(crypted);
                cryptedbuf[cryptedlen] = '\0';
-               ZVAL_STRINGL(crypted, (char *)cryptedbuf, cryptedlen, 0);
+               // TODO: avoid reallocation ???
+               ZVAL_STRINGL(crypted, (char *)cryptedbuf, cryptedlen);
+               efree(cryptedbuf);
                cryptedbuf = NULL;
                RETVAL_TRUE;
        }
 
-       if (keyresource == -1) {
+       if (keyresource == NULL) {
                EVP_PKEY_free(pkey);
        }
        if (cryptedbuf) { 
@@ -4547,19 +4500,19 @@ PHP_FUNCTION(openssl_private_decrypt)
    Encrypts data with public key */
 PHP_FUNCTION(openssl_public_encrypt)
 {
-       zval **key, *crypted;
+       zval *key, *crypted;
        EVP_PKEY *pkey;
        int cryptedlen;
        unsigned char *cryptedbuf;
        int successful = 0;
-       long keyresource = -1;
+       zend_resource *keyresource = NULL;
        long padding = RSA_PKCS1_PADDING;
        char * data;
        int data_len;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szZ|l", &data, &data_len, &crypted, &key, &padding) == FAILURE)
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szz|l", &data, &data_len, &crypted, &key, &padding) == FAILURE)
                return;
-
+       ZVAL_DEREF(crypted);
        RETVAL_FALSE;
        
        pkey = php_openssl_evp_from_zval(key, 1, NULL, 0, &keyresource TSRMLS_CC);
@@ -4588,11 +4541,13 @@ PHP_FUNCTION(openssl_public_encrypt)
        if (successful) {
                zval_dtor(crypted);
                cryptedbuf[cryptedlen] = '\0';
-               ZVAL_STRINGL(crypted, (char *)cryptedbuf, cryptedlen, 0);
+               // TODO: avoid reallocation ???
+               ZVAL_STRINGL(crypted, (char *)cryptedbuf, cryptedlen);
+               efree(cryptedbuf);
                cryptedbuf = NULL;
                RETVAL_TRUE;
        }
-       if (keyresource == -1) {
+       if (keyresource == NULL) {
                EVP_PKEY_free(pkey);
        }
        if (cryptedbuf) {
@@ -4605,20 +4560,21 @@ PHP_FUNCTION(openssl_public_encrypt)
    Decrypts data with public key */
 PHP_FUNCTION(openssl_public_decrypt)
 {
-       zval **key, *crypted;
+       zval *key, *crypted;
        EVP_PKEY *pkey;
        int cryptedlen;
        unsigned char *cryptedbuf = NULL;
        unsigned char *crypttemp;
        int successful = 0;
-       long keyresource = -1;
+       zend_resource *keyresource = NULL;
        long padding = RSA_PKCS1_PADDING;
        char * data;
        int data_len;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szZ|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szz|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) {
                return;
        }
+       ZVAL_DEREF(crypted);
        RETVAL_FALSE;
        
        pkey = php_openssl_evp_from_zval(key, 1, NULL, 0, &keyresource TSRMLS_CC);
@@ -4655,7 +4611,9 @@ PHP_FUNCTION(openssl_public_decrypt)
        if (successful) {
                zval_dtor(crypted);
                cryptedbuf[cryptedlen] = '\0';
-               ZVAL_STRINGL(crypted, (char *)cryptedbuf, cryptedlen, 0);
+               // TODO: avoid reallocation ???
+               ZVAL_STRINGL(crypted, (char *)cryptedbuf, cryptedlen);
+               efree(cryptedbuf);
                cryptedbuf = NULL;
                RETVAL_TRUE;
        }
@@ -4663,7 +4621,7 @@ PHP_FUNCTION(openssl_public_decrypt)
        if (cryptedbuf) {
                efree(cryptedbuf);
        }
-       if (keyresource == -1) {
+       if (keyresource == NULL) {
                EVP_PKEY_free(pkey);
        }
 }
@@ -4682,7 +4640,7 @@ PHP_FUNCTION(openssl_error_string)
 
        val = ERR_get_error();
        if (val) {
-               RETURN_STRING(ERR_error_string(val, buf), 1);
+               RETURN_STRING(ERR_error_string(val, buf));
        } else {
                RETURN_FALSE;
        }
@@ -4693,11 +4651,11 @@ PHP_FUNCTION(openssl_error_string)
    Signs data */
 PHP_FUNCTION(openssl_sign)
 {
-       zval **key, *signature;
+       zval *key, *signature;
        EVP_PKEY *pkey;
        int siglen;
        unsigned char *sigbuf;
-       long keyresource = -1;
+       zend_resource *keyresource = NULL;
        char * data;
        int data_len;
        EVP_MD_CTX md_ctx;
@@ -4705,9 +4663,10 @@ PHP_FUNCTION(openssl_sign)
        long signature_algo = OPENSSL_ALGO_SHA1;
        const EVP_MD *mdtype;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szZ|z", &data, &data_len, &signature, &key, &method) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szz|z", &data, &data_len, &signature, &key, &method) == FAILURE) {
                return;
        }
+       ZVAL_DEREF(signature);
        pkey = php_openssl_evp_from_zval(key, 0, "", 0, &keyresource TSRMLS_CC);
        if (pkey == NULL) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "supplied key param cannot be coerced into a private key");
@@ -4738,14 +4697,16 @@ PHP_FUNCTION(openssl_sign)
        if (EVP_SignFinal (&md_ctx, sigbuf,(unsigned int *)&siglen, pkey)) {
                zval_dtor(signature);
                sigbuf[siglen] = '\0';
-               ZVAL_STRINGL(signature, (char *)sigbuf, siglen, 0);
+               // TODO: avoid reallocation ???
+               ZVAL_STRINGL(signature, (char *)sigbuf, siglen);
+               efree(sigbuf);
                RETVAL_TRUE;
        } else {
                efree(sigbuf);
                RETVAL_FALSE;
        }
        EVP_MD_CTX_cleanup(&md_ctx);
-       if (keyresource == -1) {
+       if (keyresource == NULL) {
                EVP_PKEY_free(pkey);
        }
 }
@@ -4755,18 +4716,18 @@ PHP_FUNCTION(openssl_sign)
    Verifys data */
 PHP_FUNCTION(openssl_verify)
 {
-       zval **key;
+       zval *key;
        EVP_PKEY *pkey;
        int err;
        EVP_MD_CTX     md_ctx;
        const EVP_MD *mdtype;
-       long keyresource = -1;
+       zend_resource *keyresource = NULL;
        char * data;    int data_len;
        char * signature;       int signature_len;
        zval *method = NULL;
        long signature_algo = OPENSSL_ALGO_SHA1;
        
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssZ|z", &data, &data_len, &signature, &signature_len, &key, &method) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ssz|z", &data, &data_len, &signature, &signature_len, &key, &method) == FAILURE) {
                return;
        }
 
@@ -4797,7 +4758,7 @@ PHP_FUNCTION(openssl_verify)
        err = EVP_VerifyFinal (&md_ctx, (unsigned char *)signature, signature_len, pkey);
        EVP_MD_CTX_cleanup(&md_ctx);
 
-       if (keyresource == -1) {
+       if (keyresource == NULL) {
                EVP_PKEY_free(pkey);
        }
        RETURN_LONG(err);
@@ -4808,11 +4769,10 @@ PHP_FUNCTION(openssl_verify)
    Seals data */
 PHP_FUNCTION(openssl_seal)
 {
-       zval *pubkeys, **pubkey, *sealdata, *ekeys;
+       zval *pubkeys, *pubkey, *sealdata, *ekeys;
        HashTable *pubkeysht;
-       HashPosition pos;
        EVP_PKEY **pkeys;
-       long * key_resources;   /* so we know what to cleanup */
+       zend_resource ** key_resources; /* so we know what to cleanup */
        int i, len1, len2, *eksl, nkeys;
        unsigned char *buf = NULL, **eks;
        char * data; int data_len;
@@ -4824,7 +4784,8 @@ PHP_FUNCTION(openssl_seal)
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szza/|s", &data, &data_len, &sealdata, &ekeys, &pubkeys, &method, &method_len) == FAILURE) {
                return;
        }
-       
+       ZVAL_DEREF(sealdata);
+       ZVAL_DEREF(ekeys);      
        pubkeysht = HASH_OF(pubkeys);
        nkeys = pubkeysht ? zend_hash_num_elements(pubkeysht) : 0;
        if (!nkeys) {
@@ -4846,14 +4807,12 @@ PHP_FUNCTION(openssl_seal)
        eksl = safe_emalloc(nkeys, sizeof(*eksl), 0);
        eks = safe_emalloc(nkeys, sizeof(*eks), 0);
        memset(eks, 0, sizeof(*eks) * nkeys);
-       key_resources = safe_emalloc(nkeys, sizeof(long), 0);
-       memset(key_resources, 0, sizeof(*key_resources) * nkeys);
+       key_resources = safe_emalloc(nkeys, sizeof(zend_resource), 0);
+       memset(key_resources, 0, sizeof(zend_resource) * nkeys);
 
        /* get the public keys we are using to seal this data */
-       zend_hash_internal_pointer_reset_ex(pubkeysht, &pos);
        i = 0;
-       while (zend_hash_get_current_data_ex(pubkeysht, (void **) &pubkey,
-                               &pos) == SUCCESS) {
+       ZEND_HASH_FOREACH_VAL(pubkeysht, pubkey) {
                pkeys[i] = php_openssl_evp_from_zval(pubkey, 1, NULL, 0, &key_resources[i] TSRMLS_CC);
                if (pkeys[i] == NULL) {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "not a public key (%dth member of pubkeys)", i+1);
@@ -4861,9 +4820,8 @@ PHP_FUNCTION(openssl_seal)
                        goto clean_exit;
                }
                eks[i] = emalloc(EVP_PKEY_size(pkeys[i]) + 1);
-               zend_hash_move_forward_ex(pubkeysht, &pos);
                i++;
-       }
+       } ZEND_HASH_FOREACH_END();
 
        if (!EVP_EncryptInit(&ctx,cipher,NULL,NULL)) {
                RETVAL_FALSE;
@@ -4892,14 +4850,14 @@ PHP_FUNCTION(openssl_seal)
        if (len1 + len2 > 0) {
                zval_dtor(sealdata);
                buf[len1 + len2] = '\0';
-               buf = erealloc(buf, len1 + len2 + 1);
-               ZVAL_STRINGL(sealdata, (char *)buf, len1 + len2, 0);
+               ZVAL_STR(sealdata, STR_INIT((char*)buf, len1 + len2, 0));
+               efree(buf);
 
                zval_dtor(ekeys);
                array_init(ekeys);
                for (i=0; i<nkeys; i++) {
                        eks[i][eksl[i]] = '\0';
-                       add_next_index_stringl(ekeys, eks[i], eksl[i]);
+                       add_next_index_stringl(ekeys, (const char*)eks[i], eksl[i]);
                        efree(eks[i]);
                        eks[i] = NULL;
                }
@@ -4921,7 +4879,7 @@ PHP_FUNCTION(openssl_seal)
 
 clean_exit:
        for (i=0; i<nkeys; i++) {
-               if (key_resources[i] == -1) {
+               if (key_resources[i] == NULL) {
                        EVP_PKEY_free(pkeys[i]);
                }
                if (eks[i]) { 
@@ -4939,11 +4897,11 @@ clean_exit:
    Opens data */
 PHP_FUNCTION(openssl_open)
 {
-       zval **privkey, *opendata;
+       zval *privkey, *opendata;
        EVP_PKEY *pkey;
        int len1, len2;
        unsigned char *buf;
-       long keyresource = -1;
+       zend_resource *keyresource = NULL;
        EVP_CIPHER_CTX ctx;
        char * data;    int data_len;
        char * ekey;    int ekey_len;
@@ -4951,9 +4909,10 @@ PHP_FUNCTION(openssl_open)
        int method_len = 0;
        const EVP_CIPHER *cipher;
 
-       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szsZ|s", &data, &data_len, &opendata, &ekey, &ekey_len, &privkey, &method, &method_len) == FAILURE) {
+       if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szsz|s", &data, &data_len, &opendata, &ekey, &ekey_len, &privkey, &method, &method_len) == FAILURE) {
                return;
        }
+       ZVAL_DEREF(opendata);
 
        pkey = php_openssl_evp_from_zval(privkey, 0, "", 0, &keyresource TSRMLS_CC);
        if (pkey == NULL) {
@@ -4980,14 +4939,15 @@ PHP_FUNCTION(openssl_open)
                } else {
                        zval_dtor(opendata);
                        buf[len1 + len2] = '\0';
-                       ZVAL_STRINGL(opendata, erealloc(buf, len1 + len2 + 1), len1 + len2, 0);
+                       ZVAL_STR(opendata, STR_INIT((char*)buf, len1 + len2, 0));
+                       efree(buf);
                        RETVAL_TRUE;
                }
        } else {
                efree(buf);
                RETVAL_FALSE;
        }
-       if (keyresource == -1) {
+       if (keyresource == NULL) {
                EVP_PKEY_free(pkey);
        }
        EVP_CIPHER_CTX_cleanup(&ctx);
@@ -5069,14 +5029,18 @@ PHP_FUNCTION(openssl_digest)
        if (EVP_DigestFinal (&md_ctx, (unsigned char *)sigbuf, (unsigned int *)&siglen)) {
                if (raw_output) {
                        sigbuf[siglen] = '\0';
-                       RETVAL_STRINGL((char *)sigbuf, siglen, 0);
+                       // TODO: avoid reallocation ???
+                       RETVAL_STRINGL((char *)sigbuf, siglen);
+                       efree(sigbuf);
                } else {
                        int digest_str_len = siglen * 2;
                        char *digest_str = emalloc(digest_str_len + 1);
 
                        make_digest_ex(digest_str, sigbuf, siglen);
                        efree(sigbuf);
-                       RETVAL_STRINGL(digest_str, digest_str_len, 0);
+                       // TODO: avid reallocation ???
+                       RETVAL_STRINGL(digest_str, digest_str_len);
+                       efree(digest_str);
                }
        } else {
                efree(sigbuf);
@@ -5175,14 +5139,15 @@ PHP_FUNCTION(openssl_encrypt)
                outlen += i;
                if (options & OPENSSL_RAW_DATA) {
                        outbuf[outlen] = '\0';
-                       RETVAL_STRINGL((char *)outbuf, outlen, 0);
+                       // TODO: avoid reallocation ???
+                       RETVAL_STRINGL((char *)outbuf, outlen);
+                       efree(outbuf);
                } else {
-                       int base64_str_len;
-                       char *base64_str;
+                       zend_string *base64_str;
 
-                       base64_str = (char*)php_base64_encode(outbuf, outlen, &base64_str_len);
+                       base64_str = php_base64_encode(outbuf, outlen);
                        efree(outbuf);
-                       RETVAL_STRINGL(base64_str, base64_str_len, 0);
+                       RETVAL_STR(base64_str);
                }
        } else {
                efree(outbuf);
@@ -5209,8 +5174,7 @@ PHP_FUNCTION(openssl_decrypt)
        EVP_CIPHER_CTX cipher_ctx;
        int i, outlen, keylen;
        unsigned char *outbuf, *key;
-       int base64_str_len;
-       char *base64_str = NULL;
+       zend_string *base64_str = NULL;
        zend_bool free_iv;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|ls", &data, &data_len, &method, &method_len, &password, &password_len, &options, &iv, &iv_len) == FAILURE) {
@@ -5229,13 +5193,13 @@ PHP_FUNCTION(openssl_decrypt)
        }
 
        if (!(options & OPENSSL_RAW_DATA)) {
-               base64_str = (char*)php_base64_decode((unsigned char*)data, data_len, &base64_str_len);
+               base64_str = php_base64_decode((unsigned char*)data, data_len);
                if (!base64_str) {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to base64 decode the input");
                        RETURN_FALSE;
                }
-               data_len = base64_str_len;
-               data = base64_str;
+               data_len = base64_str->len;
+               data = base64_str->val;
        }
 
        keylen = EVP_CIPHER_key_length(cipher_type);
@@ -5265,7 +5229,9 @@ PHP_FUNCTION(openssl_decrypt)
        if (EVP_DecryptFinal(&cipher_ctx, (unsigned char *)outbuf + i, &i)) {
                outlen += i;
                outbuf[outlen] = '\0';
-               RETVAL_STRINGL((char *)outbuf, outlen, 0);
+               // TODO: avoid reallocation ???
+               RETVAL_STRINGL((char *)outbuf, outlen);
+               efree(outbuf);
        } else {
                efree(outbuf);
                RETVAL_FALSE;
@@ -5277,7 +5243,7 @@ PHP_FUNCTION(openssl_decrypt)
                efree(iv);
        }
        if (base64_str) {
-               efree(base64_str);
+               STR_RELEASE(base64_str);
        }
        EVP_CIPHER_CTX_cleanup(&cipher_ctx);
 }
@@ -5325,7 +5291,7 @@ PHP_FUNCTION(openssl_dh_compute_key)
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sr", &pub_str, &pub_len, &key) == FAILURE) {
                return;
        }
-       ZEND_FETCH_RESOURCE(pkey, EVP_PKEY *, &key, -1, "OpenSSL key", le_key);
+       ZEND_FETCH_RESOURCE(pkey, EVP_PKEY *, key, -1, "OpenSSL key", le_key);
        if (!pkey || EVP_PKEY_type(pkey->type) != EVP_PKEY_DH || !pkey->pkey.dh) {
                RETURN_FALSE;
        }
@@ -5337,7 +5303,9 @@ PHP_FUNCTION(openssl_dh_compute_key)
 
        if (len >= 0) {
                data[len] = 0;
-               RETVAL_STRINGL(data, len, 0);
+               // TODO: avoid reallocation ???
+               RETVAL_STRINGL(data, len);
+               efree(data);
        } else {
                efree(data);
                RETVAL_FALSE;
@@ -5359,6 +5327,7 @@ PHP_FUNCTION(openssl_random_pseudo_bytes)
        if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|z", &buffer_length, &zstrong_result_returned) == FAILURE) {
                return;
        }
+       ZVAL_DEREF(zstrong_result_returned);
 
        if (buffer_length <= 0) {
                RETURN_FALSE;
@@ -5392,7 +5361,9 @@ PHP_FUNCTION(openssl_random_pseudo_bytes)
 #endif
 
        buffer[buffer_length] = 0;
-       RETVAL_STRINGL((char *)buffer, buffer_length, 0);
+       // TODO: avoid reallocation ???
+       RETVAL_STRINGL((char *)buffer, buffer_length);
+       efree(buffer);
 
        if (zstrong_result_returned) {
                ZVAL_BOOL(zstrong_result_returned, strong_result);
index fbfb0774dcf65b73bbc498cba4c39ad74ad998bf..587de6c52598196818568d040ad5aa80a47d836e 100644 (file)
@@ -67,9 +67,9 @@
 #define STREAM_CRYPTO_METHOD_TLSv1_2       (1<<5)
 
 /* Simplify ssl context option retrieval */
-#define GET_VER_OPT(name)               (stream->context && SUCCESS == php_stream_context_get_option(stream->context, "ssl", name, &val))
-#define GET_VER_OPT_STRING(name, str)   if (GET_VER_OPT(name)) { convert_to_string_ex(val); str = Z_STRVAL_PP(val); }
-#define GET_VER_OPT_LONG(name, num)     if (GET_VER_OPT(name)) { convert_to_long_ex(val); num = Z_LVAL_PP(val); }
+#define GET_VER_OPT(name)               (stream->context && (val = php_stream_context_get_option(stream->context, "ssl", name)) != NULL)
+#define GET_VER_OPT_STRING(name, str)   if (GET_VER_OPT(name)) { convert_to_string_ex(val); str = Z_STRVAL_P(val); }
+#define GET_VER_OPT_LONG(name, num)     if (GET_VER_OPT(name)) { convert_to_long_ex(val); num = Z_LVAL_P(val); }
 
 /* Used for peer verification in windows */
 #define PHP_X509_NAME_ENTRY_TO_UTF8(ne, i, out) ASN1_STRING_to_UTF8(&out, X509_NAME_ENTRY_get_data(X509_NAME_get_entry(ne, i)))
@@ -121,24 +121,20 @@ typedef struct _php_openssl_netstream_data_t {
  * in an error condition arising from a network connection problem */
 static int is_http_stream_talking_to_iis(php_stream *stream TSRMLS_DC) /* {{{ */
 {
-       if (stream->wrapperdata && stream->wrapper && strcasecmp(stream->wrapper->wops->label, "HTTP") == 0) {
+       if (Z_TYPE(stream->wrapperdata) == IS_ARRAY && stream->wrapper && strcasecmp(stream->wrapper->wops->label, "HTTP") == 0) {
                /* the wrapperdata is an array zval containing the headers */
-               zval **tmp;
+               zval *tmp;
 
 #define SERVER_MICROSOFT_IIS   "Server: Microsoft-IIS"
 #define SERVER_GOOGLE "Server: GFE/"
                
-               zend_hash_internal_pointer_reset(Z_ARRVAL_P(stream->wrapperdata));
-               while (SUCCESS == zend_hash_get_current_data(Z_ARRVAL_P(stream->wrapperdata), (void**)&tmp)) {
-
-                       if (strncasecmp(Z_STRVAL_PP(tmp), SERVER_MICROSOFT_IIS, sizeof(SERVER_MICROSOFT_IIS)-1) == 0) {
+               ZEND_HASH_FOREACH_VAL(Z_ARRVAL(stream->wrapperdata), tmp) {
+                       if (strncasecmp(Z_STRVAL_P(tmp), SERVER_MICROSOFT_IIS, sizeof(SERVER_MICROSOFT_IIS)-1) == 0) {
                                return 1;
-                       } else if (strncasecmp(Z_STRVAL_PP(tmp), SERVER_GOOGLE, sizeof(SERVER_GOOGLE)-1) == 0) {
+                       } else if (strncasecmp(Z_STRVAL_P(tmp), SERVER_GOOGLE, sizeof(SERVER_GOOGLE)-1) == 0) {
                                return 1;
                        }
-                       
-                       zend_hash_move_forward(Z_ARRVAL_P(stream->wrapperdata));
-               }
+               } ZEND_HASH_FOREACH_END();
        }
        return 0;
 }
@@ -203,7 +199,7 @@ static int handle_ssl_error(php_stream *stream, int nr_bytes, zend_bool is_init
                                        do {
                                                /* NULL is automatically added */
                                                ERR_error_string_n(ecode, esbuf, sizeof(esbuf));
-                                               if (ebuf.c) {
+                                               if (ebuf.s) {
                                                        smart_str_appendc(&ebuf, '\n');
                                                }
                                                smart_str_appends(&ebuf, esbuf);
@@ -214,9 +210,9 @@ static int handle_ssl_error(php_stream *stream, int nr_bytes, zend_bool is_init
                                        php_error_docref(NULL TSRMLS_CC, E_WARNING,
                                                        "SSL operation failed with code %d. %s%s",
                                                        err,
-                                                       ebuf.c ? "OpenSSL Error messages:\n" : "",
-                                                       ebuf.c ? ebuf.c : "");
-                                       if (ebuf.c) {
+                                                       ebuf.s ? "OpenSSL Error messages:\n" : "",
+                                                       ebuf.s ? ebuf.s->val : "");
+                                       if (ebuf.s) {
                                                smart_str_free(&ebuf);
                                        }
                        }
@@ -233,7 +229,7 @@ static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) /* {{{ */
        php_stream *stream;
        SSL *ssl;
        int err, depth, ret;
-       zval **val;
+       zval *val;
        unsigned long allowed_depth = OPENSSL_DEFAULT_STREAM_VERIFY_DEPTH;
 
        TSRMLS_FETCH();
@@ -251,7 +247,7 @@ static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) /* {{{ */
        /* if allow_self_signed is set, make sure that verification succeeds */
        if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT &&
                GET_VER_OPT("allow_self_signed") &&
-               zend_is_true(*val TSRMLS_CC)
+               zend_is_true(val TSRMLS_CC)
        ) {
                ret = 1;
        }
@@ -363,7 +359,7 @@ static zend_bool matches_common_name(X509 *peer, const char *subject_name TSRMLS
 
 static int apply_peer_verification_policy(SSL *ssl, X509 *peer, php_stream *stream TSRMLS_DC) /* {{{ */
 {
-       zval **val = NULL;
+       zval *val = NULL;
        char *peer_name = NULL;
        int err,
                must_verify_peer,
@@ -374,15 +370,15 @@ static int apply_peer_verification_policy(SSL *ssl, X509 *peer, php_stream *stre
        php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
 
        must_verify_peer = GET_VER_OPT("verify_peer")
-               ? zend_is_true(*val TSRMLS_CC)
+               ? zend_is_true(val TSRMLS_CC)
                : sslsock->is_client;
 
        has_cnmatch_ctx_opt = GET_VER_OPT("CN_match");
        must_verify_peer_name = (has_cnmatch_ctx_opt || GET_VER_OPT("verify_peer_name"))
-               ? zend_is_true(*val TSRMLS_CC)
+               ? zend_is_true(val TSRMLS_CC)
                : sslsock->is_client;
 
-       must_verify_fingerprint = (GET_VER_OPT("peer_fingerprint") && zend_is_true(*val TSRMLS_CC));
+       must_verify_fingerprint = (GET_VER_OPT("peer_fingerprint") && zend_is_true(val TSRMLS_CC));
 
        if ((must_verify_peer || must_verify_peer_name || must_verify_fingerprint) && peer == NULL) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not get peer certificate");
@@ -397,7 +393,7 @@ static int apply_peer_verification_policy(SSL *ssl, X509 *peer, php_stream *stre
                                /* fine */
                                break;
                        case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
-                               if (GET_VER_OPT("allow_self_signed") && zend_is_true(*val TSRMLS_CC)) {
+                               if (GET_VER_OPT("allow_self_signed") && zend_is_true(val TSRMLS_CC)) {
                                        /* allowed */
                                        break;
                                }
@@ -414,8 +410,8 @@ static int apply_peer_verification_policy(SSL *ssl, X509 *peer, php_stream *stre
 
        /* If a peer_fingerprint match is required this trumps peer and peer_name verification */
        if (must_verify_fingerprint) {
-               if (Z_TYPE_PP(val) == IS_STRING || Z_TYPE_PP(val) == IS_ARRAY) {
-                       if (!php_x509_fingerprint_match(peer, *val TSRMLS_CC)) {
+               if (Z_TYPE_P(val) == IS_STRING || Z_TYPE_P(val) == IS_ARRAY) {
+                       if (!php_x509_fingerprint_match(peer, val TSRMLS_CC)) {
                                php_error_docref(NULL TSRMLS_CC, E_WARNING,
                                        "Peer fingerprint doesn't match"
                                );
@@ -463,16 +459,16 @@ static int apply_peer_verification_policy(SSL *ssl, X509 *peer, php_stream *stre
 static int passwd_callback(char *buf, int num, int verify, void *data) /* {{{ */
 {
        php_stream *stream = (php_stream *)data;
-       zval **val = NULL;
+       zval *val = NULL;
        char *passphrase = NULL;
        /* TODO: could expand this to make a callback into PHP user-space */
 
        GET_VER_OPT_STRING("passphrase", passphrase);
 
        if (passphrase) {
-               if (Z_STRLEN_PP(val) < num - 1) {
-                       memcpy(buf, Z_STRVAL_PP(val), Z_STRLEN_PP(val)+1);
-                       return Z_STRLEN_PP(val);
+               if (Z_STRLEN_P(val) < num - 1) {
+                       memcpy(buf, Z_STRVAL_P(val), Z_STRLEN_P(val)+1);
+                       return Z_STRLEN_P(val);
                }
        }
        return 0;
@@ -726,7 +722,7 @@ static long load_stream_cafile(X509_STORE *cert_store, const char *cafile TSRMLS
 
 static int enable_peer_verification(SSL_CTX *ctx, php_stream *stream TSRMLS_DC) /* {{{ */
 {
-       zval **val = NULL;
+       zval *val = NULL;
        char *cafile = NULL;
        char *capath = NULL;
 
@@ -734,12 +730,12 @@ static int enable_peer_verification(SSL_CTX *ctx, php_stream *stream TSRMLS_DC)
        GET_VER_OPT_STRING("capath", capath);
 
        if (!cafile) {
-               cafile = zend_ini_string("openssl.cafile", sizeof("openssl.cafile"), 0);
+               cafile = zend_ini_string("openssl.cafile", sizeof("openssl.cafile")-1, 0);
                cafile = strlen(cafile) ? cafile : NULL;
        }
 
        if (!capath) {
-               capath = zend_ini_string("openssl.capath", sizeof("openssl.capath"), 0);
+               capath = zend_ini_string("openssl.capath", sizeof("openssl.capath")-1, 0);
                capath = strlen(capath) ? capath : NULL;
        }
 
@@ -779,7 +775,7 @@ static void disable_peer_verification(SSL_CTX *ctx, php_stream *stream TSRMLS_DC
 
 static int set_local_cert(SSL_CTX *ctx, php_stream *stream TSRMLS_DC) /* {{{ */
 {
-       zval **val = NULL;
+       zval *val = NULL;
        char *certfile = NULL;
 
        GET_VER_OPT_STRING("local_cert", certfile);
@@ -936,37 +932,32 @@ static void limit_handshake_reneg(const SSL *ssl) /* {{{ */
 
        /* The token level exceeds our allowed limit */
        if (sslsock->reneg->tokens > sslsock->reneg->limit) {
-               zval **val;
+               zval *val;
 
                TSRMLS_FETCH();
 
                sslsock->reneg->should_close = 1;
 
-               if (stream->context && SUCCESS == php_stream_context_get_option(stream->context,
-                               "ssl", "reneg_limit_callback", &val)
+               if (stream->context && (val = php_stream_context_get_option(stream->context,
+                               "ssl", "reneg_limit_callback")) != NULL
                ) {
-                       zval *param, **params[1], *retval;
+                       zval param, retval;
 
-                       MAKE_STD_ZVAL(param);
-                       php_stream_to_zval(stream, param);
-                       params[0] = &param;
+                       php_stream_to_zval(stream, &param);
 
                        /* Closing the stream inside this callback would segfault! */
                        stream->flags |= PHP_STREAM_FLAG_NO_FCLOSE;
-                       if (FAILURE == call_user_function_ex(EG(function_table), NULL, *val, &retval, 1, params, 0, NULL TSRMLS_CC)) {
+                       if (FAILURE == call_user_function_ex(EG(function_table), NULL, val, &retval, 1, &param, 0, NULL TSRMLS_CC)) {
                                php_error(E_WARNING, "SSL: failed invoking reneg limit notification callback");
                        }
                        stream->flags ^= PHP_STREAM_FLAG_NO_FCLOSE;
 
                        /* If the reneg_limit_callback returned true don't auto-close */
-                       if (retval != NULL && Z_TYPE_P(retval) == IS_BOOL && Z_BVAL_P(retval) == 1) {
+                       if (Z_TYPE(retval) == IS_TRUE) {
                                sslsock->reneg->should_close = 0;
                        }
 
-                       FREE_ZVAL(param);
-                       if (retval != NULL) {
-                               zval_ptr_dtor(&retval);
-                       }
+                       zval_ptr_dtor(&retval);
                } else {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING,
                                "SSL: client-initiated handshake rate limit exceeded by peer");
@@ -986,16 +977,16 @@ static void info_callback(const SSL *ssl, int where, int ret) /* {{{ */
 
 static void init_server_reneg_limit(php_stream *stream, php_openssl_netstream_data_t *sslsock) /* {{{ */
 {
-       zval **val;
+       zval *val;
        long limit = OPENSSL_DEFAULT_RENEG_LIMIT;
        long window = OPENSSL_DEFAULT_RENEG_WINDOW;
 
        if (stream->context &&
-               SUCCESS == php_stream_context_get_option(stream->context,
-                               "ssl", "reneg_limit", &val)
+               NULL != (val = php_stream_context_get_option(stream->context,
+                               "ssl", "reneg_limit"))
        ) {
-               convert_to_long(*val);
-               limit = Z_LVAL_PP(val);
+               convert_to_long(val);
+               limit = Z_LVAL_P(val);
        }
 
        /* No renegotiation rate-limiting */
@@ -1004,11 +995,11 @@ static void init_server_reneg_limit(php_stream *stream, php_openssl_netstream_da
        }
 
        if (stream->context &&
-               SUCCESS == php_stream_context_get_option(stream->context,
-                               "ssl", "reneg_window", &val)
+               NULL != (val = php_stream_context_get_option(stream->context,
+                               "ssl", "reneg_window"))
        ) {
-               convert_to_long(*val);
-               window = Z_LVAL_PP(val);
+               convert_to_long(val);
+               window = Z_LVAL_P(val);
        }
 
        sslsock->reneg = (void*)pemalloc(sizeof(php_openssl_handshake_bucket_t),
@@ -1027,12 +1018,12 @@ static void init_server_reneg_limit(php_stream *stream, php_openssl_netstream_da
 
 static int set_server_rsa_key(php_stream *stream, SSL_CTX *ctx TSRMLS_DC) /* {{{ */
 {
-       zval *val;
+       zval *val;
        int rsa_key_size;
        RSA* rsa;
 
-       if (php_stream_context_get_option(stream->context, "ssl", "rsa_key_size", &val) == SUCCESS) {
-               rsa_key_size = (int) Z_LVAL_PP(val);
+       if ((val = php_stream_context_get_option(stream->context, "ssl", "rsa_key_size")) != NULL) {
+               rsa_key_size = (int) Z_LVAL_P(val);
                if ((rsa_key_size != 1) && (rsa_key_size & (rsa_key_size - 1))) {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "RSA key size requires a power of 2: %d", rsa_key_size);
                        rsa_key_size = 2048;
@@ -1090,14 +1081,14 @@ static int set_server_dh_param(SSL_CTX *ctx, char *dh_path TSRMLS_DC) /* {{{ */
 #ifdef HAVE_ECDH
 static int set_server_ecdh_curve(php_stream *stream, SSL_CTX *ctx TSRMLS_DC) /* {{{ */
 {
-       zval **val;
+       zval *val;
        int curve_nid;
        char *curve_str;
        EC_KEY *ecdh;
 
-       if (php_stream_context_get_option(stream->context, "ssl", "ecdh_curve", &val) == SUCCESS) {
+       if ((val = php_stream_context_get_option(stream->context, "ssl", "ecdh_curve")) != NULL) {
                convert_to_string_ex(val);
-               curve_str = Z_STRVAL_PP(val);
+               curve_str = Z_STRVAL_P(val);
                curve_nid = OBJ_sn2nid(curve_str);
                if (curve_nid == NID_undef) {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING, "Invalid ECDH curve: %s", curve_str);
@@ -1125,7 +1116,7 @@ static int set_server_ecdh_curve(php_stream *stream, SSL_CTX *ctx TSRMLS_DC) /*
 
 static int set_server_specific_opts(php_stream *stream, SSL_CTX *ctx TSRMLS_DC) /* {{{ */
 {
-       zval **val;
+       zval *val;
        long ssl_ctx_options = SSL_CTX_get_options(ctx);
 
 #ifdef HAVE_ECDH
@@ -1141,9 +1132,9 @@ static int set_server_specific_opts(php_stream *stream, SSL_CTX *ctx TSRMLS_DC)
        }
 #endif
 
-       if (php_stream_context_get_option(stream->context, "ssl", "dh_param", &val) == SUCCESS) {
+       if ((val = php_stream_context_get_option(stream->context, "ssl", "dh_param")) != NULL) {
                convert_to_string_ex(val);
-               if (FAILURE == set_server_dh_param(ctx,  Z_STRVAL_PP(val) TSRMLS_CC)) {
+               if (FAILURE == set_server_dh_param(ctx,  Z_STRVAL_P(val) TSRMLS_CC)) {
                        return FAILURE;
                }
        }
@@ -1152,23 +1143,23 @@ static int set_server_specific_opts(php_stream *stream, SSL_CTX *ctx TSRMLS_DC)
                return FAILURE;
        }
 
-       if (SUCCESS == php_stream_context_get_option(
-                               stream->context, "ssl", "honor_cipher_order", &val) &&
-                       zend_is_true(*val TSRMLS_CC)
+       if (NULL != (val = php_stream_context_get_option(
+                               stream->context, "ssl", "honor_cipher_order")) &&
+                       zend_is_true(val TSRMLS_CC)
        ) {
                ssl_ctx_options |= SSL_OP_CIPHER_SERVER_PREFERENCE;
        }
 
-       if (SUCCESS == php_stream_context_get_option(
-                               stream->context, "ssl", "single_dh_use", &val) &&
-                       zend_is_true(*val TSRMLS_CC)
+       if (NULL != (val = php_stream_context_get_option(
+                               stream->context, "ssl", "single_dh_use")) &&
+                       zend_is_true(val TSRMLS_CC)
        ) {
                ssl_ctx_options |= SSL_OP_SINGLE_DH_USE;
        }
 
-       if (SUCCESS == php_stream_context_get_option(
-                               stream->context, "ssl", "single_ecdh_use", &val) &&
-                       zend_is_true(*val TSRMLS_CC)
+       if (NULL != (val = php_stream_context_get_option(
+                               stream->context, "ssl", "single_ecdh_use")) &&
+                       zend_is_true(val TSRMLS_CC)
        ) {
                ssl_ctx_options |= SSL_OP_SINGLE_ECDH_USE;
        }
@@ -1213,19 +1204,16 @@ static int server_sni_callback(SSL *ssl_handle, int *al, void *arg) /* {{{ */
 
 static int enable_server_sni(php_stream *stream, php_openssl_netstream_data_t *sslsock TSRMLS_DC)
 {
-       zval **val;
-       zval **current;
-       char *key;
-       uint key_len;
+       zval *val;
+       zval *current;
+       zend_string *key;
        ulong key_index;
-       int key_type;
-       HashPosition pos;
        int i = 0;
        char resolved_path_buff[MAXPATHLEN];
        SSL_CTX *ctx;
 
        /* If the stream ctx disables SNI we're finished here */
-       if (GET_VER_OPT("SNI_enabled") && !zend_is_true(*val TSRMLS_CC)) {
+       if (GET_VER_OPT("SNI_enabled") && !zend_is_true(val TSRMLS_CC)) {
                return SUCCESS;
        }
 
@@ -1234,14 +1222,14 @@ static int enable_server_sni(php_stream *stream, php_openssl_netstream_data_t *s
                return SUCCESS;
        }
 
-       if (Z_TYPE_PP(val) != IS_ARRAY) {
+       if (Z_TYPE_P(val) != IS_ARRAY) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING,
                        "SNI_server_certs requires an array mapping host names to cert paths"
                );
                return FAILURE;
        }
 
-       sslsock->sni_cert_count = zend_hash_num_elements(Z_ARRVAL_PP(val));
+       sslsock->sni_cert_count = zend_hash_num_elements(Z_ARRVAL_P(val));
        if (sslsock->sni_cert_count == 0) {
                php_error_docref(NULL TSRMLS_CC, E_WARNING,
                        "SNI_server_certs host cert array must not be empty"
@@ -1253,19 +1241,15 @@ static int enable_server_sni(php_stream *stream, php_openssl_netstream_data_t *s
                sizeof(php_openssl_sni_cert_t), 0, php_stream_is_persistent(stream)
        );
 
-       for (zend_hash_internal_pointer_reset_ex(Z_ARRVAL_PP(val), &pos);
-               zend_hash_get_current_data_ex(Z_ARRVAL_PP(val), (void **)&current, &pos) == SUCCESS;
-               zend_hash_move_forward_ex(Z_ARRVAL_PP(val), &pos)
-       ) {
-               key_type = zend_hash_get_current_key_ex(Z_ARRVAL_PP(val), &key, &key_len, &key_index, 0, &pos);
-               if (key_type != HASH_KEY_IS_STRING) {
+       ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(val), key_index,key, current) {
+               if (!key) {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING,
                                "SNI_server_certs array requires string host name keys"
                        );
                        return FAILURE;
                }
 
-               if (VCWD_REALPATH(Z_STRVAL_PP(current), resolved_path_buff)) {
+               if (VCWD_REALPATH(Z_STRVAL_P(current), resolved_path_buff)) {
                        /* The hello method is not inherited by SSL structs when assigning a new context
                         * inside the SNI callback, so the just use SSLv23 */
                        ctx = SSL_CTX_new(SSLv23_server_method());
@@ -1287,18 +1271,18 @@ static int enable_server_sni(php_stream *stream, php_openssl_netstream_data_t *s
                                SSL_CTX_free(ctx);
                                return FAILURE;
                        } else {
-                               sslsock->sni_certs[i].name = pestrdup(key, php_stream_is_persistent(stream));
+                               sslsock->sni_certs[i].name = pestrdup(key->val, php_stream_is_persistent(stream));
                                sslsock->sni_certs[i].ctx = ctx;
                                ++i;
                        }
                } else {
                        php_error_docref(NULL TSRMLS_CC, E_WARNING,
                                "failed setting local cert chain file `%s'; file not found",
-                               Z_STRVAL_PP(current)
+                               Z_STRVAL_P(current)
                        );
                        return FAILURE;
                }
-       }
+       } ZEND_HASH_FOREACH_END();
 
        SSL_CTX_set_tlsext_servername_callback(sslsock->ctx, server_sni_callback);
 
@@ -1307,11 +1291,11 @@ static int enable_server_sni(php_stream *stream, php_openssl_netstream_data_t *s
 
 static void enable_client_sni(php_stream *stream, php_openssl_netstream_data_t *sslsock TSRMLS_DC) /* {{{ */
 {
-       zval **val;
+       zval *val;
        char *sni_server_name;
 
        /* If SNI is explicitly disabled we're finished here */
-       if (GET_VER_OPT("SNI_enabled") && !zend_is_true(*val TSRMLS_CC)) {
+       if (GET_VER_OPT("SNI_enabled") && !zend_is_true(val TSRMLS_CC)) {
                return;
        }
 
@@ -1340,7 +1324,7 @@ int php_openssl_setup_crypto(php_stream *stream,
        long ssl_ctx_options;
        long method_flags;
        char *cipherlist = NULL;
-       zval **val;
+       zval *val;
 
        if (sslsock->ssl_handle) {
                if (sslsock->s.is_blocked) {
@@ -1386,7 +1370,7 @@ int php_openssl_setup_crypto(php_stream *stream,
        }
 
 #if OPENSSL_VERSION_NUMBER >= 0x0090806fL
-       if (GET_VER_OPT("no_ticket") && zend_is_true(*val TSRMLS_CC)) {
+       if (GET_VER_OPT("no_ticket") && zend_is_true(val TSRMLS_CC)) {
                ssl_ctx_options |= SSL_OP_NO_TICKET;
        }
 #endif
@@ -1396,12 +1380,12 @@ int php_openssl_setup_crypto(php_stream *stream,
 #endif
 
 #if OPENSSL_VERSION_NUMBER >= 0x10000000L
-       if (!GET_VER_OPT("disable_compression") || zend_is_true(*val TSRMLS_CC)) {
+       if (!GET_VER_OPT("disable_compression") || zend_is_true(val TSRMLS_CC)) {
                ssl_ctx_options |= SSL_OP_NO_COMPRESSION;
        }
 #endif
 
-       if (GET_VER_OPT("verify_peer") && !zend_is_true(*val TSRMLS_CC)) {
+       if (GET_VER_OPT("verify_peer") && !zend_is_true(val TSRMLS_CC)) {
                disable_peer_verification(sslsock->ctx, stream TSRMLS_CC);
        } else if (FAILURE == enable_peer_verification(sslsock->ctx, stream TSRMLS_CC)) {
                return FAILURE;
@@ -1481,9 +1465,9 @@ int php_openssl_setup_crypto(php_stream *stream,
 }
 /* }}} */
 
-static zval *capture_session_meta(SSL *ssl_handle) /* {{{ */
+static zend_array *capture_session_meta(SSL *ssl_handle) /* {{{ */
 {
-       zval *meta_arr;
+       zval meta_arr;
        char *proto_str;
        long proto = SSL_version(ssl_handle);
        const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl_handle);
@@ -1499,61 +1483,55 @@ static zval *capture_session_meta(SSL *ssl_handle) /* {{{ */
                default: proto_str = "UNKNOWN";
        }
 
-       MAKE_STD_ZVAL(meta_arr);
-       array_init(meta_arr);
-       add_assoc_string(meta_arr, "protocol", proto_str, 1);
-       add_assoc_string(meta_arr, "cipher_name", (char *) SSL_CIPHER_get_name(cipher), 1);
-       add_assoc_long(meta_arr, "cipher_bits", SSL_CIPHER_get_bits(cipher, NULL));
-       add_assoc_string(meta_arr, "cipher_version", SSL_CIPHER_get_version(cipher), 1);
+       array_init(&meta_arr);
+       add_assoc_string(&meta_arr, "protocol", proto_str);
+       add_assoc_string(&meta_arr, "cipher_name", (char *) SSL_CIPHER_get_name(cipher));
+       add_assoc_long(&meta_arr, "cipher_bits", SSL_CIPHER_get_bits(cipher, NULL));
+       add_assoc_string(&meta_arr, "cipher_version", SSL_CIPHER_get_version(cipher));
 
-       return meta_arr;
+       return Z_ARR(meta_arr);
 }
 /* }}} */
 
 static int capture_peer_certs(php_stream *stream, php_openssl_netstream_data_t *sslsock, X509 *peer_cert TSRMLS_DC) /* {{{ */
 {
-       zval **val, *zcert;
+       zval *val, zcert;
        int cert_captured = 0;
 
-       if (SUCCESS == php_stream_context_get_option(stream->context,
-                       "ssl", "capture_peer_cert", &val) &&
-               zend_is_true(*val TSRMLS_CC)
+       if (NULL != (val = php_stream_context_get_option(stream->context,
+                       "ssl", "capture_peer_cert")) &&
+               zend_is_true(val TSRMLS_CC)
        ) {
-               MAKE_STD_ZVAL(zcert);
-               ZVAL_RESOURCE(zcert, zend_list_insert(peer_cert, php_openssl_get_x509_list_id() TSRMLS_CC));
-               php_stream_context_set_option(stream->context, "ssl", "peer_certificate", zcert);
+               zend_register_resource(&zcert, peer_cert, php_openssl_get_x509_list_id() TSRMLS_CC);
+               php_stream_context_set_option(stream->context, "ssl", "peer_certificate", &zcert);
                cert_captured = 1;
-               FREE_ZVAL(zcert);
        }
 
-       if (SUCCESS == php_stream_context_get_option(stream->context,
-                       "ssl", "capture_peer_cert_chain", &val) &&
-               zend_is_true(*val TSRMLS_CC)
+       if (NULL != (val = php_stream_context_get_option(stream->context,
+                       "ssl", "capture_peer_cert_chain")) &&
+               zend_is_true(val TSRMLS_CC)
        ) {
-               zval *arr;
+               zval arr;
                STACK_OF(X509) *chain;
 
-               MAKE_STD_ZVAL(arr);
                chain = SSL_get_peer_cert_chain(sslsock->ssl_handle);
 
                if (chain && sk_X509_num(chain) > 0) {
                        int i;
-                       array_init(arr);
+                       array_init(&arr);
 
                        for (i = 0; i < sk_X509_num(chain); i++) {
                                X509 *mycert = X509_dup(sk_X509_value(chain, i));
-                               MAKE_STD_ZVAL(zcert);
-                               ZVAL_RESOURCE(zcert, zend_list_insert(mycert, php_openssl_get_x509_list_id() TSRMLS_CC));
-                               add_next_index_zval(arr, zcert);
+                               zend_register_resource(&zcert, mycert, php_openssl_get_x509_list_id() TSRMLS_CC);
+                               add_next_index_zval(&arr, &zcert);
                        }
 
                } else {
-                       ZVAL_NULL(arr);
+                       ZVAL_NULL(&arr);
                }
 
-               php_stream_context_set_option(stream->context, "ssl", "peer_certificate_chain", arr);
-               zval_dtor(arr);
-               efree(arr);
+               php_stream_context_set_option(stream->context, "ssl", "peer_certificate_chain", &arr);
+               zval_dtor(&arr);
        }
 
        return cert_captured;
@@ -1671,16 +1649,16 @@ static int php_openssl_enable_crypto(php_stream *stream,
                                sslsock->ssl_active = 1;
 
                                if (stream->context) {
-                                       zval **val;
+                                       zval *val;
 
-                                       if (SUCCESS == php_stream_context_get_option(stream->context,
-                                                       "ssl", "capture_session_meta", &val) &&
-                                               zend_is_true(*val TSRMLS_CC)
+                                       if (NULL != (val = php_stream_context_get_option(stream->context,
+                                                       "ssl", "capture_session_meta")) &&
+                                               zend_is_true(val TSRMLS_CC)
                                        ) {
-                                               zval *meta_arr = capture_session_meta(sslsock->ssl_handle);
-                                               php_stream_context_set_option(stream->context, "ssl", "session_meta", meta_arr);
-                                               zval_dtor(meta_arr);
-                                               efree(meta_arr);
+                                               zval meta_arr;
+                                               ZVAL_ARR(&meta_arr, capture_session_meta(sslsock->ssl_handle));
+                                               php_stream_context_set_option(stream->context, "ssl", "session_meta", &meta_arr);
+                                               zval_dtor(&meta_arr);
                                        }
                                }
                        }
@@ -1902,7 +1880,7 @@ static inline int php_openssl_tcp_sockop_accept(php_stream *stream, php_openssl_
                        if (xparam->outputs.client) {
                                xparam->outputs.client->context = stream->context;
                                if (stream->context) {
-                                       zend_list_addref(stream->context->rsrc_id);
+                                       stream->context->res->gc.refcount++;
                                }
                        }
                }
@@ -2098,11 +2076,11 @@ php_stream_ops php_openssl_socket_ops = {
 
 static long get_crypto_method(php_stream_context *ctx, long crypto_method)
 {
-       zval **val;
+       zval *val;
 
-       if (ctx && php_stream_context_get_option(ctx, "ssl", "crypto_method", &val) == SUCCESS) {
+       if (ctx && (val = php_stream_context_get_option(ctx, "ssl", "crypto_method")) != NULL) {
                convert_to_long_ex(val);
-               crypto_method = (long)Z_LVAL_PP(val);
+               crypto_method = (long)Z_LVAL_P(val);
                crypto_method |= STREAM_CRYPTO_IS_CLIENT;
        }