Skip to content

Commit

Permalink
Merge branch 'PHP-7.4'
Browse files Browse the repository at this point in the history
  • Loading branch information
bukka committed Apr 28, 2019
2 parents 8f71468 + 78bed33 commit 5b7acc6
Show file tree
Hide file tree
Showing 8 changed files with 244 additions and 24 deletions.
6 changes: 6 additions & 0 deletions ext/openssl/openssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -1574,6 +1574,9 @@ PHP_MINIT_FUNCTION(openssl)
php_stream_xport_register("tlsv1.0", php_openssl_ssl_socket_factory);
php_stream_xport_register("tlsv1.1", php_openssl_ssl_socket_factory);
php_stream_xport_register("tlsv1.2", php_openssl_ssl_socket_factory);
#if OPENSSL_VERSION_NUMBER >= 0x10101000
php_stream_xport_register("tlsv1.3", php_openssl_ssl_socket_factory);
#endif

/* override the default tcp socket provider */
php_stream_xport_register("tcp", php_openssl_ssl_socket_factory);
Expand Down Expand Up @@ -1647,6 +1650,9 @@ PHP_MSHUTDOWN_FUNCTION(openssl)
php_stream_xport_unregister("tlsv1.0");
php_stream_xport_unregister("tlsv1.1");
php_stream_xport_unregister("tlsv1.2");
#if OPENSSL_VERSION_NUMBER >= 0x10101000
php_stream_xport_unregister("tlsv1.3");
#endif

/* reinstate the default tcp handler */
php_stream_xport_register("tcp", php_stream_generic_socket_factory);
Expand Down
58 changes: 58 additions & 0 deletions ext/openssl/tests/session_meta_capture_tlsv13.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
--TEST--
Capture SSL session meta array in stream context for TLSv1.3
--SKIPIF--
<?php
if (!extension_loaded("openssl")) die("skip openssl not loaded");
if (!function_exists("proc_open")) die("skip no proc_open");
if (OPENSSL_VERSION_NUMBER < 0x10101000) die("skip OpenSSL v1.1.1 required");
?>
--FILE--
<?php
$certFile = __DIR__ . DIRECTORY_SEPARATOR . 'session_meta_capture_tlsv13.pem.tmp';
$cacertFile = __DIR__ . DIRECTORY_SEPARATOR . 'session_meta_capture_tlsv13-ca.pem.tmp';

$serverCode = <<<'CODE'
$serverUri = "ssl://127.0.0.1:64321";
$serverFlags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN;
$serverCtx = stream_context_create(['ssl' => [
'local_cert' => '%s',
'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_3_SERVER,
]]);
$server = stream_socket_server($serverUri, $errno, $errstr, $serverFlags, $serverCtx);
phpt_notify();
@stream_socket_accept($server, 1);
CODE;
$serverCode = sprintf($serverCode, $certFile);

$peerName = 'session_meta_capture_tlsv13';
$clientCode = <<<'CODE'
$serverUri = "ssl://127.0.0.1:64321";
$clientFlags = STREAM_CLIENT_CONNECT;
$clientCtx = stream_context_create(['ssl' => [
'verify_peer' => true,
'cafile' => '%s',
'peer_name' => '%s',
'capture_session_meta' => true,
]]);
phpt_wait();
stream_context_set_option($clientCtx, 'ssl', 'crypto_method', STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT);
@stream_socket_client($serverUri, $errno, $errstr, 1, $clientFlags, $clientCtx);
$meta = stream_context_get_options($clientCtx)['ssl']['session_meta'];
var_dump($meta['protocol']);
CODE;
$clientCode = sprintf($clientCode, $cacertFile, $peerName);

include 'CertificateGenerator.inc';
$certificateGenerator = new CertificateGenerator();
$certificateGenerator->saveCaCert($cacertFile);
$certificateGenerator->saveNewCertAsFileWithKey($peerName, $certFile);

