couple of resource leaks fixes and use after free's

This commit is contained in:
David Carlier 2016-06-27 07:42:49 +01:00
parent 8de8636a2b
commit 85e985f191
16 changed files with 800 additions and 36 deletions

8
NEWS
View File

@ -2,6 +2,10 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? 2016, PHP 7.1.0beta1
- CURL:
. Add curl_multi_errno(), curl_share_errno() and curl_share_strerror()
functions. (Pierrick)
- PCRE:
. Fixed bug #72476 (Memleak in jit_stack). (Laruence)
. Fixed bug #72463 (mail fails with invalid argument). (Anatol)
@ -9,6 +13,10 @@ PHP NEWS
- Standard:
. array_multisort now uses zend_sort instead zend_qsort. (Laruence)
- OpenSSL:
. Implemented FR #61204 (Add elliptic curve support for OpenSSL).
(Dominic Luechinger)
23 Jun 2016, PHP 7.1.0alpha2
- Core:

View File

@ -392,6 +392,10 @@ ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_close, 0)
ZEND_ARG_INFO(0, mh)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_errno, 0)
ZEND_ARG_INFO(0, mh)
ZEND_END_ARG_INFO()
#if LIBCURL_VERSION_NUM >= 0x070c00 /* Available since 7.12.0 */
ZEND_BEGIN_ARG_INFO(arginfo_curl_strerror, 0)
ZEND_ARG_INFO(0, errornum)
@ -400,6 +404,10 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_curl_multi_strerror, 0)
ZEND_ARG_INFO(0, errornum)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_curl_share_strerror, 0)
ZEND_ARG_INFO(0, errornum)
ZEND_END_ARG_INFO()
#endif
ZEND_BEGIN_ARG_INFO(arginfo_curl_share_init, 0)
@ -415,6 +423,10 @@ ZEND_BEGIN_ARG_INFO(arginfo_curl_share_setopt, 0)
ZEND_ARG_INFO(0, value)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO(arginfo_curl_share_errno, 0)
ZEND_ARG_INFO(0, sh)
ZEND_END_ARG_INFO()
#if LIBCURL_VERSION_NUM >= 0x071200 /* Available since 7.18.0 */
ZEND_BEGIN_ARG_INFO(arginfo_curl_pause, 0)
ZEND_ARG_INFO(0, ch)
@ -445,6 +457,7 @@ const zend_function_entry curl_functions[] = {
#if LIBCURL_VERSION_NUM >= 0x070c00 /* 7.12.0 */
PHP_FE(curl_strerror, arginfo_curl_strerror)
PHP_FE(curl_multi_strerror, arginfo_curl_multi_strerror)
PHP_FE(curl_share_strerror, arginfo_curl_share_strerror)
#endif
#if LIBCURL_VERSION_NUM >= 0x070c01 /* 7.12.1 */
PHP_FE(curl_reset, arginfo_curl_reset)
@ -464,12 +477,14 @@ const zend_function_entry curl_functions[] = {
PHP_FE(curl_multi_getcontent, arginfo_curl_multi_getcontent)
PHP_FE(curl_multi_info_read, arginfo_curl_multi_info_read)
PHP_FE(curl_multi_close, arginfo_curl_multi_close)
PHP_FE(curl_multi_errno, arginfo_curl_multi_errno)
#if LIBCURL_VERSION_NUM >= 0x070f04 /* 7.15.4 */
PHP_FE(curl_multi_setopt, arginfo_curl_multi_setopt)
#endif
PHP_FE(curl_share_init, arginfo_curl_share_init)
PHP_FE(curl_share_close, arginfo_curl_share_close)
PHP_FE(curl_share_setopt, arginfo_curl_share_setopt)
PHP_FE(curl_share_errno, arginfo_curl_share_errno)
PHP_FE(curl_file_create, arginfo_curlfile_create)
PHP_FE_END
};

View File

@ -49,6 +49,8 @@
#include <unistd.h>
#endif
#define SAVE_CURLM_ERROR(__handle, __err) (__handle)->err.no = (int) __err;
/* {{{ proto resource curl_multi_init(void)
Returns a new cURL multi handle */
PHP_FUNCTION(curl_multi_init)
@ -77,6 +79,7 @@ PHP_FUNCTION(curl_multi_add_handle)
php_curlm *mh;
php_curl *ch;
zval tmp_val;
CURLMcode error = CURLM_OK;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr", &z_mh, &z_ch) == FAILURE) {
return;
@ -97,7 +100,10 @@ PHP_FUNCTION(curl_multi_add_handle)
zend_llist_add_element(&mh->easyh, &tmp_val);
RETURN_LONG((zend_long)curl_multi_add_handle(mh->multi, ch->cp));
error = curl_multi_add_handle(mh->multi, ch->cp);
SAVE_CURLM_ERROR(mh, error);
RETURN_LONG((zend_long) error);
}
/* }}} */
@ -137,6 +143,7 @@ PHP_FUNCTION(curl_multi_remove_handle)
zval *z_ch;
php_curlm *mh;
php_curl *ch;
CURLMcode error = CURLM_OK;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rr", &z_mh, &z_ch) == FAILURE) {
return;
@ -150,7 +157,10 @@ PHP_FUNCTION(curl_multi_remove_handle)
RETURN_FALSE;
}
RETVAL_LONG((zend_long)curl_multi_remove_handle(mh->multi, ch->cp));
error = curl_multi_remove_handle(mh->multi, ch->cp);
SAVE_CURLM_ERROR(mh, error);
RETVAL_LONG((zend_long) error);
zend_llist_del_element(&mh->easyh, z_ch, (int (*)(void *, void *))curl_compare_resources);
}
@ -178,6 +188,7 @@ PHP_FUNCTION(curl_multi_select)
int maxfd;
double timeout = 1.0;
struct timeval to;
CURLMcode error = CURLM_OK;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|d", &z_mh, &timeout) == FAILURE) {
return;
@ -193,7 +204,9 @@ PHP_FUNCTION(curl_multi_select)
FD_ZERO(&writefds);
FD_ZERO(&exceptfds);
curl_multi_fdset(mh->multi, &readfds, &writefds, &exceptfds, &maxfd);
error = curl_multi_fdset(mh->multi, &readfds, &writefds, &exceptfds, &maxfd);
SAVE_CURLM_ERROR(mh, error);
if (maxfd == -1) {
RETURN_LONG(-1);
}
@ -209,7 +222,7 @@ PHP_FUNCTION(curl_multi_exec)
zval *z_still_running;
php_curlm *mh;
int still_running;
int result;
CURLMcode error = CURLM_OK;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz/", &z_mh, &z_still_running) == FAILURE) {
return;
@ -237,10 +250,11 @@ PHP_FUNCTION(curl_multi_exec)
convert_to_long(z_still_running);
still_running = Z_LVAL_P(z_still_running);
result = curl_multi_perform(mh->multi, &still_running);
error = curl_multi_perform(mh->multi, &still_running);
ZVAL_LONG(z_still_running, still_running);
RETURN_LONG(result);
SAVE_CURLM_ERROR(mh, error);
RETURN_LONG((zend_long) error);
}
/* }}} */
@ -383,6 +397,25 @@ void _php_curl_multi_close(zend_resource *rsrc) /* {{{ */
}
/* }}} */
/* {{{ proto int curl_multi_errno(resource mh)
Return an integer containing the last multi curl error number */
PHP_FUNCTION(curl_multi_errno)
{
zval *z_mh;
php_curlm *mh;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &z_mh) == FAILURE) {
return;
}
if ((mh = (php_curlm *)zend_fetch_resource(Z_RES_P(z_mh), le_curl_multi_handle_name, le_curl_multi_handle)) == NULL) {
RETURN_FALSE;
}
RETURN_LONG(mh->err.no);
}
/* }}} */
#if LIBCURL_VERSION_NUM >= 0x070c00 /* Available since 7.12.0 */
/* {{{ proto bool curl_multi_strerror(int code)
return string describing error code */
@ -433,6 +466,7 @@ static int _php_curl_multi_setopt(php_curlm *mh, zend_long option, zval *zvalue,
break;
}
SAVE_CURLM_ERROR(mh, error);
if (error != CURLM_OK) {
return 1;
} else {

View File

@ -90,14 +90,17 @@ PHP_FUNCTION(curl_multi_info_read);
PHP_FUNCTION(curl_multi_init);
PHP_FUNCTION(curl_multi_remove_handle);
PHP_FUNCTION(curl_multi_select);
PHP_FUNCTION(curl_multi_errno);
PHP_FUNCTION(curl_share_close);
PHP_FUNCTION(curl_share_init);
PHP_FUNCTION(curl_share_setopt);
PHP_FUNCTION(curl_share_errno);
#if LIBCURL_VERSION_NUM >= 0x070c00 /* 7.12.0 */
PHP_FUNCTION(curl_strerror);
PHP_FUNCTION(curl_multi_strerror);
PHP_FUNCTION(curl_share_strerror);
#endif
#if LIBCURL_VERSION_NUM >= 0x070c01 /* 7.12.1 */
@ -114,6 +117,7 @@ PHP_FUNCTION(curl_multi_setopt);
#if LIBCURL_VERSION_NUM >= 0x071200 /* 7.18.0 */
PHP_FUNCTION(curl_pause);
#endif
PHP_FUNCTION(curl_file_create);
@ -190,10 +194,16 @@ typedef struct {
int still_running;
CURLM *multi;
zend_llist easyh;
struct {
int no;
} err;
} php_curlm;
typedef struct {
CURLSH *share;
struct {
int no;
} err;
} php_curlsh;
void _php_curl_cleanup_handle(php_curl *);

View File

@ -32,6 +32,8 @@
#include <curl/curl.h>
#define SAVE_CURLSH_ERROR(__handle, __err) (__handle)->err.no = (int) __err;
/* {{{ proto void curl_share_init()
Initialize a share curl handle */
PHP_FUNCTION(curl_share_init)
@ -85,6 +87,7 @@ static int _php_curl_share_setopt(php_curlsh *sh, zend_long option, zval *zvalue
break;
}
SAVE_CURLSH_ERROR(sh, error);
if (error != CURLSHE_OK) {
return 1;
} else {
@ -128,6 +131,48 @@ void _php_curl_share_close(zend_resource *rsrc) /* {{{ */
}
/* }}} */
/* {{{ proto int curl_share_errno(resource mh)
Return an integer containing the last share curl error number */
PHP_FUNCTION(curl_share_errno)
{
zval *z_sh;
php_curlsh *sh;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &z_sh) == FAILURE) {
return;
}
if ((sh = (php_curlsh *)zend_fetch_resource(Z_RES_P(z_sh), le_curl_share_handle_name, le_curl_share_handle)) == NULL) {
RETURN_FALSE;
}
RETURN_LONG(sh->err.no);
}
/* }}} */
#if LIBCURL_VERSION_NUM >= 0x070c00 /* Available since 7.12.0 */
/* {{{ proto bool curl_share_strerror(int code)
return string describing error code */
PHP_FUNCTION(curl_share_strerror)
{
zend_long code;
const char *str;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &code) == FAILURE) {
return;
}
str = curl_share_strerror(code);
if (str) {
RETURN_STRING(str);
} else {
RETURN_NULL();
}
}
/* }}} */
#endif
#endif
/*

View File

@ -0,0 +1,30 @@
--TEST--
curl_multi_errno and curl_multi_strerror basic test
--SKIPIF--
<?php
if (!extension_loaded("curl")) {
exit("skip curl extension not loaded");
}
$curl_version = curl_version();
if ($curl_version['version_number'] < 0x070f04) {
exit("skip: test works only with curl >= 7.15.4");
}
?>
--FILE--
<?php
$mh = curl_multi_init();
$errno = curl_multi_errno($mh);
echo $errno . PHP_EOL;
echo curl_multi_strerror($errno) . PHP_EOL;
@curl_multi_setopt($mh, -1, -1);
$errno = curl_multi_errno($mh);
echo $errno . PHP_EOL;
echo curl_multi_strerror($errno) . PHP_EOL;
?>
--EXPECTF--
0
No error
6
Unknown option

View File

@ -0,0 +1,30 @@
--TEST--
curl_share_errno and curl_share_strerror basic test
--SKIPIF--
<?php
if (!extension_loaded("curl")) {
exit("skip curl extension not loaded");
}
$curl_version = curl_version();
if ($curl_version['version_number'] < 0x070c00) {
exit("skip: test works only with curl >= 7.12.0");
}
?>
--FILE--
<?php
$sh = curl_share_init();
$errno = curl_share_errno($sh);
echo $errno . PHP_EOL;
echo curl_share_strerror($errno) . PHP_EOL;
@curl_share_setopt($sh, -1, -1);
$errno = curl_share_errno($sh);
echo $errno . PHP_EOL;
echo curl_share_strerror($errno) . PHP_EOL;
?>
--EXPECTF--
0
No error
1
Unknown share option

View File

@ -791,6 +791,7 @@ int zend_file_cache_script_store(zend_persistent_script *script, int in_shm)
if (writev(fd, vec, 3) != (ssize_t)(sizeof(info) + script->size + info.str_size)) {
zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot write to file '%s'\n", filename);
zend_string_release((zend_string*)ZCG(mem));
close(fd);
efree(mem);
unlink(filename);
efree(filename);
@ -804,6 +805,7 @@ int zend_file_cache_script_store(zend_persistent_script *script, int in_shm)
) {
zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot write to file '%s'\n", filename);
zend_string_release((zend_string*)ZCG(mem));
close(fd);
efree(mem);
unlink(filename);
efree(filename);

View File

@ -118,6 +118,9 @@ enum php_openssl_cipher_type {
PHP_FUNCTION(openssl_get_md_methods);
PHP_FUNCTION(openssl_get_cipher_methods);
#ifdef HAVE_EVP_PKEY_EC
PHP_FUNCTION(openssl_get_curve_names);
#endif
PHP_FUNCTION(openssl_digest);
PHP_FUNCTION(openssl_encrypt);
@ -379,6 +382,11 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_get_cipher_methods, 0, 0, 0)
ZEND_ARG_INFO(0, aliases)
ZEND_END_ARG_INFO()
#ifdef HAVE_EVP_PKEY_EC
ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_get_curve_names, 0, 0, 0)
ZEND_END_ARG_INFO()
#endif
ZEND_BEGIN_ARG_INFO_EX(arginfo_openssl_digest, 0, 0, 2)
ZEND_ARG_INFO(0, data)
ZEND_ARG_INFO(0, method)
@ -515,6 +523,9 @@ const zend_function_entry openssl_functions[] = {
PHP_FE(openssl_get_md_methods, arginfo_openssl_get_md_methods)
PHP_FE(openssl_get_cipher_methods, arginfo_openssl_get_cipher_methods)
#ifdef HAVE_EVP_PKEY_EC
PHP_FE(openssl_get_curve_names, arginfo_openssl_get_curve_names)
#endif
PHP_FE(openssl_dh_compute_key, arginfo_openssl_dh_compute_key)
@ -672,6 +683,10 @@ struct php_x509_request { /* {{{ */
int priv_key_encrypt;
#ifdef HAVE_EVP_PKEY_EC
int curve_name;
#endif
EVP_PKEY * priv_key;
const EVP_CIPHER * priv_key_encrypt_cipher;
@ -761,7 +776,7 @@ static time_t asn1_time_to_time_t(ASN1_UTCTIME * timestr) /* {{{ */
This is how the time string is formatted:
snprintf(p, sizeof(p), "%02d%02d%02d%02d%02d%02dZ",ts->tm_year%100,
ts->tm_mon+1,ts->tm_mday,ts->tm_hour,ts->tm_min,ts->tm_sec);
ts->tm_mon+1,ts->tm_mday,ts->tm_hour,ts->tm_min,ts->tm_sec);
*/
time_t ret;
@ -1035,6 +1050,18 @@ static int php_openssl_parse_config(struct php_x509_request * req, zval * option
}
PHP_SSL_CONFIG_SYNTAX_CHECK(extensions_section);
#ifdef HAVE_EVP_PKEY_EC
/* set the ec group curve name */
req->curve_name = NID_undef;
if (optional_args && (item = zend_hash_str_find(Z_ARRVAL_P(optional_args), "curve_name", sizeof("curve_name")-1)) != NULL
&& Z_TYPE_P(item) == IS_STRING) {
req->curve_name = OBJ_sn2nid(Z_STRVAL_P(item));
if (req->curve_name == NID_undef) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unknown elliptic curve (short) name %s", Z_STRVAL_P(item));
return FAILURE;
}
}
#endif
/* set the string mask */
str = CONF_get_string(req->req_config, req->section_name, "string_mask");
@ -3730,6 +3757,26 @@ static EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req
}
}
break;
#endif
#ifdef HAVE_EVP_PKEY_EC
case OPENSSL_KEYTYPE_EC:
{
if (req->curve_name == NID_undef) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "Missing configuration value: 'curve_name' not set");
return NULL;
}
EC_KEY *eckey = EC_KEY_new_by_curve_name(req->curve_name);
if (eckey) {
EC_KEY_set_asn1_flag(eckey, OPENSSL_EC_NAMED_CURVE);
if (EC_KEY_generate_key(eckey) &&
EVP_PKEY_assign_EC_KEY(req->priv_key, eckey)) {
return_val = req->priv_key;
} else {
EC_KEY_free(eckey);
}
}
}
break;
#endif
default:
php_error_docref(NULL, E_WARNING, "Unsupported private key type");
@ -3805,24 +3852,30 @@ static int php_openssl_is_private_key(EVP_PKEY* pkey)
}
/* }}} */
#define OPENSSL_PKEY_GET_BN(_type, _name) do { \
if (pkey->pkey._type->_name != NULL) { \
int len = BN_num_bytes(pkey->pkey._type->_name); \
zend_string *str = zend_string_alloc(len, 0); \
BN_bn2bin(pkey->pkey._type->_name, (unsigned char*)ZSTR_VAL(str)); \
ZSTR_VAL(str)[len] = 0; \
add_assoc_str(&_type, #_name, str); \
} \
} while (0)
#define OPENSSL_GET_BN(_array, _bn, _name) do { \
if (_bn != NULL) { \
int len = BN_num_bytes(_bn); \
zend_string *str = zend_string_alloc(len, 0); \
BN_bn2bin(_bn, (unsigned char*)ZSTR_VAL(str)); \
ZSTR_VAL(str)[len] = 0; \
add_assoc_str(&_array, #_name, str); \
} \
} while (0);
#define OPENSSL_PKEY_SET_BN(_ht, _type, _name) do { \
zval *bn; \
#define OPENSSL_PKEY_GET_BN(_type, _name) do { \
if (pkey->pkey._type->_name != NULL) { \
OPENSSL_GET_BN(_type, pkey->pkey._type->_name, _name); \
} \
} while (0);
#define OPENSSL_PKEY_SET_BN(_ht, _type, _name) do { \
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_P(bn), \
(int)Z_STRLEN_P(bn), NULL); \
} \
Z_TYPE_P(bn) == IS_STRING) { \
_type->_name = BN_bin2bn( \
(unsigned char*)Z_STRVAL_P(bn), \
(int)Z_STRLEN_P(bn), NULL); \
} \
} while (0);
/* {{{ php_openssl_pkey_init_dsa */
@ -3968,6 +4021,118 @@ PHP_FUNCTION(openssl_pkey_new)
php_openssl_store_errors();
}
RETURN_FALSE;
#ifdef HAVE_EVP_PKEY_EC
} else if ((data = zend_hash_str_find(Z_ARRVAL_P(args), "ec", sizeof("ec") - 1)) != NULL &&
Z_TYPE_P(data) == IS_ARRAY) {
EC_KEY *eckey = NULL;
EC_GROUP *group = NULL;
EC_POINT *pnt = NULL;
const BIGNUM *d;
pkey = EVP_PKEY_new();
if (pkey) {
eckey = EC_KEY_new();
if (eckey) {
EC_GROUP *group = NULL;
zval *bn;
zval *x;
zval *y;
if ((bn = zend_hash_str_find(Z_ARRVAL_P(data), "curve_name", sizeof("curve_name") - 1)) != NULL &&
Z_TYPE_P(bn) == IS_STRING) {
int nid = OBJ_sn2nid(Z_STRVAL_P(bn));
if (nid != NID_undef) {
group = EC_GROUP_new_by_curve_name(nid);
if (!group) {
php_openssl_store_errors();
goto clean_exit;
}
EC_GROUP_set_asn1_flag(group, OPENSSL_EC_NAMED_CURVE);
EC_GROUP_set_point_conversion_form(group, POINT_CONVERSION_UNCOMPRESSED);
if (!EC_KEY_set_group(eckey, group)) {
php_openssl_store_errors();
goto clean_exit;
}
}
}
if (group == NULL) {
php_error_docref(NULL, E_WARNING, "Unknown curve_name");
goto clean_exit;
}
// The public key 'pnt' can be calculated from 'd' or is defined by 'x' and 'y'
if ((bn = zend_hash_str_find(Z_ARRVAL_P(data), "d", sizeof("d") - 1)) != NULL &&
Z_TYPE_P(bn) == IS_STRING) {
d = BN_bin2bn((unsigned char*) Z_STRVAL_P(bn), Z_STRLEN_P(bn), NULL);
if (!EC_KEY_set_private_key(eckey, d)) {
php_openssl_store_errors();
goto clean_exit;
}
// Calculate the public key by multiplying the Point Q with the public key
// P = d * Q
pnt = EC_POINT_new(group);
if (!pnt || !EC_POINT_mul(group, pnt, d, NULL, NULL, NULL)) {
php_openssl_store_errors();
goto clean_exit;
}
} else if ((x = zend_hash_str_find(Z_ARRVAL_P(data), "x", sizeof("x") - 1)) != NULL &&
Z_TYPE_P(x) == IS_STRING &&
(y = zend_hash_str_find(Z_ARRVAL_P(data), "y", sizeof("y") - 1)) != NULL &&
Z_TYPE_P(y) == IS_STRING) {
pnt = EC_POINT_new(group);
if (pnt == NULL) {
php_openssl_store_errors();
goto clean_exit;
}
if (!EC_POINT_set_affine_coordinates_GFp(
group, pnt, BN_bin2bn((unsigned char*) Z_STRVAL_P(x), Z_STRLEN_P(x), NULL),
BN_bin2bn((unsigned char*) Z_STRVAL_P(y), Z_STRLEN_P(y), NULL), NULL)) {
php_openssl_store_errors();
goto clean_exit;
}
}
if (pnt != NULL) {
if (!EC_KEY_set_public_key(eckey, pnt)) {
php_openssl_store_errors();
goto clean_exit;
}
EC_POINT_free(pnt);
pnt = NULL;
}
if (!EC_KEY_check_key(eckey)) {
PHP_OPENSSL_RAND_ADD_TIME();
EC_KEY_generate_key(eckey);
php_openssl_store_errors();
}
if (EC_KEY_check_key(eckey) && EVP_PKEY_assign_EC_KEY(pkey, eckey)) {
EC_GROUP_free(group);
RETURN_RES(zend_register_resource(pkey, le_key));
} else {
php_openssl_store_errors();
}
} else {
php_openssl_store_errors();
}
} else {
php_openssl_store_errors();
}
clean_exit:
if (pnt != NULL) {
EC_POINT_free(pnt);
}
if (group != NULL) {
EC_GROUP_free(group);
}
if (eckey != NULL) {
EC_KEY_free(eckey);
}
if (pkey != NULL) {
EVP_PKEY_free(pkey);
}
RETURN_FALSE;
#endif
}
}
@ -4303,13 +4468,18 @@ PHP_FUNCTION(openssl_pkey_get_details)
if (pkey->pkey.ec != NULL) {
zval ec;
const EC_GROUP *ec_group;
const EC_POINT *pub;
int nid;
char *crv_sn;
ASN1_OBJECT *obj;
// openssl recommends a buffer length of 80
char oir_buf[80];
const EC_KEY *ec_key = EVP_PKEY_get1_EC_KEY(pkey);
BIGNUM *x = BN_new();
BIGNUM *y = BN_new();
const BIGNUM *d;
ec_group = EC_KEY_get0_group(EVP_PKEY_get1_EC_KEY(pkey));
ec_group = EC_KEY_get0_group(ec_key);
// Curve nid (numerical identifier) used for ASN1 mapping
nid = EC_GROUP_get_curve_name(ec_group);
@ -4327,11 +4497,27 @@ PHP_FUNCTION(openssl_pkey_get_details)
obj = OBJ_nid2obj(nid);
if (obj != NULL) {
int oir_len = OBJ_obj2txt(oir_buf, sizeof(oir_buf), obj, 1);
add_assoc_stringl(&ec, "curve_oid", (char*)oir_buf, oir_len);
add_assoc_stringl(&ec, "curve_oid", (char*) oir_buf, oir_len);
ASN1_OBJECT_free(obj);
}
pub = EC_KEY_get0_public_key(ec_key);
if (EC_POINT_get_affine_coordinates_GFp(ec_group, pub, x, y, NULL)) {
OPENSSL_GET_BN(ec, x, x);
OPENSSL_GET_BN(ec, y, y);
} else {
php_openssl_store_errors();
}
if ((d = EC_KEY_get0_private_key(pkey->pkey.ec)) != NULL) {
OPENSSL_GET_BN(ec, d, d);
}
add_assoc_zval(return_value, "ec", &ec);
BN_free(x);
BN_free(y);
}
break;
#endif
@ -5540,6 +5726,33 @@ PHP_FUNCTION(openssl_get_cipher_methods)
}
/* }}} */
/* {{{ proto array openssl_get_curve_names()
Return array of available elliptic curves */
#ifdef HAVE_EVP_PKEY_EC
PHP_FUNCTION(openssl_get_curve_names)
{
EC_builtin_curve *curves = NULL;
const char *sname;
int i;
size_t len = EC_get_builtin_curves(NULL, 0);
curves = emalloc(sizeof(EC_builtin_curve) * len);
if (!EC_get_builtin_curves(curves, len)) {
RETURN_FALSE;
}
array_init(return_value);
for (i = 0; i < len; i++) {
sname = OBJ_nid2sn(curves[i].nid);
if (sname != NULL) {
add_next_index_string(return_value, sname);
}
}
efree(curves);
}
#endif
/* }}} */
/* {{{ proto string openssl_digest(string data, string method [, bool raw_output=false])
Computes digest hash value for given data using given method, returns raw or binhex encoded string */
PHP_FUNCTION(openssl_digest)

