RE: Problem handling unexpected SSL shutdown

2007-08-16 Thread Shaw Graham George

Thanks for the response.

You'll have to bear with me, as I'm not really a low-level sockets
programmer.  But maybe you misunderstood the nature of my problem.

The problem is that, on Windows at least, my server doesn't appear to
get the SSL shutdown notify packet, for some reason.  So, if that is
to be expected, I'm looking for an alternative way of detecting the
closure.

I've now tested it on Linux, and the existing code works fine.  In other
words, when trying the SSL_Get:

1.  It fails
2.  SSL_get_error() returns SSL_ERROR_ZERO_RETURN
3.  (SSL_get_shutdown()  SSL_RECEIVED_SHUTDOWN) is true

On Windows this is not the case.

But I guess if this problem is restricted to Windows, then I can:

1.  Add the call to WSAGetLastError() just for that platform
2.  Use it to detect the socket closure and ...
3.  Softly close the server socket that way

Unless somebody has any better ideas ...

G.
 

-Original Message-
From: [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED] On Behalf Of Darryl Miles
Sent: 15 August 2007 15:40
To: openssl-users@openssl.org
Subject: Re: Problem handling unexpected SSL shutdown

Shaw Graham George wrote:
 The sequence of events goes like this:
 
 1.  The SSL handshake proceeds as normal.
 2.  The client puts an HTTP request
 3.  The server gets the HTTP request
 4.  The client then executes an (unexpected) SSL shutdown 5.  The 
 server puts the HTTP response
 
 Here I might expect the put to fail, but all appears normal.
 
 6.  As an HTTP Keep-Alive request has been made, the server enters a 
 wait for the next read event.
 7.  The read event occurs (presumably due to the SSL shutdown), and 
 now the get fails.
 
 SSL_get_error() returns SSL_ERROR_SYSCALL (I would expect 
 SSL_ERROR_ZERO_RETURN for an SSL shutdown).
 ERR_get_error() returns 0.
 (SSL_get_shutdown()  SSL_RECEIVED_SHUTDOWN) returns 0.
 
 Is this the expected behaviour?
 
 What I am looking for is a way of identifying the shutdown at the 
 server, so that I can close the connection softly.

I.e. you dont want your Keep-Alive's hanging around when the other end
has gone.



The client will take one of these actions:
  * It will simply close the socket.  This can be picked up by your 
normal read() / write() failure scenarios.

  * It will write out a SSL shutdown notify packet, and then close the

connection anyway.  The server may or may not get the SSL shutdown 
notify packet due to send buffering, socket linger options, 
retransmission timeouts etc...  But at server end will either receive 
the SSL shutdown notify before the socket close or it will just see a 
socket close.  So again there is no special trickey here.

  * It will write out a SSL shutdown notify packet and wait for the 
acknowledgment from the server.  This is 100% graceful and conceptually 
correct way to finish things off.  To handle this your SSL_read() will 
signal a shutdown has been received (and from this point on no further 
SSL data will be received on that session that just closed).



 From seeing this you have a number of options at the server:

  * ACK the shutdown and issue your own shutdown (but only after you 
have finished writing all your application data with SSL_write()).  A 
HTTP client can often send the request and then shut the socket down, 
the server can observe this right after it pulled the request off to 
process it in another thread, this does not mean you want to shut the 
socket down at your end until you have processed that request and 
finished writing the Content body back the other way, only then should 
you take action in response to seeing the client's SSL shutdown
notify.

  * Once your SSL shutdown notify has hit the kernel write socket 
buffer, issue a TCP level shutdown(fd, SHUTDOWN_SEND).

  * Then wait to receive your shutdown ack or for the socket to 
close/timeout.  This wait does not have to be forever, I have an 
implementation that will allow the client socket a configurable amount 
of time to provide the SSL shutdown notify ACK back to me, if it does 
not happen within that time I close the socket.

  * Ultimately all this work leads to closing the socket.

If you implement everything above then your server is at least complying