include 'ServerClientTestCase.inc';
ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
?>
--EXPECT--
string(7) "TLSv1.3"
1 change: 1 addition & 0 deletions ext/openssl/tests/tls_wrapper.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ tls stream wrapper
<?php
if (!extension_loaded("openssl")) die("skip openssl not loaded");
if (!function_exists("proc_open")) die("skip no proc_open");
if (OPENSSL_VERSION_NUMBER < 0x10101000) die("skip OpenSSL v1.1.1 required");
?>
--FILE--
<?php
Expand Down
66 changes: 66 additions & 0 deletions ext/openssl/tests/tls_wrapper_with_tls_v1.3.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
--TEST--
tls stream wrapper when TLS 1.3 available
--SKIPIF--
<?php
if (!extension_loaded("openssl")) die("skip openssl not loaded");
if (!function_exists("proc_open")) die("skip no proc_open");
if (OPENSSL_VERSION_NUMBER < 0x10101000) die("skip OpenSSL v1.1.1 required");
?>
--FILE--
<?php
$serverCode = <<<'CODE'
$flags = STREAM_SERVER_BIND|STREAM_SERVER_LISTEN;
$ctx = stream_context_create(['ssl' => [
'local_cert' => __DIR__ . '/streams_crypto_method.pem',
]]);
$server = stream_socket_server('tls://127.0.0.1:64321', $errno, $errstr, $flags, $ctx);
phpt_notify();
for ($i = 0; $i < (phpt_has_sslv3() ? 7 : 6); $i++) {
@stream_socket_accept($server, 3);
}
CODE;

$clientCode = <<<'CODE'
$flags = STREAM_CLIENT_CONNECT;
$ctx = stream_context_create(['ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
]]);
phpt_wait();
$client = stream_socket_client("tlsv1.0://127.0.0.1:64321", $errno, $errstr, 3, $flags, $ctx);
var_dump($client);
$client = @stream_socket_client("sslv3://127.0.0.1:64321", $errno, $errstr, 3, $flags, $ctx);
var_dump($client);
$client = @stream_socket_client("tlsv1.1://127.0.0.1:64321", $errno, $errstr, 3, $flags, $ctx);
var_dump($client);
$client = @stream_socket_client("tlsv1.2://127.0.0.1:64321", $errno, $errstr, 3, $flags, $ctx);
var_dump($client);
$client = @stream_socket_client("tlsv1.3://127.0.0.1:64321", $errno, $errstr, 3, $flags, $ctx);
var_dump($client);
$client = @stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 3, $flags, $ctx);
var_dump($client);
$client = @stream_socket_client("tls://127.0.0.1:64321", $errno, $errstr, 3, $flags, $ctx);
var_dump($client);
CODE;

include 'ServerClientTestCase.inc';
ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
?>
--EXPECTF--
resource(%d) of type (stream)
bool(false)
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)
50 changes: 50 additions & 0 deletions ext/openssl/tests/tlsv1.3_wrapper.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
--TEST--
tlsv1.3 stream wrapper
--SKIPIF--
<?php
if (!extension_loaded("openssl")) die("skip openssl not loaded");
if (!function_exists("proc_open")) die("skip no proc_open");
if (OPENSSL_VERSION_NUMBER < 0x10101000) die("skip OpenSSL v1.1.1 required");
?>
--FILE--
<?php
$serverCode = <<<'CODE'
$flags = STREAM_SERVER_BIND|STREAM_SERVER_LISTEN;
$ctx = stream_context_create(['ssl' => [
'local_cert' => __DIR__ . '/streams_crypto_method.pem',
]]);
$server = stream_socket_server('tlsv1.3://127.0.0.1:64321', $errno, $errstr, $flags, $ctx);
phpt_notify();
for ($i=0; $i < 3; $i++) {
@stream_socket_accept($server, 3);
}
CODE;

