From 225f534b1ae30b9e843c2531d3bdd38aa8ca84f7 Mon Sep 17 00:00:00 2001 From: Daniel Lowrey Date: Tue, 11 Feb 2014 05:26:08 -0700 Subject: [PATCH 01/10] Strengthen default cipher list --- ext/openssl/openssl.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 04d8b5ea237a..ef81a859fd2e 100755 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -83,6 +83,14 @@ #define HAVE_EVP_PKEY_EC 1 #endif +#define PHP_OPENSSL_DEFAULT_STREAM_CIPHERS "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:" \ + "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:" \ + "DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:" \ + "ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:" \ + "ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:" \ + "DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:" \ + "AES256-GCM-SHA384:AES128:AES256:HIGH:!SSLv2:!aNULL:!eNULL:!EXPORT:!DES:!MD5:!RC4:!ADH" + /* FIXME: Use the openssl constants instead of * enum. It is now impossible to match real values * against php constants. Also sorry to break the @@ -1151,6 +1159,9 @@ PHP_MINIT_FUNCTION(openssl) REGISTER_LONG_CONSTANT("OPENSSL_NO_PADDING", RSA_NO_PADDING, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("OPENSSL_PKCS1_OAEP_PADDING", RSA_PKCS1_OAEP_PADDING, CONST_CS|CONST_PERSISTENT); + /* Informational stream wrapper constants */ + REGISTER_STRING_CONSTANT("OPENSSL_DEFAULT_STREAM_CIPHERS", PHP_OPENSSL_DEFAULT_STREAM_CIPHERS, CONST_CS|CONST_PERSISTENT); + /* Ciphers */ #ifndef OPENSSL_NO_RC2 REGISTER_LONG_CONSTANT("OPENSSL_CIPHER_RC2_40", PHP_OPENSSL_CIPHER_RC2_40, CONST_CS|CONST_PERSISTENT); @@ -5339,7 +5350,7 @@ SSL *php_SSL_new_from_context(SSL_CTX *ctx, php_stream *stream TSRMLS_DC) /* {{{ GET_VER_OPT_STRING("ciphers", cipherlist); if (!cipherlist) { - cipherlist = "DEFAULT"; + cipherlist = PHP_OPENSSL_DEFAULT_STREAM_CIPHERS; } if (SSL_CTX_set_cipher_list(ctx, cipherlist) != 1) { return NULL; From 258d04df5cd7a579259306f491a8e8b2077f5f50 Mon Sep 17 00:00:00 2001 From: Daniel Lowrey Date: Tue, 11 Feb 2014 05:39:02 -0700 Subject: [PATCH 02/10] Explicitly set cert verify depth if not specified --- ext/openssl/openssl.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index ef81a859fd2e..82ac3dfff55a 100755 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -83,6 +83,7 @@ #define HAVE_EVP_PKEY_EC 1 #endif +#define PHP_OPENSSL_DEFAULT_STREAM_VERIFY_DEPTH 9 #define PHP_OPENSSL_DEFAULT_STREAM_CIPHERS "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:" \ "ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:" \ "DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:" \ @@ -1161,6 +1162,7 @@ PHP_MINIT_FUNCTION(openssl) /* Informational stream wrapper constants */ REGISTER_STRING_CONSTANT("OPENSSL_DEFAULT_STREAM_CIPHERS", PHP_OPENSSL_DEFAULT_STREAM_CIPHERS, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("OPENSSL_DEFAULT_STREAM_VERIFY_DEPTH", PHP_OPENSSL_DEFAULT_STREAM_VERIFY_DEPTH, CONST_CS|CONST_PERSISTENT); /* Ciphers */ #ifndef OPENSSL_NO_RC2 @@ -5339,6 +5341,8 @@ SSL *php_SSL_new_from_context(SSL_CTX *ctx, php_stream *stream TSRMLS_DC) /* {{{ if (GET_VER_OPT("verify_depth")) { convert_to_long_ex(val); SSL_CTX_set_verify_depth(ctx, Z_LVAL_PP(val)); + } else { + SSL_CTX_set_verify_depth(ctx, PHP_OPENSSL_DEFAULT_STREAM_VERIFY_DEPTH); } } From df6bfe3be209ba89a5d8a5f045f09a90db9dc16d Mon Sep 17 00:00:00 2001 From: Daniel Lowrey Date: Tue, 11 Feb 2014 05:57:15 -0700 Subject: [PATCH 03/10] Add openssl_get_cert_locations() function --- ext/openssl/openssl.c | 25 +++++++++++++++++++++++++ ext/openssl/php_openssl.h | 2 ++ 2 files changed, 27 insertions(+) diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 82ac3dfff55a..8d8871b9ff5e 100755 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -433,11 +433,16 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO(arginfo_openssl_spki_export_challenge, 0) ZEND_ARG_INFO(0, spki) ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_INFO(arginfo_openssl_get_cert_locations, 0) +ZEND_END_ARG_INFO() /* }}} */ /* {{{ openssl_functions[] */ const zend_function_entry openssl_functions[] = { + PHP_FE(openssl_get_cert_locations, arginfo_openssl_get_cert_locations) + /* spki functions */ PHP_FE(openssl_spki_new, arginfo_openssl_spki_new) PHP_FE(openssl_spki_verify, arginfo_openssl_spki_verify) @@ -1280,6 +1285,26 @@ PHP_MSHUTDOWN_FUNCTION(openssl) /* {{{ x509 cert functions */ +/* {{{ proto array openssl_get_cert_locations(void) + Retrieve an array mapping available certificate locations */ +PHP_FUNCTION(openssl_get_cert_locations) +{ + array_init(return_value); + + add_assoc_string(return_value, "default_cert_file", (char *) X509_get_default_cert_file(), 1); + add_assoc_string(return_value, "default_cert_file_env", (char *) X509_get_default_cert_file_env(), 1); + add_assoc_string(return_value, "default_cert_dir", (char *) X509_get_default_cert_dir(), 1); + add_assoc_string(return_value, "default_cert_dir_env", (char *) X509_get_default_cert_dir_env(), 1); + add_assoc_string(return_value, "default_private_dir", (char *) X509_get_default_private_dir(), 1); + add_assoc_string(return_value, "default_default_cert_area", (char *) X509_get_default_cert_area(), 1); + add_assoc_string(return_value, "ini_cafile", + zend_ini_string("openssl.cafile", sizeof("openssl.cafile"), 0), 1); + add_assoc_string(return_value, "ini_capath", + zend_ini_string("openssl.capath", sizeof("openssl.capath"), 0), 1); +} +/* }}} */ + + /* {{{ php_openssl_x509_from_zval Given a zval, coerce it into an X509 object. The zval can be: diff --git a/ext/openssl/php_openssl.h b/ext/openssl/php_openssl.h index 01e976f1f414..cab787afedd1 100644 --- a/ext/openssl/php_openssl.h +++ b/ext/openssl/php_openssl.h @@ -85,6 +85,8 @@ PHP_FUNCTION(openssl_spki_new); PHP_FUNCTION(openssl_spki_verify); PHP_FUNCTION(openssl_spki_export); PHP_FUNCTION(openssl_spki_export_challenge); + +PHP_FUNCTION(openssl_get_cert_locations); #else #define phpext_openssl_ptr NULL From b9ba011c0f2b147bd5b0faba04a6ef7aabaa48c4 Mon Sep 17 00:00:00 2001 From: Daniel Lowrey Date: Tue, 11 Feb 2014 06:24:34 -0700 Subject: [PATCH 04/10] Release ssl buffers --- ext/openssl/xp_ssl.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index 198dda3842b4..4dda5a4c72b8 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -435,6 +435,11 @@ static inline int php_openssl_setup_crypto(php_stream *stream, return -1; } +#ifdef SSL_MODE_RELEASE_BUFFERS + long mode = SSL_get_mode(sslsock->ssl_handle); + SSL_set_mode(sslsock->ssl_handle, mode | SSL_MODE_RELEASE_BUFFERS); +#endif + if (!SSL_set_fd(sslsock->ssl_handle, sslsock->s.socket)) { handle_ssl_error(stream, 0, 1 TSRMLS_CC); } From b98b093d73e935f4ab4d30423b652ed38a4c6d68 Mon Sep 17 00:00:00 2001 From: Daniel Lowrey Date: Tue, 11 Feb 2014 06:27:32 -0700 Subject: [PATCH 05/10] Disable TLS compression by default in both clients and servers --- ext/openssl/xp_ssl.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index 4dda5a4c72b8..99995b6814cb 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -418,9 +418,9 @@ static inline int php_openssl_setup_crypto(php_stream *stream, { zval **val; - if (stream->context && SUCCESS == php_stream_context_get_option( - stream->context, "ssl", "disable_compression", &val) && - zend_is_true(*val) + if (stream->context && (FAILURE == php_stream_context_get_option( + stream->context, "ssl", "disable_compression", &val) || + zend_is_true(*val)) ) { SSL_CTX_set_options(sslsock->ctx, SSL_OP_NO_COMPRESSION); } From 081c8e9d92b27eddbb3600c59f8d58d7afa4b229 Mon Sep 17 00:00:00 2001 From: Daniel Lowrey Date: Tue, 11 Feb 2014 06:42:29 -0700 Subject: [PATCH 06/10] Add 'capture_session_meta' context option --- ext/openssl/tests/session_meta_capture.phpt | 73 +++++++++++++++++++++ ext/openssl/xp_ssl.c | 37 +++++++++++ 2 files changed, 110 insertions(+) create mode 100644 ext/openssl/tests/session_meta_capture.phpt diff --git a/ext/openssl/tests/session_meta_capture.phpt b/ext/openssl/tests/session_meta_capture.phpt new file mode 100644 index 000000000000..8ef0f873c9a3 --- /dev/null +++ b/ext/openssl/tests/session_meta_capture.phpt @@ -0,0 +1,73 @@ +--TEST-- +Capture SSL session meta array in stream context +--SKIPIF-- + [ + 'local_cert' => __DIR__ . '/bug54992.pem', + 'allow_self_signed' => true +]]); +$server = stream_socket_server('ssl://127.0.0.1:64321', $errno, $errstr, $flags, $ctx); + +$pid = pcntl_fork(); +if ($pid == -1) { + die('could not fork'); +} else if ($pid) { + + // Base SSL context values + $sslCtxVars = array( + 'verify_peer' => TRUE, + 'cafile' => __DIR__ . '/bug54992-ca.pem', + 'CN_match' => 'bug54992.local', // common name from the server's "local_cert" PEM file + 'capture_session_meta' => TRUE + ); + + // SSLv3 + $ctxCopy = $sslCtxVars; + $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_SSLv3_CLIENT; + $ctx = stream_context_create(array('ssl' => $ctxCopy)); + stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx); + $meta = stream_context_get_options($ctx)['ssl']['session_meta']; + var_dump($meta['protocol']); + + // TLSv1 + $ctxCopy = $sslCtxVars; + $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT; + $ctx = stream_context_create(array('ssl' => $ctxCopy)); + stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx); + $meta = stream_context_get_options($ctx)['ssl']['session_meta']; + var_dump($meta['protocol']); + + // TLSv1.1 + $ctxCopy = $sslCtxVars; + $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT; + $ctx = stream_context_create(array('ssl' => $ctxCopy)); + stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx); + $meta = stream_context_get_options($ctx)['ssl']['session_meta']; + var_dump($meta['protocol']); + + // TLSv1.2 + $ctxCopy = $sslCtxVars; + $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT; + $ctx = stream_context_create(array('ssl' => $ctxCopy)); + stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx); + $meta = stream_context_get_options($ctx)['ssl']['session_meta']; + var_dump($meta['protocol']); + +} else { + @pcntl_wait($status); + @stream_socket_accept($server, 1); + @stream_socket_accept($server, 1); + @stream_socket_accept($server, 1); + @stream_socket_accept($server, 1); +} +--EXPECTF-- +string(5) "SSLv3" +string(5) "TLSv1" +string(7) "TLSv1.1" +string(7) "TLSv1.2" diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index 99995b6814cb..aa1d50e64d54 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -456,6 +456,31 @@ static inline int php_openssl_setup_crypto(php_stream *stream, return 0; } +static zval *php_capture_ssl_session_meta(SSL *ssl_handle) +{ + zval *meta_arr; + char *proto_str; + long proto = SSL_version(ssl_handle); + const SSL_CIPHER *cipher = SSL_get_current_cipher(ssl_handle); + + switch (proto) { + case TLS1_2_VERSION: proto_str = "TLSv1.2"; break; + case TLS1_1_VERSION: proto_str = "TLSv1.1"; break; + case TLS1_VERSION: proto_str = "TLSv1"; break; + case SSL3_VERSION: proto_str = "SSLv3"; break; + case SSL2_VERSION: proto_str = "SSLv2"; break; + default: proto_str = "UNKNOWN"; + } + + MAKE_STD_ZVAL(meta_arr); + array_init(meta_arr); + add_assoc_string(meta_arr, "protocol", proto_str, 1); + add_assoc_string(meta_arr, "cipher_name", (char *) SSL_CIPHER_get_name(cipher), 1); + add_assoc_long(meta_arr, "cipher_bits", SSL_CIPHER_get_bits(cipher, NULL)); + add_assoc_string(meta_arr, "cipher_version", SSL_CIPHER_get_version(cipher), 1); + + return meta_arr; +} static inline int php_openssl_enable_crypto(php_stream *stream, php_openssl_netstream_data_t *sslsock, php_stream_xport_crypto_param *cparam TSRMLS_DC) { @@ -581,6 +606,18 @@ static inline int php_openssl_enable_crypto(php_stream *stream, php_openssl_nets if (stream->context) { zval **val, *zcert; + if (SUCCESS == php_stream_context_get_option( + stream->context, "ssl", + "capture_session_meta", &val) && + zend_is_true(*val)) { + zval *meta_arr = php_capture_ssl_session_meta(sslsock->ssl_handle); + php_stream_context_set_option(stream->context, + "ssl", "session_meta", + meta_arr); + zval_dtor(meta_arr); + efree(meta_arr); + } + if (SUCCESS == php_stream_context_get_option( stream->context, "ssl", "capture_peer_cert", &val) && From 742fc5fb3562eff6f0ac5f53ec2b4d2c11ebfabf Mon Sep 17 00:00:00 2001 From: Daniel Lowrey Date: Wed, 19 Feb 2014 20:39:57 -0700 Subject: [PATCH 07/10] Add 'honor_cipher_order' server context option --- ext/openssl/xp_ssl.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index aa1d50e64d54..ea2e5f70fcf9 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -435,6 +435,13 @@ static inline int php_openssl_setup_crypto(php_stream *stream, return -1; } + if (!sslsock->is_client && stream->context && SUCCESS == php_stream_context_get_option( + stream->context, "ssl", "honor_cipher_order", &val) && + zend_is_true(*val) + ) { + SSL_CTX_set_options(sslsock->ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); + } + #ifdef SSL_MODE_RELEASE_BUFFERS long mode = SSL_get_mode(sslsock->ssl_handle); SSL_set_mode(sslsock->ssl_handle, mode | SSL_MODE_RELEASE_BUFFERS); From d0c9207cff83a1055767e86e8d2aa9661513224f Mon Sep 17 00:00:00 2001 From: Daniel Lowrey Date: Tue, 11 Feb 2014 08:42:34 -0700 Subject: [PATCH 08/10] Improve server forward secrecy, refactor client SNI --- ext/openssl/xp_ssl.c | 211 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 193 insertions(+), 18 deletions(-) diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index ea2e5f70fcf9..1b2271b1283a 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -37,6 +37,10 @@ #include #endif +#if !defined(OPENSSL_NO_ECDH) && OPENSSL_VERSION_NUMBER >= 0x0090800fL +#define HAVE_ECDH +#endif + int php_openssl_apply_verification_policy(SSL *ssl, X509 *peer, php_stream *stream TSRMLS_DC); SSL *php_SSL_new_from_context(SSL_CTX *ctx, php_stream *stream TSRMLS_DC); int php_openssl_get_x509_list_id(void); @@ -427,6 +431,27 @@ static inline int php_openssl_setup_crypto(php_stream *stream, } #endif + if (!sslsock->is_client && stream->context && SUCCESS == php_stream_context_get_option( + stream->context, "ssl", "honor_cipher_order", &val) && + zend_is_true(*val) + ) { + SSL_CTX_set_options(sslsock->ctx, SSL_OP_CIPHER_SERVER_PREFERENCE); + } + + if (!sslsock->is_client && stream->context && SUCCESS == php_stream_context_get_option( + stream->context, "ssl", "single_dh_use", &val) && + zend_is_true(*val) + ) { + SSL_CTX_set_options(sslsock->ctx, SSL_OP_SINGLE_DH_USE); + } + + if (!sslsock->is_client && stream->context && SUCCESS == php_stream_context_get_option( + stream->context, "ssl", "single_ecdh_use", &val) && + zend_is_true(*val) + ) { + SSL_CTX_set_options(sslsock->ctx, SSL_OP_SINGLE_ECDH_USE); + } + sslsock->ssl_handle = php_SSL_new_from_context(sslsock->ctx, stream TSRMLS_CC); if (sslsock->ssl_handle == NULL) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed to create an SSL handle"); @@ -489,7 +514,167 @@ static zval *php_capture_ssl_session_meta(SSL *ssl_handle) return meta_arr; } -static inline int php_openssl_enable_crypto(php_stream *stream, php_openssl_netstream_data_t *sslsock, php_stream_xport_crypto_param *cparam TSRMLS_DC) +static int php_set_server_rsa_key(php_stream *stream, + php_openssl_netstream_data_t *sslsock + TSRMLS_DC) +{ + zval ** val; + int rsa_key_size; + RSA* rsa; + int retval = 1; + + if (php_stream_context_get_option(stream->context, "ssl", "rsa_key_size", &val) == SUCCESS) { + rsa_key_size = (int) Z_LVAL_PP(val); + if ((rsa_key_size != 1) && (rsa_key_size & (rsa_key_size - 1))) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "RSA key size requires a power of 2: %d", + rsa_key_size); + + rsa_key_size = 2048; + } + } else { + rsa_key_size = 2048; + } + + rsa = RSA_generate_key(rsa_key_size, RSA_F4, NULL, NULL); + + if (!SSL_set_tmp_rsa(sslsock->ssl_handle, rsa)) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Failed setting RSA key"); + retval = 0; + } + + RSA_free(rsa); + + return retval; +} + + +static int php_set_server_dh_param(php_openssl_netstream_data_t *sslsock, + char *dh_path + TSRMLS_DC) +{ + DH *dh; + BIO* bio; + + bio = BIO_new_file(dh_path, "r"); + + if (bio == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Invalid dh_param file: %s", + dh_path); + + return 0; + } + + dh = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); + BIO_free(bio); + + if (dh == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Failed reading DH params from file: %s", + dh_path); + + return 0; + } + + if (SSL_set_tmp_dh(sslsock->ssl_handle, dh) < 0) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "DH param assignment failed"); + DH_free(dh); + return 0; + } + + DH_free(dh); + + return 1; +} + +static int php_enable_server_crypto_opts(php_stream *stream, + php_openssl_netstream_data_t *sslsock + TSRMLS_DC) +{ + zval **val; + + if (php_stream_context_get_option(stream->context, "ssl", "dh_param", &val) == SUCCESS) { + convert_to_string_ex(val); + if (!php_set_server_dh_param(sslsock, Z_STRVAL_PP(val) TSRMLS_CC)) { + return 0; + } + } + +#ifdef HAVE_ECDH + + int curve_nid; + EC_KEY *ecdh; + + if (php_stream_context_get_option(stream->context, "ssl", "ecdh_curve", &val) == SUCCESS) { + char *curve_str; + convert_to_string_ex(val); + curve_str = Z_STRVAL_PP(val); + curve_nid = OBJ_sn2nid(curve_str); + if (curve_nid == NID_undef) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Invalid ECDH curve: %s", + curve_str); + + return 0; + } + } else { + curve_nid = NID_X9_62_prime256v1; + } + + ecdh = EC_KEY_new_by_curve_name(curve_nid); + if (ecdh == NULL) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Failed generating ECDH curve"); + + return 0; + } + + SSL_set_tmp_ecdh(sslsock->ssl_handle, ecdh); + EC_KEY_free(ecdh); + +#else + + if (php_stream_context_get_option(stream->context, "ssl", "ecdh_curve", &val) == SUCCESS) { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "ECDH curve support not compiled into the OpenSSL lib against which PHP is linked"); + } + +#endif + + if (!php_set_server_rsa_key(stream, sslsock TSRMLS_CC)) { + return 0; + } + + return 1; +} + +static inline void enable_client_sni(php_stream *stream, php_openssl_netstream_data_t *sslsock) /* {{{ */ +{ + zval **val; + + if (stream->context && + (php_stream_context_get_option(stream->context, "ssl", "SNI_enabled", &val) == FAILURE + || zend_is_true(*val)) + ) { + if (php_stream_context_get_option(stream->context, "ssl", "SNI_server_name", &val) == SUCCESS) { + convert_to_string_ex(val); + SSL_set_tlsext_host_name(sslsock->ssl_handle, Z_STRVAL_PP(val)); + } else if (sslsock->url_name) { + SSL_set_tlsext_host_name(sslsock->ssl_handle, sslsock->url_name); + } + } else if (!stream->context && sslsock->url_name) { + SSL_set_tlsext_host_name(sslsock->ssl_handle, sslsock->url_name); + } +} +/* }}} */ + +static inline int php_openssl_enable_crypto(php_stream *stream, + php_openssl_netstream_data_t *sslsock, + php_stream_xport_crypto_param *cparam + TSRMLS_DC) { int n, retry = 1; @@ -501,26 +686,16 @@ static inline int php_openssl_enable_crypto(php_stream *stream, php_openssl_nets #if OPENSSL_VERSION_NUMBER >= 0x00908070L && !defined(OPENSSL_NO_TLSEXT) { - zval **val; - - if (sslsock->is_client && - stream->context && - (php_stream_context_get_option(stream->context, "ssl", "SNI_enabled", &val) == FAILURE - || zend_is_true(*val)) - ) { - if (php_stream_context_get_option(stream->context, "ssl", "SNI_server_name", &val) == SUCCESS) { - convert_to_string_ex(val); - SSL_set_tlsext_host_name(sslsock->ssl_handle, Z_STRVAL_PP(val)); - } else if (sslsock->url_name) { - SSL_set_tlsext_host_name(sslsock->ssl_handle, sslsock->url_name); - } - - } else if (sslsock->is_client && !stream->context && sslsock->url_name) { - SSL_set_tlsext_host_name(sslsock->ssl_handle, sslsock->url_name); + if (sslsock->is_client) { + enable_client_sni(stream, sslsock); } - } #endif + + if (!sslsock->is_client && !php_enable_server_crypto_opts(stream, sslsock TSRMLS_CC)) { + return -1; + } + if (!sslsock->state_set) { if (sslsock->is_client) { SSL_set_connect_state(sslsock->ssl_handle); From 3a9829af2062527fb4e5cb11eb4ac3e045d0b370 Mon Sep 17 00:00:00 2001 From: Daniel Lowrey Date: Tue, 11 Feb 2014 08:12:01 -0700 Subject: [PATCH 09/10] Use crypto method flags; add tlsv1.0 wrapper; add wrapper tests --- ext/openssl/openssl.c | 2 + .../tests/stream_crypto_flags_001.phpt | 58 ++++ .../tests/stream_crypto_flags_002.phpt | 67 +++++ .../tests/stream_crypto_flags_003.phpt | 68 +++++ .../tests/stream_crypto_flags_005.phpt | 67 +++++ ext/openssl/tests/streams_crypto_method.phpt | 1 - ext/openssl/tests/tlsv1.0_wrapper.phpt | 47 +++ ext/openssl/tests/tlsv1.1_wrapper.phpt | 47 +++ ext/openssl/tests/tlsv1.2_wrapper.phpt | 47 +++ ext/openssl/xp_ssl.c | 270 +++++++++--------- ext/standard/file.c | 24 +- main/streams/php_stream_transport.h | 35 ++- 12 files changed, 569 insertions(+), 164 deletions(-) create mode 100644 ext/openssl/tests/stream_crypto_flags_001.phpt create mode 100644 ext/openssl/tests/stream_crypto_flags_002.phpt create mode 100644 ext/openssl/tests/stream_crypto_flags_003.phpt create mode 100644 ext/openssl/tests/stream_crypto_flags_005.phpt create mode 100644 ext/openssl/tests/tlsv1.0_wrapper.phpt create mode 100644 ext/openssl/tests/tlsv1.1_wrapper.phpt create mode 100644 ext/openssl/tests/tlsv1.2_wrapper.phpt diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 8d8871b9ff5e..8b77d28ad1e6 100755 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -1224,6 +1224,7 @@ PHP_MINIT_FUNCTION(openssl) php_stream_xport_register("sslv2", php_openssl_ssl_socket_factory TSRMLS_CC); #endif php_stream_xport_register("tls", php_openssl_ssl_socket_factory TSRMLS_CC); + php_stream_xport_register("tlsv1.0", php_openssl_ssl_socket_factory TSRMLS_CC); #if OPENSSL_VERSION_NUMBER >= 0x10001001L php_stream_xport_register("tlsv1.1", php_openssl_ssl_socket_factory TSRMLS_CC); php_stream_xport_register("tlsv1.2", php_openssl_ssl_socket_factory TSRMLS_CC); @@ -1269,6 +1270,7 @@ PHP_MSHUTDOWN_FUNCTION(openssl) #endif php_stream_xport_unregister("sslv3" TSRMLS_CC); php_stream_xport_unregister("tls" TSRMLS_CC); + php_stream_xport_unregister("tlsv1.0" TSRMLS_CC); #if OPENSSL_VERSION_NUMBER >= 0x10001001L php_stream_xport_unregister("tlsv1.1" TSRMLS_CC); php_stream_xport_unregister("tlsv1.2" TSRMLS_CC); diff --git a/ext/openssl/tests/stream_crypto_flags_001.phpt b/ext/openssl/tests/stream_crypto_flags_001.phpt new file mode 100644 index 000000000000..6e3c69b401d5 --- /dev/null +++ b/ext/openssl/tests/stream_crypto_flags_001.phpt @@ -0,0 +1,58 @@ +--TEST-- +Basic bitwise stream crypto context flag assignment +--SKIPIF-- + [ + 'local_cert' => __DIR__ . '/bug54992.pem', + 'allow_self_signed' => true +]]); +$server = stream_socket_server('ssl://127.0.0.1:64321', $errno, $errstr, $flags, $ctx); +var_dump($server); + +$pid = pcntl_fork(); +if ($pid == -1) { + die('could not fork'); +} else if ($pid) { + + // Base SSL context values + $sslCtxVars = array( + 'verify_peer' => TRUE, + 'cafile' => __DIR__ . '/bug54992-ca.pem', + 'CN_match' => 'bug54992.local', // common name from the server's "local_cert" PEM file + ); + + // SSLv3 + $ctxCopy = $sslCtxVars; + $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_SSLv3_CLIENT; + $ctx = stream_context_create(array('ssl' => $ctxCopy)); + var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx)); + + // TLSv1 + $ctxCopy = $sslCtxVars; + $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT; + $ctx = stream_context_create(array('ssl' => $ctxCopy)); + var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx)); + + // TLS (any) + $ctxCopy = $sslCtxVars; + $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLS_CLIENT; + $ctx = stream_context_create(array('ssl' => $ctxCopy)); + var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx)); + +} else { + @pcntl_wait($status); + @stream_socket_accept($server, 1); + @stream_socket_accept($server, 1); + @stream_socket_accept($server, 1); +} +--EXPECTF-- +resource(%d) of type (stream) +resource(%d) of type (stream) +resource(%d) of type (stream) +resource(%d) of type (stream) + diff --git a/ext/openssl/tests/stream_crypto_flags_002.phpt b/ext/openssl/tests/stream_crypto_flags_002.phpt new file mode 100644 index 000000000000..c1d181bc7654 --- /dev/null +++ b/ext/openssl/tests/stream_crypto_flags_002.phpt @@ -0,0 +1,67 @@ +--TEST-- +TLSv1.1 and TLSv1.2 bitwise stream crypto flag assignment +--SKIPIF-- + [ + 'local_cert' => __DIR__ . '/bug54992.pem', + 'allow_self_signed' => true +]]); +$server = stream_socket_server('ssl://127.0.0.1:64321', $errno, $errstr, $flags, $ctx); +var_dump($server); + +$pid = pcntl_fork(); +if ($pid == -1) { + die('could not fork'); +} else if ($pid) { + + // Base SSL context values + $sslCtxVars = array( + 'verify_peer' => TRUE, + 'cafile' => __DIR__ . '/bug54992-ca.pem', + 'CN_match' => 'bug54992.local', // common name from the server's "local_cert" PEM file + ); + + // TLSv1 + $ctxCopy = $sslCtxVars; + $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT; + $ctx = stream_context_create(array('ssl' => $ctxCopy)); + var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx)); + + // TLSv1.1 + $ctxCopy = $sslCtxVars; + $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT; + $ctx = stream_context_create(array('ssl' => $ctxCopy)); + var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx)); + + // TLSv1.2 + $ctxCopy = $sslCtxVars; + $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT; + $ctx = stream_context_create(array('ssl' => $ctxCopy)); + var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx)); + + // TLS (any) + $ctxCopy = $sslCtxVars; + $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLS_CLIENT; + $ctx = stream_context_create(array('ssl' => $ctxCopy)); + var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx)); + +} else { + @pcntl_wait($status); + @stream_socket_accept($server, 1); + @stream_socket_accept($server, 1); + @stream_socket_accept($server, 1); + @stream_socket_accept($server, 1); +} +--EXPECTF-- +resource(%d) of type (stream) +resource(%d) of type (stream) +resource(%d) of type (stream) +resource(%d) of type (stream) +resource(%d) of type (stream) + diff --git a/ext/openssl/tests/stream_crypto_flags_003.phpt b/ext/openssl/tests/stream_crypto_flags_003.phpt new file mode 100644 index 000000000000..8c4dadba0dba --- /dev/null +++ b/ext/openssl/tests/stream_crypto_flags_003.phpt @@ -0,0 +1,68 @@ +--TEST-- +Server bitwise stream crypto flag assignment +--SKIPIF-- + [ + 'local_cert' => __DIR__ . '/bug54992.pem', + 'allow_self_signed' => true, + + // Only accept SSLv3 and TLSv1.2 connections + 'crypto_method' => STREAM_CRYPTO_METHOD_SSLv3_SERVER | STREAM_CRYPTO_METHOD_TLSv1_2_SERVER +]]); +$server = stream_socket_server('ssl://127.0.0.1:64321', $errno, $errstr, $flags, $ctx); +var_dump($server); + +$pid = pcntl_fork(); +if ($pid == -1) { + die('could not fork'); +} else if ($pid) { + + // Base SSL context values + $sslCtxVars = array( + 'verify_peer' => TRUE, + 'cafile' => __DIR__ . '/bug54992-ca.pem', + 'CN_match' => 'bug54992.local', // common name from the server's "local_cert" PEM file + ); + + // TLSv1.2 + $ctxCopy = $sslCtxVars; + $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT; + $ctx = stream_context_create(array('ssl' => $ctxCopy)); + var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx)); + + // SSLv3 + $ctxCopy = $sslCtxVars; + $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_SSLv3_CLIENT; + $ctx = stream_context_create(array('ssl' => $ctxCopy)); + var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx)); + + // TLSv1 (should fail) + $ctxCopy = $sslCtxVars; + $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT; + $ctx = stream_context_create(array('ssl' => $ctxCopy)); + var_dump(@stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx)); + + // TLSv1.1 (should fail) + $ctxCopy = $sslCtxVars; + $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT; + $ctx = stream_context_create(array('ssl' => $ctxCopy)); + var_dump(@stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 1, STREAM_CLIENT_CONNECT, $ctx)); + +} else { + @pcntl_wait($status); + @stream_socket_accept($server, 1); + @stream_socket_accept($server, 1); +} +--EXPECTF-- +resource(%d) of type (stream) +resource(%d) of type (stream) +resource(%d) of type (stream) +bool(false) +bool(false) + diff --git a/ext/openssl/tests/stream_crypto_flags_005.phpt b/ext/openssl/tests/stream_crypto_flags_005.phpt new file mode 100644 index 000000000000..965471f07527 --- /dev/null +++ b/ext/openssl/tests/stream_crypto_flags_005.phpt @@ -0,0 +1,67 @@ +--TEST-- +Specific protocol method specification +--SKIPIF-- + [ + 'local_cert' => __DIR__ . '/bug54992.pem', + 'allow_self_signed' => true, + 'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_0_SERVER +]]); + +$server = stream_socket_server('ssl://127.0.0.1:64321', $errno, $errstr, $flags, $ctx); +var_dump($server); + +$pid = pcntl_fork(); +if ($pid == -1) { + die('could not fork'); +} else if ($pid) { + + // Base SSL context values + $sslCtxVars = array( + 'verify_peer' => FALSE, + 'cafile' => __DIR__ . '/bug54992-ca.pem', + 'CN_match' => 'bug54992.local', // common name from the server's "local_cert" PEM file + ); + + // Should fail because the SSLv23 hello method is not supported + $ctxCopy = $sslCtxVars; + $ctx = stream_context_create(array('ssl' => $ctxCopy)); + var_dump(@stream_socket_client("ssl://127.0.0.1:64321")); + + // Should fail because the TLSv1.1 hello method is not supported + $ctxCopy = $sslCtxVars; + $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT; + $ctx = stream_context_create(array('ssl' => $ctxCopy)); + var_dump(@stream_socket_client("ssl://127.0.0.1:64321")); + + // Should fail because the TLSv1.2 hello method is not supported + $ctxCopy = $sslCtxVars; + $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT; + $ctx = stream_context_create(array('ssl' => $ctxCopy)); + var_dump(@stream_socket_client("ssl://127.0.0.1:64321")); + + // Should succeed because we use the same TLSv1 hello + $ctxCopy = $sslCtxVars; + $ctxCopy['crypto_method'] = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT; + $ctx = stream_context_create(array('ssl' => $ctxCopy)); + var_dump(stream_socket_client("ssl://127.0.0.1:64321", $errno, $errstr, 30, STREAM_CLIENT_CONNECT, $ctx)); + +} else { + @pcntl_wait($status); + @stream_socket_accept($server, 1); + @stream_socket_accept($server, 1); + @stream_socket_accept($server, 1); + @stream_socket_accept($server, 1); +} +--EXPECTF-- +resource(%d) of type (stream) +bool(false) +bool(false) +bool(false) +resource(%d) of type (stream) + diff --git a/ext/openssl/tests/streams_crypto_method.phpt b/ext/openssl/tests/streams_crypto_method.phpt index 6f6bedd63363..6eee8df5f4ea 100644 --- a/ext/openssl/tests/streams_crypto_method.phpt +++ b/ext/openssl/tests/streams_crypto_method.phpt @@ -56,4 +56,3 @@ EOS; ?> --EXPECTF-- Hello World! - diff --git a/ext/openssl/tests/tlsv1.0_wrapper.phpt b/ext/openssl/tests/tlsv1.0_wrapper.phpt new file mode 100644 index 000000000000..5366830187a2 --- /dev/null +++ b/ext/openssl/tests/tlsv1.0_wrapper.phpt @@ -0,0 +1,47 @@ +--TEST-- +tlsv1.0 stream wrapper +--SKIPIF-- + array( + 'local_cert' => __DIR__ . '/streams_crypto_method.pem', +))); + +$server = stream_socket_server('tlsv1.0://127.0.0.1:64321', $errno, $errstr, $flags, $ctx); +var_dump($server); + +$pid = pcntl_fork(); +if ($pid == -1) { + die('could not fork'); +} elseif ($pid) { + $flags = STREAM_CLIENT_CONNECT; + $ctx = stream_context_create(array('ssl' => array( + 'verify_peer' => false, + 'verify_host' => false + ))); + + $client = stream_socket_client("tlsv1.0://127.0.0.1:64321", $errno, $errstr, 1, $flags, $ctx); + var_dump($client); + + $client = @stream_socket_client("sslv3://127.0.0.1:64321", $errno, $errstr, 1, $flags, $ctx); + var_dump($client); + + $client = @stream_socket_client("tlsv1.2://127.0.0.1:64321", $errno, $errstr, 1, $flags, $ctx); + var_dump($client); + +} else { + @pcntl_wait($status); + for ($i=0; $i < 3; $i++) { + @stream_socket_accept($server, 1); + } +} +--EXPECTF-- +resource(%d) of type (stream) +resource(%d) of type (stream) +bool(false) +bool(false) diff --git a/ext/openssl/tests/tlsv1.1_wrapper.phpt b/ext/openssl/tests/tlsv1.1_wrapper.phpt new file mode 100644 index 000000000000..82048e525de7 --- /dev/null +++ b/ext/openssl/tests/tlsv1.1_wrapper.phpt @@ -0,0 +1,47 @@ +--TEST-- +tlsv1.1 stream wrapper +--SKIPIF-- + array( + 'local_cert' => __DIR__ . '/streams_crypto_method.pem', +))); + +$server = stream_socket_server('tlsv1.1://127.0.0.1:64321', $errno, $errstr, $flags, $ctx); +var_dump($server); + +$pid = pcntl_fork(); +if ($pid == -1) { + die('could not fork'); +} elseif ($pid) { + $flags = STREAM_CLIENT_CONNECT; + $ctx = stream_context_create(array('ssl' => array( + 'verify_peer' => false, + 'verify_host' => false + ))); + + $client = stream_socket_client("tlsv1.1://127.0.0.1:64321", $errno, $errstr, 1, $flags, $ctx); + var_dump($client); + + $client = @stream_socket_client("sslv3://127.0.0.1:64321", $errno, $errstr, 1, $flags, $ctx); + var_dump($client); + + $client = @stream_socket_client("tlsv1.2://127.0.0.1:64321", $errno, $errstr, 1, $flags, $ctx); + var_dump($client); + +} else { + @pcntl_wait($status); + for ($i=0; $i < 3; $i++) { + @stream_socket_accept($server, 1); + } +} +--EXPECTF-- +resource(%d) of type (stream) +resource(%d) of type (stream) +bool(false) +bool(false) diff --git a/ext/openssl/tests/tlsv1.2_wrapper.phpt b/ext/openssl/tests/tlsv1.2_wrapper.phpt new file mode 100644 index 000000000000..d58d1a12624a --- /dev/null +++ b/ext/openssl/tests/tlsv1.2_wrapper.phpt @@ -0,0 +1,47 @@ +--TEST-- +tlsv1.2 stream wrapper +--SKIPIF-- + array( + 'local_cert' => __DIR__ . '/streams_crypto_method.pem', +))); + +$server = stream_socket_server('tlsv1.2://127.0.0.1:64321', $errno, $errstr, $flags, $ctx); +var_dump($server); + +$pid = pcntl_fork(); +if ($pid == -1) { + die('could not fork'); +} elseif ($pid) { + $flags = STREAM_CLIENT_CONNECT; + $ctx = stream_context_create(array('ssl' => array( + 'verify_peer' => false, + 'verify_host' => false + ))); + + $client = stream_socket_client("tlsv1.2://127.0.0.1:64321", $errno, $errstr, 1, $flags, $ctx); + var_dump($client); + + $client = @stream_socket_client("sslv3://127.0.0.1:64321", $errno, $errstr, 1, $flags, $ctx); + var_dump($client); + + $client = @stream_socket_client("tlsv1.1://127.0.0.1:64321", $errno, $errstr, 1, $flags, $ctx); + var_dump($client); + +} else { + @pcntl_wait($status); + for ($i=0; $i < 3; $i++) { + @stream_socket_accept($server, 1); + } +} +--EXPECTF-- +resource(%d) of type (stream) +resource(%d) of type (stream) +bool(false) +bool(false) diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index 1b2271b1283a..39e95776416b 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -41,6 +41,14 @@ #define HAVE_ECDH #endif +/* Flags for determining allowed stream crypto methods */ +#define STREAM_CRYPTO_IS_CLIENT (1<<0) +#define STREAM_CRYPTO_METHOD_SSLv2 (1<<1) +#define STREAM_CRYPTO_METHOD_SSLv3 (1<<2) +#define STREAM_CRYPTO_METHOD_TLSv1_0 (1<<3) +#define STREAM_CRYPTO_METHOD_TLSv1_1 (1<<4) +#define STREAM_CRYPTO_METHOD_TLSv1_2 (1<<5) + int php_openssl_apply_verification_policy(SSL *ssl, X509 *peer, php_stream *stream TSRMLS_DC); SSL *php_SSL_new_from_context(SSL_CTX *ctx, php_stream *stream TSRMLS_DC); int php_openssl_get_x509_list_id(void); @@ -290,14 +298,97 @@ static int php_openssl_sockop_stat(php_stream *stream, php_stream_statbuf *ssb T } +static const SSL_METHOD *php_select_crypto_method(long method_value, int is_client TSRMLS_DC) +{ + if (method_value == STREAM_CRYPTO_METHOD_SSLv2) { +#ifndef OPENSSL_NO_SSL2 + return is_client ? SSLv2_client_method() : SSLv2_server_method(); +#else + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "SSLv2 support is not compiled into the OpenSSL library PHP is linked against"); + return NULL; +#endif + } else if (method_value == STREAM_CRYPTO_METHOD_SSLv3) { + return is_client ? SSLv3_client_method() : SSLv3_server_method(); + } else if (method_value == STREAM_CRYPTO_METHOD_TLSv1_0) { + return is_client ? TLSv1_client_method() : TLSv1_server_method(); + } else if (method_value == STREAM_CRYPTO_METHOD_TLSv1_1) { +#if OPENSSL_VERSION_NUMBER >= 0x10001001L + return is_client ? TLSv1_1_client_method() : TLSv1_1_server_method(); +#else + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "TLSv1.1 support is not compiled into the OpenSSL library PHP is linked against"); + return NULL; +#endif + } else if (method_value == STREAM_CRYPTO_METHOD_TLSv1_2) { +#if OPENSSL_VERSION_NUMBER >= 0x10001001L + return is_client ? TLSv1_2_client_method() : TLSv1_2_server_method(); +#else + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "TLSv1.1 support is not compiled into the OpenSSL library PHP is linked against"); + return NULL; +#endif + } else { + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "Invalid crypto method"); + return NULL; + } +} + +static long php_get_crypto_method_ctx_flags(long method_flags TSRMLS_DC) +{ + long ssl_ctx_options = SSL_OP_ALL; + +#ifndef OPENSSL_NO_SSL2 + if (!(method_flags & STREAM_CRYPTO_METHOD_SSLv2)) { + ssl_ctx_options |= SSL_OP_NO_SSLv2; + } +#endif + + if (!(method_flags & STREAM_CRYPTO_METHOD_SSLv3)) { + ssl_ctx_options |= SSL_OP_NO_SSLv3; + } + + if (!(method_flags & STREAM_CRYPTO_METHOD_TLSv1_0)) { + ssl_ctx_options |= SSL_OP_NO_TLSv1; + } + + if (!(method_flags & STREAM_CRYPTO_METHOD_TLSv1_1)) { +#if OPENSSL_VERSION_NUMBER >= 0x10001001L + ssl_ctx_options |= SSL_OP_NO_TLSv1_1; +#endif + } else { +#if OPENSSL_VERSION_NUMBER < 0x10001001L + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "TLSv1.1 support is not compiled into the OpenSSL library PHP is linked against"); + return -1; +#endif + } + + if (!(method_flags & STREAM_CRYPTO_METHOD_TLSv1_2)) { +#if OPENSSL_VERSION_NUMBER >= 0x10001001L + ssl_ctx_options |= SSL_OP_NO_TLSv1_2; +#endif + } else { +#if OPENSSL_VERSION_NUMBER < 0x10001001L + php_error_docref(NULL TSRMLS_CC, E_WARNING, + "TLSv1.2 support is not compiled into the OpenSSL library PHP is linked against"); + return -1; +#endif + } + + return ssl_ctx_options; +} + static inline int php_openssl_setup_crypto(php_stream *stream, php_openssl_netstream_data_t *sslsock, php_stream_xport_crypto_param *cparam TSRMLS_DC) { const SSL_METHOD *method; - long ssl_ctx_options = SSL_OP_ALL; - + long ssl_ctx_options; + long method_flags; + if (sslsock->ssl_handle) { if (sslsock->s.is_blocked) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL/TLS already set-up for this stream"); @@ -309,89 +400,22 @@ static inline int php_openssl_setup_crypto(php_stream *stream, /* need to do slightly different things, based on client/server method, * so lets remember which method was selected */ - - switch (cparam->inputs.method) { - case STREAM_CRYPTO_METHOD_SSLv23_CLIENT: - sslsock->is_client = 1; - method = SSLv23_client_method(); - break; - case STREAM_CRYPTO_METHOD_SSLv2_CLIENT: -#ifdef OPENSSL_NO_SSL2 - php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSLv2 support is not compiled into the OpenSSL library PHP is linked against"); + sslsock->is_client = cparam->inputs.method & STREAM_CRYPTO_IS_CLIENT; + method_flags = ((cparam->inputs.method >> 1) << 1); + + /* Should we use a specific crypto method or is generic SSLv23 okay? */ + if ((method_flags & (method_flags-1)) == 0) { + ssl_ctx_options = SSL_OP_ALL; + method = php_select_crypto_method(method_flags, sslsock->is_client TSRMLS_CC); + if (method == NULL) { return -1; -#else - sslsock->is_client = 1; - method = SSLv2_client_method(); - break; -#endif - case STREAM_CRYPTO_METHOD_SSLv3_CLIENT: - sslsock->is_client = 1; - method = SSLv3_client_method(); - break; - case STREAM_CRYPTO_METHOD_TLS_CLIENT: - sslsock->is_client = 1; - method = TLSv1_client_method(); - break; - case STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT: -#if OPENSSL_VERSION_NUMBER >= 0x10001001L - sslsock->is_client = 1; - method = TLSv1_1_client_method(); - break; -#else - php_error_docref(NULL TSRMLS_CC, E_WARNING, "TLSv1.1 support is not compiled into the OpenSSL library PHP is linked against"); - return -1; -#endif - case STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT: -#if OPENSSL_VERSION_NUMBER >= 0x10001001L - sslsock->is_client = 1; - method = TLSv1_2_client_method(); - break; -#else - php_error_docref(NULL TSRMLS_CC, E_WARNING, "TLSv1.2 support is not compiled into the OpenSSL library PHP is linked against"); - return -1; -#endif - case STREAM_CRYPTO_METHOD_SSLv23_SERVER: - sslsock->is_client = 0; - method = SSLv23_server_method(); - break; - case STREAM_CRYPTO_METHOD_SSLv3_SERVER: - sslsock->is_client = 0; - method = SSLv3_server_method(); - break; - case STREAM_CRYPTO_METHOD_SSLv2_SERVER: -#ifdef OPENSSL_NO_SSL2 - php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSLv2 support is not compiled into the OpenSSL library PHP is linked against"); - return -1; -#else - sslsock->is_client = 0; - method = SSLv2_server_method(); - break; -#endif - case STREAM_CRYPTO_METHOD_TLS_SERVER: - sslsock->is_client = 0; - method = TLSv1_server_method(); - break; - case STREAM_CRYPTO_METHOD_TLSv1_1_SERVER: -#if OPENSSL_VERSION_NUMBER >= 0x10001001L - sslsock->is_client = 0; - method = TLSv1_1_server_method(); - break; -#else - php_error_docref(NULL TSRMLS_CC, E_WARNING, "TLSv1.1 support is not compiled into the OpenSSL library PHP is linked against"); - return -1; -#endif - case STREAM_CRYPTO_METHOD_TLSv1_2_SERVER: -#if OPENSSL_VERSION_NUMBER >= 0x10001001L - sslsock->is_client = 0; - method = TLSv1_2_server_method(); - break; -#else - php_error_docref(NULL TSRMLS_CC, E_WARNING, "TLSv1.2 support is not compiled into the OpenSSL library PHP is linked against"); - return -1; -#endif - default: + } + } else { + method = sslsock->is_client ? SSLv23_client_method() : SSLv23_server_method(); + ssl_ctx_options = php_get_crypto_method_ctx_flags(method_flags TSRMLS_CC); + if (ssl_ctx_options == -1) { return -1; - + } } sslsock->ctx = SSL_CTX_new(method); @@ -911,28 +935,9 @@ static inline int php_openssl_tcp_sockop_accept(php_stream *stream, php_openssl_ } if (xparam->outputs.client && sock->enable_on_connect) { - /* apply crypto */ - switch (sock->method) { - case STREAM_CRYPTO_METHOD_SSLv23_CLIENT: - sock->method = STREAM_CRYPTO_METHOD_SSLv23_SERVER; - break; - case STREAM_CRYPTO_METHOD_SSLv2_CLIENT: - sock->method = STREAM_CRYPTO_METHOD_SSLv2_SERVER; - break; - case STREAM_CRYPTO_METHOD_SSLv3_CLIENT: - sock->method = STREAM_CRYPTO_METHOD_SSLv3_SERVER; - break; - case STREAM_CRYPTO_METHOD_TLS_CLIENT: - sock->method = STREAM_CRYPTO_METHOD_TLS_SERVER; - break; - case STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT: - sock->method = STREAM_CRYPTO_METHOD_TLSv1_1_SERVER; - break; - case STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT: - sock->method = STREAM_CRYPTO_METHOD_TLSv1_2_SERVER; - break; - default: - break; + /* remove the client bit */ + if (sock->method & STREAM_CRYPTO_IS_CLIENT) { + sock->method = ((sock->method >> 1) << 1); } clisockdata->method = sock->method; @@ -1117,32 +1122,21 @@ php_stream_ops php_openssl_socket_ops = { php_openssl_sockop_set_option, }; -static int get_crypto_method(php_stream_context *ctx) { - if (ctx) { - zval **val = NULL; - long crypto_method; - - if (php_stream_context_get_option(ctx, "ssl", "crypto_method", &val) == SUCCESS) { - convert_to_long_ex(val); - crypto_method = (long)Z_LVAL_PP(val); - - switch (crypto_method) { - case STREAM_CRYPTO_METHOD_SSLv2_CLIENT: - case STREAM_CRYPTO_METHOD_SSLv3_CLIENT: - case STREAM_CRYPTO_METHOD_SSLv23_CLIENT: - case STREAM_CRYPTO_METHOD_TLS_CLIENT: - case STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT: - case STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT: - return crypto_method; - } - - } - } - - return STREAM_CRYPTO_METHOD_SSLv23_CLIENT; +static long get_crypto_method(php_stream_context *ctx, long crypto_method) +{ + zval **val; + + if (ctx && php_stream_context_get_option(ctx, "ssl", "crypto_method", &val) == SUCCESS) { + convert_to_long_ex(val); + crypto_method = (long)Z_LVAL_PP(val); + crypto_method |= STREAM_CRYPTO_IS_CLIENT; + } + + return crypto_method; } -static char * get_url_name(const char *resourcename, size_t resourcenamelen, int is_persistent TSRMLS_DC) { +static char *get_url_name(const char *resourcename, size_t resourcenamelen, int is_persistent TSRMLS_DC) +{ php_url *url; if (!resourcename) { @@ -1184,7 +1178,7 @@ php_stream *php_openssl_ssl_socket_factory(const char *proto, size_t protolen, { php_stream *stream = NULL; php_openssl_netstream_data_t *sslsock = NULL; - + sslsock = pemalloc(sizeof(php_openssl_netstream_data_t), persistent_id ? 1 : 0); memset(sslsock, 0, sizeof(*sslsock)); @@ -1200,10 +1194,10 @@ php_stream *php_openssl_ssl_socket_factory(const char *proto, size_t protolen, /* we don't know the socket until we have determined if we are binding or * connecting */ sslsock->s.socket = -1; - + /* Initialize context as NULL */ sslsock->ctx = NULL; - + stream = php_stream_alloc_rel(&php_openssl_socket_ops, sslsock, persistent_id, "r+"); if (stream == NULL) { @@ -1213,12 +1207,7 @@ php_stream *php_openssl_ssl_socket_factory(const char *proto, size_t protolen, if (strncmp(proto, "ssl", protolen) == 0) { sslsock->enable_on_connect = 1; - - /* General ssl:// transports can use a number - * of crypto methods. The actual methhod can be - * provided in the streams context options. - */ - sslsock->method = get_crypto_method(context); + sslsock->method = get_crypto_method(context, STREAM_CRYPTO_METHOD_ANY_CLIENT); } else if (strncmp(proto, "sslv2", protolen) == 0) { #ifdef OPENSSL_NO_SSL2 php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSLv2 support is not compiled into the OpenSSL library PHP is linked against"); @@ -1232,7 +1221,10 @@ php_stream *php_openssl_ssl_socket_factory(const char *proto, size_t protolen, sslsock->method = STREAM_CRYPTO_METHOD_SSLv3_CLIENT; } else if (strncmp(proto, "tls", protolen) == 0) { sslsock->enable_on_connect = 1; - sslsock->method = STREAM_CRYPTO_METHOD_TLS_CLIENT; + sslsock->method = get_crypto_method(context, STREAM_CRYPTO_METHOD_TLS_CLIENT); + } else if (strncmp(proto, "tlsv1.0", protolen) == 0) { + sslsock->enable_on_connect = 1; + sslsock->method = STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT; } else if (strncmp(proto, "tlsv1.1", protolen) == 0) { #if OPENSSL_VERSION_NUMBER >= 0x10001001L sslsock->enable_on_connect = 1; diff --git a/ext/standard/file.c b/ext/standard/file.c index 0dab6f284a8a..74df6dc75923 100644 --- a/ext/standard/file.c +++ b/ext/standard/file.c @@ -219,18 +219,22 @@ PHP_MINIT_FUNCTION(file) REGISTER_LONG_CONSTANT("STREAM_CLIENT_ASYNC_CONNECT", PHP_STREAM_CLIENT_ASYNC_CONNECT, CONST_CS | CONST_PERSISTENT); REGISTER_LONG_CONSTANT("STREAM_CLIENT_CONNECT", PHP_STREAM_CLIENT_CONNECT, CONST_CS | CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv2_CLIENT", STREAM_CRYPTO_METHOD_SSLv2_CLIENT, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv3_CLIENT", STREAM_CRYPTO_METHOD_SSLv3_CLIENT, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_ANY_CLIENT", STREAM_CRYPTO_METHOD_ANY_CLIENT, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv2_CLIENT", STREAM_CRYPTO_METHOD_SSLv2_CLIENT, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv3_CLIENT", STREAM_CRYPTO_METHOD_SSLv3_CLIENT, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv23_CLIENT", STREAM_CRYPTO_METHOD_SSLv23_CLIENT, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLS_CLIENT", STREAM_CRYPTO_METHOD_TLS_CLIENT, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT", STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT", STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv2_SERVER", STREAM_CRYPTO_METHOD_SSLv2_SERVER, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv3_SERVER", STREAM_CRYPTO_METHOD_SSLv3_SERVER, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLS_CLIENT", STREAM_CRYPTO_METHOD_TLS_CLIENT, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT", STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT", STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT", STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_ANY_SERVER", STREAM_CRYPTO_METHOD_ANY_SERVER, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv2_SERVER", STREAM_CRYPTO_METHOD_SSLv2_SERVER, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv3_SERVER", STREAM_CRYPTO_METHOD_SSLv3_SERVER, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_SSLv23_SERVER", STREAM_CRYPTO_METHOD_SSLv23_SERVER, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLS_SERVER", STREAM_CRYPTO_METHOD_TLS_SERVER, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_1_SERVER", STREAM_CRYPTO_METHOD_TLSv1_1_SERVER, CONST_CS|CONST_PERSISTENT); - REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_2_SERVER", STREAM_CRYPTO_METHOD_TLSv1_2_SERVER, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLS_SERVER", STREAM_CRYPTO_METHOD_TLS_SERVER, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_0_SERVER", STREAM_CRYPTO_METHOD_TLSv1_0_SERVER, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_1_SERVER", STREAM_CRYPTO_METHOD_TLSv1_1_SERVER, CONST_CS|CONST_PERSISTENT); + REGISTER_LONG_CONSTANT("STREAM_CRYPTO_METHOD_TLSv1_2_SERVER", STREAM_CRYPTO_METHOD_TLSv1_2_SERVER, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("STREAM_SHUT_RD", STREAM_SHUT_RD, CONST_CS|CONST_PERSISTENT); REGISTER_LONG_CONSTANT("STREAM_SHUT_WR", STREAM_SHUT_WR, CONST_CS|CONST_PERSISTENT); diff --git a/main/streams/php_stream_transport.h b/main/streams/php_stream_transport.h index c599a65d0fe5..dc10eb4e92ff 100644 --- a/main/streams/php_stream_transport.h +++ b/main/streams/php_stream_transport.h @@ -163,23 +163,30 @@ typedef struct _php_stream_xport_param { } outputs; } php_stream_xport_param; - -/* These functions provide crypto support on the underlying transport */ +/* Because both client and server streams use the same mechanisms + for encryption we use the LSB to denote clients. +*/ typedef enum { - STREAM_CRYPTO_METHOD_SSLv2_CLIENT, - STREAM_CRYPTO_METHOD_SSLv3_CLIENT, - STREAM_CRYPTO_METHOD_SSLv23_CLIENT, - STREAM_CRYPTO_METHOD_TLS_CLIENT, - STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT, - STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT, - STREAM_CRYPTO_METHOD_SSLv2_SERVER, - STREAM_CRYPTO_METHOD_SSLv3_SERVER, - STREAM_CRYPTO_METHOD_SSLv23_SERVER, - STREAM_CRYPTO_METHOD_TLS_SERVER, - STREAM_CRYPTO_METHOD_TLSv1_1_SERVER, - STREAM_CRYPTO_METHOD_TLSv1_2_SERVER + STREAM_CRYPTO_METHOD_SSLv2_CLIENT = (1 << 1 | 1), + STREAM_CRYPTO_METHOD_SSLv3_CLIENT = (1 << 2 | 1), + STREAM_CRYPTO_METHOD_SSLv23_CLIENT = ((1 << 1) | (1 << 2) | 1), + STREAM_CRYPTO_METHOD_TLSv1_0_CLIENT = (1 << 3 | 1), + STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT = (1 << 4 | 1), + STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT = (1 << 5 | 1), + STREAM_CRYPTO_METHOD_TLS_CLIENT = ((1 << 3) | (1 << 4) | (1 << 5) | 1), + STREAM_CRYPTO_METHOD_ANY_CLIENT = ((1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5) | 1), + STREAM_CRYPTO_METHOD_SSLv2_SERVER = (1 << 1), + STREAM_CRYPTO_METHOD_SSLv3_SERVER = (1 << 2), + STREAM_CRYPTO_METHOD_SSLv23_SERVER = ((1 << 1) | (1 << 2)), + STREAM_CRYPTO_METHOD_TLSv1_0_SERVER = (1 << 3), + STREAM_CRYPTO_METHOD_TLSv1_1_SERVER = (1 << 4), + STREAM_CRYPTO_METHOD_TLSv1_2_SERVER = (1 << 5), + STREAM_CRYPTO_METHOD_TLS_SERVER = ((1 << 3) | (1 << 4) | (1 << 5)), + STREAM_CRYPTO_METHOD_ANY_SERVER = ((1 << 1) | (1 << 2) | (1 << 3) | (1 << 4) | (1 << 5)) } php_stream_xport_crypt_method_t; +/* These functions provide crypto support on the underlying transport */ + BEGIN_EXTERN_C() PHPAPI int php_stream_xport_crypto_setup(php_stream *stream, php_stream_xport_crypt_method_t crypto_method, php_stream *session_stream TSRMLS_DC); PHPAPI int php_stream_xport_crypto_enable(php_stream *stream, int activate TSRMLS_DC); From 9f94e0b51c5e5371c26890b16d9f307f66260bb5 Mon Sep 17 00:00:00 2001 From: Daniel Lowrey Date: Thu, 20 Feb 2014 17:20:40 -0700 Subject: [PATCH 10/10] Improve OpenSSL compile flag compatibility, minor updates --- ext/openssl/tests/bug66501.phpt | 2 +- ext/openssl/tests/tlsv1.0_wrapper.phpt | 1 - ext/openssl/xp_ssl.c | 32 +++++++------------------- 3 files changed, 9 insertions(+), 26 deletions(-) diff --git a/ext/openssl/tests/bug66501.phpt b/ext/openssl/tests/bug66501.phpt index cd0da1f289cb..7ad5e21749ff 100644 --- a/ext/openssl/tests/bug66501.phpt +++ b/ext/openssl/tests/bug66501.phpt @@ -3,7 +3,7 @@ Bug #66501: EC private key support in openssl_sign --SKIPIF-- = 0x10001001L + if (!(method_flags & STREAM_CRYPTO_METHOD_TLSv1_1)) { ssl_ctx_options |= SSL_OP_NO_TLSv1_1; -#endif - } else { -#if OPENSSL_VERSION_NUMBER < 0x10001001L - php_error_docref(NULL TSRMLS_CC, E_WARNING, - "TLSv1.1 support is not compiled into the OpenSSL library PHP is linked against"); - return -1; -#endif } if (!(method_flags & STREAM_CRYPTO_METHOD_TLSv1_2)) { -#if OPENSSL_VERSION_NUMBER >= 0x10001001L ssl_ctx_options |= SSL_OP_NO_TLSv1_2; -#endif - } else { -#if OPENSSL_VERSION_NUMBER < 0x10001001L - php_error_docref(NULL TSRMLS_CC, E_WARNING, - "TLSv1.2 support is not compiled into the OpenSSL library PHP is linked against"); - return -1; -#endif } +#endif return ssl_ctx_options; } @@ -388,6 +375,7 @@ static inline int php_openssl_setup_crypto(php_stream *stream, const SSL_METHOD *method; long ssl_ctx_options; long method_flags; + zval **val; if (sslsock->ssl_handle) { if (sslsock->s.is_blocked) { @@ -431,8 +419,6 @@ static inline int php_openssl_setup_crypto(php_stream *stream, #if OPENSSL_VERSION_NUMBER >= 0x0090806fL { - zval **val; - if (stream->context && SUCCESS == php_stream_context_get_option( stream->context, "ssl", "no_ticket", &val) && zend_is_true(*val) @@ -444,8 +430,6 @@ static inline int php_openssl_setup_crypto(php_stream *stream, #if OPENSSL_VERSION_NUMBER >= 0x10000000L { - zval **val; - if (stream->context && (FAILURE == php_stream_context_get_option( stream->context, "ssl", "disable_compression", &val) || zend_is_true(*val))