with all the available mechanisms within SSL during the shutdown 
sequence.  I'm sure many implementations skip all the more complex 
points and jump right to the close the socket.



I don't fully see the problem with your code, nor the concern of having 
a solution that works on Unix and Win32 because most people in the 
situation you are in would put the socket into idle state but listening 
for more data (an active Keep-Alive idle list).

You will always get an event from listening for more data that will 
indicate the socket has been closed, or the socket has received a SSL 
shutdown notify request.  You won't miss it.


Here is a random fragment of my read code from Unix, it interests me if 
the there is a difference for Win32 but I would expect SSL_read() to 
return

Re: Problem handling unexpected SSL shutdown

2007-08-16 Thread Darryl Miles

Shaw Graham George wrote:

The problem is that, on Windows at least, my server doesn't appear to
get the SSL shutdown notify packet, for some reason.  So, if that is
to be expected, I'm looking for an alternative way of detecting the
closure.

I've now tested it on Linux, and the existing code works fine.  In other
words, when trying the SSL_Get:

SSL_read() ?


1.  It fails
2.  SSL_get_error() returns SSL_ERROR_ZERO_RETURN
3.  (SSL_get_shutdown()  SSL_RECEIVED_SHUTDOWN) is true

On Windows this is not the case.

But I guess if this problem is restricted to Windows, then I can:

1.  Add the call to WSAGetLastError() just for that platform
2.  Use it to detect the socket closure and ...
3.  Softly close the server socket that way

Unless somebody has any better ideas ...



Can you log the OpenSSL API calls you make and the return values you 
see.  When seeing any errors from OpenSSL don't forget the idiom's:


int err = SSL_get_error(client-ssl, n);
int wsa_errno = WSAGetLastError();

and log the values you see.  Please also include the OpenSSL API calls 
made just before the other end disappears.



This would clear up in my mind what you are observing :

 * You don't get the read-ready wakeup event from Win32 API ?  So you 
never get a chance to call SSL_read().


 * You don't see an error from SSL_read() ?  But what did it return 
instead ?


 * You never see '(SSL_get_shutdown()  SSL_RECEIVED_SHUTDOWN) is true' 
condition, even though you have written you own client and can confirm 
it does/will send a SSL shutdown notify packet, will ensure the data 
is flushed to the socket and will keep the socket open waiting to 
receive a SSL shutdown notify packet from the other end ?



If you get the read-ready wakeup event from Win32 API, then your code 
will end up calling SSL_read() and that call should attempt to process 
another packet and pull data from the socket as necessary until no more 
progress can be made at this time.  This will implicitly process the 
SSL shutdown notify packet.



Darryl
__
OpenSSL Project http://www.openssl.org
User Support Mailing Listopenssl-users@openssl.org
Automated List Manager   [EMAIL PROTECTED]


RE: Problem handling unexpected SSL shutdown

2007-08-16 Thread Shaw Graham George

Sure.

1.  The server receives the HTTP request, using SSL_read() and
SSL_pending().  The request contains a Keep-Alive request.
2.  The server writes the data out to another process.
3.  The server then it sits on an event handler that multiplexes a
select() (or Windows equivalent) on sockets it has an interest in, and
other events such as receiving data from other processes.  At this time
it actually has no interest in any events at the socket, as it is
waiting for the processing to complete.
4.  The SSL client lose patience with a lack of response, and does an
SSL shutdown and socket close.
5.  An event is detected, and the server receives the result from the
background processing.
6.  It adds write interest to the socket and goes back to sitting on the
event handler.
7.  An event is detected and the server then performs an SSL_write() to
the (non-existent) client, which is successful.
8.  It then adds read interest in the socket, as it is a Keep-Alive
socket, so it is waiting for the next HTTP request.  It goes back to
sitting on the event handler.
9.  An event is detected and the server then performs:

9a. SSL_read() which fails (return code is -1).
9b. SSL_get_error() which returns SSL_ERROR_SYSCALL.
9c. ERR_get_error() which returns 0.