$clientCode = <<<'CODE'
$flags = STREAM_CLIENT_CONNECT;
$ctx = stream_context_create(['ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
]]);
phpt_wait();
$client = stream_socket_client("tlsv1.3://127.0.0.1:64321", $errno, $errstr, 3, $flags, $ctx);
var_dump($client);
$client = @stream_socket_client("tlsv1.0://127.0.0.1:64321", $errno, $errstr, 3, $flags, $ctx);
var_dump($client);
$client = @stream_socket_client("tlsv1.2://127.0.0.1:64321", $errno, $errstr, 3, $flags, $ctx);
var_dump($client);
CODE;

include 'ServerClientTestCase.inc';
ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
?>
--EXPECTF--
resource(%d) of type (stream)
bool(false)
bool(false)
68 changes: 51 additions & 17 deletions ext/openssl/xp_ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -58,18 +58,13 @@
#define STREAM_CRYPTO_METHOD_TLSv1_0 (1<<3)
#define STREAM_CRYPTO_METHOD_TLSv1_1 (1<<4)
#define STREAM_CRYPTO_METHOD_TLSv1_2 (1<<5)

#ifndef OPENSSL_NO_SSL3
#define HAVE_SSL3 1
#define PHP_OPENSSL_MIN_PROTO_VERSION STREAM_CRYPTO_METHOD_SSLv3
#else
#define PHP_OPENSSL_MIN_PROTO_VERSION STREAM_CRYPTO_METHOD_TLSv1_0
#endif
#define PHP_OPENSSL_MAX_PROTO_VERSION STREAM_CRYPTO_METHOD_TLSv1_2

#define STREAM_CRYPTO_METHOD_TLSv1_3 (1<<6)

#define HAVE_TLS11 1
#define HAVE_TLS12 1
#if OPENSSL_VERSION_NUMBER >= 0x10101000
#define HAVE_TLS13 1
#endif

#ifndef OPENSSL_NO_ECDH
#define HAVE_ECDH 1
Expand All @@ -86,6 +81,18 @@
#define HAVE_SEC_LEVEL 1
#endif

#ifndef OPENSSL_NO_SSL3
#define HAVE_SSL3 1
#define PHP_OPENSSL_MIN_PROTO_VERSION STREAM_CRYPTO_METHOD_SSLv3
#else
#define PHP_OPENSSL_MIN_PROTO_VERSION STREAM_CRYPTO_METHOD_TLSv1_0
#endif
#ifdef HAVE_TLS13
#define PHP_OPENSSL_MAX_PROTO_VERSION STREAM_CRYPTO_METHOD_TLSv1_3
#else
#define PHP_OPENSSL_MAX_PROTO_VERSION STREAM_CRYPTO_METHOD_TLSv1_2
#endif

/* Simplify ssl context option retrieval */
#define GET_VER_OPT(name) \
(PHP_STREAM_CONTEXT(stream) && (val = php_stream_context_get_option(PHP_STREAM_CONTEXT(stream), "ssl", name)) != NULL)
Expand Down Expand Up @@ -998,6 +1005,11 @@ static int php_openssl_get_crypto_method_ctx_flags(int method_flags) /* {{{ */
ssl_ctx_options |= SSL_OP_NO_TLSv1_2;
}
#endif
#ifdef HAVE_TLS13
if (!(method_flags & STREAM_CRYPTO_METHOD_TLSv1_3)) {
ssl_ctx_options |= SSL_OP_NO_TLSv1_3;
}
#endif

return ssl_ctx_options;
}
Expand All @@ -1012,7 +1024,7 @@ static inline int php_openssl_get_min_proto_version_flag(int flags) /* {{{ */
return ver;
}
}
return STREAM_CRYPTO_METHOD_TLSv1_2;
return PHP_OPENSSL_MAX_PROTO_VERSION;
}
/* }}} */

Expand All @@ -1024,26 +1036,30 @@ static inline int php_openssl_get_max_proto_version_flag(int flags) /* {{{ */
return ver;
}
}
return STREAM_CRYPTO_METHOD_TLSv1_2;
return STREAM_CRYPTO_METHOD_TLSv1_3;
}
/* }}} */

