From 843807c6470866cec3b02973cb1e2aeec190dda0 Mon Sep 17 00:00:00 2001 From: Wez Furlong Date: Sat, 25 Dec 2004 02:02:56 +0000 Subject: [PATCH] When a socket is non-blocking, don't block ssl enabled sockets. Allow for non-blocking negotiation when calling stream_socket_enable_crypto(). That function will return the foolowing values: false - negotiation failed 0 - try again when more data is available (only for non-blocking sockets) true - ssl was enabled --- ext/openssl/xp_ssl.c | 20 +++++++++++++++----- ext/standard/streamsfuncs.c | 15 +++++++++++++-- 2 files changed, 28 insertions(+), 7 deletions(-) diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index 1607b9d486..4b995cdc32 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -46,6 +46,8 @@ typedef struct _php_openssl_netstream_data_t { int is_client; int ssl_active; php_stream_xport_crypt_method_t method; + unsigned state_set:1; + unsigned _spare:31; } php_openssl_netstream_data_t; php_stream_ops php_openssl_socket_ops; @@ -92,6 +94,8 @@ static int handle_ssl_error(php_stream *stream, int nr_bytes TSRMLS_DC) case SSL_ERROR_WANT_WRITE: /* re-negotiation, or perhaps the SSL layer needs more * packets: retry in next iteration */ + errno = EAGAIN; + retry = sslsock->s.is_blocked; break; case SSL_ERROR_SYSCALL: if (ERR_peek_error() == 0) { @@ -159,6 +163,7 @@ static int handle_ssl_error(php_stream *stream, int nr_bytes TSRMLS_DC) } retry = 0; + errno = 0; } return retry; } @@ -210,7 +215,7 @@ static size_t php_openssl_sockop_read(php_stream *stream, char *buf, size_t coun if (nr_bytes <= 0) { retry = handle_ssl_error(stream, nr_bytes TSRMLS_CC); - stream->eof = (retry == 0 && !SSL_pending(sslsock->ssl_handle)); + stream->eof = (retry == 0 && errno != EAGAIN && !SSL_pending(sslsock->ssl_handle)); } else { /* we got the data */ @@ -377,10 +382,13 @@ static inline int php_openssl_enable_crypto(php_stream *stream, int n, retry = 1; if (cparam->inputs.activate && !sslsock->ssl_active) { - if (sslsock->is_client) { - SSL_set_connect_state(sslsock->ssl_handle); - } else { - SSL_set_accept_state(sslsock->ssl_handle); + if (!sslsock->state_set) { + if (sslsock->is_client) { + SSL_set_connect_state(sslsock->ssl_handle); + } else { + SSL_set_accept_state(sslsock->ssl_handle); + } + sslsock->state_set = 1; } do { @@ -409,6 +417,8 @@ static inline int php_openssl_enable_crypto(php_stream *stream, } X509_free(peer_cert); + } else { + n = errno == EAGAIN ? 0 : -1; } return n; diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c index 7ee44a0752..949a14656a 100644 --- a/ext/standard/streamsfuncs.c +++ b/ext/standard/streamsfuncs.c @@ -1290,7 +1290,7 @@ PHP_FUNCTION(stream_set_write_buffer) } /* }}} */ -/* {{{ proto bool stream_socket_enable_crypto(resource stream, bool enable [, int cryptokind, resource sessionstream]) +/* {{{ proto int stream_socket_enable_crypto(resource stream, bool enable [, int cryptokind, resource sessionstream]) Enable or disable a specific kind of crypto on the stream */ PHP_FUNCTION(stream_socket_enable_crypto) { @@ -1298,6 +1298,7 @@ PHP_FUNCTION(stream_socket_enable_crypto) zval *zstream, *zsessstream = NULL; php_stream *stream, *sessstream = NULL; zend_bool enable; + int ret; if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rb|lr", &zstream, &enable, &cryptokind, &zsessstream) == FAILURE) { RETURN_FALSE; @@ -1315,7 +1316,17 @@ PHP_FUNCTION(stream_socket_enable_crypto) } } - RETURN_BOOL(php_stream_xport_crypto_enable(stream, enable TSRMLS_CC) < 0 ? 0 : 1); + ret = php_stream_xport_crypto_enable(stream, enable TSRMLS_CC); + switch (ret) { + case -1: + RETURN_FALSE; + + case 0: + RETURN_LONG(0); + + default: + RETURN_TRUE; + } } /* }}} */ -- 2.40.0