|
|
cfc571 |
Backported for 5.4.16 from PHP 5.5.23, 5.5.24 and 5.5.25
|
|
|
cfc571 |
|
|
|
cfc571 |
ext/openssl/xp_ssl.c is in sync with latest 5.5 (.38)
|
|
|
cfc571 |
|
|
|
cfc571 |
|
|
|
cfc571 |
From 9ad97cd48903ea5454853960f2c14de326e0f624 Mon Sep 17 00:00:00 2001
|
|
|
cfc571 |
From: Christopher Jones <sixd@php.net>
|
|
|
cfc571 |
Date: Wed, 14 Aug 2013 20:36:50 -0700
|
|
|
cfc571 |
Subject: [PATCH] Reduce (some) compile noise of 'unused variable' and 'may be
|
|
|
cfc571 |
used uninitialized' warnings.
|
|
|
cfc571 |
|
|
|
cfc571 |
---
|
|
|
cfc571 |
ext/date/php_date.c | 6 +++---
|
|
|
cfc571 |
ext/dba/dba.c | 1 -
|
|
|
cfc571 |
ext/dba/libinifile/inifile.c | 2 +-
|
|
|
cfc571 |
ext/dom/xpath.c | 2 +-
|
|
|
cfc571 |
ext/gmp/gmp.c | 2 +-
|
|
|
cfc571 |
ext/intl/grapheme/grapheme_util.c | 2 +-
|
|
|
cfc571 |
ext/intl/resourcebundle/resourcebundle_class.c | 4 ++--
|
|
|
cfc571 |
ext/openssl/openssl.c | 2 +-
|
|
|
cfc571 |
ext/openssl/xp_ssl.c | 2 +-
|
|
|
cfc571 |
ext/session/session.c | 2 +-
|
|
|
cfc571 |
ext/simplexml/simplexml.c | 2 +-
|
|
|
cfc571 |
ext/snmp/snmp.c | 2 +-
|
|
|
cfc571 |
ext/spl/spl_array.c | 2 +-
|
|
|
cfc571 |
ext/spl/spl_dllist.c | 2 +-
|
|
|
cfc571 |
ext/standard/array.c | 9 ++++-----
|
|
|
cfc571 |
ext/standard/html.c | 6 +++---
|
|
|
cfc571 |
ext/standard/string.c | 4 ++--
|
|
|
cfc571 |
ext/standard/url_scanner_ex.re | 2 +-
|
|
|
cfc571 |
ext/xsl/xsltprocessor.c | 2 +-
|
|
|
cfc571 |
ext/zip/php_zip.c | 2 +-
|
|
|
cfc571 |
main/php_variables.c | 2 +-
|
|
|
cfc571 |
main/rfc1867.c | 2 +-
|
|
|
cfc571 |
sapi/cli/php_cli_server.c | 2 +-
|
|
|
cfc571 |
23 files changed, 31 insertions(+), 33 deletions(-)
|
|
|
cfc571 |
|
|
|
cfc571 |
diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
index e19e8f098d05..6e74d8024f5a 100644
|
|
|
cfc571 |
--- a/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
+++ b/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
@@ -472,7 +472,7 @@ static inline int php_openssl_enable_crypto(php_stream *stream,
|
|
|
cfc571 |
|
|
|
cfc571 |
do {
|
|
|
cfc571 |
struct timeval cur_time,
|
|
|
cfc571 |
- elapsed_time;
|
|
|
cfc571 |
+ elapsed_time = {0};
|
|
|
cfc571 |
|
|
|
cfc571 |
if (sslsock->is_client) {
|
|
|
cfc571 |
n = SSL_connect(sslsock->ssl_handle);
|
|
|
cfc571 |
|
|
|
cfc571 |
From 32be79dcfa1bc5af8682d9f512da68c5b3e2cbf3 Mon Sep 17 00:00:00 2001
|
|
|
cfc571 |
From: Chris Wright <github@daverandom.com>
|
|
|
cfc571 |
Date: Sat, 23 Aug 2014 01:40:19 +0100
|
|
|
cfc571 |
Subject: [PATCH] Fix stream_select() issue with OpenSSL buffer
|
|
|
cfc571 |
|
|
|
cfc571 |
Ensure data from OpenSSL internal buffer has been
|
|
|
cfc571 |
transfered to PHP stream buffer before a select()
|
|
|
cfc571 |
emulation operation is performed
|
|
|
cfc571 |
|
|
|
cfc571 |
Addresses bug #65137
|
|
|
cfc571 |
https://bugs.php.net/bug.php?id=65137
|
|
|
cfc571 |
|
|
|
cfc571 |
Conflicts:
|
|
|
cfc571 |
ext/openssl/xp_ssl.c
|
|
|
cfc571 |
---
|
|
|
cfc571 |
ext/openssl/xp_ssl.c | 13 +++++++++++++
|
|
|
cfc571 |
main/php_streams.h | 3 +++
|
|
|
cfc571 |
main/streams/streams.c | 8 ++++----
|
|
|
cfc571 |
3 files changed, 20 insertions(+), 4 deletions(-)
|
|
|
cfc571 |
|
|
|
cfc571 |
diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
index b7b8690165e1..956ffd0547fe 100644
|
|
|
cfc571 |
--- a/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
+++ b/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
@@ -825,6 +825,19 @@ static int php_openssl_sockop_cast(php_stream *stream, int castas, void **ret TS
|
|
|
cfc571 |
|
|
|
cfc571 |
case PHP_STREAM_AS_FD_FOR_SELECT:
|
|
|
cfc571 |
if (ret) {
|
|
|
cfc571 |
+ if (sslsock->ssl_active) {
|
|
|
cfc571 |
+ /* OpenSSL has an internal buffer which select() cannot see. If we don't
|
|
|
cfc571 |
+ fetch it into the stream's buffer, no activity will be reported on the
|
|
|
cfc571 |
+ stream even though there is data waiting to be read - but we only fetch
|
|
|
cfc571 |
+ the number of bytes OpenSSL has ready to give us since we weren't asked
|
|
|
cfc571 |
+ for any data at this stage. This is only likely to cause issues with
|
|
|
cfc571 |
+ non-blocking streams, but it's harmless to always do it. */
|
|
|
cfc571 |
+ int bytes;
|
|
|
cfc571 |
+ while ((bytes = SSL_pending(sslsock->ssl_handle)) > 0) {
|
|
|
cfc571 |
+ php_stream_fill_read_buffer(stream, (size_t)bytes);
|
|
|
cfc571 |
+ }
|
|
|
cfc571 |
+ }
|
|
|
cfc571 |
+
|
|
|
cfc571 |
*(int *)ret = sslsock->s.socket;
|
|
|
cfc571 |
}
|
|
|
cfc571 |
return SUCCESS;
|
|
|
cfc571 |
diff --git a/main/php_streams.h b/main/php_streams.h
|
|
|
cfc571 |
index 2e4a3a2a18c1..89b877fdb167 100644
|
|
|
cfc571 |
--- a/main/php_streams.h
|
|
|
cfc571 |
+++ b/main/php_streams.h
|
|
|
cfc571 |
@@ -301,6 +301,9 @@ PHPAPI size_t _php_stream_write(php_stream *stream, const char *buf, size_t coun
|
|
|
cfc571 |
#define php_stream_write_string(stream, str) _php_stream_write(stream, str, strlen(str) TSRMLS_CC)
|
|
|
cfc571 |
#define php_stream_write(stream, buf, count) _php_stream_write(stream, (buf), (count) TSRMLS_CC)
|
|
|
cfc571 |
|
|
|
cfc571 |
+PHPAPI void _php_stream_fill_read_buffer(php_stream *stream, size_t size TSRMLS_DC);
|
|
|
cfc571 |
+#define php_stream_fill_read_buffer(stream, size) _php_stream_fill_read_buffer((stream), (size) TSRMLS_CC)
|
|
|
cfc571 |
+
|
|
|
cfc571 |
#ifdef ZTS
|
|
|
cfc571 |
PHPAPI size_t _php_stream_printf(php_stream *stream TSRMLS_DC, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 3, 4);
|
|
|
cfc571 |
#else
|
|
|
cfc571 |
diff --git a/main/streams/streams.c b/main/streams/streams.c
|
|
|
cfc571 |
index 3fd4ab37968a..fbcc1ca4e365 100644
|
|
|
cfc571 |
--- a/main/streams/streams.c
|
|
|
cfc571 |
+++ b/main/streams/streams.c
|
|
|
cfc571 |
@@ -573,7 +573,7 @@ fprintf(stderr, "stream_free: %s:%p[%s] preserve_handle=%d release_cast=%d remov
|
|
|
cfc571 |
|
|
|
cfc571 |
/* {{{ generic stream operations */
|
|
|
cfc571 |
|
|
|
cfc571 |
-static void php_stream_fill_read_buffer(php_stream *stream, size_t size TSRMLS_DC)
|
|
|
cfc571 |
+PHPAPI void _php_stream_fill_read_buffer(php_stream *stream, size_t size TSRMLS_DC)
|
|
|
cfc571 |
{
|
|
|
cfc571 |
/* allocate/fill the buffer */
|
|
|
cfc571 |
|
|
|
cfc571 |
@@ -737,7 +737,7 @@ PHPAPI size_t _php_stream_read(php_stream *stream, char *buf, size_t size TSRMLS
|
|
|
cfc571 |
if (!stream->readfilters.head && (stream->flags & PHP_STREAM_FLAG_NO_BUFFER || stream->chunk_size == 1)) {
|
|
|
cfc571 |
toread = stream->ops->read(stream, buf, size TSRMLS_CC);
|
|
|
cfc571 |
} else {
|
|
|
cfc571 |
- php_stream_fill_read_buffer(stream, size TSRMLS_CC);
|
|
|
cfc571 |
+ php_stream_fill_read_buffer(stream, size);
|
|
|
cfc571 |
|
|
|
cfc571 |
toread = stream->writepos - stream->readpos;
|
|
|
cfc571 |
if (toread > size) {
|
|
|
cfc571 |
@@ -973,7 +973,7 @@ PHPAPI char *_php_stream_get_line(php_stream *stream, char *buf, size_t maxlen,
|
|
|
cfc571 |
}
|
|
|
cfc571 |
}
|
|
|
cfc571 |
|
|
|
cfc571 |
- php_stream_fill_read_buffer(stream, toread TSRMLS_CC);
|
|
|
cfc571 |
+ php_stream_fill_read_buffer(stream, toread);
|
|
|
cfc571 |
|
|
|
cfc571 |
if (stream->writepos - stream->readpos == 0) {
|
|
|
cfc571 |
break;
|
|
|
cfc571 |
@@ -1048,7 +1048,7 @@ PHPAPI char *php_stream_get_record(php_stream *stream, size_t maxlen, size_t *re
|
|
|
cfc571 |
|
|
|
cfc571 |
to_read_now = MIN(maxlen - buffered_len, stream->chunk_size);
|
|
|
cfc571 |
|
|
|
cfc571 |
- php_stream_fill_read_buffer(stream, buffered_len + to_read_now TSRMLS_CC);
|
|
|
cfc571 |
+ php_stream_fill_read_buffer(stream, buffered_len + to_read_now);
|
|
|
cfc571 |
|
|
|
cfc571 |
just_read = STREAM_BUFFERED_AMOUNT(stream) - buffered_len;
|
|
|
cfc571 |
|
|
|
cfc571 |
From f86b2193a483f56b0bd056570a0cdb57ebe66e2f Mon Sep 17 00:00:00 2001
|
|
|
cfc571 |
From: Daniel Lowrey <rdlowrey@php.net>
|
|
|
cfc571 |
Date: Tue, 9 Sep 2014 07:37:57 -0600
|
|
|
cfc571 |
Subject: [PATCH] Bug #67965: Fix blocking behavior in non-blocking crypto
|
|
|
cfc571 |
streams
|
|
|
cfc571 |
|
|
|
cfc571 |
---
|
|
|
cfc571 |
ext/openssl/xp_ssl.c | 24 +++++++++++++-----------
|
|
|
cfc571 |
1 file changed, 13 insertions(+), 11 deletions(-)
|
|
|
cfc571 |
|
|
|
cfc571 |
diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
index 956ffd0547fe..76095b4df2d7 100644
|
|
|
cfc571 |
--- a/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
+++ b/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
@@ -825,17 +825,19 @@ static int php_openssl_sockop_cast(php_stream *stream, int castas, void **ret TS
|
|
|
cfc571 |
|
|
|
cfc571 |
case PHP_STREAM_AS_FD_FOR_SELECT:
|
|
|
cfc571 |
if (ret) {
|
|
|
cfc571 |
- if (sslsock->ssl_active) {
|
|
|
cfc571 |
- /* OpenSSL has an internal buffer which select() cannot see. If we don't
|
|
|
cfc571 |
- fetch it into the stream's buffer, no activity will be reported on the
|
|
|
cfc571 |
- stream even though there is data waiting to be read - but we only fetch
|
|
|
cfc571 |
- the number of bytes OpenSSL has ready to give us since we weren't asked
|
|
|
cfc571 |
- for any data at this stage. This is only likely to cause issues with
|
|
|
cfc571 |
- non-blocking streams, but it's harmless to always do it. */
|
|
|
cfc571 |
- int bytes;
|
|
|
cfc571 |
- while ((bytes = SSL_pending(sslsock->ssl_handle)) > 0) {
|
|
|
cfc571 |
- php_stream_fill_read_buffer(stream, (size_t)bytes);
|
|
|
cfc571 |
- }
|
|
|
cfc571 |
+ /* OpenSSL has an internal buffer which select() cannot see. If we don't
|
|
|
cfc571 |
+ * fetch it into the stream's buffer, no activity will be reported on the
|
|
|
cfc571 |
+ * stream even though there is data waiting to be read - but we only fetch
|
|
|
cfc571 |
+ * the lower of bytes OpenSSL has ready to give us or chunk_size since we
|
|
|
cfc571 |
+ * weren't asked for any data at this stage. This is only likely to cause
|
|
|
cfc571 |
+ * issues with non-blocking streams, but it's harmless to always do it. */
|
|
|
cfc571 |
+ size_t pending;
|
|
|
cfc571 |
+ if (stream->writepos == stream->readpos
|
|
|
cfc571 |
+ && sslsock->ssl_active
|
|
|
cfc571 |
+ && (pending = (size_t)SSL_pending(sslsock->ssl_handle)) > 0) {
|
|
|
cfc571 |
+ php_stream_fill_read_buffer(stream, pending < stream->chunk_size
|
|
|
cfc571 |
+ ? pending
|
|
|
cfc571 |
+ : stream->chunk_size);
|
|
|
cfc571 |
}
|
|
|
cfc571 |
|
|
|
cfc571 |
*(int *)ret = sslsock->s.socket;
|
|
|
cfc571 |
From fd4641696cc67fedf494717b5e4d452019f04d6f Mon Sep 17 00:00:00 2001
|
|
|
cfc571 |
From: Brad Broerman <bbroerman@bbroerman.net>
|
|
|
cfc571 |
Date: Wed, 28 Jan 2015 00:04:20 -0500
|
|
|
cfc571 |
Subject: [PATCH] Updated with SSL fixes (backported from trunk)
|
|
|
cfc571 |
|
|
|
cfc571 |
---
|
|
|
cfc571 |
ext/openssl/xp_ssl.c | 204 +++++++++++++++++++++++++++++++++++++++------------
|
|
|
cfc571 |
1 file changed, 159 insertions(+), 45 deletions(-)
|
|
|
cfc571 |
|
|
|
cfc571 |
diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
index 6b74a2bb7362..53c48beca766 100644
|
|
|
cfc571 |
--- a/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
+++ b/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
@@ -40,6 +40,9 @@
|
|
|
cfc571 |
int php_openssl_apply_verification_policy(SSL *ssl, X509 *peer, php_stream *stream TSRMLS_DC);
|
|
|
cfc571 |
SSL *php_SSL_new_from_context(SSL_CTX *ctx, php_stream *stream TSRMLS_DC);
|
|
|
cfc571 |
int php_openssl_get_x509_list_id(void);
|
|
|
cfc571 |
+static struct timeval subtract_timeval( struct timeval a, struct timeval b );
|
|
|
cfc571 |
+static int compare_timeval( struct timeval a, struct timeval b );
|
|
|
cfc571 |
+static size_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, size_t count TSRMLS_DC);
|
|
|
cfc571 |
|
|
|
cfc571 |
/* This implementation is very closely tied to the that of the native
|
|
|
cfc571 |
* sockets implemented in the core.
|
|
|
cfc571 |
@@ -171,69 +174,167 @@ static int handle_ssl_error(php_stream *stream, int nr_bytes, zend_bool is_init
|
|
|
cfc571 |
return retry;
|
|
|
cfc571 |
}
|
|
|
cfc571 |
|
|
|
cfc571 |
-
|
|
|
cfc571 |
static size_t php_openssl_sockop_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
|
|
|
cfc571 |
{
|
|
|
cfc571 |
+ return php_openssl_sockop_io( 0, stream, buf, count );
|
|
|
cfc571 |
+}
|
|
|
cfc571 |
+
|
|
|
cfc571 |
+static size_t php_openssl_sockop_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
|
|
|
cfc571 |
+{
|
|
|
cfc571 |
+ return php_openssl_sockop_io( 1, stream, buf, count );
|
|
|
cfc571 |
+}
|
|
|
cfc571 |
+
|
|
|
cfc571 |
+/**
|
|
|
cfc571 |
+ * Factored out common functionality (blocking, timeout, loop management) for read and write.
|
|
|
cfc571 |
+ * Perform IO (read or write) to an SSL socket. If we have a timeout, we switch to non-blocking mode
|
|
|
cfc571 |
+ * for the duration of the operation, using select to do our waits. If we time out, or we have an error
|
|
|
cfc571 |
+ * report that back to PHP
|
|
|
cfc571 |
+ *
|
|
|
cfc571 |
+ */
|
|
|
cfc571 |
+static size_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, size_t count TSRMLS_DC)
|
|
|
cfc571 |
+{
|
|
|
cfc571 |
php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
|
|
|
cfc571 |
- int didwrite;
|
|
|
cfc571 |
+ int nr_bytes = 0;
|
|
|
cfc571 |
|
|
|
cfc571 |
+ /* Only do this if SSL is active. */
|
|
|
cfc571 |
if (sslsock->ssl_active) {
|
|
|
cfc571 |
int retry = 1;
|
|
|
cfc571 |
+ struct timeval start_time,
|
|
|
cfc571 |
+ *timeout;
|
|
|
cfc571 |
+ int blocked = sslsock->s.is_blocked,
|
|
|
cfc571 |
+ has_timeout = 0;
|
|
|
cfc571 |
|
|
|
cfc571 |
- do {
|
|
|
cfc571 |
- didwrite = SSL_write(sslsock->ssl_handle, buf, count);
|
|
|
cfc571 |
+ /* Begin by making the socket non-blocking. This allows us to check the timeout. */
|
|
|
cfc571 |
+ if (SUCCESS == php_set_sock_blocking(sslsock->s.socket, 0 TSRMLS_CC)) {
|
|
|
cfc571 |
+ sslsock->s.is_blocked = 0;
|
|
|
cfc571 |
+ }
|
|
|
cfc571 |
|
|
|
cfc571 |
- if (didwrite <= 0) {
|
|
|
cfc571 |
- retry = handle_ssl_error(stream, didwrite, 0 TSRMLS_CC);
|
|
|
cfc571 |
- } else {
|
|
|
cfc571 |
- break;
|
|
|
cfc571 |
- }
|
|
|
cfc571 |
- } while(retry);
|
|
|
cfc571 |
+ /* Get the timeout value (and make sure we are to check it. */
|
|
|
cfc571 |
+ timeout = sslsock->is_client ? &sslsock->connect_timeout : &sslsock->s.timeout;
|
|
|
cfc571 |
+ has_timeout = !sslsock->s.is_blocked && (timeout->tv_sec || timeout->tv_usec);
|
|
|
cfc571 |
|
|
|
cfc571 |
- if (didwrite > 0) {
|
|
|
cfc571 |
- php_stream_notify_progress_increment(stream->context, didwrite, 0);
|
|
|
cfc571 |
- }
|
|
|
cfc571 |
- } else {
|
|
|
cfc571 |
- didwrite = php_stream_socket_ops.write(stream, buf, count TSRMLS_CC);
|
|
|
cfc571 |
+ /* gettimeofday is not monotonic; using it here is not strictly correct */
|
|
|
cfc571 |
+ if (has_timeout) {
|
|
|
cfc571 |
+ gettimeofday(&start_time, NULL);
|
|
|
cfc571 |
}
|
|
|
cfc571 |
|
|
|
cfc571 |
- if (didwrite < 0) {
|
|
|
cfc571 |
- didwrite = 0;
|
|
|
cfc571 |
- }
|
|
|
cfc571 |
+ /* Main IO loop. */
|
|
|
cfc571 |
+ do {
|
|
|
cfc571 |
+ struct timeval cur_time, elapsed_time, left_time;
|
|
|
cfc571 |
|
|
|
cfc571 |
- return didwrite;
|
|
|
cfc571 |
-}
|
|
|
cfc571 |
+ /* If we have a timeout to check, figure out how much time has elapsed since we started. */
|
|
|
cfc571 |
+ if (has_timeout) {
|
|
|
cfc571 |
+ gettimeofday(&cur_time, NULL);
|
|
|
cfc571 |
|
|
|
cfc571 |
-static size_t php_openssl_sockop_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
|
|
|
cfc571 |
-{
|
|
|
cfc571 |
- php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
|
|
|
cfc571 |
- int nr_bytes = 0;
|
|
|
cfc571 |
+ /* Determine how much time we've taken so far. */
|
|
|
cfc571 |
+ elapsed_time = subtract_timeval( cur_time, start_time );
|
|
|
cfc571 |
|
|
|
cfc571 |
- if (sslsock->ssl_active) {
|
|
|
cfc571 |
- int retry = 1;
|
|
|
cfc571 |
+ /* and return an error if we've taken too long. */
|
|
|
cfc571 |
+ if (compare_timeval( elapsed_time, *timeout) > 0 ) {
|
|
|
cfc571 |
+ /* If the socket was originally blocking, set it back. */
|
|
|
cfc571 |
+ if (blocked) {
|
|
|
cfc571 |
+ php_set_sock_blocking(sslsock->s.socket, 1 TSRMLS_CC);
|
|
|
cfc571 |
+ sslsock->s.is_blocked = 1;
|
|
|
cfc571 |
+ }
|
|
|
cfc571 |
+ return -1;
|
|
|
cfc571 |
+ }
|
|
|
cfc571 |
+ }
|
|
|
cfc571 |
|
|
|
cfc571 |
- do {
|
|
|
cfc571 |
+ /* Now, do the IO operation. Don't block if we can't complete... */
|
|
|
cfc571 |
+ if (read) {
|
|
|
cfc571 |
nr_bytes = SSL_read(sslsock->ssl_handle, buf, count);
|
|
|
cfc571 |
|
|
|
cfc571 |
+ if (sslsock->reneg && sslsock->reneg->should_close) {
|
|
|
cfc571 |
+ /* renegotiation rate limiting triggered */
|
|
|
cfc571 |
+ php_stream_xport_shutdown(stream, (stream_shutdown_t)SHUT_RDWR);
|
|
|
cfc571 |
+ nr_bytes = 0;
|
|
|
cfc571 |
+ stream->eof = 1;
|
|
|
cfc571 |
+ break;
|
|
|
cfc571 |
+ }
|
|
|
cfc571 |
+ } else {
|
|
|
cfc571 |
+ nr_bytes = SSL_write(sslsock->ssl_handle, buf, count);
|
|
|
cfc571 |
+ }
|
|
|
cfc571 |
+
|
|
|
cfc571 |
+ /* Now, how much time until we time out? */
|
|
|
cfc571 |
+ if (has_timeout) {
|
|
|
cfc571 |
+ left_time = subtract_timeval( *timeout, elapsed_time );
|
|
|
cfc571 |
+ }
|
|
|
cfc571 |
+
|
|
|
cfc571 |
+ /* If we didn't do anything on the last loop (or an error) check to see if we should retry or exit. */
|
|
|
cfc571 |
if (nr_bytes <= 0) {
|
|
|
cfc571 |
+
|
|
|
cfc571 |
+ /* Get the error code from SSL, and check to see if it's an error or not. */
|
|
|
cfc571 |
+ int err = SSL_get_error(sslsock->ssl_handle, nr_bytes );
|
|
|
cfc571 |
retry = handle_ssl_error(stream, nr_bytes, 0 TSRMLS_CC);
|
|
|
cfc571 |
+
|
|
|
cfc571 |
+ /* If we get this (the above doesn't check) then we'll retry as well. */
|
|
|
cfc571 |
+ if (errno == EAGAIN && err == SSL_ERROR_WANT_READ && read) {
|
|
|
cfc571 |
+ retry = 1;
|
|
|
cfc571 |
+ }
|
|
|
cfc571 |
+ if (errno == EAGAIN && SSL_ERROR_WANT_WRITE && read == 0) {
|
|
|
cfc571 |
+ retry = 1;
|
|
|
cfc571 |
+ }
|
|
|
cfc571 |
+
|
|
|
cfc571 |
+ /* Also, on reads, we may get this condition on an EOF. We should check properly. */
|
|
|
cfc571 |
+ if (read) {
|
|
|
cfc571 |
stream->eof = (retry == 0 && errno != EAGAIN && !SSL_pending(sslsock->ssl_handle));
|
|
|
cfc571 |
+ }
|
|
|
cfc571 |
|
|
|
cfc571 |
+ /* Now, if we have to wait some time, and we're supposed to be blocking, wait for the socket to become
|
|
|
cfc571 |
+ * available. Now, php_pollfd_for uses select to wait up to our time_left value only...
|
|
|
cfc571 |
+ */
|
|
|
cfc571 |
+ if (retry && blocked) {
|
|
|
cfc571 |
+ if (read) {
|
|
|
cfc571 |
+ php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_WRITE) ?
|
|
|
cfc571 |
+ (POLLOUT|POLLPRI) : (POLLIN|POLLPRI), has_timeout ? &left_time : NULL);
|
|
|
cfc571 |
+ } else {
|
|
|
cfc571 |
+ php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_READ) ?
|
|
|
cfc571 |
+ (POLLIN|POLLPRI) : (POLLOUT|POLLPRI), has_timeout ? &left_time : NULL);
|
|
|
cfc571 |
+ }
|
|
|
cfc571 |
+ }
|
|
|
cfc571 |
} else {
|
|
|
cfc571 |
- /* we got the data */
|
|
|
cfc571 |
+ /* Else, if we got bytes back, check for possible errors. */
|
|
|
cfc571 |
+ int err = SSL_get_error(sslsock->ssl_handle, nr_bytes );
|
|
|
cfc571 |
+
|
|
|
cfc571 |
+ /* If we didn't get any error, then let's return it to PHP. */
|
|
|
cfc571 |
+ if (err == SSL_ERROR_NONE)
|
|
|
cfc571 |
break;
|
|
|
cfc571 |
+
|
|
|
cfc571 |
+ /* Otherwise, we need to wait again (up to time_left or we get an error) */
|
|
|
cfc571 |
+ if (blocked)
|
|
|
cfc571 |
+ if (read) {
|
|
|
cfc571 |
+ php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_WRITE) ?
|
|
|
cfc571 |
+ (POLLOUT|POLLPRI) : (POLLIN|POLLPRI), has_timeout ? &left_time : NULL);
|
|
|
cfc571 |
+ } else {
|
|
|
cfc571 |
+ php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_READ) ?
|
|
|
cfc571 |
+ (POLLIN|POLLPRI) : (POLLOUT|POLLPRI), has_timeout ? &left_time : NULL);
|
|
|
cfc571 |
+ }
|
|
|
cfc571 |
}
|
|
|
cfc571 |
+ /* Finally, we keep going until we got data, and an SSL_ERROR_NONE, unless we had an error. */
|
|
|
cfc571 |
} while (retry);
|
|
|
cfc571 |
|
|
|
cfc571 |
+ /* Tell PHP if we read / wrote bytes. */
|
|
|
cfc571 |
if (nr_bytes > 0) {
|
|
|
cfc571 |
php_stream_notify_progress_increment(stream->context, nr_bytes, 0);
|
|
|
cfc571 |
}
|
|
|
cfc571 |
+
|
|
|
cfc571 |
+ /* And if we were originally supposed to be blocking, let's reset the socket to that. */
|
|
|
cfc571 |
+ if (blocked) {
|
|
|
cfc571 |
+ php_set_sock_blocking(sslsock->s.socket, 1 TSRMLS_CC);
|
|
|
cfc571 |
+ sslsock->s.is_blocked = 1;
|
|
|
cfc571 |
}
|
|
|
cfc571 |
- else
|
|
|
cfc571 |
- {
|
|
|
cfc571 |
+ } else {
|
|
|
cfc571 |
+ /*
|
|
|
cfc571 |
+ * This block is if we had no timeout... We will just sit and wait forever on the IO operation.
|
|
|
cfc571 |
+ */
|
|
|
cfc571 |
+ if (read) {
|
|
|
cfc571 |
nr_bytes = php_stream_socket_ops.read(stream, buf, count TSRMLS_CC);
|
|
|
cfc571 |
+ } else {
|
|
|
cfc571 |
+ nr_bytes = php_stream_socket_ops.write(stream, buf, count TSRMLS_CC);
|
|
|
cfc571 |
}
|
|
|
cfc571 |
+ }
|
|
|
cfc571 |
|
|
|
cfc571 |
+ /* PHP doesn't expect a negative return. */
|
|
|
cfc571 |
if (nr_bytes < 0) {
|
|
|
cfc571 |
nr_bytes = 0;
|
|
|
cfc571 |
}
|
|
|
cfc571 |
@@ -241,6 +342,31 @@ static size_t php_openssl_sockop_read(php_stream *stream, char *buf, size_t coun
|
|
|
cfc571 |
return nr_bytes;
|
|
|
cfc571 |
}
|
|
|
cfc571 |
|
|
|
cfc571 |
+struct timeval subtract_timeval( struct timeval a, struct timeval b )
|
|
|
cfc571 |
+{
|
|
|
cfc571 |
+ struct timeval difference;
|
|
|
cfc571 |
+
|
|
|
cfc571 |
+ difference.tv_sec = a.tv_sec - b.tv_sec;
|
|
|
cfc571 |
+ difference.tv_usec = a.tv_usec - b.tv_usec;
|
|
|
cfc571 |
+
|
|
|
cfc571 |
+ if (a.tv_usec < b.tv_usec) {
|
|
|
cfc571 |
+ b.tv_sec -= 1L;
|
|
|
cfc571 |
+ b.tv_usec += 1000000L;
|
|
|
cfc571 |
+ }
|
|
|
cfc571 |
+
|
|
|
cfc571 |
+ return difference;
|
|
|
cfc571 |
+}
|
|
|
cfc571 |
+
|
|
|
cfc571 |
+int compare_timeval( struct timeval a, struct timeval b )
|
|
|
cfc571 |
+{
|
|
|
cfc571 |
+ if (a.tv_sec > b.tv_sec || (a.tv_sec == b.tv_sec && a.tv_usec > b.tv_usec) ) {
|
|
|
cfc571 |
+ return 1;
|
|
|
cfc571 |
+ } else if( a.tv_sec == b.tv_sec && a.tv_usec == b.tv_usec ) {
|
|
|
cfc571 |
+ return 0;
|
|
|
cfc571 |
+ } else {
|
|
|
cfc571 |
+ return -1;
|
|
|
cfc571 |
+ }
|
|
|
cfc571 |
+}
|
|
|
cfc571 |
|
|
|
cfc571 |
static int php_openssl_sockop_close(php_stream *stream, int close_handle TSRMLS_DC)
|
|
|
cfc571 |
{
|
|
|
cfc571 |
@@ -482,16 +608,9 @@ static inline int php_openssl_enable_crypto(php_stream *stream,
|
|
|
cfc571 |
|
|
|
cfc571 |
if (has_timeout) {
|
|
|
cfc571 |
gettimeofday(&cur_time, NULL);
|
|
|
cfc571 |
- elapsed_time.tv_sec = cur_time.tv_sec - start_time.tv_sec;
|
|
|
cfc571 |
- elapsed_time.tv_usec = cur_time.tv_usec - start_time.tv_usec;
|
|
|
cfc571 |
- if (cur_time.tv_usec < start_time.tv_usec) {
|
|
|
cfc571 |
- elapsed_time.tv_sec -= 1L;
|
|
|
cfc571 |
- elapsed_time.tv_usec += 1000000L;
|
|
|
cfc571 |
- }
|
|
|
cfc571 |
+ elapsed_time = subtract_timeval( cur_time, start_time );
|
|
|
cfc571 |
|
|
|
cfc571 |
- if (elapsed_time.tv_sec > timeout->tv_sec ||
|
|
|
cfc571 |
- (elapsed_time.tv_sec == timeout->tv_sec &&
|
|
|
cfc571 |
- elapsed_time.tv_usec > timeout->tv_usec)) {
|
|
|
cfc571 |
+ if (compare_timeval( elapsed_time, *timeout) > 0) {
|
|
|
cfc571 |
php_error_docref(NULL TSRMLS_CC, E_WARNING, "SSL: crypto enabling timeout");
|
|
|
cfc571 |
return -1;
|
|
|
cfc571 |
}
|
|
|
cfc571 |
@@ -507,12 +626,7 @@ static inline int php_openssl_enable_crypto(php_stream *stream,
|
|
|
cfc571 |
struct timeval left_time;
|
|
|
cfc571 |
|
|
|
cfc571 |
if (has_timeout) {
|
|
|
cfc571 |
- left_time.tv_sec = timeout->tv_sec - elapsed_time.tv_sec;
|
|
|
cfc571 |
- left_time.tv_usec = timeout->tv_usec - elapsed_time.tv_usec;
|
|
|
cfc571 |
- if (timeout->tv_usec < elapsed_time.tv_usec) {
|
|
|
cfc571 |
- left_time.tv_sec -= 1L;
|
|
|
cfc571 |
- left_time.tv_usec += 1000000L;
|
|
|
cfc571 |
- }
|
|
|
cfc571 |
+ left_time = subtract_timeval( *timeout, elapsed_time );
|
|
|
cfc571 |
}
|
|
|
cfc571 |
php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_READ) ?
|
|
|
cfc571 |
(POLLIN|POLLPRI) : POLLOUT, has_timeout ? &left_time : NULL);
|
|
|
cfc571 |
From 1482ed2d5660c3875add40706a18fe29e2b3ff70 Mon Sep 17 00:00:00 2001
|
|
|
cfc571 |
From: Brad Broerman <bbroerman@bbroerman.net>
|
|
|
cfc571 |
Date: Wed, 28 Jan 2015 22:36:41 -0500
|
|
|
cfc571 |
Subject: [PATCH] reneg and should_close are not yet members of sslsock.
|
|
|
cfc571 |
Removing...
|
|
|
cfc571 |
|
|
|
cfc571 |
---
|
|
|
cfc571 |
ext/openssl/xp_ssl.c | 10 +---------
|
|
|
cfc571 |
1 file changed, 1 insertion(+), 9 deletions(-)
|
|
|
cfc571 |
|
|
|
cfc571 |
diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
index 53c48beca766..842829f384a4 100644
|
|
|
cfc571 |
--- a/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
+++ b/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
@@ -242,15 +242,7 @@ static size_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, siz
|
|
|
cfc571 |
|
|
|
cfc571 |
/* Now, do the IO operation. Don't block if we can't complete... */
|
|
|
cfc571 |
if (read) {
|
|
|
cfc571 |
- nr_bytes = SSL_read(sslsock->ssl_handle, buf, count);
|
|
|
cfc571 |
-
|
|
|
cfc571 |
- if (sslsock->reneg && sslsock->reneg->should_close) {
|
|
|
cfc571 |
- /* renegotiation rate limiting triggered */
|
|
|
cfc571 |
- php_stream_xport_shutdown(stream, (stream_shutdown_t)SHUT_RDWR);
|
|
|
cfc571 |
- nr_bytes = 0;
|
|
|
cfc571 |
- stream->eof = 1;
|
|
|
cfc571 |
- break;
|
|
|
cfc571 |
- }
|
|
|
cfc571 |
+ nr_bytes = SSL_read(sslsock->ssl_handle, buf, count);
|
|
|
cfc571 |
} else {
|
|
|
cfc571 |
nr_bytes = SSL_write(sslsock->ssl_handle, buf, count);
|
|
|
cfc571 |
}
|
|
|
cfc571 |
From dddbe0fc338a0f01ba336e84755694fb9bfbeb53 Mon Sep 17 00:00:00 2001
|
|
|
cfc571 |
From: Brad Broerman <bbroerman@bbroerman.net>
|
|
|
cfc571 |
Date: Wed, 4 Feb 2015 10:13:36 -0500
|
|
|
cfc571 |
Subject: [PATCH] Update xp_ssl.c
|
|
|
cfc571 |
|
|
|
cfc571 |
Added TSRMLS_CC to php_openssl_sockop_io calls.
|
|
|
cfc571 |
---
|
|
|
cfc571 |
ext/openssl/xp_ssl.c | 4 ++--
|
|
|
cfc571 |
1 file changed, 2 insertions(+), 2 deletions(-)
|
|
|
cfc571 |
|
|
|
cfc571 |
diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
index 842829f384a4..4b8a8955ae43 100644
|
|
|
cfc571 |
--- a/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
+++ b/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
@@ -176,12 +176,12 @@ static int handle_ssl_error(php_stream *stream, int nr_bytes, zend_bool is_init
|
|
|
cfc571 |
|
|
|
cfc571 |
static size_t php_openssl_sockop_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
|
|
|
cfc571 |
{
|
|
|
cfc571 |
- return php_openssl_sockop_io( 0, stream, buf, count );
|
|
|
cfc571 |
+ return php_openssl_sockop_io( 0, stream, buf, count TSRMLS_CC);
|
|
|
cfc571 |
}
|
|
|
cfc571 |
|
|
|
cfc571 |
static size_t php_openssl_sockop_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
|
|
|
cfc571 |
{
|
|
|
cfc571 |
- return php_openssl_sockop_io( 1, stream, buf, count );
|
|
|
cfc571 |
+ return php_openssl_sockop_io( 1, stream, buf, count TSRMLS_CC);
|
|
|
cfc571 |
}
|
|
|
cfc571 |
|
|
|
cfc571 |
/**
|
|
|
cfc571 |
From 1eef4f2a0cf855b8f453e9fe8fb2499907754022 Mon Sep 17 00:00:00 2001
|
|
|
cfc571 |
From: Daniel Lowrey <rdlowrey@php.net>
|
|
|
cfc571 |
Date: Mon, 9 Feb 2015 11:42:17 -0500
|
|
|
cfc571 |
Subject: [PATCH] Miscellaneous cleanup
|
|
|
cfc571 |
|
|
|
cfc571 |
---
|
|
|
cfc571 |
ext/openssl/xp_ssl.c | 56 ++++++++++++++++++++++++++--------------------------
|
|
|
cfc571 |
1 file changed, 28 insertions(+), 28 deletions(-)
|
|
|
cfc571 |
|
|
|
cfc571 |
diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
index 4b8a8955ae43..5adff1f953fd 100644
|
|
|
cfc571 |
--- a/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
+++ b/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
@@ -174,14 +174,14 @@ static int handle_ssl_error(php_stream *stream, int nr_bytes, zend_bool is_init
|
|
|
cfc571 |
return retry;
|
|
|
cfc571 |
}
|
|
|
cfc571 |
|
|
|
cfc571 |
-static size_t php_openssl_sockop_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
|
|
|
cfc571 |
+static size_t php_openssl_sockop_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
|
|
|
cfc571 |
{
|
|
|
cfc571 |
- return php_openssl_sockop_io( 0, stream, buf, count TSRMLS_CC);
|
|
|
cfc571 |
+ return php_openssl_sockop_io(1, stream, buf, count TSRMLS_CC);
|
|
|
cfc571 |
}
|
|
|
cfc571 |
|
|
|
cfc571 |
-static size_t php_openssl_sockop_read(php_stream *stream, char *buf, size_t count TSRMLS_DC)
|
|
|
cfc571 |
+static size_t php_openssl_sockop_write(php_stream *stream, const char *buf, size_t count TSRMLS_DC)
|
|
|
cfc571 |
{
|
|
|
cfc571 |
- return php_openssl_sockop_io( 1, stream, buf, count TSRMLS_CC);
|
|
|
cfc571 |
+ return php_openssl_sockop_io(0, stream, (char*)buf, count TSRMLS_CC);
|
|
|
cfc571 |
}
|
|
|
cfc571 |
|
|
|
cfc571 |
/**
|
|
|
cfc571 |
@@ -194,15 +194,15 @@ static size_t php_openssl_sockop_read(php_stream *stream, char *buf, size_t coun
|
|
|
cfc571 |
static size_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, size_t count TSRMLS_DC)
|
|
|
cfc571 |
{
|
|
|
cfc571 |
php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
|
|
|
cfc571 |
- int nr_bytes = 0;
|
|
|
cfc571 |
+ int nr_bytes = 0;
|
|
|
cfc571 |
|
|
|
cfc571 |
- /* Only do this if SSL is active. */
|
|
|
cfc571 |
+ /* Only do this if SSL is active. */
|
|
|
cfc571 |
if (sslsock->ssl_active) {
|
|
|
cfc571 |
int retry = 1;
|
|
|
cfc571 |
- struct timeval start_time,
|
|
|
cfc571 |
- *timeout;
|
|
|
cfc571 |
- int blocked = sslsock->s.is_blocked,
|
|
|
cfc571 |
- has_timeout = 0;
|
|
|
cfc571 |
+ struct timeval start_time;
|
|
|
cfc571 |
+ struct timeval *timeout;
|
|
|
cfc571 |
+ int blocked = sslsock->s.is_blocked;
|
|
|
cfc571 |
+ int has_timeout = 0;
|
|
|
cfc571 |
|
|
|
cfc571 |
/* Begin by making the socket non-blocking. This allows us to check the timeout. */
|
|
|
cfc571 |
if (SUCCESS == php_set_sock_blocking(sslsock->s.socket, 0 TSRMLS_CC)) {
|
|
|
cfc571 |
@@ -216,7 +216,7 @@ static size_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, siz
|
|
|
cfc571 |
/* gettimeofday is not monotonic; using it here is not strictly correct */
|
|
|
cfc571 |
if (has_timeout) {
|
|
|
cfc571 |
gettimeofday(&start_time, NULL);
|
|
|
cfc571 |
- }
|
|
|
cfc571 |
+ }
|
|
|
cfc571 |
|
|
|
cfc571 |
/* Main IO loop. */
|
|
|
cfc571 |
do {
|
|
|
cfc571 |
@@ -263,7 +263,7 @@ static size_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, siz
|
|
|
cfc571 |
if (errno == EAGAIN && err == SSL_ERROR_WANT_READ && read) {
|
|
|
cfc571 |
retry = 1;
|
|
|
cfc571 |
}
|
|
|
cfc571 |
- if (errno == EAGAIN && SSL_ERROR_WANT_WRITE && read == 0) {
|
|
|
cfc571 |
+ if (errno == EAGAIN && SSL_ERROR_WANT_WRITE && read == 0) {
|
|
|
cfc571 |
retry = 1;
|
|
|
cfc571 |
}
|
|
|
cfc571 |
|
|
|
cfc571 |
@@ -289,11 +289,12 @@ static size_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, siz
|
|
|
cfc571 |
int err = SSL_get_error(sslsock->ssl_handle, nr_bytes );
|
|
|
cfc571 |
|
|
|
cfc571 |
/* If we didn't get any error, then let's return it to PHP. */
|
|
|
cfc571 |
- if (err == SSL_ERROR_NONE)
|
|
|
cfc571 |
- break;
|
|
|
cfc571 |
+ if (err == SSL_ERROR_NONE) {
|
|
|
cfc571 |
+ break;
|
|
|
cfc571 |
+ }
|
|
|
cfc571 |
|
|
|
cfc571 |
/* Otherwise, we need to wait again (up to time_left or we get an error) */
|
|
|
cfc571 |
- if (blocked)
|
|
|
cfc571 |
+ if (blocked) {
|
|
|
cfc571 |
if (read) {
|
|
|
cfc571 |
php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_WRITE) ?
|
|
|
cfc571 |
(POLLOUT|POLLPRI) : (POLLIN|POLLPRI), has_timeout ? &left_time : NULL);
|
|
|
cfc571 |
@@ -301,6 +302,7 @@ static size_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, siz
|
|
|
cfc571 |
php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_READ) ?
|
|
|
cfc571 |
(POLLIN|POLLPRI) : (POLLOUT|POLLPRI), has_timeout ? &left_time : NULL);
|
|
|
cfc571 |
}
|
|
|
cfc571 |
+ }
|
|
|
cfc571 |
}
|
|
|
cfc571 |
/* Finally, we keep going until we got data, and an SSL_ERROR_NONE, unless we had an error. */
|
|
|
cfc571 |
} while (retry);
|
|
|
cfc571 |
@@ -312,21 +314,19 @@ static size_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, siz
|
|
|
cfc571 |
|
|
|
cfc571 |
/* And if we were originally supposed to be blocking, let's reset the socket to that. */
|
|
|
cfc571 |
if (blocked) {
|
|
|
cfc571 |
- php_set_sock_blocking(sslsock->s.socket, 1 TSRMLS_CC);
|
|
|
cfc571 |
- sslsock->s.is_blocked = 1;
|
|
|
cfc571 |
- }
|
|
|
cfc571 |
- } else {
|
|
|
cfc571 |
- /*
|
|
|
cfc571 |
- * This block is if we had no timeout... We will just sit and wait forever on the IO operation.
|
|
|
cfc571 |
- */
|
|
|
cfc571 |
- if (read) {
|
|
|
cfc571 |
- nr_bytes = php_stream_socket_ops.read(stream, buf, count TSRMLS_CC);
|
|
|
cfc571 |
- } else {
|
|
|
cfc571 |
- nr_bytes = php_stream_socket_ops.write(stream, buf, count TSRMLS_CC);
|
|
|
cfc571 |
+ php_set_sock_blocking(sslsock->s.socket, 1 TSRMLS_CC);
|
|
|
cfc571 |
+ sslsock->s.is_blocked = 1;
|
|
|
cfc571 |
+ }
|
|
|
cfc571 |
+ } else {
|
|
|
cfc571 |
+ /* This block is if we had no timeout... We will just sit and wait forever on the IO operation. */
|
|
|
cfc571 |
+ if (read) {
|
|
|
cfc571 |
+ nr_bytes = php_stream_socket_ops.read(stream, buf, count TSRMLS_CC);
|
|
|
cfc571 |
+ } else {
|
|
|
cfc571 |
+ nr_bytes = php_stream_socket_ops.write(stream, buf, count TSRMLS_CC);
|
|
|
cfc571 |
+ }
|
|
|
cfc571 |
}
|
|
|
cfc571 |
- }
|
|
|
cfc571 |
|
|
|
cfc571 |
- /* PHP doesn't expect a negative return. */
|
|
|
cfc571 |
+ /* PHP doesn't expect a negative return. */
|
|
|
cfc571 |
if (nr_bytes < 0) {
|
|
|
cfc571 |
nr_bytes = 0;
|
|
|
cfc571 |
}
|
|
|
cfc571 |
From 5ff77b005b646e1ae497640d9ddfa37f486f09a8 Mon Sep 17 00:00:00 2001
|
|
|
cfc571 |
From: Anatol Belski <ab@php.net>
|
|
|
cfc571 |
Date: Fri, 13 Feb 2015 13:39:46 +0100
|
|
|
cfc571 |
Subject: [PATCH] fix condition
|
|
|
cfc571 |
|
|
|
cfc571 |
---
|
|
|
cfc571 |
ext/openssl/xp_ssl.c | 2 +-
|
|
|
cfc571 |
1 file changed, 1 insertion(+), 1 deletion(-)
|
|
|
cfc571 |
|
|
|
cfc571 |
diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
index 5adff1f953fd..b8d747b5ec10 100644
|
|
|
cfc571 |
--- a/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
+++ b/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
@@ -263,7 +263,7 @@ static size_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, siz
|
|
|
cfc571 |
if (errno == EAGAIN && err == SSL_ERROR_WANT_READ && read) {
|
|
|
cfc571 |
retry = 1;
|
|
|
cfc571 |
}
|
|
|
cfc571 |
- if (errno == EAGAIN && SSL_ERROR_WANT_WRITE && read == 0) {
|
|
|
cfc571 |
+ if (errno == EAGAIN && err == SSL_ERROR_WANT_WRITE && read == 0) {
|
|
|
cfc571 |
retry = 1;
|
|
|
cfc571 |
}
|
|
|
cfc571 |
|
|
|
cfc571 |
From bbfd4a5e62cf058cb18d53a0817860edc01c371c Mon Sep 17 00:00:00 2001
|
|
|
cfc571 |
From: Daniel Lowrey <rdlowrey@php.net>
|
|
|
cfc571 |
Date: Mon, 9 Mar 2015 15:53:26 -0600
|
|
|
cfc571 |
Subject: [PATCH] Fix crypto stream timeout regressions
|
|
|
cfc571 |
|
|
|
cfc571 |
---
|
|
|
cfc571 |
ext/openssl/xp_ssl.c | 37 +++++++++++++++++++------------------
|
|
|
cfc571 |
1 file changed, 19 insertions(+), 18 deletions(-)
|
|
|
cfc571 |
|
|
|
cfc571 |
diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
index b8d747b5ec10..e8bc6ae39d35 100644
|
|
|
cfc571 |
--- a/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
+++ b/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
@@ -200,21 +200,22 @@ static size_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, siz
|
|
|
cfc571 |
if (sslsock->ssl_active) {
|
|
|
cfc571 |
int retry = 1;
|
|
|
cfc571 |
struct timeval start_time;
|
|
|
cfc571 |
- struct timeval *timeout;
|
|
|
cfc571 |
- int blocked = sslsock->s.is_blocked;
|
|
|
cfc571 |
+ struct timeval *timeout = NULL;
|
|
|
cfc571 |
+ int began_blocked = sslsock->s.is_blocked;
|
|
|
cfc571 |
int has_timeout = 0;
|
|
|
cfc571 |
|
|
|
cfc571 |
- /* Begin by making the socket non-blocking. This allows us to check the timeout. */
|
|
|
cfc571 |
- if (SUCCESS == php_set_sock_blocking(sslsock->s.socket, 0 TSRMLS_CC)) {
|
|
|
cfc571 |
- sslsock->s.is_blocked = 0;
|
|
|
cfc571 |
+ /* never use a timeout with non-blocking sockets */
|
|
|
cfc571 |
+ if (began_blocked && &sslsock->s.timeout) {
|
|
|
cfc571 |
+ timeout = &sslsock->s.timeout;
|
|
|
cfc571 |
}
|
|
|
cfc571 |
|
|
|
cfc571 |
- /* Get the timeout value (and make sure we are to check it. */
|
|
|
cfc571 |
- timeout = sslsock->is_client ? &sslsock->connect_timeout : &sslsock->s.timeout;
|
|
|
cfc571 |
- has_timeout = !sslsock->s.is_blocked && (timeout->tv_sec || timeout->tv_usec);
|
|
|
cfc571 |
+ if (timeout && php_set_sock_blocking(sslsock->s.socket, 0 TSRMLS_CC) == SUCCESS) {
|
|
|
cfc571 |
+ sslsock->s.is_blocked = 0;
|
|
|
cfc571 |
+ }
|
|
|
cfc571 |
|
|
|
cfc571 |
- /* gettimeofday is not monotonic; using it here is not strictly correct */
|
|
|
cfc571 |
- if (has_timeout) {
|
|
|
cfc571 |
+ if (!sslsock->s.is_blocked && timeout && (timeout->tv_sec || timeout->tv_usec)) {
|
|
|
cfc571 |
+ has_timeout = 1;
|
|
|
cfc571 |
+ /* gettimeofday is not monotonic; using it here is not strictly correct */
|
|
|
cfc571 |
gettimeofday(&start_time, NULL);
|
|
|
cfc571 |
}
|
|
|
cfc571 |
|
|
|
cfc571 |
@@ -227,15 +228,16 @@ static size_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, siz
|
|
|
cfc571 |
gettimeofday(&cur_time, NULL);
|
|
|
cfc571 |
|
|
|
cfc571 |
/* Determine how much time we've taken so far. */
|
|
|
cfc571 |
- elapsed_time = subtract_timeval( cur_time, start_time );
|
|
|
cfc571 |
+ elapsed_time = subtract_timeval(cur_time, start_time);
|
|
|
cfc571 |
|
|
|
cfc571 |
/* and return an error if we've taken too long. */
|
|
|
cfc571 |
- if (compare_timeval( elapsed_time, *timeout) > 0 ) {
|
|
|
cfc571 |
+ if (compare_timeval(elapsed_time, *timeout) > 0 ) {
|
|
|
cfc571 |
/* If the socket was originally blocking, set it back. */
|
|
|
cfc571 |
- if (blocked) {
|
|
|
cfc571 |
+ if (began_blocked) {
|
|
|
cfc571 |
php_set_sock_blocking(sslsock->s.socket, 1 TSRMLS_CC);
|
|
|
cfc571 |
sslsock->s.is_blocked = 1;
|
|
|
cfc571 |
}
|
|
|
cfc571 |
+ sslsock->s.timeout_event = 1;
|
|
|
cfc571 |
return -1;
|
|
|
cfc571 |
}
|
|
|
cfc571 |
}
|
|
|
cfc571 |
@@ -275,7 +277,7 @@ static size_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, siz
|
|
|
cfc571 |
/* Now, if we have to wait some time, and we're supposed to be blocking, wait for the socket to become
|
|
|
cfc571 |
* available. Now, php_pollfd_for uses select to wait up to our time_left value only...
|
|
|
cfc571 |
*/
|
|
|
cfc571 |
- if (retry && blocked) {
|
|
|
cfc571 |
+ if (retry && began_blocked) {
|
|
|
cfc571 |
if (read) {
|
|
|
cfc571 |
php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_WRITE) ?
|
|
|
cfc571 |
(POLLOUT|POLLPRI) : (POLLIN|POLLPRI), has_timeout ? &left_time : NULL);
|
|
|
cfc571 |
@@ -286,7 +288,7 @@ static size_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, siz
|
|
|
cfc571 |
}
|
|
|
cfc571 |
} else {
|
|
|
cfc571 |
/* Else, if we got bytes back, check for possible errors. */
|
|
|
cfc571 |
- int err = SSL_get_error(sslsock->ssl_handle, nr_bytes );
|
|
|
cfc571 |
+ int err = SSL_get_error(sslsock->ssl_handle, nr_bytes);
|
|
|
cfc571 |
|
|
|
cfc571 |
/* If we didn't get any error, then let's return it to PHP. */
|
|
|
cfc571 |
if (err == SSL_ERROR_NONE) {
|
|
|
cfc571 |
@@ -294,7 +296,7 @@ static size_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, siz
|
|
|
cfc571 |
}
|
|
|
cfc571 |
|
|
|
cfc571 |
/* Otherwise, we need to wait again (up to time_left or we get an error) */
|
|
|
cfc571 |
- if (blocked) {
|
|
|
cfc571 |
+ if (began_blocked) {
|
|
|
cfc571 |
if (read) {
|
|
|
cfc571 |
php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_WRITE) ?
|
|
|
cfc571 |
(POLLOUT|POLLPRI) : (POLLIN|POLLPRI), has_timeout ? &left_time : NULL);
|
|
|
cfc571 |
@@ -313,8 +315,7 @@ static size_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, siz
|
|
|
cfc571 |
}
|
|
|
cfc571 |
|
|
|
cfc571 |
/* And if we were originally supposed to be blocking, let's reset the socket to that. */
|
|
|
cfc571 |
- if (blocked) {
|
|
|
cfc571 |
- php_set_sock_blocking(sslsock->s.socket, 1 TSRMLS_CC);
|
|
|
cfc571 |
+ if (began_blocked && php_set_sock_blocking(sslsock->s.socket, 1 TSRMLS_CC) == SUCCESS) {
|
|
|
cfc571 |
sslsock->s.is_blocked = 1;
|
|
|
cfc571 |
}
|
|
|
cfc571 |
} else {
|
|
|
cfc571 |
From 601d60a978b9e053ab8e6dc0f12ff850fc642ced Mon Sep 17 00:00:00 2001
|
|
|
cfc571 |
From: Daniel Lowrey <rdlowrey@php.net>
|
|
|
cfc571 |
Date: Tue, 14 Apr 2015 09:12:28 -0600
|
|
|
cfc571 |
Subject: [PATCH] Fix Bug #69402: Reading empty SSL stream hangs until timeout
|
|
|
cfc571 |
|
|
|
cfc571 |
---
|
|
|
cfc571 |
NEWS | 4 ++++
|
|
|
cfc571 |
ext/openssl/xp_ssl.c | 13 +++++++++----
|
|
|
cfc571 |
2 files changed, 13 insertions(+), 4 deletions(-)
|
|
|
cfc571 |
|
|
|
cfc571 |
diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
index e8bc6ae39d35..6c80c2228733 100644
|
|
|
cfc571 |
--- a/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
+++ b/ext/openssl/xp_ssl.c
|
|
|
cfc571 |
@@ -195,7 +195,7 @@ static size_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, siz
|
|
|
cfc571 |
{
|
|
|
cfc571 |
php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t*)stream->abstract;
|
|
|
cfc571 |
int nr_bytes = 0;
|
|
|
cfc571 |
-
|
|
|
cfc571 |
+
|
|
|
cfc571 |
/* Only do this if SSL is active. */
|
|
|
cfc571 |
if (sslsock->ssl_active) {
|
|
|
cfc571 |
int retry = 1;
|
|
|
cfc571 |
@@ -271,13 +271,18 @@ static size_t php_openssl_sockop_io(int read, php_stream *stream, char *buf, siz
|
|
|
cfc571 |
|
|
|
cfc571 |
/* Also, on reads, we may get this condition on an EOF. We should check properly. */
|
|
|
cfc571 |
if (read) {
|
|
|
cfc571 |
- stream->eof = (retry == 0 && errno != EAGAIN && !SSL_pending(sslsock->ssl_handle));
|
|
|
cfc571 |
+ stream->eof = (retry == 0 && errno != EAGAIN && !SSL_pending(sslsock->ssl_handle));
|
|
|
cfc571 |
}
|
|
|
cfc571 |
-
|
|
|
cfc571 |
+
|
|
|
cfc571 |
+ /* Don't loop indefinitely in non-blocking mode if no data is available */
|
|
|
cfc571 |
+ if (began_blocked == 0) {
|
|
|
cfc571 |
+ break;
|
|
|
cfc571 |
+ }
|
|
|
cfc571 |
+
|
|
|
cfc571 |
/* Now, if we have to wait some time, and we're supposed to be blocking, wait for the socket to become
|
|
|
cfc571 |
* available. Now, php_pollfd_for uses select to wait up to our time_left value only...
|
|
|
cfc571 |
*/
|
|
|
cfc571 |
- if (retry && began_blocked) {
|
|
|
cfc571 |
+ if (retry) {
|
|
|
cfc571 |
if (read) {
|
|
|
cfc571 |
php_pollfd_for(sslsock->s.socket, (err == SSL_ERROR_WANT_WRITE) ?
|
|
|
cfc571 |
(POLLOUT|POLLPRI) : (POLLIN|POLLPRI), has_timeout ? &left_time : NULL);
|