#if PHP_OPENSSL_API_VERSION >= 0x10100
static inline int php_openssl_map_proto_version(int flag) /* {{{ */
{
switch (flag) {
#ifdef HAVE_TLS13
case STREAM_CRYPTO_METHOD_TLSv1_3:
return TLS1_3_VERSION;
#endif
case STREAM_CRYPTO_METHOD_TLSv1_2:
return TLS1_2_VERSION;
case STREAM_CRYPTO_METHOD_TLSv1_1:
return TLS1_1_VERSION;
case STREAM_CRYPTO_METHOD_TLSv1_0:
return TLS1_VERSION;
#ifdef HAVE_SSL3
case STREAM_CRYPTO_METHOD_SSLv3:
return SSL3_VERSION;
#endif
case STREAM_CRYPTO_METHOD_TLSv1_0:
return TLS1_VERSION;
case STREAM_CRYPTO_METHOD_TLSv1_1:
return TLS1_1_VERSION;
/* case STREAM_CRYPTO_METHOD_TLSv1_2: */
default:
return TLS1_2_VERSION;

}
}
/* }}} */
Expand Down Expand Up @@ -1788,6 +1804,11 @@ static zend_array *php_openssl_capture_session_meta(SSL *ssl_handle) /* {{{ */
char version_str[PHP_SSL_MAX_VERSION_LEN];

