summaryrefslogtreecommitdiff
path: root/ext/openssl
diff options
context:
space:
mode:
authorOndřej Surý <ondrej@sury.org>2010-03-09 11:57:54 +0100
committerOndřej Surý <ondrej@sury.org>2010-03-09 11:57:54 +0100
commit855a09f4eded707941180c9d90acd17c25e29447 (patch)
treea40947efaa9876f31b6ee3956c3f3775768143bb /ext/openssl
parentc852c28a88fccf6e34a2cb091fdfa72bce2b59c7 (diff)
downloadphp-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.c25
-rw-r--r--ext/openssl/php_openssl.h4
-rw-r--r--ext/openssl/tests/bug48182.phpt6
-rw-r--r--ext/openssl/tests/sni_001.phpt178
-rw-r--r--ext/openssl/xp_ssl.c63
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;