pavan
pavan

Reputation: 1135

SSL_read failing with SSL_ERROR_SYSCALL error

We have implemented tls using openssl. While downloading larger data from server getting SSL_ERROR_SYSCALL error after receiving the some data. For smaller files I am not getting this error, able to download without any error. ERR_get_error() is showing zero for larger files.

We are using linux and c++ framework. How to find reason for the failure? What could be the reason for failure? kindly provide your suggestions.

Upvotes: 31

Views: 169951

Answers (6)

agarwalanup
agarwalanup

Reputation: 41

We encountered this error in a Go application. We were using a third party library to connect to underlying openssl library from Go. While reading data the third party library was converting the length of buffer/data to be read to C.int which is 32bits. For large data >= 2GB this lead to overflow and a negative value being passed to C.SSL_read function. It raised SSL_ERROR_SYSCALL error in that case.

Upvotes: 1

Samuel Thompson
Samuel Thompson

Reputation: 2574

I found the issue to be my companies firewall blocking the requests. Go home and it should work

Upvotes: 13

Margach Chris
Margach Chris

Reputation: 1749

The problem is caused by the network connection being cut and the server re-setting.

Just make sure the connection is Ok before downloading the data.

A similar problem can be seen here when using vagrant.

https://github.com/hashicorp/vagrant/issues/9612

Upvotes: 2

Thomas
Thomas

Reputation: 51

Check if you call SSL_read() with a buffer size of 0. I have made the following mistake using SSL_pending():

int waitForReadFd = nBuf < bufSize;

if (waitForReadFd)
    FD_SET(fd, &rfds);

// ...
// select

int doReadFd = FD_ISSET(fd, &rfds) || SSL_pending(ssl);

if (doReadFd)
    n = SSL_read(ssl, buf, bufSize - nBuf);

If nBuf == bufSize SSL_read() will be called with a buffer size of 0 what leads to SSL_ERROR_SYSCALL with errno == 0.

Changing the doReadFd check will avoid this problem:

int doReadFd = FD_ISSET(fd, &rfds) || nBuf < bufSize && SSL_pending(ssl);

Upvotes: 5

wonder.mice
wonder.mice

Reputation: 7593

If you look into the source code for SSL_get_error() you'll see, that it returns SSL_ERROR_SYSCALL whenever it not sure what exactly happened. It's basically default return code for "unknown" case.

For example, in my case (doing non-blocking IO with BIO):

int buf;
const int n = SSL_read(ssl, &buf, 0);
const int err = SSL_get_error(ssl, n);
const int st = ERR_get_error();

When n is 0, err will be SSL_ERROR_SYSCALL just because. However st still will be 0 indicating that there was no real error. SSL_read just returned 0 because 0 bytes was written to the buf.

However, look for errno / WSAGetLastError() values after the call for more details.

Upvotes: 6

Jay
Jay

Reputation: 24905

SSL_ERROR_SYSCALL indicates that some problem happened with the underlying I/O (Should be TCP in this case). So, you can try checking with errno.

OpenSSL help says:

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), ret can be used to find out more about the error: If ret == 0, an EOF was observed that violates the protocol. If ret == -1, the underlying BIO reported an I/O error (for socket I/O on Unix systems, consult errno for details).

Upvotes: 22

Related Questions