Excuse me if I am saying the obvious. 

But did you factor the fact that an SSL renegotiation
or handshake can happen anytime during the
conversation? 

Irrespective of whether you are doing SSL_read or
SSL_write... That is why you have to check for pending
write during a SSL_read and vice versa in the non
blocking case.

This is what the manpage says at least. I may be wrong
here.

--- Henrik Thuermer <[EMAIL PROTECTED]> wrote:

> At 11:59 17.07.2006 +0100, you wrote:
> >Henrik Thuermer wrote:
> >> If we receive some data we process it via one
> BIO_write call followed by
> >> SSL_read calls until the call to SSL_read fails
> with SSL_get_error() ==
> >> SSL_ERROR_WANT_READ or SSL_read returns no more
> data (SSL_ERROR_WANT_WRITE
> >> is also handled correctly - I hope). Then we stop
> reading from the ssl
> >> connection until we receive new data.
> >
> >Just to confirm your understanding on this point,
> as your description is
> >unclear.
> 
> Sorry if I was unclear in my email.
> 
> >
> >You may not necessarily receive new data, as in new
> >application level data.
> >
> 
> I do not understand what you mean here. Maybe the
> misunderstanding is that
> you assume the ssl library handles the tcp socket?
> But in our case the
> socket handling (send/recv) is done by the
> application not by the ssl library.
> 
> If I write "receive some data" I mean our
> application reads the data from a
> TCP socket and transfer it to the ssl connection via
> BIO_write. Our read
> routine looks something like this (The BIO was
> "connected" to the ssl
> object with SSL_set_bio before ssl connection
> setup):
> 
> void ReceiveSomeData(SSL* ssl, SOCKET s, BIO*
> bioRead)
> {
> 
>     ....
> 
>     int rcvd = recv(s, recvBuffer, 8192, 0);
> 
>     int bytesWritten = BIO_write(bioRead,
> recvBuffer, rcvd);
> 
>     if (bytesWritten != rcvd) {
>       assert(false);
>       // this never happens during our tests
>     }
> 
>     while (true) {
> 
>        char buffer[bufferLength];
>         int bytesRead = SSL_read (ssl, buffer,
> bufferLenght);
> 
>         if (bytesRead > 0) 
>             DoSomethingWithTheData();
>         else if (bytesRead == 0) 
>             // nothing more to decrypt -> stop here
> until we receive more data
>             break;
>         else if (bytesRead < 0) {
>             if (SSL_get_error() ==
> SSL_ERROR_WANT_READ) {
>                 // nothing more to decrypt -> stop
> here until we receive
> more data
>                 ERR_clear_error();
>                 break;
>             }
>             if (SSL_get_error() ==
> SSL_ERROR_WANT_WRITE) {
>                 // never happens during our test
> (initial ssl connection
> setup is done
>                 // at another place)
>                 ERR_clear_error();
>                 SendOutStandingSSLData();
>             }
>         }
>     }
> 
>     ...
> }
> 
> >
> >It is safe to keep trying SSL_write() after every
> SSL_read() to see if
> >it can do more work, otherwise it will persist with
> the WANT_READ state.
> >
> 
> I'm really not familiar with the library sorce code.
> I only stepped into it
> during debugging and found the following:
> 
> SSL_read internally calls ssl2_read_internal:
> 
> static int ssl2_read_internal(SSL *s, void *buf, int
> len, int peek)
> {
> 
> ...
> 
>     if (s->rstate == SSL_ST_READ_BODY)
>         {
>         n=s->s2->rlength+2+s->s2->three_byte_header;
>         if (n > (int)s->packet_length)
>             {
>             n-=s->packet_length;
>             i=read_n(s,(unsigned int)n,(unsigned
> int)n,1);
>             if (i <= 0) return(i); /* ERROR */
>             }
> 
> ...
> 
> }
> 
> In our case this returns in the line marked with /*
> ERROR */ (should this
> be /* error or non-blocking */ like at the other
> call to read_n?). The
> internal read state remains SSL_ST_READ_BODY. If
> SSL_read is called the
> next time it immediatly falls into this if statement
> evaluating
> 
> n=s->s2->rlength+2+s->s2->three_byte_header;
> 
> But if we have called SSL_write before, it may have
> changed the value of
> s->s2->three_byte_header. 
> I did not test wether SSL_write really _changed_ 
> s->s2->three_byte_header
> (it certainly will touch it).
> But: Our problem disappears if we do not call
> SSL_write in this situation
> but wait until some more data is available and we
> can call
> BIO_write/SSL_read again hoping that this will
> change the read state to
> SSL_ST_READ_HEADER :-). This leads me to the
> assumption that sometimes you
> should not call SSL_write (unlikely?) or that we use
> the ssl library in the
> wrong way (likely, but where is the mistake?).
> 
> 
> >
> >If you are non-blocking the only special case is to
> start ignoring the
> >select/poll/read/write writability event mechanism
> to drive your writes
> >at the point you get WANT_READ from SSL_write(). 
> But keep watching and
> >processing readability events like normal, but
> while ignoring
> >writability events after each call to SSL_read()
> (successful or not)
> >attempt a SSL_write(), if that no longer returns
> WANT_READ then you can
> >stop ignoring and start using your writability
> event indication to drive
> >SSL_write() again.
> >
> 
> I think we handle WANT_READ/WANT_WRITE correctly (at
> least the cases which
> happens in our test environment) because:
> -ssl connection setup is always successful
> -after ssl connection setup the only error we get is
> WANT_READ after
> SSL_read returns with -1, which the application
> interprets as: no more or
> not enough encrypted data in internal buffer, wait
> until new data is received.
> 
> 
> >
> >
> >> This works but it is only a hack, of course (and
> may deadlock sometimes if
> >> ssl->rstate == SSL_ST_READ_HEADER on both sides
> of the connection at the
> >> same time). What we are doing wrong?
> >
> >I've not taken in the problem completely here.  If
> this deadlock is
> >correct, can you provide a packet/data dump of the
> session.
> >
> 
> The deadlock did not happen up to now and it's  an
> "application level"
> 
=== message truncated ===


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around 
http://mail.yahoo.com 
______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to