cURL / Mailing Lists / curl-library / Single Mail

curl-library

Re: issue with quick reconnect

From: <koettermarkus_at_gmx.de>
Date: Thu, 20 Aug 2009 02:04:33 +0200

Peter Sylvester wrote:
>
> It seems to me that when the Curl_Send function
> returns 0, then either the openssl statemachine had returned
> SSL_ERROR_WANT_READ or
> SSL_ERROR_WANT_WRITE.
>
> rc = SSL_write(conn->ssl[sockindex].handle, mem, memlen);
>
> if(rc < 0) {
> err = SSL_get_error(conn->ssl[sockindex].handle, rc);
>
> switch(err) {
> case SSL_ERROR_WANT_READ:
> case SSL_ERROR_WANT_WRITE:
> /* The operation did not complete; the same TLS/SSL I/O function
> should be called again later. This is basicly an EWOULDBLOCK
> equivalent. */
> return 0;
>
> Depending on that one must select for reading or writing,
> (in a loop), but how?
>
> http://www.openssl.org/docs/ssl/SSL_get_error.html

I've been into nonblocking tls with openssl lately, had problems to get
it right the first time too, and I just took the time to look on curl's
way to get things done.

Things I'd call flaws in ssluse.c:

line 804,
int Curl_ossl_shutdown(struct connectdata *conn, int sockindex)
* blocking code (nonblocking with timeout)
* SSL_shutdown is used wrong ( see http://www.honeynet.org/node/437 )

line 2279,
ossl_connect_common(struct connectdata *conn,
                     int sockindex,
                     bool nonblocking,
                     bool *done)
* blocking code (nonblocking with timeout) to connect to ssl services
including handshake

line 2414,
ssize_t Curl_ossl_send(struct connectdata *conn,
                        int sockindex,
                        const void *mem,
                        size_t len)
* SSL_write is used wrong in multiple ways:
man SSL_write: When an SSL_write() operation has to be repeated because
of SSL_ERROR_WANT_READ or SSL_ERROR_WANT_WRITE, it must be repeated with
the same arguments.
Same args means same buffer, same len.
curl fails here, SSL_ERROR_WANT_READ is not respected, I doubt pollin
will trigger a call to Curl_ossl_send, and for the (semi) working case
pollout SSL_write does not use the same args as for the previous call.

line 2465,
ssize_t Curl_ossl_recv(struct connectdata *conn, /* connection data */
                        ...
                        bool *wouldblock)
* SSL_ERROR_ZERO_RETURN is not handeld correctly

Openssl is sometimes not really intuitive, but -for my experience- the
only ssl layer you *can* use nonblocking, even if it is sometimes really
hard to do right.

For curl, the way it is done seems to work, but yet there are some
misunderstandings.

For SSL_write, I have no idea how to make curl call SSL_write for a
pollin event.
As mentioned before, I had to do it myself, but as I use callbacks for
events, I could move the pollin callback to SSL_write, and restore the
pollin callback to SSL_read once SSL_write was satisfied in its
read-requirements.
How to keep the arguments alive for a repeated SSL_write call?

MfG
Markus
Received on 2009-08-20