254
ext/openssl/tests/029.phpt Normal file
View File

@ -0,0 +1,254 @@
--TEST--
openssl_pkey_new() with EC key
--SKIPIF--
<?php
if (!extension_loaded("openssl")) die("skip");
if (!defined("OPENSSL_KEYTYPE_EC")) die("skip no EC available");
?>
--FILE--
<?php
$key = openssl_pkey_get_private("file://" . dirname(__FILE__) . "/private_ec.key");
$details = openssl_pkey_get_details($key);
print_r($details);
echo "Use details an create the same key pair\n";
$key2 = openssl_pkey_new($details);
$details2 = openssl_pkey_get_details($key2);
print_r($details2);
var_dump(array_diff($details["ec"], $details2["ec"]));
echo "Missing 'd' parameter (private key part) => no private key informations\n";
$detailsCopy3 = $details;
unset($detailsCopy3["ec"]["d"]);
$key3 = openssl_pkey_new($detailsCopy3);
$details3 = openssl_pkey_get_details($key3);
print_r($details3);
var_dump(array_diff($details["ec"], $details3["ec"]));
$privateKey3 = openssl_pkey_get_private($key3);
var_dump($privateKey3);
$publicKey3 = openssl_pkey_get_public($key3);
var_dump($publicKey3);
var_dump($details["key"] === $details3["key"]);
echo "Missing 'x' parameter will not change the details. The public key is calculated from the private key 'd'\n";
$detailsCopy4 = $details;
unset($detailsCopy4["ec"]["x"]);
$key4 = openssl_pkey_new($detailsCopy4);
$details4 = openssl_pkey_get_details($key4);
print_r($details4);
var_dump(array_diff($details["ec"], $details4["ec"]));
echo "Missing 'y' parameter will not change the details. The public key is calculated from the private key 'd'\n";
$detailsCopy5 = $details;
unset($detailsCopy5["ec"]["y"]);
$key5 = openssl_pkey_new($detailsCopy5);
$details5 = openssl_pkey_get_details($key5);
print_r($details5);
var_dump(array_diff($details["ec"], $details5["ec"]));
echo "Missing 'd' and 'x' parameters will generate a new public key pair\n";
$detailsCopy6 = $details;
unset($detailsCopy6["ec"]["d"]);
unset($detailsCopy6["ec"]["x"]);
$key6 = openssl_pkey_new($detailsCopy6);
$details6 = openssl_pkey_get_details($key6);
print_r($details6);
var_dump(array_diff($details["ec"], $details6["ec"]));
echo "Missing 'd' and 'y' parameters will generate a new public key pair\n";
$detailsCopy7 = $details;
unset($detailsCopy7["ec"]["d"]);
unset($detailsCopy7["ec"]["y"]);
$key7 = openssl_pkey_new($detailsCopy7);
$details7 = openssl_pkey_get_details($key7);
print_r($details7);
var_dump(array_diff($details["ec"], $details7["ec"]));
// Tests vectors from http://point-at-infinity.org/ecc/nisttv
echo "Create a private key from scratch 1\n";
$detailsFromScratch8 = array(
"ec" => array(
"curve_name" => "prime256v1",
"d" => "\1",
),
);
$key8 = openssl_pkey_new($detailsFromScratch8);
$details8 = openssl_pkey_get_details($key8);
var_dump(strtoupper(bin2hex($details8["ec"]["x"])) === "6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296");
var_dump(strtoupper(bin2hex($details8["ec"]["y"])) === "4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5");
echo "Create a private key from scratch 2\n";
$detailsFromScratch9 = array(
"ec" => array(
"curve_name" => "prime192v1",
"d" => hex2bin("7FFFFFFFFE0000007FFFFE003FFFFFE0007FFF1FFFFE0800"),
),
);
$key9 = openssl_pkey_new($detailsFromScratch9);
$details9 = openssl_pkey_get_details($key9);
var_dump(strtoupper(bin2hex($details9["ec"]["x"])) === "45DAF0A306121BDB3B82E734CB44FDF65C9930F0E4FD2068");
var_dump(strtoupper(bin2hex($details9["ec"]["y"])) === "F039FACE58EB7DE34E3374ADB28DF81F019C4548BAA75B64");
?>
--EXPECTF--
Array
(
[bits] => 256
[key] => -----BEGIN PUBLIC KEY-----%a
-----END PUBLIC KEY-----
[ec] => Array
(
[curve_name] => prime256v1
[curve_oid] => 1.2.840.10045.3.1.7
[x] => %a
[y] => %a
[d] => %a
)
[type] => 3
)
Use details an create the same key pair
Array
(
[bits] => 256
[key] => -----BEGIN PUBLIC KEY-----%a
-----END PUBLIC KEY-----
[ec] => Array
(
[curve_name] => prime256v1
[curve_oid] => 1.2.840.10045.3.1.7
[x] => %a
[y] => %a
[d] => %a
)
[type] => 3
)
array(0) {
}
Missing 'd' parameter (private key part) => no private key informations
Array
(
[bits] => 256
[key] => -----BEGIN PUBLIC KEY-----%a
-----END PUBLIC KEY-----
[ec] => Array
(
[curve_name] => prime256v1
[curve_oid] => 1.2.840.10045.3.1.7
[x] => %a
[y] => %a
)
[type] => 3
)
array(1) {
["d"]=>
string(32) "%a"
}
Warning: openssl_pkey_get_private(): supplied key param is a public key in %s on line %d
bool(false)
resource(%d) of type (OpenSSL key)
bool(true)
Missing 'x' parameter will not change the details. The public key is calculated from the private key 'd'
Array
(
[bits] => 256
[key] => -----BEGIN PUBLIC KEY-----%a
-----END PUBLIC KEY-----
[ec] => Array
(
[curve_name] => prime256v1
[curve_oid] => 1.2.840.10045.3.1.7
[x] => %a
[y] => %a
[d] => %a
)
[type] => 3
)
array(0) {
}
Missing 'y' parameter will not change the details. The public key is calculated from the private key 'd'
Array
(
[bits] => 256
[key] => -----BEGIN PUBLIC KEY-----%a
-----END PUBLIC KEY-----
[ec] => Array
(
[curve_name] => prime256v1
[curve_oid] => 1.2.840.10045.3.1.7
[x] => %a
[y] => %a
[d] => %a
)
[type] => 3
)
array(0) {
}
Missing 'd' and 'x' parameters will generate a new public key pair
Array
(
[bits] => 256
[key] => -----BEGIN PUBLIC KEY-----%a
-----END PUBLIC KEY-----
[ec] => Array
(
[curve_name] => prime256v1
[curve_oid] => 1.2.840.10045.3.1.7
[x] => %a
[y] => %a
[d] => %a
)
[type] => 3
)
array(3) {
["x"]=>
string(32) "%a"
["y"]=>
string(32) "%a"
["d"]=>
string(32) "%a"
}
Missing 'd' and 'y' parameters will generate a new public key pair
Array
(
[bits] => 256
[key] => -----BEGIN PUBLIC KEY-----%a
-----END PUBLIC KEY-----
[ec] => Array
(
[curve_name] => prime256v1
[curve_oid] => 1.2.840.10045.3.1.7
[x] => %a
[y] => %a
[d] => %a
)
[type] => 3
)
array(3) {
["x"]=>
string(32) "%a"
["y"]=>
string(32) "%a"
["d"]=>
string(32) "%a"
}
Create a private key from scratch 1
bool(true)
bool(true)
Create a private key from scratch 2
bool(true)
bool(true)

