diff options
| author | Arnaud Le Blanc <lbarnaud@php.net> | 2009-11-30 13:31:53 +0000 |
|---|---|---|
| committer | Arnaud Le Blanc <lbarnaud@php.net> | 2009-11-30 13:31:53 +0000 |
| commit | 7c0803a8ca75105bf60f7658dc8e21518ca2f8e7 (patch) | |
| tree | cba198b8ea66b8ec7679a3681fce20e38a4a5357 /ext/openssl/xp_ssl.c | |
| parent | 832e1813049221e8b8578852740d4089b2c3ef27 (diff) | |
| download | php-git-7c0803a8ca75105bf60f7658dc8e21518ca2f8e7.tar.gz | |
merge from trunk: openssl sni support (rev 289831)
Diffstat (limited to 'ext/openssl/xp_ssl.c')
| -rw-r--r-- | ext/openssl/xp_ssl.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index 2590461c8c..aa2e3810f2 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -20,6 +20,7 @@ #include "php.h" #include "ext/standard/file.h" +#include "ext/standard/url.h" #include "streams/php_streams_int.h" #include "ext/standard/php_smart_str.h" #include "php_network.h" @@ -54,6 +55,7 @@ typedef struct _php_openssl_netstream_data_t { int is_client; int ssl_active; php_stream_xport_crypt_method_t method; + char *sni; unsigned state_set:1; unsigned _spare:31; } php_openssl_netstream_data_t; @@ -283,6 +285,9 @@ static int php_openssl_sockop_close(php_stream *stream, int close_handle TSRMLS_ } } + if (sslsock->sni) { + pefree(sslsock->sni, php_stream_is_persistent(stream)); + } pefree(sslsock, php_stream_is_persistent(stream)); return 0; @@ -393,6 +398,12 @@ static inline int php_openssl_enable_crypto(php_stream *stream, float timeout = sslsock->connect_timeout.tv_sec + sslsock->connect_timeout.tv_usec / 1000000; int blocked = sslsock->s.is_blocked; +#if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT) + if (sslsock->is_client && sslsock->sni) { + SSL_set_tlsext_host_name(sslsock->ssl_handle, sslsock->sni); + } +#endif + if (!sslsock->state_set) { if (sslsock->is_client) { SSL_set_connect_state(sslsock->ssl_handle); @@ -759,6 +770,52 @@ php_stream_ops php_openssl_socket_ops = { php_openssl_sockop_set_option, }; +static char * get_sni(php_stream_context *ctx, char *resourcename, long resourcenamelen, int is_persistent TSRMLS_DC) { + + php_url *url; + + if (ctx) { + zval **val = NULL; + + if (php_stream_context_get_option(ctx, "ssl", "SNI_enabled", &val) == SUCCESS && !zend_is_true(*val)) { + return NULL; + } + if (php_stream_context_get_option(ctx, "ssl", "SNI_server_name", &val) == SUCCESS) { + convert_to_string_ex(val); + return pestrdup(Z_STRVAL_PP(val), is_persistent); + } + } + + if (!resourcename) { + return NULL; + } + + url = php_url_parse_ex(resourcename, resourcenamelen); + if (!url) { + return NULL; + } + + if (url->host) { + const char * host = url->host; + char * sni = NULL; + size_t len = strlen(host); + + /* skip trailing dots */ + while (len && host[len-1] == '.') { + --len; + } + + if (len) { + sni = pestrndup(host, len, is_persistent); + } + + php_url_free(url); + return sni; + } + + php_url_free(url); + return NULL; +} php_stream *php_openssl_ssl_socket_factory(const char *proto, long protolen, char *resourcename, long resourcenamelen, @@ -795,6 +852,8 @@ php_stream *php_openssl_ssl_socket_factory(const char *proto, long protolen, return NULL; } + sslsock->sni = get_sni(context, resourcename, resourcenamelen, !!persistent_id TSRMLS_CC); + if (strncmp(proto, "ssl", protolen) == 0) { sslsock->enable_on_connect = 1; sslsock->method = STREAM_CRYPTO_METHOD_SSLv23_CLIENT; |
