diff --git a/doc/man3/SSL_get_error.pod b/doc/man3/SSL_get_error.pod index a1f8bc0f5b061271a0d8691f9ab2f4cff64f40bf..db8f85c90a7e0af72e16cb222aa4123cda516199 100644 --- a/doc/man3/SSL_get_error.pod +++ b/doc/man3/SSL_get_error.pod @@ -38,12 +38,12 @@ if and only if B 0>. =item SSL_ERROR_ZERO_RETURN -The TLS/SSL connection has been closed. If the protocol version is SSL 3.0 -or TLS 1.0, this result code is returned only if a closure -alert has occurred in the protocol, i.e. if the connection has been -closed cleanly. Note that in this case B -does not necessarily indicate that the underlying transport -has been closed. +The TLS/SSL connection has been closed. +If the protocol version is SSL 3.0 or higher, this result code is returned only +if a closure alert has occurred in the protocol, i.e. if the connection has been +closed cleanly. +Note that in this case B does not necessarily +indicate that the underlying transport has been closed. =item SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE @@ -112,12 +112,9 @@ thread has completed. =item SSL_ERROR_SYSCALL -Some I/O error occurred. The OpenSSL error queue may contain more -information on the error. If the error queue is empty -(i.e. ERR_get_error() returns 0), B can be used to find out more -about the error: If B, an EOF was observed that violates -the protocol. If B, the underlying B reported an -I/O error (for socket I/O on Unix systems, consult B for details). +Some non-recoverable I/O error occurred. +The OpenSSL error queue may contain more information on the error. +For socket I/O on Unix systems, consult B for details. =item SSL_ERROR_SSL diff --git a/doc/man3/SSL_read.pod b/doc/man3/SSL_read.pod index e2490d4f47527206db6b779aed8b9e3ffc1a1155..215d4c52923ec749de3efd291c9c2df75376755d 100644 --- a/doc/man3/SSL_read.pod +++ b/doc/man3/SSL_read.pod @@ -9,17 +9,17 @@ SSL_read_ex, SSL_read, SSL_peek_ex, SSL_peek #include - int SSL_read_ex(SSL *ssl, void *buf, size_t num, size_t *read); + int SSL_read_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes); int SSL_read(SSL *ssl, void *buf, int num); - int SSL_peek_ex(SSL *ssl, void *buf, size_t num, size_t *read); + int SSL_peek_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes); int SSL_peek(SSL *ssl, void *buf, int num); =head1 DESCRIPTION SSL_read_ex() and SSL_read() try to read B bytes from the specified B into the buffer B. On success SSL_read_ex() will store the number of bytes -actually read in B<*read>. +actually read in B<*readbytes>. SSL_peek_ex() and SSL_peek() are identical to SSL_read_ex() and SSL_read() respectively except no bytes are actually removed from the underlying BIO during @@ -90,38 +90,32 @@ with the same arguments. SSL_read_ex() and SSL_peek_ex() will return 1 for success or 0 for failure. Success means that 1 or more application data bytes have been read from the SSL -connection. Failure means that no bytes could be read from the SSL connection. +connection. +Failure means that no bytes could be read from the SSL connection. Failures can be retryable (e.g. we are waiting for more bytes to -be delivered by the network) or non-retryable (e.g. a fatal network error). In -the event of a failure call L to find out the reason which +be delivered by the network) or non-retryable (e.g. a fatal network error). +In the event of a failure call L to find out the reason which indicates whether the call is retryable or not. For SSL_read() and SSL_peek() the following return values can occur: =over 4 -=item E0 +=item E 0 -The read operation was successful; the return value is the number of -bytes actually read from the TLS/SSL connection. +The read operation was successful. +The return value is the number of bytes actually read from the TLS/SSL +connection. -=item Z<>0 +=item Z<><= 0 -The read operation was not successful. The reason may either be a clean -shutdown due to a "close notify" alert sent by the peer (in which case -the SSL_RECEIVED_SHUTDOWN flag in the ssl shutdown state is set -(see L, -L). It is also possible, that -the peer simply shut down the underlying transport and the shutdown is -incomplete. Call SSL_get_error() with the return value B to find out, -whether an error occurred or the connection was shut down cleanly -(SSL_ERROR_ZERO_RETURN). +The read operation was not successful, because either the connection was closed, +an error occurred or action must be taken by the calling process. +Call L with the return value B to find out the reason. -=item E0 - -The read operation was not successful, because either an error occurred -or action must be taken by the calling process. Call SSL_get_error() with the -return value B to find out the reason. +Old documentation indicated a difference between 0 and -1, and that -1 was +retryable. +You should instead call SSL_get_error() to find out if it's retryable. =back diff --git a/doc/man3/SSL_write.pod b/doc/man3/SSL_write.pod index 8ed91929bba214f6b474abd64795fb5267b9e230..2a751107bb95af8ce38d64d2cb2586234554bf7c 100644 --- a/doc/man3/SSL_write.pod +++ b/doc/man3/SSL_write.pod @@ -86,23 +86,20 @@ For SSL_write() the following return values can occur: =over 4 -=item E0 +=item E 0 The write operation was successful, the return value is the number of bytes actually written to the TLS/SSL connection. -=item Z<>0 +=item Z<><= 0 -The write operation was not successful. Probably the underlying connection -was closed. Call SSL_get_error() with the return value B to find out, -whether an error occurred or the connection was shut down cleanly -(SSL_ERROR_ZERO_RETURN). +The write operation was not successful, because either the connection was +closed, an error occurred or action must be taken by the calling process. +Call SSL_get_error() with the return value B to find out the reason. -=item E0 - -The write operation was not successful, because either an error occurred -or action must be taken by the calling process. Call SSL_get_error() with the -return value B to find out the reason. +Old documentation indicated a difference between 0 and -1, and that -1 was +retryable. +You should instead call SSL_get_error() to find out if it's retryable. =back diff --git a/include/openssl/ssl.h b/include/openssl/ssl.h index f428af72ae09c79ddb9b6534d6f02e72cbe2801b..1f9aaf855ea79fa812c36428447034b1146c171e 100644 --- a/include/openssl/ssl.h +++ b/include/openssl/ssl.h @@ -1580,9 +1580,9 @@ __owur int SSL_get_changed_async_fds(SSL *s, OSSL_ASYNC_FD *addfd, __owur int SSL_accept(SSL *ssl); __owur int SSL_connect(SSL *ssl); __owur int SSL_read(SSL *ssl, void *buf, int num); -__owur int SSL_read_ex(SSL *ssl, void *buf, size_t num, size_t *read); +__owur int SSL_read_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes); __owur int SSL_peek(SSL *ssl, void *buf, int num); -__owur int SSL_peek_ex(SSL *ssl, void *buf, size_t num, size_t *read); +__owur int SSL_peek_ex(SSL *ssl, void *buf, size_t num, size_t *readbytes); __owur int SSL_write(SSL *ssl, const void *buf, int num); __owur int SSL_write_ex(SSL *s, const void *buf, size_t num, size_t *written); long SSL_ctrl(SSL *ssl, int cmd, long larg, void *parg); diff --git a/ssl/record/rec_layer_s3.c b/ssl/record/rec_layer_s3.c index 779a29fddd20b05f239e241c150605264b8f4d1b..317ee30aa924541ab83af18c3a2bdbb6bf9e46c5 100644 --- a/ssl/record/rec_layer_s3.c +++ b/ssl/record/rec_layer_s3.c @@ -178,10 +178,7 @@ const char *SSL_rstate_string(const SSL *s) } /* - * Return values are as per SSL_read(), i.e. - * 1 Success - * 0 Failure (not retryable) - * <0 Failure (may be retryable) + * Return values are as per SSL_read() */ int ssl3_read_n(SSL *s, size_t n, size_t max, int extend, int clearold, size_t *readbytes) @@ -319,7 +316,7 @@ int ssl3_read_n(SSL *s, size_t n, size_t max, int extend, int clearold, if (s->mode & SSL_MODE_RELEASE_BUFFERS && !SSL_IS_DTLS(s)) if (len + left == 0) ssl3_release_read_buffer(s); - return -1; + return ret; } left += bioread; /* @@ -897,10 +894,7 @@ int do_ssl3_write(SSL *s, int type, const unsigned char *buf, /* if s->s3->wbuf.left != 0, we need to call this * - * Return values are as per SSL_read(), i.e. - * 1 Success - * 0 Failure (not retryable) - * <0 Failure (may be retryable) + * Return values are as per SSL_write() */ int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, size_t len, size_t *written) @@ -955,7 +949,7 @@ int ssl3_write_pending(SSL *s, int type, const unsigned char *buf, size_t len, */ SSL3_BUFFER_set_left(&wb[currbuf], 0); } - return -1; + return (i); } SSL3_BUFFER_add_offset(&wb[currbuf], tmpwrit); SSL3_BUFFER_sub_left(&wb[currbuf], tmpwrit); diff --git a/test/asynciotest.c b/test/asynciotest.c index 23d0907dc9151ece990d757e68ff3012bd1d3695..a4f43f8127b645412446d55a52299429a6cb5ca5 100644 --- a/test/asynciotest.c +++ b/test/asynciotest.c @@ -297,32 +297,59 @@ int main(int argc, char *argv[]) * we hit at least one async event in both reading and writing */ for (j = 0; j < 2; j++) { + int len; + /* * Write some test data. It should never take more than 2 attempts - * (the first one might be a retryable fail). A zero return from - * SSL_write() is a non-retryable failure, so fail immediately if - * we get that. + * (the first one might be a retryable fail). */ - for (ret = -1, i = 0; ret < 0 && i < 2 * sizeof(testdata); i++) - ret = SSL_write(clientssl, testdata, sizeof(testdata)); - if (ret <= 0) { - printf("Test %d failed: Failed to write app data\n", test); + for (ret = -1, i = 0, len = 0; len != sizeof(testdata) && i < 2; + i++) { + ret = SSL_write(clientssl, testdata + len, + sizeof(testdata) - len); + if (ret > 0) { + len += ret; + } else { + int ssl_error = SSL_get_error(clientssl, ret); + + if (ssl_error == SSL_ERROR_SYSCALL || + ssl_error == SSL_ERROR_SSL) { + printf("Test %d failed: Failed to write app data\n", test); + err = -1; + goto end; + } + } + } + if (len != sizeof(testdata)) { + err = -1; + printf("Test %d failed: Failed to write all app data\n", test); goto end; } /* * Now read the test data. It may take more attemps here because * it could fail once for each byte read, including all overhead - * bytes from the record header/padding etc. Fail immediately if we - * get a zero return from SSL_read(). + * bytes from the record header/padding etc. */ - for (ret = -1, i = 0; ret < 0 && i < MAX_ATTEMPTS; i++) - ret = SSL_read(serverssl, buf, sizeof(buf)); - if (ret <= 0) { - printf("Test %d failed: Failed to read app data\n", test); - goto end; + for (ret = -1, i = 0, len = 0; len != sizeof(testdata) && + i < MAX_ATTEMPTS; i++) + { + ret = SSL_read(serverssl, buf + len, sizeof(buf) - len); + if (ret > 0) { + len += ret; + } else { + int ssl_error = SSL_get_error(serverssl, ret); + + if (ssl_error == SSL_ERROR_SYSCALL || + ssl_error == SSL_ERROR_SSL) { + printf("Test %d failed: Failed to read app data\n", test); + err = -1; + goto end; + } + } } - if (ret != sizeof(testdata) + if (len != sizeof(testdata) || memcmp(buf, testdata, sizeof(testdata)) != 0) { + err = -1; printf("Test %d failed: Unexpected app data received\n", test); goto end; }