diff options
| author | Ondřej Surý <ondrej@sury.org> | 2010-03-09 11:57:54 +0100 |
|---|---|---|
| committer | Ondřej Surý <ondrej@sury.org> | 2010-03-09 11:57:54 +0100 |
| commit | 855a09f4eded707941180c9d90acd17c25e29447 (patch) | |
| tree | a40947efaa9876f31b6ee3956c3f3775768143bb /ext/openssl | |
| parent | c852c28a88fccf6e34a2cb091fdfa72bce2b59c7 (diff) | |
| download | php-upstream/5.3.2.tar.gz | |
Imported Upstream version 5.3.2upstream/5.3.2
Diffstat (limited to 'ext/openssl')
| -rw-r--r-- | ext/openssl/openssl.c | 25 | ||||
| -rw-r--r-- | ext/openssl/php_openssl.h | 4 | ||||
| -rw-r--r-- | ext/openssl/tests/bug48182.phpt | 6 | ||||
| -rw-r--r-- | ext/openssl/tests/sni_001.phpt | 178 | ||||
| -rw-r--r-- | ext/openssl/xp_ssl.c | 63 |
5 files changed, 264 insertions, 12 deletions
diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index d3e425eee..8df0d9d69 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2009 The PHP Group | + | Copyright (c) 1997-2010 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -20,7 +20,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: openssl.c 289443 2009-10-09 19:08:56Z pajoye $ */ +/* $Id: openssl.c 294508 2010-02-04 09:23:22Z pajoye $ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -51,13 +51,19 @@ /* Common */ #include <time.h> +#ifdef NETWARE +#define timezone _timezone /* timezone is called _timezone in LibC */ +#endif + #define DEFAULT_KEY_LENGTH 512 #define MIN_KEY_LENGTH 384 #define OPENSSL_ALGO_SHA1 1 #define OPENSSL_ALGO_MD5 2 #define OPENSSL_ALGO_MD4 3 +#ifdef HAVE_OPENSSL_MD2_H #define OPENSSL_ALGO_MD2 4 +#endif #define OPENSSL_ALGO_DSS1 5 #define DEBUG_SMIME 0 @@ -913,9 +919,11 @@ static EVP_MD * php_openssl_get_evp_md_from_algo(long algo) { /* {{{ */ case OPENSSL_ALGO_MD4: mdtype = (EVP_MD *) EVP_md4(); break; +#ifdef HAVE_OPENSSL_MD2_H case OPENSSL_ALGO_MD2: mdtype = (EVP_MD *) EVP_md2(); break; +#endif case OPENSSL_ALGO_DSS1: mdtype = (EVP_MD *) EVP_dss1(); break; @@ -997,7 +1005,9 @@ PHP_MINIT_FUNCTION(openssl) REGISTER_LONG_CONSTANT("OPENSSL_ALGO_SHA1", OPENSSL_ALGO_SHA1, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OPENSSL_ALGO_MD5", OPENSSL_ALGO_MD5, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OPENSSL_ALGO_MD4", OPENSSL_ALGO_MD4, CONST_CS|CONST_PERSISTENT); +#ifdef HAVE_OPENSSL_MD2_H REGISTER_LONG_CONSTANT("OPENSSL_ALGO_MD2", OPENSSL_ALGO_MD2, CONST_CS|CONST_PERSISTENT); +#endif REGISTER_LONG_CONSTANT("OPENSSL_ALGO_DSS1", OPENSSL_ALGO_DSS1, CONST_CS|CONST_PERSISTENT); /* flags for S/MIME */ @@ -1037,6 +1047,11 @@ PHP_MINIT_FUNCTION(openssl) REGISTER_LONG_CONSTANT("OPENSSL_KEYTYPE_EC", OPENSSL_KEYTYPE_EC, CONST_CS|CONST_PERSISTENT); #endif +#if OPENSSL_VERSION_NUMBER >= 0x0090806fL && !defined(OPENSSL_NO_TLSEXT) + /* SNI support included in OpenSSL >= 0.9.8j */ + REGISTER_LONG_CONSTANT("OPENSSL_TLSEXT_SERVER_NAME", 1, CONST_CS|CONST_PERSISTENT); +#endif + /* Determine default SSL configuration file */ config_filename = getenv("OPENSSL_CONF"); if (config_filename == NULL) { @@ -1738,18 +1753,18 @@ PHP_FUNCTION(openssl_pkcs12_export_to_file) int filename_len; char * pass; int pass_len; - zval *zcert = NULL, *zpkey = NULL, *args = NULL; + zval **zcert = NULL, *zpkey = NULL, *args = NULL; EVP_PKEY *priv_key = NULL; long certresource, keyresource; zval ** item; STACK_OF(X509) *ca = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zszs|a", &zcert, &filename, &filename_len, &zpkey, &pass, &pass_len, &args) == FAILURE) + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "Zszs|a", &zcert, &filename, &filename_len, &zpkey, &pass, &pass_len, &args) == FAILURE) return; RETVAL_FALSE; - cert = php_openssl_x509_from_zval(&zcert, 0, &certresource TSRMLS_CC); + cert = php_openssl_x509_from_zval(zcert, 0, &certresource TSRMLS_CC); if (cert == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "cannot get cert from parameter 1"); return; diff --git a/ext/openssl/php_openssl.h b/ext/openssl/php_openssl.h index 1aa8adf8d..bddd8e732 100644 --- a/ext/openssl/php_openssl.h +++ b/ext/openssl/php_openssl.h @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2009 The PHP Group | + | Copyright (c) 1997-2010 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -17,7 +17,7 @@ +----------------------------------------------------------------------+ */ -/* $Id: php_openssl.h 272370 2008-12-31 11:15:49Z sebastian $ */ +/* $Id: php_openssl.h 293036 2010-01-03 09:23:27Z sebastian $ */ #ifndef PHP_OPENSSL_H #define PHP_OPENSSL_H diff --git a/ext/openssl/tests/bug48182.phpt b/ext/openssl/tests/bug48182.phpt index 0af04e1a9..7471c4c5d 100644 --- a/ext/openssl/tests/bug48182.phpt +++ b/ext/openssl/tests/bug48182.phpt @@ -28,12 +28,12 @@ function ssl_server($port) { $r = array($link); $w = array(); $e = array(); - if (stream_select($r, $w, $e, 0, 1000) != 0) + if (stream_select($r, $w, $e, 1, 0) != 0) $data .= fread($link, 8192); $r = array(); $w = array($link); - if (stream_select($r, $w, $e, 0, 1000) != 0) + if (stream_select($r, $w, $e, 1, 0) != 0) $wrote = fwrite($link, $data, strlen($data)); // close stuff @@ -59,7 +59,7 @@ function ssl_async_client($port) { $r = array($socket); $w = array(); $e = array(); - if (stream_select($r, $w, $e, 0, 10) != 0) + if (stream_select($r, $w, $e, 1, 0) != 0) { $data .= fread($socket, 1024); } diff --git a/ext/openssl/tests/sni_001.phpt b/ext/openssl/tests/sni_001.phpt new file mode 100644 index 000000000..3d7798cf8 --- /dev/null +++ b/ext/openssl/tests/sni_001.phpt @@ -0,0 +1,178 @@ +--TEST-- +SNI 001 +--SKIPIF-- +<?php + if (!extension_loaded('openssl')) die("skip openssl extension not available"); + if (!getenv('SNI_TESTS')) die("skip Set SNI_TESTS to enable this test (uses remote resources)"); +?> +--FILE-- +<?php +/* Server Name Indication (SNI) tests + * + * This test relies on https://sni.velox.ch/ and thus is disabled by default. + * + * sni.velox.ch uses 3 certificates : + * - CN=alice.sni.velox.ch (sent in response to server_name = alice.sni.velox.ch or not set) + * - CN=bob.sni.velox.ch (sent in response to server_name = bob.sni.velox.ch) + * - CN=*.sni.velox.ch (sent in response to server_name = mallory.sni.velox.ch or *.sni.velox.ch or sni.velox.ch) + * + * The test sends requests to the server, sending different names, and checks which certificate + * the server returned. + */ + +function context() { + return stream_context_create(array( + 'ssl' => array( + 'capture_peer_cert' => true, + ), + )); +} + +function get_CN($context) { + + $ary = stream_context_get_options($context); + assert($ary); + + $cert = $ary['ssl']['peer_certificate']; + assert($cert); + + $cert_ary = openssl_x509_parse($cert); + return $cert_ary['subject']['CN']; +} + +function do_http_test($url, $context) { + + $fh = fopen($url, 'r', false, $context); + assert($fh); + + var_dump(get_CN($context)); +} + +function do_ssl_test($url, $context) { + + $fh = stream_socket_client($url, $errno, $errstr, + ini_get("default_socket_timeout"), STREAM_CLIENT_CONNECT, $context); + assert($fh); + + var_dump(get_CN($context)); +} + +function do_enable_crypto_test($url, $context) { + + $fh = stream_socket_client($url, $errno, $errstr, + ini_get("default_socket_timeout"), STREAM_CLIENT_CONNECT, $context); + assert($fh); + + $r = stream_socket_enable_crypto($fh, true, STREAM_CRYPTO_METHOD_TLS_CLIENT); + assert($r); + + var_dump(get_CN($context)); +} + +/* Test https:// streams */ + +echo "-- auto host name (1) --\n"; +do_http_test('https://alice.sni.velox.ch/', context()); + +echo "-- auto host name (2) --\n"; +do_http_test('https://bob.sni.velox.ch/', context()); + +echo "-- auto host name (3) --\n"; +do_http_test('https://bob.sni.velox.ch./', context()); + +echo "-- user supplied server name --\n"; + +$context = context(); +stream_context_set_option($context, 'ssl', 'SNI_server_name', 'bob.sni.velox.ch'); +stream_context_set_option($context, 'http', 'header', b'Host: bob.sni.velox.ch'); +do_http_test('https://alice.sni.velox.ch/', $context); + +echo "-- sni disabled --\n"; + +$context = context(); +stream_context_set_option($context, 'ssl', 'SNI_enabled', false); +do_http_test('https://bob.sni.velox.ch/', $context); + +/* Test ssl:// socket streams */ + +echo "-- raw SSL stream (1) --\n"; +do_ssl_test('ssl://bob.sni.velox.ch:443', context()); + +echo "-- raw SSL stream (2) --\n"; +do_ssl_test('ssl://mallory.sni.velox.ch:443', context()); + +echo "-- raw SSL stream with user supplied sni --\n"; + +$context = context(); +stream_context_set_option($context, 'ssl', 'SNI_server_name', 'bob.sni.velox.ch'); + +do_ssl_test('ssl://mallory.sni.velox.ch:443', $context); + +echo "-- raw SSL stream with sni disabled --\n"; + +$context = context(); +stream_context_set_option($context, 'ssl', 'SNI_enabled', false); + +do_ssl_test('ssl://mallory.sni.velox.ch:443', $context); + +/* Test tcp:// socket streams with SSL enabled */ + +echo "-- stream_socket_enable_crypto (1) --\n"; + +do_enable_crypto_test('tcp://bob.sni.velox.ch:443', context()); + +echo "-- stream_socket_enable_crypto (2) --\n"; + +do_enable_crypto_test('tcp://mallory.sni.velox.ch:443', context()); + +echo "-- stream_socket_enable_crypto with user supplied sni --\n"; + +$context = context(); +stream_context_set_option($context, 'ssl', 'SNI_server_name', 'bob.sni.velox.ch'); + +do_enable_crypto_test('tcp://mallory.sni.velox.ch:443', $context); + +echo "-- stream_socket_enable_crypto with sni disabled --\n"; + +$context = context(); +stream_context_set_option($context, 'ssl', 'SNI_enabled', false); + +do_enable_crypto_test('tcp://mallory.sni.velox.ch:443', $context); + +echo "-- stream_socket_enable_crypto with long name --\n"; + +$context = context(); +stream_context_set_option($context, 'ssl', 'SNI_server_name', str_repeat('a.', 500) . '.sni.velox.ch'); + +do_enable_crypto_test('tcp://mallory.sni.velox.ch:443', $context); + +?> +--EXPECTF-- +-- auto host name (1) -- +%unicode|string%(18) "alice.sni.velox.ch" +-- auto host name (2) -- +%unicode|string%(16) "bob.sni.velox.ch" +-- auto host name (3) -- +%unicode|string%(16) "bob.sni.velox.ch" +-- user supplied server name -- +%unicode|string%(16) "bob.sni.velox.ch" +-- sni disabled -- +%unicode|string%(18) "alice.sni.velox.ch" +-- raw SSL stream (1) -- +%unicode|string%(16) "bob.sni.velox.ch" +-- raw SSL stream (2) -- +%unicode|string%(14) "*.sni.velox.ch" +-- raw SSL stream with user supplied sni -- +%unicode|string%(16) "bob.sni.velox.ch" +-- raw SSL stream with sni disabled -- +%unicode|string%(18) "alice.sni.velox.ch" +-- stream_socket_enable_crypto (1) -- +%unicode|string%(16) "bob.sni.velox.ch" +-- stream_socket_enable_crypto (2) -- +%unicode|string%(14) "*.sni.velox.ch" +-- stream_socket_enable_crypto with user supplied sni -- +%unicode|string%(16) "bob.sni.velox.ch" +-- stream_socket_enable_crypto with sni disabled -- +%unicode|string%(18) "alice.sni.velox.ch" +-- stream_socket_enable_crypto with long name -- +%unicode|string%(18) "alice.sni.velox.ch" diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index 9462e0f91..212c003a7 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -2,7 +2,7 @@ +----------------------------------------------------------------------+ | PHP Version 5 | +----------------------------------------------------------------------+ - | Copyright (c) 1997-2009 The PHP Group | + | Copyright (c) 1997-2010 The PHP Group | +----------------------------------------------------------------------+ | This source file is subject to version 3.01 of the PHP license, | | that is bundled with this package in the file LICENSE, and is | @@ -16,10 +16,11 @@ +----------------------------------------------------------------------+ */ -/* $Id: xp_ssl.c 289416 2009-10-09 14:20:17Z pajoye $ */ +/* $Id: xp_ssl.c 293036 2010-01-03 09:23:27Z sebastian $ */ #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; |