110
ext/openssl/tests/ecc.phpt Normal file
View File

@ -0,0 +1,110 @@
--TEST--
openssl_*() with OPENSSL_KEYTYPE_EC
--SKIPIF--
<?php if (!extension_loaded("openssl") && !defined("OPENSSL_KEYTYPE_EC")) print "skip"; ?>
--FILE--
<?php
$args = array(
"curve_name" => "secp384r1",
"private_key_type" => OPENSSL_KEYTYPE_EC,
);
echo "Testing openssl_pkey_new\n";
$key1 = openssl_pkey_new($args);
var_dump($key1);
$argsFailed = array(
"curve_name" => "invalid_cuve_name",
"private_key_type" => OPENSSL_KEYTYPE_EC,
);
$keyFailed = openssl_pkey_new($argsFailed);
var_dump($keyFailed);
$d1 = openssl_pkey_get_details($key1);
var_dump($d1["bits"]);
var_dump(strlen($d1["key"]));
var_dump($d1["ec"]["curve_name"]);
var_dump($d1["type"] == OPENSSL_KEYTYPE_EC);
$key2 = openssl_pkey_new($d1);
var_dump($key2);
$d2 = openssl_pkey_get_details($key2);
// Compare array
var_dump($d1 === $d2);
$dn = array(
"countryName" => "BR",
"stateOrProvinceName" => "Rio Grande do Sul",
"localityName" => "Porto Alegre",
"commonName" => "Henrique do N. Angelo",
"emailAddress" => "hnangelo@php.net"
);
// openssl_csr_new creates a new public key pair if the key argument is null
echo "Testing openssl_csr_new with key generation\n";
$keyGenerate = null;
var_dump($keyGenerate);
$csr = openssl_csr_new($dn, $keyGenerate, $args);
var_dump($keyGenerate);
$args["digest_alg"] = "sha1";
echo "Testing openssl_csr_new with existing ecc key\n";
$csr = openssl_csr_new($dn, $key1, $args);
var_dump($csr);
$pubkey1 = openssl_pkey_get_details(openssl_csr_get_public_key($csr));
var_dump(isset($pubkey1["ec"]["priv_key"]));
unset($d1["ec"]["priv_key"]);
var_dump(array_diff($d1["ec"], $pubkey1["ec"]));
$x509 = openssl_csr_sign($csr, null, $key1, 365, $args);
var_dump($x509);
echo "Testing openssl_x509_check_private_key\n";
var_dump(openssl_x509_check_private_key($x509, $key1));
$key3 = openssl_pkey_new($args);
var_dump(openssl_x509_check_private_key($x509, $key3));
echo "Testing openssl_get_curve_names\n";
$curve_names = openssl_get_curve_names();
var_dump(is_array($curve_names));
foreach ($curve_names as $curve_name) {
if ("secp384r1" === $curve_name) {
echo "Found secp384r1 in curve names\n";
}
}
?>
--EXPECTF--
Testing openssl_pkey_new
resource(%d) of type (OpenSSL key)
Warning: openssl_pkey_new(): Unknown elliptic curve (short) name invalid_cuve_name in %s on line %d
bool(false)
int(384)
int(215)
string(9) "secp384r1"
bool(true)
resource(%d) of type (OpenSSL key)
bool(true)
Testing openssl_csr_new with key generation
NULL
resource(%d) of type (OpenSSL key)
Testing openssl_csr_new with existing ecc key
resource(%d) of type (OpenSSL X.509 CSR)
bool(false)
array(1) {
["d"]=>
string(48) "%a"
}
resource(%d) of type (OpenSSL X.509)
Testing openssl_x509_check_private_key
bool(true)
bool(false)
Testing openssl_get_curve_names
bool(true)
Found secp384r1 in curve names

