Skip to content

Commit

Permalink
Fixed #5552, see swoole_runtime/ssl/enable_crypto.phpt
Browse files Browse the repository at this point in the history
  • Loading branch information
matyhtf committed Nov 5, 2024
1 parent fd01ed7 commit 6d35c00
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 31 deletions.
24 changes: 10 additions & 14 deletions ext-src/swoole_runtime.cc
Original file line number Diff line number Diff line change
Expand Up @@ -775,28 +775,26 @@ static int socket_enable_crypto(php_stream *stream, Socket *sock, php_stream_xpo
php_stream_context *context = PHP_STREAM_CONTEXT(stream);
if (cparam->inputs.activate && !sock->ssl_is_available()) {
sock->enable_ssl_encrypt();
if (!sock->ssl_check_context()) {
return -1;
}
if (!socket_ssl_set_options(sock, context)) {
return -1;
}
if (!sock->ssl_handshake()) {
return -1;
}
return 0;
} else if (!cparam->inputs.activate && sock->ssl_is_available()) {
return sock->ssl_shutdown() ? 0 : -1;
}

if (context) {
zval *val = php_stream_context_get_option(context, "ssl", "capture_peer_cert");
if (val && zend_is_true(val) && !php_openssl_capture_peer_certs(stream, sock)) {
return -1;
}
/**
* returns 1: The TLS/SSL handshake was successfully completed, a TLS/SSL connection has been established.
*/
return 1;
} else if (!cparam->inputs.activate && sock->ssl_is_available()) {
sock->ssl_shutdown();
return -1;
}

return 0;
return 1;
}
#endif

