summaryrefslogtreecommitdiff
path: root/ext/openssl/xp_ssl.c
diff options
context:
space:
mode:
authorArnaud Le Blanc <lbarnaud@php.net>2009-11-30 13:31:53 +0000
committerArnaud Le Blanc <lbarnaud@php.net>2009-11-30 13:31:53 +0000
commit7c0803a8ca75105bf60f7658dc8e21518ca2f8e7 (patch)
treecba198b8ea66b8ec7679a3681fce20e38a4a5357 /ext/openssl/xp_ssl.c
parent832e1813049221e8b8578852740d4089b2c3ef27 (diff)
downloadphp-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.c59
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;