View File

@ -2,8 +2,10 @@
openssl_pkey_export() with EC key
--SKIPIF--
<?php
if (!extension_loaded("openssl")) die("skip");
if (!defined('OPENSSL_KEYTYPE_EC')) die("skip no EC available");
if (!extension_loaded("openssl"))
die("skip");
if (!defined('OPENSSL_KEYTYPE_EC'))
die("skip no EC available");
?>
--FILE--
<?php
@ -28,9 +30,9 @@ var_dump(OPENSSL_KEYTYPE_EC === $details['type']);
// Read public key
$pKey = openssl_pkey_get_public('file://' . dirname(__FILE__) . '/public_ec.key');
var_dump($pKey);
// The details are the same for a public or private key
var_dump($details === openssl_pkey_get_details($pKey));
// The details are the same for a public or private key, expect the private key parameter 'd
$detailsPKey = openssl_pkey_get_details($pKey);
var_dump(array_diff_assoc($details['ec'], $detailsPKey['ec']));
// Export to file
$tempname = tempnam(sys_get_temp_dir(), 'openssl_ec');
@ -40,7 +42,6 @@ var_dump(OPENSSL_KEYTYPE_EC === $details['type']);
// Clean the temporary file
@unlink($tempname);
?>
--EXPECTF--
resource(%d) of type (OpenSSL key)
@ -49,6 +50,9 @@ bool(true)
bool(true)
bool(true)
resource(%d) of type (OpenSSL key)
bool(true)
array(1) {
["d"]=>
string(32) "%a"
}
bool(true)
bool(true)