Expand Down Expand Up @@ -1051,11 +1049,9 @@ static bool socket_ssl_set_options(Socket *sock, php_stream_context *context) {
add_alias("verify_depth", "ssl_verify_depth");
add_alias("disable_compression", "ssl_disable_compression");

php_swoole_socket_set_ssl(sock, &zalias);
if (!sock->ssl_check_context()) {
return false;
}
bool ret = php_swoole_socket_set_ssl(sock, &zalias);
zval_dtor(&zalias);
return ret;
}
#endif
}
Expand Down
12 changes: 3 additions & 9 deletions ext-src/swoole_socket_coro.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1129,7 +1129,6 @@ SW_API bool php_swoole_socket_set(Socket *cli, zval *zset) {
SW_API bool php_swoole_socket_set_ssl(Socket *sock, zval *zset) {
HashTable *vht = Z_ARRVAL_P(zset);
zval *ztmp;
bool ret = true;

if (php_swoole_array_get_value(vht, "ssl_protocols", ztmp)) {
zend_long v = zval_get_long(ztmp);
Expand All @@ -1146,7 +1145,7 @@ SW_API bool php_swoole_socket_set_ssl(Socket *sock, zval *zset) {
sock->get_ssl_context()->cert_file = str_v.to_std_string();
} else {
php_swoole_fatal_error(E_WARNING, "ssl cert file[%s] not found", str_v.val());
ret = false;
return false;
}
}
if (php_swoole_array_get_value(vht, "ssl_key_file", ztmp)) {
Expand All @@ -1155,7 +1154,7 @@ SW_API bool php_swoole_socket_set_ssl(Socket *sock, zval *zset) {
sock->get_ssl_context()->key_file = str_v.to_std_string();
} else {
php_swoole_fatal_error(E_WARNING, "ssl key file[%s] not found", str_v.val());
ret = false;
return false;
}
}
if (!sock->get_ssl_context()->cert_file.empty() && sock->get_ssl_context()->key_file.empty()) {
Expand Down Expand Up @@ -1195,18 +1194,13 @@ SW_API bool php_swoole_socket_set_ssl(Socket *sock, zval *zset) {
if (php_swoole_array_get_value(vht, "ssl_ecdh_curve", ztmp)) {
sock->get_ssl_context()->ecdh_curve = zend::String(ztmp).to_std_string();
}

#ifdef OPENSSL_IS_BORINGSSL
if (php_swoole_array_get_value(vht, "ssl_grease", ztmp)) {
zend_long v = zval_get_long(ztmp);
sock->get_ssl_context()->grease = SW_MAX(0, SW_MIN(v, UINT8_MAX));
}
#endif

if (!sock->ssl_check_context()) {
ret = false;
}
return ret;
return true;
}
#endif

Expand Down
3 changes: 2 additions & 1 deletion include/swoole_coroutine_socket.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ class Socket {
return ssl_context.get();
}

bool ssl_check_context();
bool ssl_listen();
bool ssl_handshake();
bool ssl_verify(bool allow_self_signed);
std::string ssl_get_peer_cert();
Expand Down Expand Up @@ -441,6 +441,7 @@ class Socket {
bool ssl_handshaked = false;
std::shared_ptr<SSLContext> ssl_context = nullptr;
std::string ssl_host_name;
bool ssl_context_create();
bool ssl_create(SSLContext *ssl_context);
#endif

Expand Down
1 change: 1 addition & 0 deletions include/swoole_error.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ enum swErrorCode {
SW_ERROR_SSL_BAD_PROTOCOL,
SW_ERROR_SSL_RESET,
SW_ERROR_SSL_HANDSHAKE_FAILED,
SW_ERROR_SSL_CREATE_CONTEXT_FAILED,

SW_ERROR_PACKAGE_LENGTH_TOO_LARGE = 1201,
SW_ERROR_PACKAGE_LENGTH_NOT_FOUND,
Expand Down
29 changes: 22 additions & 7 deletions src/coroutine/socket.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1137,7 +1137,10 @@ bool Socket::listen(int backlog) {
return false;
}
#ifdef SW_USE_OPENSSL
ssl_is_server = true;
if (ssl_is_enable() && !ssl_listen()) {
set_err(SW_ERROR_SSL_CREATE_CONTEXT_FAILED);
return false;
}
#endif
return true;
}
Expand Down Expand Up @@ -1171,10 +1174,7 @@ Socket *Socket::accept(double timeout) {
}

#ifdef SW_USE_OPENSSL
bool Socket::ssl_check_context() {
if (socket->ssl || (get_ssl_context() && get_ssl_context()->get_context())) {
return true;
}
bool Socket::ssl_context_create() {
if (socket->is_dgram()) {
#ifdef SW_SUPPORT_DTLS
socket->dtls = 1;
Expand All @@ -1187,7 +1187,6 @@ bool Socket::ssl_check_context() {
}
ssl_context->http_v2 = http2;
if (!ssl_context->create()) {
swoole_warning("swSSL_get_context() error");
return false;
}
socket->ssl_send_ = 1;
Expand All @@ -1214,19 +1213,35 @@ bool Socket::ssl_create(SSLContext *ssl_context) {
return true;
}

bool Socket::ssl_listen() {
ssl_is_server = true;
if (ssl_context->context == nullptr && !ssl_context_create()) {
return false;
}
return true;
}

bool Socket::ssl_handshake() {
if (ssl_handshaked) {
return false;
}
if (sw_unlikely(!is_available(SW_EVENT_RDWR))) {
return false;
}
if (!ssl_check_context()) {
/**
* If the ssl_context is empty, it indicates that this socket was not a connection
* returned by a server socket accept, and a new ssl_context needs to be created.
*/
if (ssl_context->context == nullptr && !ssl_context_create()) {
return false;
}
if (!ssl_create(get_ssl_context())) {
return false;
}
/**
* The server will use ssl_accept to complete the SSL handshake,
* while the client will use ssl_connect.
*/
if (!ssl_is_server) {
while (true) {
if (socket->ssl_connect() < 0) {
Expand Down
62 changes: 62 additions & 0 deletions tests/swoole_runtime/ssl/enable_crypto.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
--TEST--
swoole_runtime/ssl: stream_socket_enable_crypto
--SKIPIF--
<?php
require __DIR__ . '/../../include/skipif.inc';
skip_if_no_ssl();
?>
--FILE--
<?php
require __DIR__ . '/../../include/bootstrap.php';

Swoole\Runtime::enableCoroutine();

$ready = new Chan;

go(function () use ($ready) {
$context = stream_context_create();
stream_context_set_option($context, 'ssl', 'allow_self_signed', true);
stream_context_set_option($context, 'ssl', 'verify_peer', true);
stream_context_set_option($context, 'ssl', 'local_cert', SSL_FILE_DIR.'/server.crt');
stream_context_set_option($context, 'ssl', 'local_pk', SSL_FILE_DIR.'/server.key');
stream_context_set_option($context, 'ssl', 'cafile', SSL_FILE_DIR.'/ca.crt');

$socket = stream_socket_server("ssl://0.0.0.0:8000", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN, $context);
if (!$socket) {
echo "$errstr ($errno)<br />\n";
} else {
$ready->push(true);
$conn = stream_socket_accept($socket);

fwrite($conn, 'The local time is ' . date('n/j/Y g:i a'));
fclose($conn);
fclose($socket);
echo "OK\n";
}
});

go(function () use ($ready) {
$ready->pop();

$fp = stream_socket_client("tcp://127.0.0.1:8000", $errno, $errstr, 30);
if (!$fp) {
echo "$errstr ($errno)<br />\n";
} else {
stream_context_set_option($fp, ["ssl" => [
"local_cert" => SSL_FILE_DIR . '/client.crt',
"local_pk" => SSL_FILE_DIR . '/client.key',
]]);
// Enable SSL encryption after the connection is established
Assert::assert(stream_socket_enable_crypto($fp, true, STREAM_CRYPTO_METHOD_TLS_CLIENT));
$data = fread($fp, 8192);
fclose($fp);
Assert::assert(strpos($data, 'local time') !== false);
echo "OK\n";
}
});

Swoole\Event::wait();
?>
--EXPECT--
OK
OK

0 comments on commit 6d35c00

Please sign in to comment.