In the original code SSL_get_shutdown() would not be called unless
SSL_get_error() returns SSL_ERROR_ZERO_RETURN, but I added an extra
debug call after the call to SSL_get_error(), and it did not show
SSL_RECEIVED_SHUTDOWN.

And I have now added a call to WSAGetLastError() after the call to
ERR_get_error(), and it returns WSAECONNABORTED.

So I do get a read event on the socket.  I do call SSL_read.  It fails.
But the shutdown is apparently not received, as:

a.  SSL_get_error() does not return SSL_ERROR_ZERO_RETURN
b.  SSL_get_shutdown() does not show SSL_RECEIVED_SHUTDOWN

I hope that's clear.

As I say, the code works fine on Linux.

G.


-Original Message-
From: [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED] On Behalf Of Darryl Miles
Sent: 16 August 2007 17:44
To: openssl-users@openssl.org
Subject: Re: Problem handling unexpected SSL shutdown

Shaw Graham George wrote:
 The problem is that, on Windows at least, my server doesn't appear to 
 get the SSL shutdown notify packet, for some reason.  So, if that is

 to be expected, I'm looking for an alternative way of detecting the 
 closure.
 
 I've now tested it on Linux, and the existing code works fine.  In 
 other words, when trying the SSL_Get:
SSL_read() ?
 
 1.  It fails
 2.  SSL_get_error() returns SSL_ERROR_ZERO_RETURN 3.  
 (SSL_get_shutdown()  SSL_RECEIVED_SHUTDOWN) is true
 
 On Windows this is not the case.
 
 But I guess if this problem is restricted to Windows, then I can:
 
 1.  Add the call to WSAGetLastError() just for that platform 2.  Use 
 it to detect the socket closure and ...
 3.  Softly close the server socket that way
 
 Unless somebody has any better ideas ...


Can you log the OpenSSL API calls you make and the return values you
see.  When seeing any errors from OpenSSL don't forget the idiom's:

int err = SSL_get_error(client-ssl, n); int wsa_errno =
WSAGetLastError();

and log the values you see.  Please also include the OpenSSL API calls
made just before the other end disappears.


This would clear up in my mind what you are observing :

  * You don't get the read-ready wakeup event from Win32 API ?  So you 
never get a chance to call SSL_read().

  * You don't see an error from SSL_read() ?  But what did it return 
instead ?

  * You never see '(SSL_get_shutdown()  SSL_RECEIVED_SHUTDOWN) is true'

condition, even though you have written you own client and can confirm 
it does/will send a SSL shutdown notify packet, will ensure the data 
is flushed to the socket and will keep the socket open waiting to 
receive a SSL shutdown notify packet from the other end ?


If you get the read-ready wakeup event from Win32 API, then your code 
will end up calling SSL_read() and that call should attempt to process 
another packet and pull data from the socket as necessary until no more 
progress can be made at this time.  This will implicitly process the 
SSL shutdown notify packet.


Darryl
__
OpenSSL Project http://www.openssl.org
User Support Mailing Listopenssl-users@openssl.org
Automated List Manager   [EMAIL PROTECTED]
__
OpenSSL Project http://www.openssl.org
User Support Mailing Listopenssl-users@openssl.org
Automated List Manager   [EMAIL PROTECTED]


Re: Problem handling unexpected SSL shutdown

2007-08-16 Thread Darryl Miles

Shaw Graham George wrote:

Sure.

1.  The server receives the HTTP request, using SSL_read() and
SSL_pending().  The request contains a Keep-Alive request.
2.  The server writes the data out to another process.
3.  The server then it sits on an event handler that multiplexes a
select() (or Windows equivalent) on sockets it has an interest in, and
other events such as receiving data from other processes.


What is the sleep/wakeup IO mechanism you are employing on windows ? 
WaitForMultipleObjects() ?


Side track: Is it possible to make the window platform listen on  31 
sockets at once per thread ?  (or whatever is small limit was)



 At this time
it actually has no interest in any events at the socket, as it is
waiting for the processing to complete.


I take this to mean you revoke all interest in the socket 
readability/writability.  So the server is no oblivious to what the 
client is doing.



