Skip to content

Commit

Permalink
Support ssl sni (#3908)
Browse files Browse the repository at this point in the history
* support SNI

* fix

* fix 2

* Refactor SSLContext

* Optimize code

* fix 3

* fix 4

* Optimize code [2]

* fix

* fix 2

* fix 3

* fix 4

* fix 5

* fix 6

* fix 7

* fix 8

* fix 9

* Optimize code

* Optimize code [2]
  • Loading branch information
matyhtf authored Dec 3, 2020
1 parent dc7aa6a commit 754f5e3
Show file tree
Hide file tree
Showing 61 changed files with 1,354 additions and 810 deletions.
6 changes: 3 additions & 3 deletions examples/http2/server.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@
'trace_flags' => SWOOLE_TRACE_HTTP2,
'log_level' => 0,
]);
$key_dir = dirname(dirname(__DIR__)) . '/tests/include/api/swoole_http_server/localhost-ssl';
$key_dir = __DIR__ . '/../ssl/';
$http = new swoole_http_server("0.0.0.0", 9501, SWOOLE_BASE, SWOOLE_SOCK_TCP | SWOOLE_SSL);
$http->set([
'open_http2_protocol' => 1,
'enable_static_handler' => TRUE,
'document_root' => dirname(__DIR__),
'ssl_cert_file' => $key_dir . '/server.crt',
'ssl_key_file' => $key_dir . '/server.key',
'ssl_cert_file' => $key_dir . '/ssl.crt',
'ssl_key_file' => $key_dir . '/ssl.key',
]);