switch (proto) {
#ifdef HAVE_TLS13
case TLS1_3_VERSION:
proto_str = "TLSv1.3";
break;
#endif
#ifdef HAVE_TLS12
case TLS1_2_VERSION:
proto_str = "TLSv1.2";
Expand Down Expand Up @@ -2392,6 +2413,9 @@ static int php_openssl_sockop_set_option(php_stream *stream, int option, int val
array_init(&tmp);

switch (SSL_version(sslsock->ssl_handle)) {
#ifdef HAVE_TLS13
case TLS1_3_VERSION: proto_str = "TLSv1.3"; break;
#endif
#ifdef HAVE_TLS12
case TLS1_2_VERSION: proto_str = "TLSv1.2"; break;
#endif
Expand Down Expand Up @@ -2731,6 +2755,16 @@ php_stream *php_openssl_ssl_socket_factory(const char *proto, size_t protolen,
"TLSv1.2 support is not compiled into the OpenSSL library against which PHP is linked");
php_stream_close(stream);
return NULL;
#endif
} else if (strncmp(proto, "tlsv1.3", protolen) == 0) {
#ifdef HAVE_TLS13
sslsock->enable_on_connect = 1;
sslsock->method = STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT;
#else
php_error_docref(NULL, E_WARNING,
"TLSv1.3 support is not compiled into the OpenSSL library against which PHP is linked");
php_stream_close(stream);
return NULL;
#endif
}

Expand Down
3 changes: 3 additions & 0 deletions ext/standard/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ PHP_MINIT_FUNCTION(file)
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT", STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT", STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT", STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT", STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_ANY_SERVER", STREAM_CRYPTO_METHOD_ANY_SERVER, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv2_SERVER", STREAM_CRYPTO_METHOD_SSLv2_SERVER, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv3_SERVER", STREAM_CRYPTO_METHOD_SSLv3_SERVER, CONST_CS|CONST_PERSISTENT);
Expand All @@ -225,11 +226,13 @@ PHP_MINIT_FUNCTION(file)
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_0_SERVER", STREAM_CRYPTO_METHOD_TLSv1_0_SERVER, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_1_SERVER", STREAM_CRYPTO_METHOD_TLSv1_1_SERVER, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_2_SERVER", STREAM_CRYPTO_METHOD_TLSv1_2_SERVER, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_3_SERVER", STREAM_CRYPTO_METHOD_TLSv1_3_SERVER, CONST_CS|CONST_PERSISTENT);

REGISTER_LONG_CONSTANT("STREAM_CRYPTO_PROTO_SSLv3", STREAM_CRYPTO_METHOD_SSLv3_SERVER, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_PROTO_TLSv1_0", STREAM_CRYPTO_METHOD_TLSv1_0_SERVER, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_PROTO_TLSv1_1", STREAM_CRYPTO_METHOD_TLSv1_1_SERVER, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_PROTO_TLSv1_2", STREAM_CRYPTO_METHOD_TLSv1_2_SERVER, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("STREAM_CRYPTO_PROTO_TLSv1_3", STREAM_CRYPTO_METHOD_TLSv1_3_SERVER, CONST_CS|CONST_PERSISTENT);

REGISTER_LONG_CONSTANT("STREAM_SHUT_RD", STREAM_SHUT_RD, CONST_CS|CONST_PERSISTENT);
REGISTER_LONG_CONSTANT("STREAM_SHUT_WR", STREAM_SHUT_WR, CONST_CS|CONST_PERSISTENT);
Expand Down
16 changes: 9 additions & 7 deletions main/streams/php_stream_transport.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,21 +171,23 @@ typedef enum {
STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT = (1 << 3 | 1),
STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT = (1 << 4 | 1),
STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT = (1 << 5 | 1),
STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT = (1 << 6 | 1),
/* TLS equates to TLS_ANY as of PHP 7.2 */
STREAM_CRYPTO_METHOD_TLS_CLIENT = ((1 << 3) | (1 << 4) | (1 << 5) | 1),
STREAM_CRYPTO_METHOD_TLS_ANY_CLIENT = ((1 << 3) | (1 << 4) | (1 << 5) | 1),
STREAM_CRYPTO_METHOD_ANY_CLIENT = ((1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | 1),
STREAM_CRYPTO_METHOD_TLS_CLIENT = ((1 << 3) | (1 << 4) | (1 << 5) | (1 << 6) | 1),
STREAM_CRYPTO_METHOD_TLS_ANY_CLIENT = ((1 << 3) | (1 << 4) | (1 << 5) | (1 << 6) | 1),
STREAM_CRYPTO_METHOD_ANY_CLIENT = ((1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6) | 1),
STREAM_CRYPTO_METHOD_SSLv2_SERVER = (1 << 1),
STREAM_CRYPTO_METHOD_SSLv3_SERVER = (1 << 2),
/* v23 no longer negotiates SSL2 or SSL3 */
STREAM_CRYPTO_METHOD_SSLv23_SERVER = ((1 << 3) | (1 << 4) | (1 << 5)),
STREAM_CRYPTO_METHOD_SSLv23_SERVER = ((1 << 3) | (1 << 4) | (1 << 5) | (1 << 6)),
STREAM_CRYPTO_METHOD_TLSv1_0_SERVER = (1 << 3),
STREAM_CRYPTO_METHOD_TLSv1_1_SERVER = (1 << 4),
STREAM_CRYPTO_METHOD_TLSv1_2_SERVER = (1 << 5),
STREAM_CRYPTO_METHOD_TLSv1_3_SERVER = (1 << 6),
/* TLS equates to TLS_ANY as of PHP 7.2 */
STREAM_CRYPTO_METHOD_TLS_SERVER = ((1 << 3) | (1 << 4) | (1 << 5)),
STREAM_CRYPTO_METHOD_TLS_ANY_SERVER = ((1 << 3) | (1 << 4) | (1 << 5)),
STREAM_CRYPTO_METHOD_ANY_SERVER = ((1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5))
STREAM_CRYPTO_METHOD_TLS_SERVER = ((1 << 3) | (1 << 4) | (1 << 5) | (1 << 6)),
STREAM_CRYPTO_METHOD_TLS_ANY_SERVER = ((1 << 3) | (1 << 4) | (1 << 5) | (1 << 6)),
STREAM_CRYPTO_METHOD_ANY_SERVER = ((1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | (1 << 6))
} php_stream_xport_crypt_method_t;

/* These functions provide crypto support on the underlying transport */
Expand Down

0 comments on commit 5b7acc6

Please sign in to comment.