Permalink
Browse files

Merge branch 'PHP-5.6'

* PHP-5.6:
  Improve OpenSSL compile flag compatibility, minor updates
  Use crypto method flags; add tlsv1.0 wrapper; add wrapper tests
  Improve server forward secrecy, refactor client SNI
  Add 'honor_cipher_order' server context option
  Add 'capture_session_meta' context option
  Disable TLS compression by default in both clients and servers
  Release ssl buffers
  Add openssl_get_cert_locations() function
  Explicitly set cert verify depth if not specified
  Strengthen default cipher list
  • Loading branch information...
2 parents 0140e83 + dcf27a1 commit 86d9235de5b0fd5576e01c601f1bd04333d13ba3 @rdlowrey rdlowrey committed Feb 21, 2014
View
@@ -83,6 +83,15 @@
#define HAVE_EVP_PKEY_EC 1
#endif
+#define PHP_OPENSSL_DEFAULT_STREAM_VERIFY_DEPTH 9
+#define PHP_OPENSSL_DEFAULT_STREAM_CIPHERS "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:" \
+ "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:" \
+ "DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:" \
+ "ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:" \
+ "ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:" \
+ "DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:" \
+ "AES256-GCM-SHA384:AES128:AES256:HIGH:!SSLv2:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!RC4:!ADH"
+
/* FIXME: Use the openssl constants instead of
* enum. It is now impossible to match real values
* against php constants. Also sorry to break the
@@ -424,11 +433,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)
@@ -1151,6 +1165,10 @@ 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", PHP_OPENSSL_DEFAULT_STREAM_CIPHERS, CONST_CS|CONST_PERSISTENT);
+ REGISTER_LONG_CONSTANT("OPENSSL_DEFAULT_STREAM_VERIFY_DEPTH", PHP_OPENSSL_DEFAULT_STREAM_VERIFY_DEPTH, 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);
@@ -1206,6 +1224,7 @@ 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);
@@ -1251,6 +1270,7 @@ 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);
@@ -1267,6 +1287,26 @@ PHP_MSHUTDOWN_FUNCTION(openssl)
/* {{{ 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(), 1);
+ add_assoc_string(return_value, "default_cert_file_env", (char *) X509_get_default_cert_file_env(), 1);
+ add_assoc_string(return_value, "default_cert_dir", (char *) X509_get_default_cert_dir(), 1);
+ add_assoc_string(return_value, "default_cert_dir_env", (char *) X509_get_default_cert_dir_env(), 1);
+ add_assoc_string(return_value, "default_private_dir", (char *) X509_get_default_private_dir(), 1);
+ add_assoc_string(return_value, "default_default_cert_area", (char *) X509_get_default_cert_area(), 1);
+ add_assoc_string(return_value, "ini_cafile",
+ zend_ini_string("openssl.cafile", sizeof("openssl.cafile"), 0), 1);
+ add_assoc_string(return_value, "ini_capath",
+ zend_ini_string("openssl.capath", sizeof("openssl.capath"), 0), 1);
+}
+/* }}} */
+
+
/* {{{ php_openssl_x509_from_zval
Given a zval, coerce it into an X509 object.
The zval can be:
@@ -5328,6 +5368,8 @@ SSL *php_SSL_new_from_context(SSL_CTX *ctx, php_stream *stream TSRMLS_DC) /* {{{
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_depth(ctx, PHP_OPENSSL_DEFAULT_STREAM_VERIFY_DEPTH);
}
}
@@ -5339,7 +5381,7 @@ SSL *php_SSL_new_from_context(SSL_CTX *ctx, php_stream *stream TSRMLS_DC) /* {{{
GET_VER_OPT_STRING("ciphers", cipherlist);
if (!cipherlist) {
- cipherlist = "DEFAULT";
+ cipherlist = PHP_OPENSSL_DEFAULT_STREAM_CIPHERS;
}
if (SSL_CTX_set_cipher_list(ctx, cipherlist) != 1) {
return NULL;
@@ -85,6 +85,8 @@ PHP_FUNCTION(openssl_spki_new);
PHP_FUNCTION(openssl_spki_verify);
PHP_FUNCTION(openssl_spki_export);
PHP_FUNCTION(openssl_spki_export_challenge);
+
+PHP_FUNCTION(openssl_get_cert_locations);
#else
#define phpext_openssl_ptr NULL
@@ -3,7 +3,7 @@ Bug #66501: EC private key support in openssl_sign
--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
$pkey = 'ASN1 OID: prime256v1
@@ -0,0 +1,73 @@
+--TEST--
+Capture SSL session meta array in stream context
+--SKIPIF--
+<?php
+if (!extension_loaded("openssl")) die("skip");
+if (!function_exists('pcntl_fork')) die("skip no fork");
+if (OPENSSL_VERSION_NUMBER < 0x10001001) die("skip OpenSSLv1.0.1 required");
+--FILE--
+<?php
+$flags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN;
+$ctx = stream_context_create(['ssl' => [
+ 'local_cert' => __DIR__ . '/bug54992.pem',
+ 'allow_self_signed' => true
+]]);
+$server = stream_socket_server('ssl://127.0.0.1:64321', $errno, $errstr, $flags, $ctx);
+
+$pid = pcntl_fork();
+if ($pid == -1) {
+ die('could not fork');
+} else if ($pid) {
+
+ // Base SSL context values
+ $sslCtxVars = array(
+ 'verify_peer' => TRUE,
+ 'cafile' => __DIR__ . '/bug54992-ca.pem',
+ 'CN_match' => 'bug54992.local', // common name from the server's "local_cert" PEM file
+ 'capture_session_meta' => TRUE
+ );
+
+ // SSLv3
+ $ctxCopy = $sslCtxVars;
+ $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_SSLv3_CLIENT;
+ $ctx = stream_context_create(array('ssl' => $ctxCopy));
+ stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx);
+ $meta = stream_context_get_options($ctx)['ssl']['session_meta'];
+ var_dump($meta['protocol']);
+
+ // TLSv1
+ $ctxCopy = $sslCtxVars;
+ $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT;
+ $ctx = stream_context_create(array('ssl' => $ctxCopy));
+ stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx);
+ $meta = stream_context_get_options($ctx)['ssl']['session_meta'];
+ var_dump($meta['protocol']);
+
+ // TLSv1.1
+ $ctxCopy = $sslCtxVars;
+ $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
+ $ctx = stream_context_create(array('ssl' => $ctxCopy));
+ stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx);
+ $meta = stream_context_get_options($ctx)['ssl']['session_meta'];
+ var_dump($meta['protocol']);
+
+ // TLSv1.2
+ $ctxCopy = $sslCtxVars;
+ $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
+ $ctx = stream_context_create(array('ssl' => $ctxCopy));
+ stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx);
+ $meta = stream_context_get_options($ctx)['ssl']['session_meta'];
+ var_dump($meta['protocol']);
+
+} else {
+ @pcntl_wait($status);
+ @stream_socket_accept($server, 1);
+ @stream_socket_accept($server, 1);
+ @stream_socket_accept($server, 1);
+ @stream_socket_accept($server, 1);
+}
+--EXPECTF--
+string(5) "SSLv3"
+string(5) "TLSv1"
+string(7) "TLSv1.1"
+string(7) "TLSv1.2"
@@ -0,0 +1,58 @@
+--TEST--
+Basic bitwise stream crypto context flag assignment
+--SKIPIF--
+<?php
+if (!extension_loaded("openssl")) die("skip");
+if (!function_exists('pcntl_fork')) die("skip no fork");
+--FILE--
+<?php
+$flags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN;
+$ctx = stream_context_create(['ssl' => [
+ 'local_cert' => __DIR__ . '/bug54992.pem',
+ 'allow_self_signed' => true
+]]);
+$server = stream_socket_server('ssl://127.0.0.1:64321', $errno, $errstr, $flags, $ctx);
+var_dump($server);
+
+$pid = pcntl_fork();
+if ($pid == -1) {
+ die('could not fork');
+} else if ($pid) {
+
+ // Base SSL context values
+ $sslCtxVars = array(
+ 'verify_peer' => TRUE,
+ 'cafile' => __DIR__ . '/bug54992-ca.pem',
+ 'CN_match' => 'bug54992.local', // common name from the server's "local_cert" PEM file
+ );
+
+ // SSLv3
+ $ctxCopy = $sslCtxVars;
+ $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_SSLv3_CLIENT;
+ $ctx = stream_context_create(array('ssl' => $ctxCopy));
+ var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx));
+
+ // TLSv1
+ $ctxCopy = $sslCtxVars;
+ $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT;
+ $ctx = stream_context_create(array('ssl' => $ctxCopy));
+ var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx));
+
+ // TLS (any)
+ $ctxCopy = $sslCtxVars;
+ $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLS_CLIENT;
+ $ctx = stream_context_create(array('ssl' => $ctxCopy));
+ var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx));
+
+} else {
+ @pcntl_wait($status);
+ @stream_socket_accept($server, 1);
+ @stream_socket_accept($server, 1);
+ @stream_socket_accept($server, 1);
+}
+--EXPECTF--
+resource(%d) of type (stream)
+resource(%d) of type (stream)
+resource(%d) of type (stream)
+resource(%d) of type (stream)
+
@@ -0,0 +1,67 @@
+--TEST--
+TLSv1.1 and TLSv1.2 bitwise stream crypto flag assignment
+--SKIPIF--
+<?php
+if (!extension_loaded("openssl")) die("skip");
+if (!function_exists('pcntl_fork')) die("skip no fork");
+if (OPENSSL_VERSION_NUMBER < 0x10001001) die("skip OpenSSLv1.0.1 required");
+--FILE--
+<?php
+$flags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN;
+$ctx = stream_context_create(['ssl' => [
+ 'local_cert' => __DIR__ . '/bug54992.pem',
+ 'allow_self_signed' => true
+]]);
+$server = stream_socket_server('ssl://127.0.0.1:64321', $errno, $errstr, $flags, $ctx);
+var_dump($server);
+
+$pid = pcntl_fork();
+if ($pid == -1) {
+ die('could not fork');
+} else if ($pid) {
+
+ // Base SSL context values
+ $sslCtxVars = array(
+ 'verify_peer' => TRUE,
+ 'cafile' => __DIR__ . '/bug54992-ca.pem',
+ 'CN_match' => 'bug54992.local', // common name from the server's "local_cert" PEM file
+ );
+
+ // TLSv1
+ $ctxCopy = $sslCtxVars;
+ $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT;
+ $ctx = stream_context_create(array('ssl' => $ctxCopy));
+ var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx));
+
+ // TLSv1.1
+ $ctxCopy = $sslCtxVars;
+ $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
+ $ctx = stream_context_create(array('ssl' => $ctxCopy));
+ var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx));
+
+ // TLSv1.2
+ $ctxCopy = $sslCtxVars;
+ $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
+ $ctx = stream_context_create(array('ssl' => $ctxCopy));
+ var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx));
+
+ // TLS (any)
+ $ctxCopy = $sslCtxVars;
+ $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLS_CLIENT;
+ $ctx = stream_context_create(array('ssl' => $ctxCopy));
+ var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx));
+
+} else {
+ @pcntl_wait($status);
+ @stream_socket_accept($server, 1);
+ @stream_socket_accept($server, 1);
+ @stream_socket_accept($server, 1);
+ @stream_socket_accept($server, 1);
+}
+--EXPECTF--
+resource(%d) of type (stream)
+resource(%d) of type (stream)
+resource(%d) of type (stream)
+resource(%d) of type (stream)
+resource(%d) of type (stream)
+
@@ -0,0 +1,68 @@
+--TEST--
+Server bitwise stream crypto flag assignment
+--SKIPIF--
+<?php
+if (!extension_loaded("openssl")) die("skip");
+if (!function_exists('pcntl_fork')) die("skip no fork");
+if (OPENSSL_VERSION_NUMBER < 0x10001001) die("skip OpenSSLv1.0.1 required");
+--FILE--
+<?php
+$flags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN;
+$ctx = stream_context_create(['ssl' => [
+ 'local_cert' => __DIR__ . '/bug54992.pem',
+ 'allow_self_signed' => true,
+
+ // Only accept SSLv3 and TLSv1.2 connections
+ 'crypto_method' => STREAM_CRYPTO_METHOD_SSLv3_SERVER | STREAM_CRYPTO_METHOD_TLSv1_2_SERVER
+]]);
+$server = stream_socket_server('ssl://127.0.0.1:64321', $errno, $errstr, $flags, $ctx);
+var_dump($server);
+
+$pid = pcntl_fork();
+if ($pid == -1) {
+ die('could not fork');
+} else if ($pid) {
+
+ // Base SSL context values
+ $sslCtxVars = array(
+ 'verify_peer' => TRUE,
+ 'cafile' => __DIR__ . '/bug54992-ca.pem',
+ 'CN_match' => 'bug54992.local', // common name from the server's "local_cert" PEM file
+ );
+
+ // TLSv1.2
+ $ctxCopy = $sslCtxVars;
+ $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT;
+ $ctx = stream_context_create(array('ssl' => $ctxCopy));
+ var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx));
+
+ // SSLv3
+ $ctxCopy = $sslCtxVars;
+ $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_SSLv3_CLIENT;
+ $ctx = stream_context_create(array('ssl' => $ctxCopy));
+ var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx));
+
+ // TLSv1 (should fail)
+ $ctxCopy = $sslCtxVars;
+ $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT;
+ $ctx = stream_context_create(array('ssl' => $ctxCopy));
+ var_dump(@stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx));
+
+ // TLSv1.1 (should fail)
+ $ctxCopy = $sslCtxVars;
+ $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT;
+ $ctx = stream_context_create(array('ssl' => $ctxCopy));
+ var_dump(@stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx));
+
+} else {
+ @pcntl_wait($status);
+ @stream_socket_accept($server, 1);
+ @stream_socket_accept($server, 1);
+}
+--EXPECTF--
+resource(%d) of type (stream)
+resource(%d) of type (stream)
+resource(%d) of type (stream)
+bool(false)
+bool(false)
+
Oops, something went wrong.

0 comments on commit 86d9235

Please sign in to comment.