David Schwartz wrote:
What return value makes sense with your model? If it says it sent
everything, you will not call into SSL again unless you have something to
write or expect to read something. If neither is the case, when will OpenSSL
get the chance to send those C bytes left over?

If the SSL implementation works in this way then trying to shoe-horn SSL into a similar 3 argument API as the kernel was a bad design decision.

int SSL_write(SSL *ssl, const void  *buf, int buflen, int *committedlenptr);

If you stand back from the problem a minute its easy to see there are 2 things that should be returned with a successful operation: * The amount of data from the original application buffer that was committed. i.e. there is no need for the application to represent this data and any bytes beyond this maybe changed for the next call. So committedlenptr would always be set to something between 0 and buflen. * The status of the flush operation to the next layer down, passed as the return value (and through the SSL_get_error() mechanism). Which would retain the error of WANT_WRITE or return the entire length presented in buflen.


Additional to the above an API call (pick your choice of naming) SSL_write_{has_pending,needs_flush}(SSL *) to return a boolean state of if there is anything to be flushed.

Then making the call SSL_write(ssl, NULL, 0, NULL) a valid call which would simply flush the left over data but not commit any new application data. It would return a new error SSL_ERROR_FLUSHED (or reuse SSL_ERROR_NONE) when there was no more data to be flushed. It would retain the WANT_WRITE error when there is data. This would allow the write machinery to be serviced. This call could also be used in situations where your peer decided it wanted to renegotiate and you implicit response was sent.


Think of the above as the direct opposite of SSL_peek(SSL *ssl, void *buf, int buflen)

Its probably a bit late in the game to go changing the SSL_write() call so maybe SSL_write_foobar() could be implemented over the top of the existing protocol infrastructure.


The problem of partial writes seen from an application are much less of a headache than this witch-craft and voodoo of MOVING_WRITE_BUFFERS and working with the requirement of having to represent the same data (with no adequate quality/test mechanism to ensure the API user is complying with this requirement). What I mean by this is that its possible for someone to write a seemingly well behaved application but it fails rarely under load with no specific reason given.

It would make sense to store the previous write address, the previous length and checksum the previous data and validate all these things in a debugging build of OpenSSL so that no application designer could get away with misusing the API because OpenSSL validates the usage rules. This way the error is given at the point when the error was made not at some unspecified point in time later.


This is not rocket science the problem with the existing design is simply down to poor choices, probably seemed right at the time but for a general purpose library fraught with danger.


Darryl

______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
Development Mailing List                       [email protected]
Automated List Manager                           [EMAIL PROTECTED]

Reply via email to