From 424aebbf3643b3fc1b1074ecddf2104cb9465f02 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 7 May 2014 01:09:42 +0400 Subject: [PATCH] Added support for ext/openssl --- ext/openssl/openssl.c | 923 ++++++++++++++++++++---------------------- ext/openssl/xp_ssl.c | 260 ++++++------ 2 files changed, 566 insertions(+), 617 deletions(-) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 42f8196aa0..94056ce04b 100755 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -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, ¬ext) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zp|b", &zcert, &filename, &filename_len, ¬ext) == 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, ¬ext) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz|b", &zcert, &zout, ¬ext) == 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 **)¤t, &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, ¬ext) == 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, ¬ext) == 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; ilen; + 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); diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index fbfb0774dc..587de6c525 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -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] = ¶m; + php_stream_to_zval(stream, ¶m); /* 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, ¶m, 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 **)¤t, &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; } -- 2.40.0