Rajeswari K wrote:
In our application we open "non blocking socket" for read and write
operation and pass the  fd to openssl through BOI API's like this

bio = BIO_new(BIO_s_socket());
BIO_set_fd(bio, socket_fd, BIO_NOCLOSE);
And
we update this bio to SSL using SSL_set_bio() function.

My query is do we need to update SSL_CTX with these modes when we use
"non blocking sockets"?

SSL_CTX_set_mode(ctx, SSL_MODE_ENABLE_PARTIAL_WRITE);

SSL_CTX_set_mode(ctx, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);


Or without setting this also non blocking sockets work?


If you want belt and braces approach then set both of these flags, since setting them will not cause any observable effect that you don't already deal with(*) and will provide peace of mind over the question.

NOTE(*) non-blocking already deals with partial write concerns, which you may see if you are trying to send large enough buffers (around >16Mb/>32Mb)



Did you research this already ?

http://markmail.org/message/coiqiqkuim3k4ys5   [read the whole thread]

Obviously the emails above relate to the version of OpenSSL at the time.



Basically the purpose of SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER is more folklore than any practical purpose.

I would be grateful if someone can counter my statement above by citing where openssl changes behaviour (somewhere other than the self-serving error return, explained below) based on SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER being set/not-set.



Naive proof of my claim (along with some details of why) :



[openssl-1.0.1f]$ find -type f -exec fgrep -Hn "ACCEPT_MOVING_WRITE_BUFFER" {} \;

./CHANGES:8746: SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER Don't insist that SSL_write ./ssl/s2_pkt.c:478: !(s->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER)))
./ssl/ssl.h:637:#define SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER 0x00000002L
./ssl/s3_pkt.c:868: !(s->mode & SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER))
./doc/ssl/SSL_CTX_set_mode.pod:44:=item SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER

If you take a look at the *.c code, there is a self-serving check there.

When you don't set this flag you might get an error, when you do set this flag you never get the error.

Now the challenge is to find the line of code that actively does something different when the SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER flag is changed (other than the lines I point out above).

It is possible there is a magic number check for s->mode somewhere in the code. If there is such a thing this code should be changed (to use macro as value!) and better documented, by using SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER instead of the magic number 0x00000002L.

Otherwise all applications should set SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER and the true purpose of this flag is to "suppress the self-serving error check".

My claim is there is no other active purpose of this flag.

This would mean the lines I point out above can be safely removed from the OpenSSL project. Removing the *.h macro definition will break peoples code so I guess in another 15 years a new major release might be rolled to do this.



[openssl-1.0.1f]$ find -type f -exec fgrep -Hn "ENABLE_PARTIAL_WRITE" {} \;

./demos/easy_tls/easy-tls.c:667: SSL_CTX_set_mode(ret, SSL_MODE_ENABLE_PARTIAL_WRITE); ./CHANGES:8744: SSL_MODE_ENABLE_PARTIAL_WRITE Allow SSL_write to report success when ./ssl/s2_pkt.c:458: (s->mode & SSL_MODE_ENABLE_PARTIAL_WRITE))
./ssl/ssl.h:632:#define SSL_MODE_ENABLE_PARTIAL_WRITE       0x00000001L
./ssl/s3_pkt.c:618: (s->mode & SSL_MODE_ENABLE_PARTIAL_WRITE))) ./doc/ssl/SSL_write.pod:53:can be changed with the SSL_MODE_ENABLE_PARTIAL_WRITE option of
./doc/ssl/SSL_CTX_set_mode.pod:35:=item SSL_MODE_ENABLE_PARTIAL_WRITE

This one is more tricky to understand why it is also a nonsense feature the SSL_MODE_ENABLE_PARTIAL_WRITE only makes sense for blocking sockets.

With non-blocking socket the do_ssl3_write() call that takes place will return -1/WANT_WRITE and cause immediate return, or it will take an amount of data presented to it that maybe clipped by the s->max_send_fragment size.

Non-blocking I/O accepts that partial writes are normal when flow control is engaged stopping data from being pushed down to lower layers.


But with a blocking socket, it is possible for the kernel (or lower level BIO) to accept a smaller amount of data out of some larger size presented to write. The first attempt to write to the blocking socket will block. (for an indeterminate amount of time - the definition of blocking).

This is kind of an instruction to flush some more data, but only give the lower layer one chance to take what it can, then return control back to caller. But this chance has the right to block.

This feature serves no obvious (to me at least!) useful purpose.


An application programmer either wants non-blocking or is happy to block until the entire write being performed is complete.

Why would a programmer want blocking with partial write ? This feature is nonsense. Blocking partial writes only make sense when the application programmer can control how long the API call will block for by passing a timeout value. Now that would be a useful feature with practical purpose.


Note also that SSL uses chunking, it is not possible to send huge (>32Mb) writes as one fragment (by the protocol size/record length limitations).

So another caveat of turning it on might be that if you are sending huge writes you observe each write you may hit maximum SSL record length limits and return control back to the application.

Again this is not a useful feature but something that maybe observable if you watch closely.



HTH

--
Darryl




______________________________________________________________________
OpenSSL Project                                 http://www.openssl.org
User Support Mailing List                    openssl-users@openssl.org
Automated List Manager                           majord...@openssl.org

Reply via email to