View File

@ -3,11 +3,11 @@ openssl_pkey_get_details() with EC key
--SKIPIF--
<?php
if (!extension_loaded("openssl")) die("skip");
if (!defined('OPENSSL_KEYTYPE_EC')) die("skip no EC available");
if (!defined("OPENSSL_KEYTYPE_EC")) die("skip no EC available");
?>
--FILE--
<?php
$key = openssl_pkey_get_private('file://' . dirname(__FILE__) . '/private_ec.key');
$key = openssl_pkey_get_private("file://" . dirname(__FILE__) . "/private_ec.key");
print_r(openssl_pkey_get_details($key));
?>
@ -22,6 +22,9 @@ Array
(
[curve_name] => prime256v1
[curve_oid] => 1.2.840.10045.3.1.7
[x] => %a
[y] => %a
[d] => %a
)
[type] => 3

View File

@ -758,6 +758,7 @@ int fcgi_listen(const char *path, int backlog)
bind(listen_socket, (struct sockaddr *) &sa, sock_len) < 0 ||
listen(listen_socket, backlog) < 0) {
close(listen_socket);
fcgi_log(FCGI_ERROR, "Cannot bind/listen socket - [%d] %s.\n",errno, strerror(errno));
return -1;
}

View File

@ -224,8 +224,10 @@ char** save_ps_args(int argc, char** argv)
for (i = 0; i < argc; i++)
{
new_argv[i] = strdup(argv[i]);
if (!new_argv[i])
if (!new_argv[i]) {
free(new_argv);
goto clobber_error;
}
}
new_argv[argc] = NULL;

View File

@ -1433,6 +1433,7 @@ phpdbg_main:
case 'i': { /* set init file */
if (init_file) {
free(init_file);
init_file = NULL;
}
init_file_len = strlen(php_optarg);
@ -1786,7 +1787,9 @@ phpdbg_main:
/* initialize from file */
PHPDBG_G(flags) |= PHPDBG_IS_INITIALIZING;
zend_try {
phpdbg_init(init_file, init_file_len, init_file_default);
if (init_file) {
phpdbg_init(init_file, init_file_len, init_file_default);
}
if (bp_tmp) {
PHPDBG_G(flags) |= PHPDBG_DISCARD_OUTPUT;
phpdbg_string_init(bp_tmp);