4.  The SSL client lose patience with a lack of response, and does an
SSL shutdown and socket close.


Okay you closed your ears to the read event ?  On Unix the select() has 
an exceptfds which can be used to pickup a socket error/close (but may 
not be reliable if there is readable data first, since by convention of 
TCPs orderly shutdown that has to be eaten before the socket close can 
be seen).



5.  An event is detected, and the server receives the result from the
background processing.


I take this event to mean a read wakeup on channel facing the request 
processing process ?



6.  It adds write interest to the socket and goes back to sitting on the
event handler.
7.  An event is detected and the server then performs an SSL_write() to
the (non-existent) client, which is successful.


This write may succeed due to kernel buffering and the unread data still 
in the read buffer of the kernel until that is read the normal TCP 
shutdown/close condition may not be seen.  Or it may fail SSL_write() == 
-1  SSL_get_error() == SSL_ERROR_SYSCALL.


But the problem here is that your application is being single minded, in 
that it has shut its ears to processing more TCP level data (even tho 
the SSL protocol handling layer might require some read processing to 
take place, even during writes, but you cut of the SSL protocol layer's 
source of data).


I can understand why you do it, since you don't want the application to 
be holding onto data relating to the next pipelined request just yet as 
you have no intention on servicing it.


What you really wanted in this scenario is continue to observe read 
interest in the client TCP socket but use an SSL_peek() call.  I have 
called for this API call before, that is an OpenSSL API function that 
allows WANT_READ processing to take place but does not destructively 
return application data.


Since OpenSSL doesn't have a SSL_peek() call and your application could 
hold onto a small buffer of extraneous application data then it would be 
possible to over-read by one (before you drop read interest).  This 
would not detect the situation where the client wrote multiple requests 
to the server, waited a short time, then reverted to sending a SSL 
shutdown notify and closing the socket.