$http->on('request', function (swoole_http_request $request, swoole_http_response $response) {
Expand Down
1 change: 1 addition & 0 deletions ext-src/php_swoole.h
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,7 @@ static sw_inline zend_string* sw_zend_string_recycle(zend_string *s, size_t allo

#define php_swoole_array_length(zarray) zend_hash_num_elements(Z_ARRVAL_P(zarray))
#define php_swoole_array_get_value(ht, str, v) ((v = zend_hash_str_find(ht, str, sizeof(str)-1)) && !ZVAL_IS_NULL(v))
#define php_swoole_array_get_value_ex(ht, str, v) ((v = zend_hash_str_find(ht, str, strlen(str))) && !ZVAL_IS_NULL(v))

static sw_inline int php_swoole_array_length_safe(zval *zarray)
{
Expand Down
13 changes: 8 additions & 5 deletions ext-src/php_swoole_library.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
* Generated by build-library.php, Please DO NOT modify!
*/

/* $Id: 5eeedc0652a4fb7ed887f0821b6eb108dc37844d */
/* $Id: cd54ea3ae2452750769151a5432f6e49f9e7aaf1 */

static const char* swoole_library_source_constants =
"\n"
Expand Down Expand Up @@ -6724,6 +6724,8 @@ static const char* swoole_library_source_core_server_helper =
" ];\n"
"\n"
" const PORT_OPTIONS = [\n"
" 'ssl_cert_file' => true,\n"
" 'ssl_key_file' => true,\n"
" 'backlog' => true,\n"
" 'socket_buffer_size' => true,\n"
" 'kernel_socket_recv_buffer_size' => true,\n"
Expand Down Expand Up @@ -6758,8 +6760,6 @@ static const char* swoole_library_source_core_server_helper =
" 'package_body_start' => true,\n"
" 'package_length_func' => true,\n"
" 'package_max_length' => true,\n"
" 'ssl_cert_file' => true,\n"
" 'ssl_key_file' => true,\n"
" 'ssl_compress' => true,\n"
" 'ssl_protocols' => true,\n"
" 'ssl_verify_peer' => true,\n"
Expand All @@ -6770,6 +6770,7 @@ static const char* swoole_library_source_core_server_helper =
" 'ssl_ciphers' => true,\n"
" 'ssl_ecdh_curve' => true,\n"
" 'ssl_dhparam' => true,\n"
" 'ssl_sni_certs' => true,\n"
" ];\n"
"\n"
" const HELPER_OPTIONS = [\n"
Expand Down Expand Up @@ -7177,15 +7178,17 @@ static const char* swoole_library_source_ext_sockets =
" return swoole_last_error();\n"
"}\n"
"\n"
"function swoole_socket_set_block(Socket $socket ) {\n"
"function swoole_socket_set_block(Socket $socket)\n"
"{\n"
" if (isset($socket->__ext_sockets_nonblock) and $socket->__ext_sockets_nonblock) {\n"
" $socket->setOption(SOL_SOCKET, SO_RCVTIMEO, $socket->__ext_sockets_timeout);\n"
" }\n"
" $socket->__ext_sockets_nonblock = false;\n"
" return true;\n"
"}\n"
"\n"
"function swoole_socket_set_nonblock(Socket $socket ) {\n"
"function swoole_socket_set_nonblock(Socket $socket)\n"
"{\n"
" if (isset($socket->__ext_sockets_nonblock) and $socket->__ext_sockets_nonblock) {\n"
" return true;\n"
" }\n"
Expand Down
34 changes: 14 additions & 20 deletions ext-src/swoole_client.cc
Original file line number Diff line number Diff line change
Expand Up @@ -267,57 +267,54 @@ void php_swoole_client_check_ssl_setting(Client *cli, zval *zset) {
zval *ztmp;

if (php_swoole_array_get_value(vht, "ssl_protocols", ztmp)) {
zend_long v = zval_get_long(ztmp);
cli->ssl_option.protocols = v;
cli->ssl_context->set_protocols(zval_get_long(ztmp));
}
if (php_swoole_array_get_value(vht, "ssl_compress", ztmp)) {
cli->ssl_option.disable_compress = !zval_is_true(ztmp);
cli->ssl_context->disable_compress = !zval_is_true(ztmp);
}
if (php_swoole_array_get_value(vht, "ssl_cert_file", ztmp)) {
zend::String str_v(ztmp);
if (access(str_v.val(), R_OK) < 0) {
if (!cli->ssl_context->set_cert_file(str_v.to_std_string())) {
php_swoole_fatal_error(E_ERROR, "ssl cert file[%s] not found", str_v.val());
return;
}
cli->ssl_option.cert_file = sw_strdup(str_v.val());
}
if (php_swoole_array_get_value(vht, "ssl_key_file", ztmp)) {
zend::String str_v(ztmp);
if (access(str_v.val(), R_OK) < 0) {
if (!cli->ssl_context->set_key_file(str_v.to_std_string())) {
php_swoole_fatal_error(E_ERROR, "ssl key file[%s] not found", str_v.val());
return;
}
cli->ssl_option.key_file = sw_strdup(str_v.val());
}
if (php_swoole_array_get_value(vht, "ssl_passphrase", ztmp)) {
zend::String str_v(ztmp);
cli->ssl_option.passphrase = sw_strdup(str_v.val());
cli->ssl_context->passphrase = str_v.to_std_string();
}
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
if (php_swoole_array_get_value(vht, "ssl_host_name", ztmp)) {
zend::String str_v(ztmp);
cli->ssl_option.tls_host_name = sw_strdup(str_v.val());
cli->ssl_context->tls_host_name = str_v.to_std_string();
}
#endif
if (php_swoole_array_get_value(vht, "ssl_verify_peer", ztmp)) {
cli->ssl_option.verify_peer = zval_is_true(ztmp);
cli->ssl_context->verify_peer = zval_is_true(ztmp);
}
if (php_swoole_array_get_value(vht, "ssl_allow_self_signed", ztmp)) {
cli->ssl_option.allow_self_signed = zval_is_true(ztmp);
cli->ssl_context->allow_self_signed = zval_is_true(ztmp);
}
if (php_swoole_array_get_value(vht, "ssl_cafile", ztmp)) {
zend::String str_v(ztmp);
cli->ssl_option.cafile = sw_strdup(str_v.val());
cli->ssl_context->cafile = str_v.to_std_string();
}
if (php_swoole_array_get_value(vht, "ssl_capath", ztmp)) {
zend::String str_v(ztmp);
cli->ssl_option.capath = sw_strdup(str_v.val());
cli->ssl_context->capath = str_v.to_std_string();
}
if (php_swoole_array_get_value(vht, "ssl_verify_depth", ztmp)) {
zend_long v = zval_get_long(ztmp);
cli->ssl_option.verify_depth = SW_MAX(0, SW_MIN(v, UINT8_MAX));
cli->ssl_context->verify_depth = SW_MAX(0, SW_MIN(v, UINT8_MAX));
}
if (cli->ssl_option.cert_file && !cli->ssl_option.key_file) {
if (!cli->ssl_context->cert_file.empty() && cli->ssl_context->key_file.empty()) {
php_swoole_fatal_error(E_ERROR, "ssl require key file");
return;
}
Expand Down Expand Up @@ -684,7 +681,7 @@ static Client *php_swoole_client_new(zval *zobject, char *host, int host_len, in

#ifdef SW_USE_OPENSSL
if (type & SW_SOCK_SSL) {
cli->open_ssl = 1;
cli->enable_ssl_encrypt();
}
#endif

Expand Down Expand Up @@ -1313,14 +1310,11 @@ static PHP_METHOD(swoole_client, enableSSL) {
php_swoole_fatal_error(E_WARNING, "SSL has been enabled");
RETURN_FALSE;
}
cli->open_ssl = 1;
cli->enable_ssl_encrypt();
zval *zset = sw_zend_read_property_ex(swoole_client_ce, ZEND_THIS, SW_ZSTR_KNOWN(SW_ZEND_STR_SETTING), 0);
if (ZVAL_IS_ARRAY(zset)) {
php_swoole_client_check_ssl_setting(cli, zset);
}
if (cli->enable_ssl_encrypt() < 0) {
RETURN_FALSE;
}
if (cli->ssl_handshake() < 0) {
RETURN_FALSE;
}
Expand Down
63 changes: 24 additions & 39 deletions ext-src/swoole_client_coro.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ using swoole::network::Address;
using swoole::Socks5Proxy;
using swoole::HttpProxy;
using swoole::String;
#ifdef SW_USE_OPENSSL
using swoole::SSLContext;
#endif

static zend_class_entry *swoole_client_coro_ce;
static zend_object_handlers swoole_client_coro_handlers;
Expand Down Expand Up @@ -231,7 +234,7 @@ static Socket *client_coro_new(zval *zobject, int port) {

#ifdef SW_USE_OPENSSL
if (type & SW_SOCK_SSL) {
cli->open_ssl = true;
cli->enable_ssl_encrypt();
}
#endif

Expand Down Expand Up @@ -398,83 +401,65 @@ bool php_swoole_socket_set_ssl(Socket *sock, zval *zset) {

if (php_swoole_array_get_value(vht, "ssl_protocols", ztmp)) {
zend_long v = zval_get_long(ztmp);
sock->ssl_option.protocols = v;
sock->get_ssl_context()->protocols = v;
}
if (php_swoole_array_get_value(vht, "ssl_compress", ztmp)) {
sock->ssl_option.disable_compress = !zval_is_true(ztmp);
sock->get_ssl_context()->disable_compress = !zval_is_true(ztmp);
} else if (php_swoole_array_get_value(vht, "ssl_disable_compression", ztmp)) {
sock->ssl_option.disable_compress = !zval_is_true(ztmp);
sock->get_ssl_context()->disable_compress = !zval_is_true(ztmp);
}
if (php_swoole_array_get_value(vht, "ssl_cert_file", ztmp)) {
zend::String str_v(ztmp);
if (sock->ssl_option.cert_file) {
sw_free(sock->ssl_option.cert_file);
sock->ssl_option.cert_file = nullptr;
}
if (access(str_v.val(), R_OK) == 0) {
sock->ssl_option.cert_file = str_v.dup();
sock->get_ssl_context()->cert_file = str_v.to_std_string();
} else {
php_swoole_fatal_error(E_WARNING, "ssl cert file[%s] not found", sock->ssl_option.cert_file);
php_swoole_fatal_error(E_WARNING, "ssl cert file[%s] not found", str_v.val());
ret = false;
}
}
if (php_swoole_array_get_value(vht, "ssl_key_file", ztmp)) {
zend::String str_v(ztmp);
if (sock->ssl_option.key_file) {
sw_free(sock->ssl_option.key_file);
sock->ssl_option.key_file = nullptr;
}
if (access(str_v.val(), R_OK) == 0) {
sock->ssl_option.key_file = str_v.dup();
sock->get_ssl_context()->key_file = str_v.to_std_string();
} else {
php_swoole_fatal_error(E_WARNING, "ssl key file[%s] not found", sock->ssl_option.key_file);
php_swoole_fatal_error(E_WARNING, "ssl key file[%s] not found", str_v.val());
ret = false;
}
}
if (sock->ssl_option.cert_file && !sock->ssl_option.key_file) {
if (!sock->get_ssl_context()->cert_file.empty() && sock->get_ssl_context()->key_file.empty()) {
php_swoole_fatal_error(E_WARNING, "ssl require key file");
} else if (sock->ssl_option.key_file && !sock->ssl_option.cert_file) {
} else if (!sock->get_ssl_context()->key_file.empty() && sock->get_ssl_context()->cert_file.empty()) {
php_swoole_fatal_error(E_WARNING, "ssl require cert file");
}
if (php_swoole_array_get_value(vht, "ssl_passphrase", ztmp)) {
if (sock->ssl_option.passphrase) {
sw_free(sock->ssl_option.passphrase);
}
sock->ssl_option.passphrase = zend::String(ztmp).dup();
sock->get_ssl_context()->passphrase = zend::String(ztmp).to_std_string();
}
#ifdef SSL_CTRL_SET_TLSEXT_HOSTNAME
if (php_swoole_array_get_value(vht, "ssl_host_name", ztmp)) {
if (sock->ssl_option.tls_host_name) {
sw_free(sock->ssl_option.tls_host_name);
}
sock->ssl_option.tls_host_name = zend::String(ztmp).dup();
sock->get_ssl_context()->tls_host_name = zend::String(ztmp).to_std_string();
/* if user set empty ssl_host_name, disable it, otherwise the underlying may set it automatically */
sock->ssl_option.disable_tls_host_name = !sock->ssl_option.tls_host_name;
sock->get_ssl_context()->disable_tls_host_name = sock->get_ssl_context()->tls_host_name.empty();
}
#endif
if (php_swoole_array_get_value(vht, "ssl_verify_peer", ztmp)) {
sock->ssl_option.verify_peer = zval_is_true(ztmp);
sock->get_ssl_context()->verify_peer = zval_is_true(ztmp);
}
if (php_swoole_array_get_value(vht, "ssl_allow_self_signed", ztmp)) {
sock->ssl_option.allow_self_signed = zval_is_true(ztmp);
sock->get_ssl_context()->allow_self_signed = zval_is_true(ztmp);
}
if (php_swoole_array_get_value(vht, "ssl_cafile", ztmp)) {
if (sock->ssl_option.cafile) {
sw_free(sock->ssl_option.cafile);
}
sock->ssl_option.cafile = zend::String(ztmp).dup();
sock->get_ssl_context()->cafile = zend::String(ztmp).to_std_string();
}
if (php_swoole_array_get_value(vht, "ssl_capath", ztmp)) {
if (sock->ssl_option.capath) {
sw_free(sock->ssl_option.capath);
}
sock->ssl_option.capath = zend::String(ztmp).dup();
sock->get_ssl_context()->capath = zend::String(ztmp).to_std_string();
}
if (php_swoole_array_get_value(vht, "ssl_verify_depth", ztmp)) {
zend_long v = zval_get_long(ztmp);
sock->ssl_option.verify_depth = SW_MAX(0, SW_MIN(v, UINT8_MAX));
sock->get_ssl_context()->verify_depth = SW_MAX(0, SW_MIN(v, UINT8_MAX));
}
if (!sock->ssl_check_context()) {
ret = false;
}

return ret;
}
#endif
Expand Down
14 changes: 8 additions & 6 deletions ext-src/swoole_http2_client_coro.cc
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ class Client {
public:
std::string host;
int port;
bool ssl;
bool open_ssl;
double timeout = network::Socket::default_read_timeout;

Socket *client = nullptr;
Expand All @@ -88,7 +88,7 @@ class Client {
Client(const char *_host, size_t _host_len, int _port, bool _ssl, zval *__zobject) {
host = std::string(_host, _host_len);
port = _port;
ssl = _ssl;
open_ssl = _ssl;
_zobject = *__zobject;
zobject = &_zobject;
swHttp2_init_settings(&local_settings);
Expand Down Expand Up @@ -252,7 +252,7 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_http2_client_coro_construct, 0, 0, 1)
ZEND_ARG_INFO(0, host)
ZEND_ARG_INFO(0, port)
ZEND_ARG_INFO(0, ssl)
ZEND_ARG_INFO(0, open_ssl)
ZEND_END_ARG_INFO()

ZEND_BEGIN_ARG_INFO_EX(arginfo_swoole_http2_client_coro_set, 0, 0, 1)
Expand Down Expand Up @@ -408,7 +408,9 @@ bool Client::connect() {
}
client->set_zero_copy(true);
#ifdef SW_USE_OPENSSL
client->open_ssl = ssl;
if (open_ssl) {
client->enable_ssl_encrypt();
}
#endif
client->http2 = 1;
client->open_length_check = 1;
Expand Down Expand Up @@ -991,7 +993,7 @@ ssize_t Client::build_header(zval *zobject, zval *zrequest, char *buffer) {
} else {
headers.add(ZEND_STRL(":path"), Z_STRVAL_P(zpath), Z_STRLEN_P(zpath));
}
if (h2c->ssl) {
if (h2c->open_ssl) {
headers.add(ZEND_STRL(":scheme"), ZEND_STRL("https"));
} else {
headers.add(ZEND_STRL(":scheme"), ZEND_STRL("http"));
Expand Down Expand Up @@ -1023,7 +1025,7 @@ ssize_t Client::build_header(zval *zobject, zval *zrequest, char *buffer) {
#ifndef SW_USE_OPENSSL
if (h2c->port != 80)
#else
if (!h2c->ssl ? h2c->port != 80 : h2c->port != 443)
if (!h2c->open_ssl ? h2c->port != 80 : h2c->port != 443)
#endif
{
_host = std_string::format("%s:%d", h2c->host.c_str(), h2c->port);
Expand Down
8 changes: 5 additions & 3 deletions ext-src/swoole_http_client_coro.cc
Original file line number Diff line number Diff line change
Expand Up @@ -778,7 +778,7 @@ void HttpClient::apply_setting(zval *zset, const bool check_all) {
if (socket) {
php_swoole_client_set(socket, zset);
#ifdef SW_USE_OPENSSL
if (socket->http_proxy && !socket->open_ssl)
if (socket->http_proxy && !socket->ssl_is_enable())
#else
if (socket->http_proxy)
#endif
Expand Down Expand Up @@ -833,7 +833,9 @@ bool HttpClient::connect() {
return false;
}
#ifdef SW_USE_OPENSSL
socket->open_ssl = ssl;
if (ssl) {
socket->enable_ssl_encrypt();
}
#endif
// apply settings
apply_setting(
Expand Down Expand Up @@ -969,7 +971,7 @@ bool HttpClient::send() {

// ============ path & proxy ============
#ifdef SW_USE_OPENSSL
if (socket->http_proxy && !socket->open_ssl)
if (socket->http_proxy && !socket->ssl_is_enable())
#else
if (socket->http_proxy)
#endif
Expand Down
Loading

0 comments on commit 754f5e3

Please sign in to comment.