diff options
Diffstat (limited to 'ext/openssl/openssl.c')
-rwxr-xr-x[-rw-r--r--] | ext/openssl/openssl.c | 1644 |
1 files changed, 768 insertions, 876 deletions
diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 4aac4e3137..c4b155b478 100644..100755 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -1,8 +1,8 @@ /* +----------------------------------------------------------------------+ - | PHP Version 5 | + | PHP Version 7 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2013 The PHP Group | + | Copyright (c) 1997-2014 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -27,6 +27,7 @@ #endif #include "php.h" +#include "php_ini.h" #include "php_openssl.h" /* PHP Includes */ @@ -77,6 +78,10 @@ #endif #define DEBUG_SMIME 0 +#if !defined(OPENSSL_NO_EC) && defined(EVP_PKEY_EC) +#define HAVE_EVP_PKEY_EC 1 +#endif + /* FIXME: Use the openssl constants instead of * enum. It is now impossible to match real values * against php constants. Also sorry to break the @@ -87,7 +92,7 @@ enum php_openssl_key_type { OPENSSL_KEYTYPE_DSA, OPENSSL_KEYTYPE_DH, OPENSSL_KEYTYPE_DEFAULT = OPENSSL_KEYTYPE_RSA, -#ifdef EVP_PKEY_EC +#ifdef HAVE_EVP_PKEY_EC OPENSSL_KEYTYPE_EC = OPENSSL_KEYTYPE_DH +1 #endif }; @@ -129,6 +134,12 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_x509_export, 0, 0, 2) ZEND_ARG_INFO(0, notext) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_x509_fingerprint, 0, 0, 1) + ZEND_ARG_INFO(0, x509) + ZEND_ARG_INFO(0, method) + ZEND_ARG_INFO(0, raw_output) +ZEND_END_ARG_INFO() + ZEND_BEGIN_ARG_INFO(arginfo_openssl_x509_check_private_key, 0) ZEND_ARG_INFO(0, cert) ZEND_ARG_INFO(0, key) @@ -412,11 +423,16 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_openssl_spki_export_challenge, 0) ZEND_ARG_INFO(0, spki) ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO(arginfo_openssl_get_cert_locations, 0) +ZEND_END_ARG_INFO() /* }}} */ /* {{{ openssl_functions[] */ const zend_function_entry openssl_functions[] = { + PHP_FE(openssl_get_cert_locations, arginfo_openssl_get_cert_locations) + /* spki functions */ PHP_FE(openssl_spki_new, arginfo_openssl_spki_new) PHP_FE(openssl_spki_verify, arginfo_openssl_spki_verify) @@ -443,6 +459,7 @@ const zend_function_entry openssl_functions[] = { PHP_FE(openssl_x509_checkpurpose, arginfo_openssl_x509_checkpurpose) PHP_FE(openssl_x509_check_private_key, arginfo_openssl_x509_check_private_key) PHP_FE(openssl_x509_export, arginfo_openssl_x509_export) + PHP_FE(openssl_x509_fingerprint, arginfo_openssl_x509_fingerprint) PHP_FE(openssl_x509_export_to_file, arginfo_openssl_x509_export_to_file) /* PKCS12 funcs */ @@ -525,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; @@ -534,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); @@ -558,6 +575,16 @@ inline static int php_openssl_open_base_dir_chk(char *filename TSRMLS_DC) } /* }}} */ +php_stream* php_openssl_get_stream_from_ssl_handle(const SSL *ssl) +{ + return (php_stream*)SSL_get_ex_data(ssl, ssl_stream_data_index); +} + +int php_openssl_get_ssl_stream_data_index() +{ + return ssl_stream_data_index; +} + /* openssl -> PHP "bridging" */ /* true global; readonly after module startup */ static char default_ssl_conf_filename[MAXPATHLEN]; @@ -588,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 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; @@ -608,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++) { @@ -638,31 +664,29 @@ 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, 1); - } 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), 1); - add_next_index_stringl(subentries, (char *)to_add, to_add_len, 1); - 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, zend_string_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, 1); + 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); } } /* }}} */ static void add_assoc_asn1_string(zval * val, char * key, ASN1_STRING * str) /* {{{ */ { - add_assoc_stringl(val, key, (char *)str->data, str->length, 1); + add_assoc_stringl(val, key, (char *)str->data, str->length); } /* }}} */ @@ -681,18 +705,33 @@ static time_t asn1_time_to_time_t(ASN1_UTCTIME * timestr TSRMLS_DC) /* {{{ */ char * thestr; long gmadjust = 0; - if (timestr->length < 13) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "extension author too lazy to parse %s correctly", timestr->data); + if (ASN1_STRING_type(timestr) != V_ASN1_UTCTIME && ASN1_STRING_type(timestr) != V_ASN1_GENERALIZEDTIME) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "illegal ASN1 data type for timestamp"); + return (time_t)-1; + } + + if (ASN1_STRING_length(timestr) != strlen((const char*)ASN1_STRING_data(timestr))) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "illegal length in timestamp"); return (time_t)-1; } - strbuf = estrdup((char *)timestr->data); + if (ASN1_STRING_length(timestr) < 13) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to parse time string %s correctly", timestr->data); + return (time_t)-1; + } + + if (ASN1_STRING_type(timestr) == V_ASN1_GENERALIZEDTIME && ASN1_STRING_length(timestr) < 15) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "unable to parse time string %s correctly", timestr->data); + return (time_t)-1; + } + + strbuf = estrdup((char *)ASN1_STRING_data(timestr)); memset(&thetime, 0, sizeof(thetime)); /* we work backwards so that we can use atoi more easily */ - thestr = strbuf + timestr->length - 3; + thestr = strbuf + ASN1_STRING_length(timestr) - 3; thetime.tm_sec = atoi(thestr); *thestr = '\0'; @@ -707,14 +746,21 @@ static time_t asn1_time_to_time_t(ASN1_UTCTIME * timestr TSRMLS_DC) /* {{{ */ *thestr = '\0'; thestr -= 2; thetime.tm_mon = atoi(thestr)-1; + *thestr = '\0'; - thestr -= 2; - thetime.tm_year = atoi(thestr); + if( ASN1_STRING_type(timestr) == V_ASN1_UTCTIME ) { + thestr -= 2; + thetime.tm_year = atoi(thestr); - if (thetime.tm_year < 68) { - thetime.tm_year += 100; + if (thetime.tm_year < 68) { + thetime.tm_year += 100; + } + } else if( ASN1_STRING_type(timestr) == V_ASN1_GENERALIZEDTIME ) { + thestr -= 4; + thetime.tm_year = atoi(thestr) - 1900; } + thetime.tm_isdst = -1; ret = mktime(&thetime); @@ -792,25 +838,25 @@ 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 && Z_TYPE_P(item) == IS_STRING) \ + 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 && Z_TYPE_P(item) == IS_LONG) \ + varname = Z_LVAL_P(item); \ else \ varname = defval -static const EVP_CIPHER * php_openssl_get_evp_cipher_from_algo(long algo); +static const EVP_CIPHER * php_openssl_get_evp_cipher_from_algo(zend_long algo); 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"); @@ -844,8 +890,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) { @@ -858,8 +904,9 @@ 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 + && Z_TYPE_P(item) == IS_LONG) { + zend_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."); @@ -881,7 +928,7 @@ static int php_openssl_parse_config(struct php_x509_request * req, zval * option req->digest = req->md_alg = EVP_get_digestbyname(req->digest_name); } if (req->md_alg == NULL) { - req->md_alg = req->digest = EVP_md5(); + req->md_alg = req->digest = EVP_sha1(); } PHP_SSL_CONFIG_SYNTAX_CHECK(extensions_section); @@ -965,7 +1012,7 @@ static int php_openssl_write_rand_file(const char * file, int egdsocket, int see } /* }}} */ -static EVP_MD * php_openssl_get_evp_md_from_algo(long algo) { /* {{{ */ +static EVP_MD * php_openssl_get_evp_md_from_algo(zend_long algo) { /* {{{ */ EVP_MD *mdtype; switch (algo) { @@ -1011,7 +1058,7 @@ static EVP_MD * php_openssl_get_evp_md_from_algo(long algo) { /* {{{ */ } /* }}} */ -static const EVP_CIPHER * php_openssl_get_evp_cipher_from_algo(long algo) { /* {{{ */ +static const EVP_CIPHER * php_openssl_get_evp_cipher_from_algo(zend_long algo) { /* {{{ */ switch (algo) { #ifndef OPENSSL_NO_RC2 case PHP_OPENSSL_CIPHER_RC2_40: @@ -1054,6 +1101,13 @@ static const EVP_CIPHER * php_openssl_get_evp_cipher_from_algo(long algo) { /* { } /* }}} */ +/* {{{ INI Settings */ +PHP_INI_BEGIN() + PHP_INI_ENTRY("openssl.cafile", NULL, PHP_INI_PERDIR, NULL) + PHP_INI_ENTRY("openssl.capath", NULL, PHP_INI_PERDIR, NULL) +PHP_INI_END() +/* }}} */ + /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(openssl) @@ -1121,6 +1175,9 @@ PHP_MINIT_FUNCTION(openssl) REGISTER_LONG_CONSTANT("OPENSSL_NO_PADDING", RSA_NO_PADDING, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OPENSSL_PKCS1_OAEP_PADDING", RSA_PKCS1_OAEP_PADDING, CONST_CS|CONST_PERSISTENT); + /* Informational stream wrapper constants */ + REGISTER_STRING_CONSTANT("OPENSSL_DEFAULT_STREAM_CIPHERS", OPENSSL_DEFAULT_STREAM_CIPHERS, CONST_CS|CONST_PERSISTENT); + /* Ciphers */ #ifndef OPENSSL_NO_RC2 REGISTER_LONG_CONSTANT("OPENSSL_CIPHER_RC2_40", PHP_OPENSSL_CIPHER_RC2_40, CONST_CS|CONST_PERSISTENT); @@ -1143,7 +1200,7 @@ PHP_MINIT_FUNCTION(openssl) REGISTER_LONG_CONSTANT("OPENSSL_KEYTYPE_DSA", OPENSSL_KEYTYPE_DSA, CONST_CS|CONST_PERSISTENT); #endif REGISTER_LONG_CONSTANT("OPENSSL_KEYTYPE_DH", OPENSSL_KEYTYPE_DH, CONST_CS|CONST_PERSISTENT); -#ifdef EVP_PKEY_EC +#ifdef HAVE_EVP_PKEY_EC REGISTER_LONG_CONSTANT("OPENSSL_KEYTYPE_EC", OPENSSL_KEYTYPE_EC, CONST_CS|CONST_PERSISTENT); #endif @@ -1176,13 +1233,20 @@ PHP_MINIT_FUNCTION(openssl) php_stream_xport_register("sslv2", php_openssl_ssl_socket_factory TSRMLS_CC); #endif php_stream_xport_register("tls", php_openssl_ssl_socket_factory TSRMLS_CC); + php_stream_xport_register("tlsv1.0", php_openssl_ssl_socket_factory TSRMLS_CC); +#if OPENSSL_VERSION_NUMBER >= 0x10001001L + php_stream_xport_register("tlsv1.1", php_openssl_ssl_socket_factory TSRMLS_CC); + php_stream_xport_register("tlsv1.2", php_openssl_ssl_socket_factory TSRMLS_CC); +#endif /* override the default tcp socket provider */ php_stream_xport_register("tcp", php_openssl_ssl_socket_factory TSRMLS_CC); php_register_url_stream_wrapper("https", &php_stream_http_wrapper TSRMLS_CC); php_register_url_stream_wrapper("ftps", &php_stream_ftp_wrapper TSRMLS_CC); - + + REGISTER_INI_ENTRIES(); + return SUCCESS; } /* }}} */ @@ -1196,6 +1260,7 @@ PHP_MINFO_FUNCTION(openssl) php_info_print_table_row(2, "OpenSSL Library Version", SSLeay_version(SSLEAY_VERSION)); php_info_print_table_row(2, "OpenSSL Header Version", OPENSSL_VERSION_TEXT); php_info_print_table_end(); + DISPLAY_INI_ENTRIES(); } /* }}} */ @@ -1214,16 +1279,43 @@ PHP_MSHUTDOWN_FUNCTION(openssl) #endif php_stream_xport_unregister("sslv3" TSRMLS_CC); php_stream_xport_unregister("tls" TSRMLS_CC); + php_stream_xport_unregister("tlsv1.0" TSRMLS_CC); +#if OPENSSL_VERSION_NUMBER >= 0x10001001L + php_stream_xport_unregister("tlsv1.1" TSRMLS_CC); + php_stream_xport_unregister("tlsv1.2" TSRMLS_CC); +#endif /* reinstate the default tcp handler */ php_stream_xport_register("tcp", php_stream_generic_socket_factory TSRMLS_CC); + UNREGISTER_INI_ENTRIES(); + return SUCCESS; } /* }}} */ /* {{{ x509 cert functions */ +/* {{{ proto array openssl_get_cert_locations(void) + Retrieve an array mapping available certificate locations */ +PHP_FUNCTION(openssl_get_cert_locations) +{ + array_init(return_value); + + 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")-1, 0)); + add_assoc_string(return_value, "ini_capath", + zend_ini_string("openssl.capath", sizeof("openssl.capath")-1, 0)); +} +/* }}} */ + + /* {{{ php_openssl_x509_from_zval Given a zval, coerce it into an X509 object. The zval can be: @@ -1233,14 +1325,14 @@ PHP_MSHUTDOWN_FUNCTION(openssl) 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; @@ -1251,7 +1343,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; @@ -1261,22 +1354,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; } @@ -1285,7 +1378,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; } @@ -1298,7 +1391,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; } @@ -1310,14 +1403,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; + size_t 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; @@ -1343,7 +1436,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); @@ -1355,11 +1448,12 @@ PHP_FUNCTION(openssl_x509_export_to_file) outputting results to var */ PHP_FUNCTION(openssl_spki_new) { - int challenge_len; - char * challenge = NULL, * spkstr = NULL, * s = NULL; - long keyresource = -1; + size_t challenge_len; + char * challenge = NULL, * spkstr = NULL; + zend_string * s = NULL; + zend_resource *keyresource = NULL; const char *spkac = "SPKAC="; - long algo = OPENSSL_ALGO_MD5; + zend_long algo = OPENSSL_ALGO_MD5; zval *method = NULL; zval * zpkey = NULL; @@ -1372,7 +1466,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"); @@ -1419,30 +1513,31 @@ PHP_FUNCTION(openssl_spki_new) goto cleanup; } - s = emalloc(strlen(spkac) + strlen(spkstr) + 1); - sprintf(s, "%s%s", spkac, spkstr); + s = zend_string_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) { + zend_string_release(s); } } /* }}} */ @@ -1451,7 +1546,8 @@ cleanup: Verifies spki returns boolean */ PHP_FUNCTION(openssl_spki_verify) { - int spkstr_len, i = 0; + size_t spkstr_len; + int i = 0; char *spkstr = NULL, * spkstr_cleaned = NULL; EVP_PKEY *pkey = NULL; @@ -1511,7 +1607,7 @@ cleanup: Exports public key from existing spki to var */ PHP_FUNCTION(openssl_spki_export) { - int spkstr_len; + size_t spkstr_len; char *spkstr = NULL, * spkstr_cleaned = NULL, * s = NULL; EVP_PKEY *pkey = NULL; @@ -1571,7 +1667,7 @@ cleanup: Exports spkac challenge from existing spki to var */ PHP_FUNCTION(openssl_spki_export_challenge) { - int spkstr_len; + size_t spkstr_len; char *spkstr = NULL, * spkstr_cleaned = NULL; NETSCAPE_SPKI *spki = NULL; @@ -1595,7 +1691,7 @@ PHP_FUNCTION(openssl_spki_export_challenge) goto cleanup; } - RETVAL_STRING(ASN1_STRING_data(spki->spkac->challenge), 1); + RETVAL_STRING((char *) ASN1_STRING_data(spki->spkac->challenge)); goto cleanup; cleanup: @@ -1628,12 +1724,12 @@ 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; } RETVAL_FALSE; @@ -1653,30 +1749,88 @@ 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); } /* }}} */ +zend_string* php_openssl_x509_fingerprint(X509 *peer, const char *method, zend_bool raw TSRMLS_DC) +{ + unsigned char md[EVP_MAX_MD_SIZE]; + const EVP_MD *mdtype; + unsigned int n; + zend_string *ret; + + if (!(mdtype = EVP_get_digestbyname(method))) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown signature algorithm"); + return NULL; + } else if (!X509_digest(peer, mdtype, md, &n)) { + php_error_docref(NULL TSRMLS_CC, E_ERROR, "Could not generate signature"); + return NULL; + } + + if (raw) { + ret = zend_string_init((char*)md, n, 0); + } else { + ret = zend_string_alloc(n * 2, 0); + make_digest_ex(ret->val, md, n); + ret->val[n * 2] = '\0'; + } + + return ret; +} + +PHP_FUNCTION(openssl_x509_fingerprint) +{ + X509 *cert; + zval *zcert; + zend_resource *certresource; + zend_bool raw_output = 0; + char *method = "sha1"; + size_t method_len; + zend_string *fingerprint; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "z|sb", &zcert, &method, &method_len, &raw_output) == FAILURE) { + return; + } + + 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_FALSE; + } + + fingerprint = php_openssl_x509_fingerprint(cert, method, raw_output TSRMLS_CC); + if (fingerprint) { + RETVAL_STR(fingerprint); + } else { + RETVAL_FALSE; + } + + if (certresource == NULL && cert) { + X509_free(cert); + } +} + /* {{{ proto bool openssl_x509_check_private_key(mixed cert, mixed key) 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); @@ -1688,10 +1842,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); } } @@ -1769,20 +1923,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); @@ -1792,7 +1946,7 @@ PHP_FUNCTION(openssl_x509_parse) array_init(return_value); if (cert->name) { - add_assoc_string(return_value, "name", cert->name, 1); + add_assoc_string(return_value, "name", cert->name); } /* add_assoc_bool(return_value, "valid", cert->valid); */ @@ -1801,13 +1955,13 @@ PHP_FUNCTION(openssl_x509_parse) { char buf[32]; snprintf(buf, sizeof(buf), "%08lx", X509_subject_name_hash(cert)); - add_assoc_string(return_value, "hash", buf, 1); + add_assoc_string(return_value, "hash", buf); } add_assoc_name_entry(return_value, "issuer", X509_get_issuer_name(cert), useshortnames TSRMLS_CC); add_assoc_long(return_value, "version", X509_get_version(cert)); - add_assoc_string(return_value, "serialNumber", i2s_ASN1_INTEGER(NULL, X509_get_serialNumber(cert)), 1); + add_assoc_string(return_value, "serialNumber", i2s_ASN1_INTEGER(NULL, X509_get_serialNumber(cert))); add_assoc_asn1_string(return_value, "validFrom", X509_get_notBefore(cert)); add_assoc_asn1_string(return_value, "validTo", X509_get_notAfter(cert)); @@ -1817,15 +1971,14 @@ PHP_FUNCTION(openssl_x509_parse) tmpstr = (char *)X509_alias_get0(cert, NULL); if (tmpstr) { - add_assoc_string(return_value, "alias", tmpstr, 1); + add_assoc_string(return_value, "alias", tmpstr); } /* add_assoc_long(return_value, "signaturetypeLONG", X509_get_signature_type(cert)); - add_assoc_string(return_value, "signaturetype", OBJ_nid2sn(X509_get_signature_type(cert)), 1); - add_assoc_string(return_value, "signaturetypeLN", OBJ_nid2ln(X509_get_signature_type(cert)), 1); + 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 */ @@ -1833,31 +1986,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, 1); + 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++) { @@ -1874,10 +2025,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, 1); + 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); @@ -1886,15 +2037,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, 1); + 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); } } @@ -1982,16 +2133,17 @@ 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; + zend_long purpose; char * untrusted = NULL; - int untrusted_len = 0, ret; + size_t untrusted_len = 0; + int 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; } @@ -2021,7 +2173,7 @@ PHP_FUNCTION(openssl_x509_checkpurpose) } clean_exit: - if (certresource == 1 && cert) { + if (certresource == NULL && cert) { X509_free(cert); } if (cainfo) { @@ -2041,8 +2193,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; + zend_stat_t sb; store = X509_STORE_new(); @@ -2051,39 +2204,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()); @@ -2105,14 +2251,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!"); @@ -2131,8 +2278,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)); } /* }}} */ @@ -2150,27 +2297,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) { @@ -2179,9 +2323,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); @@ -2190,7 +2332,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; @@ -2213,16 +2355,16 @@ PHP_FUNCTION(openssl_pkcs12_export_to_file) PKCS12 * p12 = NULL; char * filename; char * friendly_name = NULL; - int filename_len; + size_t filename_len; char * pass; - int pass_len; - zval **zcert = NULL, *zpkey = NULL, *args = NULL; + size_t pass_len; + 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; @@ -2232,7 +2374,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; @@ -2246,14 +2388,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 && Z_TYPE_P(item) == IS_STRING) + 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 */ @@ -2278,10 +2420,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); } } @@ -2296,24 +2438,24 @@ 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; + size_t 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) + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zz/zs|a", &zcert, &zout, &zpkey, &pass, &pass_len, &args) == FAILURE) return; 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; @@ -2324,10 +2466,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 && Z_TYPE_P(item) == IS_STRING) + 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 */ @@ -2339,7 +2481,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; } @@ -2350,10 +2492,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); } } @@ -2363,9 +2505,9 @@ 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; + size_t pass_len, zp12_len; PKCS12 * p12 = NULL; EVP_PKEY * pkey = NULL; X509 * cert = NULL; @@ -2373,7 +2515,7 @@ PHP_FUNCTION(openssl_pkcs12_read) BIO * bio_in = NULL; int i; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szs", &zp12, &zp12_len, &zout, &pass, &pass_len) == FAILURE) + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz/s", &zp12, &zp12_len, &zout, &pass, &pass_len) == FAILURE) return; RETVAL_FALSE; @@ -2394,9 +2536,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); @@ -2404,17 +2545,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; @@ -2422,9 +2561,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); @@ -2433,9 +2571,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; @@ -2488,42 +2626,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++) { @@ -2574,30 +2704,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 */ @@ -2623,33 +2744,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)) { @@ -2657,7 +2779,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); @@ -2673,16 +2795,17 @@ PHP_FUNCTION(openssl_csr_export_to_file) X509_REQ * csr; zval * zcsr = NULL; zend_bool notext = 1; - char * filename = NULL; int filename_len; + char * filename = NULL; + size_t 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; @@ -2703,7 +2826,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); @@ -2718,15 +2841,15 @@ PHP_FUNCTION(openssl_csr_export) zval * zcsr = NULL, *zout=NULL; zend_bool notext = 1; BIO * bio_out; + zend_resource *csr_resource; - long csr_resource; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz|b", &zcsr, &zout, ¬ext) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rz/|b", &zcsr, &zout, ¬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; @@ -2744,12 +2867,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); @@ -2760,17 +2883,17 @@ PHP_FUNCTION(openssl_csr_export) Signs a cert with another CERT */ PHP_FUNCTION(openssl_csr_sign) { - zval ** zcert = NULL, **zcsr, **zpkey, *args = NULL; - long num_days; - long serial = 0L; + zval * zcert = NULL, *zcsr, *zpkey, *args = NULL; + zend_long num_days; + zend_long serial = Z_L(0); 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; @@ -2829,6 +2952,7 @@ PHP_FUNCTION(openssl_csr_sign) if (!X509_set_version(new_cert, 2)) goto cleanup; + ASN1_INTEGER_set(X509_get_serialNumber(new_cert), serial); X509_set_subject_name(new_cert, X509_REQ_get_subject_name(csr)); @@ -2862,7 +2986,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: @@ -2872,16 +2996,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) { @@ -2899,9 +3023,9 @@ 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) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "az/|a!a!", &dn, &out_pkey, &args, &attribs) == FAILURE) { return; } RETVAL_FALSE; @@ -2911,7 +3035,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; } @@ -2939,7 +3063,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"); @@ -2948,9 +3072,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! */ } } @@ -2975,13 +3099,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; } @@ -3003,14 +3127,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; } @@ -3021,7 +3145,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; } /* }}} */ @@ -3043,16 +3167,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) {\ @@ -3061,35 +3185,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; @@ -3098,7 +3221,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 */ @@ -3134,18 +3258,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 */ @@ -3153,7 +3277,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; @@ -3171,7 +3295,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) { @@ -3314,6 +3438,15 @@ static int php_openssl_is_private_key(EVP_PKEY* pkey TSRMLS_DC) } break; #endif +#ifdef HAVE_EVP_PKEY_EC + case EVP_PKEY_EC: + assert(pkey->pkey.ec != NULL); + + if ( NULL == EC_KEY_get0_private_key(pkey->pkey.ec)) { + return 0; + } + break; +#endif default: php_error_docref(NULL TSRMLS_CC, E_WARNING, "key type not supported in this PHP build!"); break; @@ -3325,20 +3458,20 @@ static int php_openssl_is_private_key(EVP_PKEY* pkey TSRMLS_DC) #define OPENSSL_PKEY_GET_BN(_type, _name) do { \ if (pkey->pkey._type->_name != NULL) { \ int len = BN_num_bytes(pkey->pkey._type->_name); \ - char *str = emalloc(len + 1); \ - BN_bn2bin(pkey->pkey._type->_name, (unsigned char*)str); \ - str[len] = 0; \ - add_assoc_stringl(_type, #_name, str, len, 0); \ + zend_string *str = zend_string_alloc(len, 0); \ + BN_bn2bin(pkey->pkey._type->_name, (unsigned char*)str->val); \ + str->val[len] = 0; \ + add_assoc_str(&_type, #_name, 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); @@ -3349,7 +3482,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; @@ -3359,23 +3492,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); @@ -3383,23 +3517,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); @@ -3407,22 +3542,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); @@ -3439,7 +3575,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; } @@ -3453,15 +3589,17 @@ PHP_FUNCTION(openssl_pkey_new) PHP_FUNCTION(openssl_pkey_export_to_file) { struct php_x509_request req; - zval ** zpkey, * args = NULL; - char * passphrase = NULL; int passphrase_len = 0; - char * filename = NULL; int filename_len = 0; - long key_resource = -1; + zval * zpkey, * args = NULL; + char * passphrase = NULL; + size_t passphrase_len = 0; + char * filename = NULL; + size_t filename_len = 0; + 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; @@ -3499,7 +3637,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) { @@ -3513,14 +3651,14 @@ PHP_FUNCTION(openssl_pkey_export_to_file) PHP_FUNCTION(openssl_pkey_export) { struct php_x509_request req; - zval ** zpkey, * args = NULL, *out; - char * passphrase = NULL; int passphrase_len = 0; - long key_resource = -1; + zval * zpkey, * args = NULL, *out; + char * passphrase = NULL; size_t passphrase_len = 0; + 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; } RETVAL_FALSE; @@ -3556,12 +3694,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) { @@ -3574,19 +3712,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); } /* }}} */ @@ -3600,8 +3738,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)); } /* }}} */ @@ -3609,21 +3747,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; + size_t 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); } /* }}} */ @@ -3637,12 +3776,12 @@ PHP_FUNCTION(openssl_pkey_get_details) BIO *out; unsigned int pbio_len; char *pbio; - long ktype; + zend_long ktype; 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; } @@ -3652,7 +3791,7 @@ PHP_FUNCTION(openssl_pkey_get_details) array_init(return_value); add_assoc_long(return_value, "bits", EVP_PKEY_bits(pkey)); - add_assoc_stringl(return_value, "key", pbio, pbio_len, 1); + add_assoc_stringl(return_value, "key", pbio, pbio_len); /*TODO: Use the real values once the openssl constants are used * See the enum at the top of this file */ @@ -3662,10 +3801,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); @@ -3674,7 +3812,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; @@ -3685,16 +3823,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: @@ -3702,19 +3839,18 @@ 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; -#ifdef EVP_PKEY_EC +#ifdef HAVE_EVP_PKEY_EC case EVP_PKEY_EC: ktype = OPENSSL_KEYTYPE_EC; break; @@ -3737,11 +3873,14 @@ PHP_FUNCTION(openssl_pkey_get_details) Generates a PKCS5 v2 PBKDF2 string, defaults to sha1 */ PHP_FUNCTION(openssl_pbkdf2) { - long key_length = 0, iterations = 0; - char *password; int password_len; - char *salt; int salt_len; - char *method; int method_len = 0; - unsigned char *out_buffer; + zend_long key_length = 0, iterations = 0; + char *password; + size_t password_len; + char *salt; + size_t salt_len; + char *method; + size_t method_len = 0; + zend_string *out_buffer; const EVP_MD *digest; @@ -3768,13 +3907,13 @@ PHP_FUNCTION(openssl_pbkdf2) RETURN_FALSE; } - out_buffer = emalloc(key_length + 1); - out_buffer[key_length] = '\0'; + out_buffer = zend_string_alloc(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); + if (PKCS5_PBKDF2_HMAC(password, password_len, (unsigned char *)salt, salt_len, iterations, digest, key_length, (unsigned char*)out_buffer->val) == 1) { + out_buffer->val[key_length] = 0; + RETURN_STR(out_buffer); } else { - efree(out_buffer); + zend_string_release(out_buffer); RETURN_FALSE; } } @@ -3794,11 +3933,15 @@ PHP_FUNCTION(openssl_pkcs7_verify) STACK_OF(X509) *others = NULL; PKCS7 * p7 = NULL; BIO * in = NULL, * datain = NULL, * dataout = NULL; - long flags = 0; - char * filename; int filename_len; - char * extracerts = NULL; int extracerts_len = 0; - char * signersfilename = NULL; int signersfilename_len = 0; - char * datafilename = NULL; int datafilename_len = 0; + zend_long flags = 0; + char * filename; + size_t filename_len; + char * extracerts = NULL; + size_t extracerts_len = 0; + char * signersfilename = NULL; + size_t signersfilename_len = 0; + char * datafilename = NULL; + size_t datafilename_len = 0; RETVAL_LONG(-1); @@ -3897,25 +4040,24 @@ 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; + zend_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; - char * infilename = NULL; int infilename_len; - char * outfilename = NULL; int outfilename_len; + zend_long cipherid = PHP_OPENSSL_CIPHER_DEFAULT; + zend_string * strindex; + char * infilename = NULL; + size_t infilename_len; + char * outfilename = NULL; + size_t 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; @@ -3937,17 +4079,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); @@ -3956,19 +4097,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); @@ -3995,21 +4134,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); @@ -4034,24 +4167,24 @@ 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; + zend_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; - 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", + zend_resource *certresource = NULL, *keyresource = NULL; + zend_string * strindex; + char * infilename; + size_t infilename_len; + char * outfilename; + size_t outfilename_len; + char * extracertsfilename = NULL; + size_t extracertsfilename_len; + + 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) { @@ -4105,20 +4238,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); @@ -4132,10 +4260,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); } } @@ -4146,16 +4274,18 @@ 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; + char * infilename; + size_t infilename_len; + char * outfilename; + size_t 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; } @@ -4200,10 +4330,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); } } @@ -4215,17 +4345,17 @@ 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; + zend_string *cryptedbuf = NULL; int successful = 0; - long keyresource = -1; + zend_resource *keyresource = NULL; char * data; - int data_len; - long padding = RSA_PKCS1_PADDING; + size_t data_len; + zend_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, "sz/z|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) { return; } RETVAL_FALSE; @@ -4238,14 +4368,14 @@ PHP_FUNCTION(openssl_private_encrypt) } cryptedlen = EVP_PKEY_size(pkey); - cryptedbuf = emalloc(cryptedlen + 1); + cryptedbuf = zend_string_alloc(cryptedlen, 0); switch (pkey->type) { case EVP_PKEY_RSA: case EVP_PKEY_RSA2: successful = (RSA_private_encrypt(data_len, (unsigned char *)data, - cryptedbuf, + (unsigned char *)cryptedbuf->val, pkey->pkey.rsa, padding) == cryptedlen); break; @@ -4255,15 +4385,15 @@ PHP_FUNCTION(openssl_private_encrypt) if (successful) { zval_dtor(crypted); - cryptedbuf[cryptedlen] = '\0'; - ZVAL_STRINGL(crypted, (char *)cryptedbuf, cryptedlen, 0); + cryptedbuf->val[cryptedlen] = '\0'; + ZVAL_NEW_STR(crypted, cryptedbuf); cryptedbuf = NULL; RETVAL_TRUE; } if (cryptedbuf) { - efree(cryptedbuf); + zend_string_release(cryptedbuf); } - if (keyresource == -1) { + if (keyresource == NULL) { EVP_PKEY_free(pkey); } } @@ -4273,18 +4403,18 @@ 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; + zend_string *cryptedbuf = NULL; unsigned char *crypttemp; int successful = 0; - long padding = RSA_PKCS1_PADDING; - long keyresource = -1; + zend_long padding = RSA_PKCS1_PADDING; + zend_resource *keyresource = NULL; char * data; - int data_len; + size_t 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, "sz/z|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) { return; } RETVAL_FALSE; @@ -4307,8 +4437,8 @@ PHP_FUNCTION(openssl_private_decrypt) pkey->pkey.rsa, padding); if (cryptedlen != -1) { - cryptedbuf = emalloc(cryptedlen + 1); - memcpy(cryptedbuf, crypttemp, cryptedlen); + cryptedbuf = zend_string_alloc(cryptedlen, 0); + memcpy(cryptedbuf->val, crypttemp, cryptedlen); successful = 1; } break; @@ -4320,17 +4450,17 @@ PHP_FUNCTION(openssl_private_decrypt) if (successful) { zval_dtor(crypted); - cryptedbuf[cryptedlen] = '\0'; - ZVAL_STRINGL(crypted, (char *)cryptedbuf, cryptedlen, 0); + cryptedbuf->val[cryptedlen] = '\0'; + ZVAL_NEW_STR(crypted, cryptedbuf); cryptedbuf = NULL; RETVAL_TRUE; } - if (keyresource == -1) { + if (keyresource == NULL) { EVP_PKEY_free(pkey); } if (cryptedbuf) { - efree(cryptedbuf); + zend_string_release(cryptedbuf); } } /* }}} */ @@ -4339,19 +4469,18 @@ 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; + zend_string *cryptedbuf; int successful = 0; - long keyresource = -1; - long padding = RSA_PKCS1_PADDING; + zend_resource *keyresource = NULL; + zend_long padding = RSA_PKCS1_PADDING; char * data; - int data_len; + size_t 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, "sz/z|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) return; - RETVAL_FALSE; pkey = php_openssl_evp_from_zval(key, 1, NULL, 0, &keyresource TSRMLS_CC); @@ -4361,14 +4490,14 @@ PHP_FUNCTION(openssl_public_encrypt) } cryptedlen = EVP_PKEY_size(pkey); - cryptedbuf = emalloc(cryptedlen + 1); + cryptedbuf = zend_string_alloc(cryptedlen, 0); switch (pkey->type) { case EVP_PKEY_RSA: case EVP_PKEY_RSA2: successful = (RSA_public_encrypt(data_len, (unsigned char *)data, - cryptedbuf, + (unsigned char *)cryptedbuf->val, pkey->pkey.rsa, padding) == cryptedlen); break; @@ -4379,16 +4508,16 @@ PHP_FUNCTION(openssl_public_encrypt) if (successful) { zval_dtor(crypted); - cryptedbuf[cryptedlen] = '\0'; - ZVAL_STRINGL(crypted, (char *)cryptedbuf, cryptedlen, 0); + cryptedbuf->val[cryptedlen] = '\0'; + ZVAL_NEW_STR(crypted, cryptedbuf); cryptedbuf = NULL; RETVAL_TRUE; } - if (keyresource == -1) { + if (keyresource == NULL) { EVP_PKEY_free(pkey); } if (cryptedbuf) { - efree(cryptedbuf); + zend_string_release(cryptedbuf); } } /* }}} */ @@ -4397,18 +4526,18 @@ 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; + zend_string *cryptedbuf = NULL; unsigned char *crypttemp; int successful = 0; - long keyresource = -1; - long padding = RSA_PKCS1_PADDING; + zend_resource *keyresource = NULL; + zend_long padding = RSA_PKCS1_PADDING; char * data; - int data_len; + size_t 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, "sz/z|l", &data, &data_len, &crypted, &key, &padding) == FAILURE) { return; } RETVAL_FALSE; @@ -4431,8 +4560,8 @@ PHP_FUNCTION(openssl_public_decrypt) pkey->pkey.rsa, padding); if (cryptedlen != -1) { - cryptedbuf = emalloc(cryptedlen + 1); - memcpy(cryptedbuf, crypttemp, cryptedlen); + cryptedbuf = zend_string_alloc(cryptedlen, 0); + memcpy(cryptedbuf->val, crypttemp, cryptedlen); successful = 1; } break; @@ -4446,16 +4575,16 @@ PHP_FUNCTION(openssl_public_decrypt) if (successful) { zval_dtor(crypted); - cryptedbuf[cryptedlen] = '\0'; - ZVAL_STRINGL(crypted, (char *)cryptedbuf, cryptedlen, 0); + cryptedbuf->val[cryptedlen] = '\0'; + ZVAL_NEW_STR(crypted, cryptedbuf); cryptedbuf = NULL; RETVAL_TRUE; } if (cryptedbuf) { - efree(cryptedbuf); + zend_string_release(cryptedbuf); } - if (keyresource == -1) { + if (keyresource == NULL) { EVP_PKEY_free(pkey); } } @@ -4474,7 +4603,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; } @@ -4485,19 +4614,19 @@ 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; + unsigned int siglen; + zend_string *sigbuf; + zend_resource *keyresource = NULL; char * data; - int data_len; + size_t data_len; EVP_MD_CTX md_ctx; zval *method = NULL; - long signature_algo = OPENSSL_ALGO_SHA1; + zend_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, "sz/z|z", &data, &data_len, &signature, &key, &method) == FAILURE) { return; } pkey = php_openssl_evp_from_zval(key, 0, "", 0, &keyresource TSRMLS_CC); @@ -4523,21 +4652,22 @@ PHP_FUNCTION(openssl_sign) } siglen = EVP_PKEY_size(pkey); - sigbuf = emalloc(siglen + 1); + sigbuf = zend_string_alloc(siglen, 0); EVP_SignInit(&md_ctx, mdtype); EVP_SignUpdate(&md_ctx, data, data_len); - if (EVP_SignFinal (&md_ctx, sigbuf,(unsigned int *)&siglen, pkey)) { + if (EVP_SignFinal (&md_ctx, (unsigned char*)sigbuf->val, &siglen, pkey)) { zval_dtor(signature); - sigbuf[siglen] = '\0'; - ZVAL_STRINGL(signature, (char *)sigbuf, siglen, 0); + sigbuf->val[siglen] = '\0'; + sigbuf->len = siglen; + ZVAL_NEW_STR(signature, sigbuf); RETVAL_TRUE; } else { efree(sigbuf); RETVAL_FALSE; } EVP_MD_CTX_cleanup(&md_ctx); - if (keyresource == -1) { + if (keyresource == NULL) { EVP_PKEY_free(pkey); } } @@ -4547,18 +4677,20 @@ 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; - char * data; int data_len; - char * signature; int signature_len; + zend_resource *keyresource = NULL; + char * data; + size_t data_len; + char * signature; + size_t signature_len; zval *method = NULL; - long signature_algo = OPENSSL_ALGO_SHA1; + zend_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; } @@ -4589,7 +4721,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); @@ -4600,23 +4732,22 @@ 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; + char * data; + size_t data_len; char *method =NULL; - int method_len = 0; + size_t method_len = 0; const EVP_CIPHER *cipher; EVP_CIPHER_CTX ctx; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szza/|s", &data, &data_len, &sealdata, &ekeys, &pubkeys, &method, &method_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz/z/a/|s", &data, &data_len, &sealdata, &ekeys, &pubkeys, &method, &method_len) == FAILURE) { return; } - pubkeysht = HASH_OF(pubkeys); nkeys = pubkeysht ? zend_hash_num_elements(pubkeysht) : 0; if (!nkeys) { @@ -4638,14 +4769,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); @@ -4653,12 +4782,12 @@ 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; + EVP_CIPHER_CTX_cleanup(&ctx); goto clean_exit; } @@ -4669,10 +4798,12 @@ PHP_FUNCTION(openssl_seal) #endif /* allocate one byte extra to make room for \0 */ buf = emalloc(data_len + EVP_CIPHER_CTX_block_size(&ctx)); + EVP_CIPHER_CTX_cleanup(&ctx); if (!EVP_SealInit(&ctx, cipher, eks, eksl, NULL, pkeys, nkeys) || !EVP_SealUpdate(&ctx, buf, &len1, (unsigned char *)data, data_len)) { RETVAL_FALSE; efree(buf); + EVP_CIPHER_CTX_cleanup(&ctx); goto clean_exit; } @@ -4681,14 +4812,15 @@ 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_NEW_STR(sealdata, zend_string_init((char*)buf, len1 + len2, 0)); + efree(buf); zval_dtor(ekeys); array_init(ekeys); for (i=0; i<nkeys; i++) { eks[i][eksl[i]] = '\0'; - add_next_index_stringl(ekeys, erealloc(eks[i], eksl[i] + 1), eksl[i], 0); + add_next_index_stringl(ekeys, (const char*)eks[i], eksl[i]); + efree(eks[i]); eks[i] = NULL; } #if 0 @@ -4696,7 +4828,8 @@ PHP_FUNCTION(openssl_seal) zval_dtor(*ivec); if (ivlen) { iv[ivlen] = '\0'; - ZVAL_STRINGL(*ivec, erealloc(iv, ivlen + 1), ivlen, 0); + ZVAL_STRINGL(*ivec, iv, ivlen); + efree(iv); } else { ZVAL_EMPTY_STRING(*ivec); } @@ -4705,10 +4838,11 @@ PHP_FUNCTION(openssl_seal) efree(buf); } RETVAL_LONG(len1 + len2); + EVP_CIPHER_CTX_cleanup(&ctx); clean_exit: for (i=0; i<nkeys; i++) { - if (key_resources[i] == -1) { + if (key_resources[i] == NULL) { EVP_PKEY_free(pkeys[i]); } if (eks[i]) { @@ -4726,19 +4860,21 @@ clean_exit: Opens data */ PHP_FUNCTION(openssl_open) { - zval **privkey, *opendata; + zval *privkey, *opendata; EVP_PKEY *pkey; int len1, len2; unsigned char *buf; - long keyresource = -1; + zend_resource *keyresource = NULL; EVP_CIPHER_CTX ctx; - char * data; int data_len; - char * ekey; int ekey_len; + char * data; + size_t data_len; + char * ekey; + size_t ekey_len; char *method =NULL; - int method_len = 0; + size_t method_len = 0; const EVP_CIPHER *cipher; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "szsZ|s", &data, &data_len, &opendata, &ekey, &ekey_len, &privkey, &method, &method_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sz/sz|s", &data, &data_len, &opendata, &ekey, &ekey_len, &privkey, &method, &method_len) == FAILURE) { return; } @@ -4763,285 +4899,35 @@ PHP_FUNCTION(openssl_open) if (EVP_OpenInit(&ctx, cipher, (unsigned char *)ekey, ekey_len, NULL, pkey) && EVP_OpenUpdate(&ctx, buf, &len1, (unsigned char *)data, data_len)) { if (!EVP_OpenFinal(&ctx, buf + len1, &len2) || (len1 + len2 == 0)) { efree(buf); - if (keyresource == -1) { - EVP_PKEY_free(pkey); - } - RETURN_FALSE; + RETVAL_FALSE; + } else { + zval_dtor(opendata); + buf[len1 + len2] = '\0'; + ZVAL_NEW_STR(opendata, zend_string_init((char*)buf, len1 + len2, 0)); + efree(buf); + RETVAL_TRUE; } } else { efree(buf); - if (keyresource == -1) { - EVP_PKEY_free(pkey); - } - RETURN_FALSE; + RETVAL_FALSE; } - if (keyresource == -1) { + if (keyresource == NULL) { EVP_PKEY_free(pkey); } - zval_dtor(opendata); - buf[len1 + len2] = '\0'; - ZVAL_STRINGL(opendata, erealloc(buf, len1 + len2 + 1), len1 + len2, 0); - RETURN_TRUE; -} -/* }}} */ - -/* SSL verification functions */ - -#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); } - -static int verify_callback(int preverify_ok, X509_STORE_CTX *ctx) /* {{{ */ -{ - php_stream *stream; - SSL *ssl; - X509 *err_cert; - int err, depth, ret; - zval **val; - - ret = preverify_ok; - - /* determine the status for the current cert */ - err_cert = X509_STORE_CTX_get_current_cert(ctx); - err = X509_STORE_CTX_get_error(ctx); - depth = X509_STORE_CTX_get_error_depth(ctx); - - /* conjure the stream & context to use */ - ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); - stream = (php_stream*)SSL_get_ex_data(ssl, ssl_stream_data_index); - - /* 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") && zval_is_true(*val)) { - ret = 1; - } - - /* check the depth */ - if (GET_VER_OPT("verify_depth")) { - convert_to_long_ex(val); - - if (depth > Z_LVAL_PP(val)) { - ret = 0; - X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_CHAIN_TOO_LONG); - } - } - - return ret; - -} -/* }}} */ - -int php_openssl_apply_verification_policy(SSL *ssl, X509 *peer, php_stream *stream TSRMLS_DC) /* {{{ */ -{ - zval **val = NULL; - char *cnmatch = NULL; - X509_NAME *name; - char buf[1024]; - int err; - - /* verification is turned off */ - if (!(GET_VER_OPT("verify_peer") && zval_is_true(*val))) { - return SUCCESS; - } - - if (peer == NULL) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not get peer certificate"); - return FAILURE; - } - - err = SSL_get_verify_result(ssl); - switch (err) { - case X509_V_OK: - /* fine */ - break; - case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT: - if (GET_VER_OPT("allow_self_signed") && zval_is_true(*val)) { - /* allowed */ - break; - } - /* not allowed, so fall through */ - default: - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Could not verify peer: code:%d %s", err, X509_verify_cert_error_string(err)); - return FAILURE; - } - - /* if the cert passed the usual checks, apply our own local policies now */ - - name = X509_get_subject_name(peer); - - /* Does the common name match ? (used primarily for https://) */ - GET_VER_OPT_STRING("CN_match", cnmatch); - if (cnmatch) { - int match = 0; - int name_len = X509_NAME_get_text_by_NID(name, NID_commonName, buf, sizeof(buf)); - - if (name_len == -1) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to locate peer certificate CN"); - return FAILURE; - } else if (name_len != strlen(buf)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Peer certificate CN=`%.*s' is malformed", name_len, buf); - return FAILURE; - } - - match = strcmp(cnmatch, buf) == 0; - if (!match && strlen(buf) > 3 && buf[0] == '*' && buf[1] == '.') { - /* Try wildcard */ - - if (strchr(buf+2, '.')) { - char *tmp = strstr(cnmatch, buf+1); - - match = tmp && strcmp(tmp, buf+2) && tmp == strchr(cnmatch, '.'); - } - } - - if (!match) { - /* didn't match */ - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Peer certificate CN=`%.*s' did not match expected CN=`%s'", name_len, buf, cnmatch); - return FAILURE; - } - } - - return SUCCESS; -} -/* }}} */ - -static int passwd_callback(char *buf, int num, int verify, void *data) /* {{{ */ -{ - php_stream *stream = (php_stream *)data; - 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); - } - } - return 0; -} -/* }}} */ - -SSL *php_SSL_new_from_context(SSL_CTX *ctx, php_stream *stream TSRMLS_DC) /* {{{ */ -{ - zval **val = NULL; - char *cafile = NULL; - char *capath = NULL; - char *certfile = NULL; - char *cipherlist = NULL; - int ok = 1; - - ERR_clear_error(); - - /* look at context options in the stream and set appropriate verification flags */ - if (GET_VER_OPT("verify_peer") && zval_is_true(*val)) { - - /* turn on verification callback */ - SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, verify_callback); - - /* CA stuff */ - GET_VER_OPT_STRING("cafile", cafile); - GET_VER_OPT_STRING("capath", capath); - - if (cafile || capath) { - if (!SSL_CTX_load_verify_locations(ctx, cafile, capath)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set verify locations `%s' `%s'", cafile, capath); - return NULL; - } - } - - if (GET_VER_OPT("verify_depth")) { - convert_to_long_ex(val); - SSL_CTX_set_verify_depth(ctx, Z_LVAL_PP(val)); - } - } else { - SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL); - } - - /* callback for the passphrase (for localcert) */ - if (GET_VER_OPT("passphrase")) { - SSL_CTX_set_default_passwd_cb_userdata(ctx, stream); - SSL_CTX_set_default_passwd_cb(ctx, passwd_callback); - } - - GET_VER_OPT_STRING("ciphers", cipherlist); - if (!cipherlist) { - cipherlist = "DEFAULT"; - } - if (SSL_CTX_set_cipher_list(ctx, cipherlist) != 1) { - return NULL; - } - - GET_VER_OPT_STRING("local_cert", certfile); - if (certfile) { - X509 *cert = NULL; - EVP_PKEY *key = NULL; - SSL *tmpssl; - char resolved_path_buff[MAXPATHLEN]; - const char * private_key = NULL; - - if (VCWD_REALPATH(certfile, resolved_path_buff)) { - /* a certificate to use for authentication */ - if (SSL_CTX_use_certificate_chain_file(ctx, resolved_path_buff) != 1) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set local cert chain file `%s'; Check that your cafile/capath settings include details of your certificate and its issuer", certfile); - return NULL; - } - GET_VER_OPT_STRING("local_pk", private_key); - - if (private_key) { - char resolved_path_buff_pk[MAXPATHLEN]; - if (VCWD_REALPATH(private_key, resolved_path_buff_pk)) { - if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff_pk, SSL_FILETYPE_PEM) != 1) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set private key file `%s'", resolved_path_buff_pk); - return NULL; - } - } - } else { - if (SSL_CTX_use_PrivateKey_file(ctx, resolved_path_buff, SSL_FILETYPE_PEM) != 1) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to set private key file `%s'", resolved_path_buff); - return NULL; - } - } - - tmpssl = SSL_new(ctx); - cert = SSL_get_certificate(tmpssl); - - if (cert) { - key = X509_get_pubkey(cert); - EVP_PKEY_copy_parameters(key, SSL_get_privatekey(tmpssl)); - EVP_PKEY_free(key); - } - SSL_free(tmpssl); - - if (!SSL_CTX_check_private_key(ctx)) { - php_error_docref(NULL TSRMLS_CC, E_WARNING, "Private key does not match certificate!"); - } - } - } - if (ok) { - SSL *ssl = SSL_new(ctx); - - if (ssl) { - /* map SSL => stream */ - SSL_set_ex_data(ssl, ssl_stream_data_index, stream); - } - return ssl; - } - - return NULL; + EVP_CIPHER_CTX_cleanup(&ctx); } /* }}} */ static void openssl_add_method_or_alias(const OBJ_NAME *name, void *arg) /* {{{ */ { - add_next_index_string((zval*)arg, (char*)name->name, 1); + add_next_index_string((zval*)arg, (char*)name->name); } /* }}} */ static void openssl_add_method(const OBJ_NAME *name, void *arg) /* {{{ */ { if (name->alias == 0) { - add_next_index_string((zval*)arg, (char*)name->name, 1); + add_next_index_string((zval*)arg, (char*)name->name); } } /* }}} */ @@ -5084,11 +4970,11 @@ PHP_FUNCTION(openssl_digest) { zend_bool raw_output = 0; char *data, *method; - int data_len, method_len; + size_t data_len, method_len; const EVP_MD *mdtype; EVP_MD_CTX md_ctx; - int siglen; - unsigned char *sigbuf; + unsigned int siglen; + zend_string *sigbuf; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "ss|b", &data, &data_len, &method, &method_len, &raw_output) == FAILURE) { return; @@ -5100,24 +4986,26 @@ PHP_FUNCTION(openssl_digest) } siglen = EVP_MD_size(mdtype); - sigbuf = emalloc(siglen + 1); + sigbuf = zend_string_alloc(siglen, 0); EVP_DigestInit(&md_ctx, mdtype); EVP_DigestUpdate(&md_ctx, (unsigned char *)data, data_len); - if (EVP_DigestFinal (&md_ctx, (unsigned char *)sigbuf, (unsigned int *)&siglen)) { + if (EVP_DigestFinal (&md_ctx, (unsigned char *)sigbuf->val, &siglen)) { if (raw_output) { - sigbuf[siglen] = '\0'; - RETVAL_STRINGL((char *)sigbuf, siglen, 0); + sigbuf->val[siglen] = '\0'; + sigbuf->len = siglen; + RETVAL_STR(sigbuf); } else { int digest_str_len = siglen * 2; - char *digest_str = emalloc(digest_str_len + 1); + zend_string *digest_str = zend_string_alloc(digest_str_len, 0); - make_digest_ex(digest_str, sigbuf, siglen); - efree(sigbuf); - RETVAL_STRINGL(digest_str, digest_str_len, 0); + make_digest_ex(digest_str->val, (unsigned char*)sigbuf->val, siglen); + digest_str->val[digest_str_len] = '\0'; + zend_string_release(sigbuf); + RETVAL_STR(digest_str); } } else { - efree(sigbuf); + zend_string_release(sigbuf); RETVAL_FALSE; } } @@ -5161,13 +5049,14 @@ static zend_bool php_openssl_validate_iv(char **piv, int *piv_len, int iv_requir Encrypts given data with given method and key, returns raw or base64 encoded string */ PHP_FUNCTION(openssl_encrypt) { - long options = 0; + zend_long options = 0; char *data, *method, *password, *iv = ""; - int data_len, method_len, password_len, iv_len = 0, max_iv_len; + size_t data_len, method_len, password_len, iv_len = 0, max_iv_len; const EVP_CIPHER *cipher_type; EVP_CIPHER_CTX cipher_ctx; int i=0, outlen, keylen; - unsigned char *outbuf, *key; + zend_string *outbuf; + unsigned char *key; zend_bool free_iv; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|ls", &data, &data_len, &method, &method_len, &password, &password_len, &options, &iv, &iv_len) == FAILURE) { @@ -5192,10 +5081,10 @@ PHP_FUNCTION(openssl_encrypt) if (iv_len <= 0 && max_iv_len > 0) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Using an empty Initialization Vector (iv) is potentially insecure and not recommended"); } - free_iv = php_openssl_validate_iv(&iv, &iv_len, max_iv_len TSRMLS_CC); + free_iv = php_openssl_validate_iv(&iv, (int *)&iv_len, max_iv_len TSRMLS_CC); outlen = data_len + EVP_CIPHER_block_size(cipher_type); - outbuf = emalloc(outlen + 1); + outbuf = zend_string_alloc(outlen, 0); EVP_EncryptInit(&cipher_ctx, cipher_type, NULL, NULL); if (password_len > keylen) { @@ -5206,24 +5095,24 @@ PHP_FUNCTION(openssl_encrypt) EVP_CIPHER_CTX_set_padding(&cipher_ctx, 0); } if (data_len > 0) { - EVP_EncryptUpdate(&cipher_ctx, outbuf, &i, (unsigned char *)data, data_len); + EVP_EncryptUpdate(&cipher_ctx, (unsigned char*)outbuf->val, &i, (unsigned char *)data, data_len); } outlen = i; - if (EVP_EncryptFinal(&cipher_ctx, (unsigned char *)outbuf + i, &i)) { + if (EVP_EncryptFinal(&cipher_ctx, (unsigned char *)outbuf->val + i, &i)) { outlen += i; if (options & OPENSSL_RAW_DATA) { - outbuf[outlen] = '\0'; - RETVAL_STRINGL((char *)outbuf, outlen, 0); + outbuf->val[outlen] = '\0'; + outbuf->len = outlen; + RETVAL_STR(outbuf); } else { - int base64_str_len; - char *base64_str; + zend_string *base64_str; - base64_str = (char*)php_base64_encode(outbuf, outlen, &base64_str_len); - efree(outbuf); - RETVAL_STRINGL(base64_str, base64_str_len, 0); + base64_str = php_base64_encode((unsigned char*)outbuf->val, outlen); + zend_string_release(outbuf); + RETVAL_STR(base64_str); } } else { - efree(outbuf); + zend_string_release(outbuf); RETVAL_FALSE; } if (key != (unsigned char*)password) { @@ -5240,15 +5129,15 @@ PHP_FUNCTION(openssl_encrypt) Takes raw or base64 encoded string and dectupt it using given method and key */ PHP_FUNCTION(openssl_decrypt) { - long options = 0; + zend_long options = 0; char *data, *method, *password, *iv = ""; - int data_len, method_len, password_len, iv_len = 0; + size_t data_len, method_len, password_len, iv_len = 0; const EVP_CIPHER *cipher_type; EVP_CIPHER_CTX cipher_ctx; int i, outlen, keylen; - unsigned char *outbuf, *key; - int base64_str_len; - char *base64_str = NULL; + zend_string *outbuf; + unsigned char *key; + zend_string *base64_str = NULL; zend_bool free_iv; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sss|ls", &data, &data_len, &method, &method_len, &password, &password_len, &options, &iv, &iv_len) == FAILURE) { @@ -5267,13 +5156,13 @@ PHP_FUNCTION(openssl_decrypt) } if (!(options & OPENSSL_RAW_DATA)) { - base64_str = (char*)php_base64_decode((unsigned char*)data, data_len, &base64_str_len); + base64_str = php_base64_decode((unsigned char*)data, data_len); if (!base64_str) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "Failed to base64 decode the input"); RETURN_FALSE; } - data_len = base64_str_len; - data = base64_str; + data_len = base64_str->len; + data = base64_str->val; } keylen = EVP_CIPHER_key_length(cipher_type); @@ -5285,10 +5174,10 @@ PHP_FUNCTION(openssl_decrypt) key = (unsigned char*)password; } - free_iv = php_openssl_validate_iv(&iv, &iv_len, EVP_CIPHER_iv_length(cipher_type) TSRMLS_CC); + free_iv = php_openssl_validate_iv(&iv, (int *)&iv_len, EVP_CIPHER_iv_length(cipher_type) TSRMLS_CC); outlen = data_len + EVP_CIPHER_block_size(cipher_type); - outbuf = emalloc(outlen + 1); + outbuf = zend_string_alloc(outlen, 0); EVP_DecryptInit(&cipher_ctx, cipher_type, NULL, NULL); if (password_len > keylen) { @@ -5298,14 +5187,15 @@ PHP_FUNCTION(openssl_decrypt) if (options & OPENSSL_ZERO_PADDING) { EVP_CIPHER_CTX_set_padding(&cipher_ctx, 0); } - EVP_DecryptUpdate(&cipher_ctx, outbuf, &i, (unsigned char *)data, data_len); + EVP_DecryptUpdate(&cipher_ctx, (unsigned char*)outbuf->val, &i, (unsigned char *)data, data_len); outlen = i; - if (EVP_DecryptFinal(&cipher_ctx, (unsigned char *)outbuf + i, &i)) { + if (EVP_DecryptFinal(&cipher_ctx, (unsigned char *)outbuf->val + i, &i)) { outlen += i; - outbuf[outlen] = '\0'; - RETVAL_STRINGL((char *)outbuf, outlen, 0); + outbuf->val[outlen] = '\0'; + outbuf->len = outlen; + RETVAL_STR(outbuf); } else { - efree(outbuf); + zend_string_release(outbuf); RETVAL_FALSE; } if (key != (unsigned char*)password) { @@ -5315,7 +5205,7 @@ PHP_FUNCTION(openssl_decrypt) efree(iv); } if (base64_str) { - efree(base64_str); + zend_string_release(base64_str); } EVP_CIPHER_CTX_cleanup(&cipher_ctx); } @@ -5325,7 +5215,7 @@ PHP_FUNCTION(openssl_decrypt) PHP_FUNCTION(openssl_cipher_iv_length) { char *method; - int method_len; + size_t method_len; const EVP_CIPHER *cipher_type; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &method, &method_len) == FAILURE) { @@ -5349,35 +5239,36 @@ PHP_FUNCTION(openssl_cipher_iv_length) /* {{{ proto string openssl_dh_compute_key(string pub_key, resource dh_key) - Computes shared sicret for public value of remote DH key and local DH key */ + Computes shared secret for public value of remote DH key and local DH key */ PHP_FUNCTION(openssl_dh_compute_key) { zval *key; char *pub_str; - int pub_len; + size_t pub_len; EVP_PKEY *pkey; BIGNUM *pub; - char *data; + zend_string *data; int len; 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; } pub = BN_bin2bn((unsigned char*)pub_str, pub_len, NULL); - data = emalloc(DH_size(pkey->pkey.dh) + 1); - len = DH_compute_key((unsigned char*)data, pub, pkey->pkey.dh); + data = zend_string_alloc(DH_size(pkey->pkey.dh), 0); + len = DH_compute_key((unsigned char*)data->val, pub, pkey->pkey.dh); if (len >= 0) { - data[len] = 0; - RETVAL_STRINGL(data, len, 0); + data->len = len; + data->val[len] = 0; + RETVAL_STR(data); } else { - efree(data); + zend_string_release(data); RETVAL_FALSE; } @@ -5389,12 +5280,12 @@ PHP_FUNCTION(openssl_dh_compute_key) Returns a string of the length specified filled with random pseudo bytes */ PHP_FUNCTION(openssl_random_pseudo_bytes) { - long buffer_length; - unsigned char *buffer = NULL; + zend_long buffer_length; + zend_string *buffer = NULL; zval *zstrong_result_returned = NULL; int strong_result = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|z", &buffer_length, &zstrong_result_returned) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l|z/", &buffer_length, &zstrong_result_returned) == FAILURE) { return; } @@ -5407,21 +5298,21 @@ PHP_FUNCTION(openssl_random_pseudo_bytes) ZVAL_BOOL(zstrong_result_returned, 0); } - buffer = emalloc(buffer_length + 1); + buffer = zend_string_alloc(buffer_length, 0); #ifdef PHP_WIN32 strong_result = 1; /* random/urandom equivalent on Windows */ - if (php_win32_get_random_bytes(buffer, (size_t) buffer_length) == FAILURE){ - efree(buffer); + if (php_win32_get_random_bytes((unsigned char*)buffer->val, (size_t) buffer_length) == FAILURE){ + zend_string_release(buffer); if (zstrong_result_returned) { ZVAL_BOOL(zstrong_result_returned, 0); } RETURN_FALSE; } #else - if ((strong_result = RAND_pseudo_bytes(buffer, buffer_length)) < 0) { - efree(buffer); + if ((strong_result = RAND_pseudo_bytes((unsigned char*)buffer->val, buffer_length)) < 0) { + zend_string_release(buffer); if (zstrong_result_returned) { ZVAL_BOOL(zstrong_result_returned, 0); } @@ -5429,8 +5320,8 @@ PHP_FUNCTION(openssl_random_pseudo_bytes) } #endif - buffer[buffer_length] = 0; - RETVAL_STRINGL((char *)buffer, buffer_length, 0); + buffer->val[buffer_length] = 0; + RETVAL_STR(buffer); if (zstrong_result_returned) { ZVAL_BOOL(zstrong_result_returned, strong_result); @@ -5446,3 +5337,4 @@ PHP_FUNCTION(openssl_random_pseudo_bytes) * vim600: sw=4 ts=4 fdm=marker * vim<600: sw=4 ts=4 */ + |