What you really wanted to know was out-of-band indication from the 
kernel that the client reset the connection.  Knowing that client had 
TCP send shutdown is not useful, only if a connection reset was known 
about before, which requires the client to have actually sent a TCP 
reset packet (which I think occurs in the situation you are in, due to 
the WSAGetLastError() == WSAECONNABORTED.




8.  It then adds read interest in the socket, as it is a Keep-Alive
socket, so it is waiting for the next HTTP request.  It goes back to
sitting on the event handler.



9.  An event is detected and the server then performs:

9a. SSL_read() which fails (return code is -1).
9b. SSL_get_error() which returns SSL_ERROR_SYSCALL.
9c. ERR_get_error() which returns 0.

In the original code SSL_get_shutdown() would not be called unless
SSL_get_error() returns SSL_ERROR_ZERO_RETURN, but I added an extra
debug call after the call to SSL_get_error(), and it did not show
SSL_RECEIVED_SHUTDOWN.

And I have now added a call to WSAGetLastError() after the call to
ERR_get_error(), and it returns WSAECONNABORTED.

So I do get a read event on the socket.  I do call SSL_read.  It fails.
But the shutdown is apparently not received, as:

a.  SSL_get_error() does not return SSL_ERROR_ZERO_RETURN
b.  SSL_get_shutdown() does not show SSL_RECEIVED_SHUTDOWN

I hope that's clear.


Okay knowing that WSAGetLastError() == WSAECONNABORTED as this time is 
irrelevant, since any SSL_read() == -1  SSL_get_error() == 
SSL_ERROR_SYSCALL would always be a sitution to cleanup and close the 
socket.  Since OpenSSL already processes the Winsock API error returns 
for WANT_READ and WANT_WRITE on non-blocking sockets itself.  Getting a 
SSL_ERROR_SYSCALL is not a recoverable situation.  Work through my code 
snippet to see exactly this 

RE: Problem handling unexpected SSL shutdown

2007-08-16 Thread David Schwartz

 Side track: Is it possible to make the window platform listen on  31
 sockets at once per thread ?  (or whatever is small limit was)

IOCP.

 Okay you closed your ears to the read event ?  On Unix the select() has
 an exceptfds which can be used to pickup a socket error/close (but may
 not be reliable if there is readable data first, since by convention of
 TCPs orderly shutdown that has to be eaten before the socket close can
 be seen).

Neither errors nor closes are 'select' exceptions. Perhaps you are thinking
of 'poll' and 'POLLERR'/'POLLHUP'?

DS


__
OpenSSL Project http://www.openssl.org
User Support Mailing Listopenssl-users@openssl.org
Automated List Manager   [EMAIL PROTECTED]


Problem handling unexpected SSL shutdown

2007-08-15 Thread Shaw Graham George
Hi,

We have an application that provides HTTPS, either as client or server,
for our customers.  At the moment I am doing some testing between our
client and our server, as a result of a problem with one of our
customers, and there is a particular sequence of events, that involves
an unexpected SSL shutdown, that is giving an unexpected behaviour (at
least to me).

The sequence of events goes like this:

1.  The SSL handshake proceeds as normal.
2.  The client puts an HTTP request
3.  The server gets the HTTP request
4.  The client then executes an (unexpected) SSL shutdown
5.  The server puts the HTTP response

Here I might expect the put to fail, but all appears normal.

6.  As an HTTP Keep-Alive request has been made, the server enters a
wait for the next read event.
7.  The read event occurs (presumably due to the SSL shutdown), and now
the get fails.

SSL_get_error() returns SSL_ERROR_SYSCALL (I would expect
SSL_ERROR_ZERO_RETURN for an SSL shutdown).
ERR_get_error() returns 0.
(SSL_get_shutdown()  SSL_RECEIVED_SHUTDOWN) returns 0.

Is this the expected behaviour?

What I am looking for is a way of identifying the shutdown at the
server, so that I can close the connection softly.

The version is 0.9.8e.  All sockets are non-blocking.  The test platform
is Windows - but our application runs on many platforms, I can test on
those as well if required.

Thanks in advance,

G.
__
OpenSSL Project http://www.openssl.org
User Support Mailing Listopenssl-users@openssl.org
Automated List Manager   [EMAIL PROTECTED]


RE: Problem handling unexpected SSL shutdown

2007-08-15 Thread Shaw Graham George

Some more information and thoughts.

I can replicate the server behaviour using openssl s_client, sending the
HTTP request, and then shutting down the client with a Q.

I'm wondering if the problem is that, once the HTTP request is received
by my server, then it has no read interest in the socket (as it now
wants to write the HTTP response).  So it will put the response whatever
the state of the socket.  Then maybe the put affects the state of the
socket, so that the shutdown state is no longer present.

So should I always have a read interest in the socket, in case of
shutdown?

Or should I check for a shutdown before actually doing the put?

But I would still have thought that the put should return an error if
the socket has been shutdown.

Thanks again,

G.
 

-Original Message-
From: [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED] On Behalf Of Shaw Graham George
Sent: 15 August 2007 11:38
To: openssl-users@openssl.org
Subject: Problem handling unexpected SSL shutdown

Hi,

We have an application that provides HTTPS, either as client or server,
for our customers.  At the moment I am doing some testing between our
client and our server, as a result of a problem with one of our
customers, and there is a particular sequence of events, that involves
an unexpected SSL shutdown, that is giving an unexpected behaviour (at
least to me).

The sequence of events goes like this:

1.  The SSL handshake proceeds as normal.
2.  The client puts an HTTP request
3.  The server gets the HTTP request
4.  The client then executes an (unexpected) SSL shutdown 5.  The server
puts the HTTP response

Here I might expect the put to fail, but all appears normal.

6.  As an HTTP Keep-Alive request has been made, the server enters a
wait for the next read event.
7.  The read event occurs (presumably due to the SSL shutdown), and now
the get fails.

SSL_get_error() returns SSL_ERROR_SYSCALL (I would expect
SSL_ERROR_ZERO_RETURN for an SSL shutdown).
ERR_get_error() returns 0.
(SSL_get_shutdown()  SSL_RECEIVED_SHUTDOWN) returns 0.

Is this the expected behaviour?

What I am looking for is a way of identifying the shutdown at the
server, so that I can close the connection softly.

The version is 0.9.8e.  All sockets are non-blocking.  The test platform
is Windows - but our application runs on many platforms, I can test on
those as well if required.

Thanks in advance,

G.
__
OpenSSL Project http://www.openssl.org
User Support Mailing Listopenssl-users@openssl.org
Automated List Manager   [EMAIL PROTECTED]
__
OpenSSL Project http://www.openssl.org
User Support Mailing Listopenssl-users@openssl.org
Automated List Manager   [EMAIL PROTECTED]


Re: Problem handling unexpected SSL shutdown

2007-08-15 Thread jimmy bahuleyan
Shaw Graham George wrote:
 Hi,
 
 We have an application that provides HTTPS, either as client or server,
 for our customers.  At the moment I am doing some testing between our
 client and our server, as a result of a problem with one of our
 customers, and there is a particular sequence of events, that involves
 an unexpected SSL shutdown, that is giving an unexpected behaviour (at
 least to me).
 
 The sequence of events goes like this:
 
 1.  The SSL handshake proceeds as normal.
 2.  The client puts an HTTP request
 3.  The server gets the HTTP request
 4.  The client then executes an (unexpected) SSL shutdown

Is this only a SSL_shutdown() or is SSL_shutdown() followed by a socket
close by the client?

Well if you had been listening for a read, both the SSL_shutdown and the
socket close are capable of generating read events in select()

If it was only a SSL_shutdown, i suppose you should be getting
SSL_ERROR_ZERO_RETURN. In the other case SSL_ERROR_SYSCALL with
errno=EPIPE seems possible.


 5.  The server puts the HTTP response
 
 Here I might expect the put to fail, but all appears normal.
 
 6.  As an HTTP Keep-Alive request has been made, the server enters a
 wait for the next read event.
 7.  The read event occurs (presumably due to the SSL shutdown), and now
 the get fails.
 
 SSL_get_error() returns SSL_ERROR_SYSCALL (I would expect

Did you check errno here?

 SSL_ERROR_ZERO_RETURN for an SSL shutdown).
 ERR_get_error() returns 0.
 (SSL_get_shutdown()  SSL_RECEIVED_SHUTDOWN) returns 0.
 
 Is this the expected behaviour?
 
 What I am looking for is a way of identifying the shutdown at the
 server, so that I can close the connection softly.
 
 The version is 0.9.8e.  All sockets are non-blocking.  The test platform
 is Windows - but our application runs on many platforms, I can test on
 those as well if required.
 
 Thanks in advance,
 
 G.

-jb
-- 
Tact is the art of making a point without making an enemy.
__
OpenSSL Project http://www.openssl.org
User Support Mailing Listopenssl-users@openssl.org
Automated List Manager   [EMAIL PROTECTED]


Re: Problem handling unexpected SSL shutdown

2007-08-15 Thread jimmy bahuleyan
jimmy bahuleyan wrote:
 Shaw Graham George wrote:
 Hi,

 We have an application that provides HTTPS, either as client or server,
 for our customers.  At the moment I am doing some testing between our
 client and our server, as a result of a problem with one of our
 customers, and there is a particular sequence of events, that involves
 an unexpected SSL shutdown, that is giving an unexpected behaviour (at
 least to me).

 The sequence of events goes like this:

 1.  The SSL handshake proceeds as normal.
 2.  The client puts an HTTP request
 3.  The server gets the HTTP request
 4.  The client then executes an (unexpected) SSL shutdown
 
 Is this only a SSL_shutdown() or is SSL_shutdown() followed by a socket
 close by the client?
 
 Well if you had been listening for a read, both the SSL_shutdown and the
 socket close are capable of generating read events in select()
 
 If it was only a SSL_shutdown, i suppose you should be getting
 SSL_ERROR_ZERO_RETURN. In the other case SSL_ERROR_SYSCALL with
 errno=EPIPE seems possible.
 
 
 5.  The server puts the HTTP response

 Here I might expect the put to fail, but all appears normal.

 6.  As an HTTP Keep-Alive request has been made, the server enters a
 wait for the next read event.
 7.  The read event occurs (presumably due to the SSL shutdown), and now
 the get fails.

 SSL_get_error() returns SSL_ERROR_SYSCALL (I would expect
 
 Did you check errno here?

i mean WSAGetLastError() or whatever.

-jb
-- 
Tact is the art of making a point without making an enemy.
__
OpenSSL Project http://www.openssl.org
User Support Mailing Listopenssl-users@openssl.org
Automated List Manager   [EMAIL PROTECTED]


RE: Problem handling unexpected SSL shutdown

2007-08-15 Thread Shaw Graham George
Hi,

More information.

Before the server put:

(SSL_get_shutdown()  SSL_RECEIVED_SHUTDOWN) returns 0.

... so that's of no use.

After the server get:

errno returns 0.
WSAGetLastError() returns WSAECONNABORTED.

That's one step forward, maybe.  But my code must work for all supported
platforms, so I need to find a solution that will work on UNIX as well.

I guess I should make a test on UNIX to see if the same problem occurs,
or if this is a Windows-specific problem.

G.


-Original Message-
From: [EMAIL PROTECTED]
[mailto:[EMAIL PROTECTED] On Behalf Of jimmy bahuleyan
Sent: 15 August 2007 14:01
To: openssl-users@openssl.org
Subject: Re: Problem handling unexpected SSL shutdown

jimmy bahuleyan wrote:
 Shaw Graham George wrote:
 Hi,

 We have an application that provides HTTPS, either as client or 
 server, for our customers.  At the moment I am doing some testing 
 between our client and our server, as a result of a problem with one 
 of our customers, and there is a particular sequence of events, that 
 involves an unexpected SSL shutdown, that is giving an unexpected 
 behaviour (at least to me).

 The sequence of events goes like this:

 1.  The SSL handshake proceeds as normal.
 2.  The client puts an HTTP request
 3.  The server gets the HTTP request
 4.  The client then executes an (unexpected) SSL shutdown
 
 Is this only a SSL_shutdown() or is SSL_shutdown() followed by a 
 socket close by the client?
 
 Well if you had been listening for a read, both the SSL_shutdown and 
 the socket close are capable of generating read events in select()
 
 If it was only a SSL_shutdown, i suppose you should be getting 
 SSL_ERROR_ZERO_RETURN. In the other case SSL_ERROR_SYSCALL with 
 errno=EPIPE seems possible.
 
 
 5.  The server puts the HTTP response

 Here I might expect the put to fail, but all appears normal.

 6.  As an HTTP Keep-Alive request has been made, the server enters a 
 wait for the next read event.
 7.  The read event occurs (presumably due to the SSL shutdown), and 
 now the get fails.

 SSL_get_error() returns SSL_ERROR_SYSCALL (I would expect
 
 Did you check errno here?

i mean WSAGetLastError() or whatever.

-jb
--
Tact is the art of making a point without making an enemy.
__
OpenSSL Project http://www.openssl.org
User Support Mailing Listopenssl-users@openssl.org
Automated List Manager   [EMAIL PROTECTED]
__
OpenSSL Project http://www.openssl.org
User Support Mailing Listopenssl-users@openssl.org
Automated List Manager   [EMAIL PROTECTED]


Re: Problem handling unexpected SSL shutdown

2007-08-15 Thread Darryl Miles

Shaw Graham George wrote:

The sequence of events goes like this:

1.  The SSL handshake proceeds as normal.
2.  The client puts an HTTP request
3.  The server gets the HTTP request
4.  The client then executes an (unexpected) SSL shutdown
5.  The server puts the HTTP response

Here I might expect the put to fail, but all appears normal.

6.  As an HTTP Keep-Alive request has been made, the server enters a
wait for the next read event.
7.  The read event occurs (presumably due to the SSL shutdown), and now
the get fails.

SSL_get_error() returns SSL_ERROR_SYSCALL (I would expect
SSL_ERROR_ZERO_RETURN for an SSL shutdown).
ERR_get_error() returns 0.
(SSL_get_shutdown()  SSL_RECEIVED_SHUTDOWN) returns 0.

Is this the expected behaviour?

What I am looking for is a way of identifying the shutdown at the
server, so that I can close the connection softly.


I.e. you dont want your Keep-Alive's hanging around when the other end 
has gone.




The client will take one of these actions:
 * It will simply close the socket.  This can be picked up by your 
normal read() / write() failure scenarios.


 * It will write out a SSL shutdown notify packet, and then close the 
connection anyway.  The server may or may not get the SSL shutdown 
notify packet due to send buffering, socket linger options, 
retransmission timeouts etc...  But at server end will either receive 
the SSL shutdown notify before the socket close or it will just see a 
socket close.  So again there is no special trickey here.


 * It will write out a SSL shutdown notify packet and wait for the 
acknowledgment from the server.  This is 100% graceful and conceptually 
correct way to finish things off.  To handle this your SSL_read() will 
signal a shutdown has been received (and from this point on no further 
SSL data will be received on that session that just closed).




From seeing this you have a number of options at the server:

 * ACK the shutdown and issue your own shutdown (but only after you 
have finished writing all your application data with SSL_write()).  A 
HTTP client can often send the request and then shut the socket down, 
the server can observe this right after it pulled the request off to 
process it in another thread, this does not mean you want to shut the 
socket down at your end until you have processed that request and 
finished writing the Content body back the other way, only then should 
you take action in response to seeing the client's SSL shutdown notify.


 * Once your SSL shutdown notify has hit the kernel write socket 
buffer, issue a TCP level shutdown(fd, SHUTDOWN_SEND).


 * Then wait to receive your shutdown ack or for the socket to 
close/timeout.  This wait does not have to be forever, I have an 
implementation that will allow the client socket a configurable amount 
of time to provide the SSL shutdown notify ACK back to me, if it does 
not happen within that time I close the socket.


 * Ultimately all this work leads to closing the socket.

If you implement everything above then your server is at least complying 
with all the available mechanisms within SSL during the shutdown 
sequence.  I'm sure many implementations skip all the more complex 
points and jump right to the close the socket.




I don't fully see the problem with your code, nor the concern of having 
a solution that works on Unix and Win32 because most people in the 
situation you are in would put the socket into idle state but listening 
for more data (an active Keep-Alive idle list).


You will always get an event from listening for more data that will 
indicate the socket has been closed, or the socket has received a SSL 
shutdown notify request.  You won't miss it.



Here is a random fragment of my read code from Unix, it interests me if 
the there is a difference for Win32 but I would expect SSL_read() to 
return  0, when you can do your WSAGetLastError() returns 
WSAECONNABORTED to see why.


int n = SSL_read(client-ssl, buffer, sizeof(buffer));

if(n  0) {
  int err = SSL_get_error(client-ssl, n);
  switch(err) {
  case SSL_ERROR_WANT_READ:
... // put the 'fd' on the read interested list
break;
  case SSL_ERROR_WANT_WRITE:
... // put the 'fd' on the write interested list
break;
  case SSL_ERROR_ZERO_RETURN:
... // peer change their mind on connecting to us
// unrecoverable error so cleanup
break;
  case SSL_ERROR__WHATEVER:
... // unrecoverable error so cleanup
break;
  default:
... // unrecoverable error so cleanup
// This is where I'd expect you to put your:
//  int wsa_errno = WSAGetLastError()
// if you really want to know the exact cause of the error,
//  but the corrective action by the application at this
//  point is all the same (no matter what WSAGetLastError()
//  actually is.
break;
  }
} else if(n == 0) {
  if((SSL_get_shutdown(client-ssl)  SSL_RECEIVED_SHUTDOWN) != 0) {
/* recv_shutdown_notify */
// Peer signalled he is not going to send