Thanks Bodo for taking the time to reply.
On Fri, 17 Dec 1999, Bodo Moeller wrote:
> On Mon, Nov 08, 1999 at 08:18:09PM +0000, Geoff Thorpe wrote:
>
> [...]
> > I'm getting extremely weird reference counts on SSLs and BIOs as below -
> > this is happening with 0_9_4 and with a recent snapshot of 0_9_5.
> >
> > (1) I create two BIOs, a read (bio_read) and write (bio_write) that are
> > both BIO_s_mem()s, an SSL bio (bio_ssl), and an SSL object (ssl). At this
> > point they all have reference count 1. Ie. in crude ASCII-art form;
> >
> > +-----+ <--- bio_read
> > bio_ssl <---> | ssl |
> > +-----+ ---> bio_write
> >
> > (2) I add set the read and write BIOs to "ssl" with
> > SSL_set_bio(ssl, bio_read, bio_write). This does not change the
> > reference count on anything (everything remains at 1). I'd have expected
> > this to up the reference count on bio_read and bio_write.
>
> The idea is that you hand those BIOs over to the SSL library, you
> usually don't keep pointers of your own. SSL_free(ssl) will call
> BIO_free for each of them, but just once if bio_read == bio_write, so
> usually everything works as intended. Obviously this is not the
> cleanest interface conceivable ...
Well as I mentioned repeatedly on the SSL_SESSION discussion a while back,
"the idea is that ..." seems to be common justification for deliberate and
lazy inconsistency, both from the point of view of the library design, and
from the point of view of library-usage. In this case I think the
programmer(s) just wanted to "throw the BIOs into the SSL and forget about
them" ... ie. why free your reference when you can just pass it over to
another structure and forget about your references? Whilst this "works" it
makes a mockery of the so-called "reference counting mechanism" and leaves
programmers constantly in a quandry as how to correctly manage references
- and occasionally how to avoid race-conditions too!
> > (3) When I call SSL_free(ssl) later, it causes the reference counts for
> > all of ssl, bio_read and bio_write to be decremented. This is inconsistent
> > with (2) but seems the right way to operate.
>
> This description is not quite accurate because BIO_free is called only
> once if bio_read and bio_write are the same. So if we were to add a
> variant of SSL_set_bio that increases the reference counts of
> bio_read and bio_write it should add just one for consistency with the
> existing interface.
In this case I was using memory BIOs because I already had a well-formed
networking "engine" (non-blocking) and frankly didn't want to work around
it and leave OpenSSL's socket handling in control. So the BIOs at all ends
of this diagram were part of a "memory BIO sandbox" which I was in turn
reading and writing to with my networking code. So the read and write BIOs
on the encrypted end of the BIO were not the same.
> > (4) When I call BIO_set_ssl(bio_ssl, ssl, ...) it cause an increment in
> > ONLY the reference count of bio_read - this is the weirdest of all. I
> > would expect this to cause ssl, bio_read AND bio_write to all get
> > incremented but it only increments bio_read.
>
> This time the SSL is handed over to the BIO. There is no need to
> increase the reference counts of bio_read and bio_write for this
> because no new pointers to them are created; but bio_read is chained
This is a by-product of the reference counting ambiguities ... your point
assumes that we "hand the SSL over to the BIO" - ie we simply forget
about our SSL reference so we can't operate on that SSL reference
independantly of the ssl BIO. If the reference counting were consistent
we could operate on them both, including freeing both of them in any
particular order and all things would be cleaned up as appropriate.
"handing over" references and such cutting of corners leads to these
inflexibilities in the way these objects/structures can be used.
> to bio_ssl at the "next_bio" pointer, which leads to the extra
> reference count. It's not clear what this is accomplishes except
> confusing people, maybe the intention is that some general BIO control
> codes would have to be forwarded down the chain (thus ignoring
> bio_write if you don't use the same BIO for both direction). If you
> keep only the bio_ssl pointer, BIO_free_all will free everything
> (bio_read will be freed twice because it's also at the next_bio
> pointer, so its reference count goes down to zero).
But I don't want to "keep only the bio_ssl pointer" ... for one thing,
once that handshake is complete I want to examine the session negotiated,
grab the peer certificate (both of which reveal further reference counting
anomalies but that's another soap-box), and possibly other SSL things that
have nothing to do with the BIO which is simply an IO device. Yet again, I
reiterate - if the reference counting was consistent I would be free to
use all "objects" with the references I created (or obtained via a _get_
call) and the connections between all these objects would also be
accounted for in the reference counts so that I can use and free objects
as and when I choose.
> > (5) Calling BIO_free(bio_ssl) decrements the reference counts for all of
> > ssl, bio_read, and bio_write. This is reasonable but inconsistent with (4)
> > and pretty much everything else.
>
> That's why the comment in bio.h says "WARNING WARNING ... make sure
> you are doing a BIO_free_all()" since SSLeay 0.9.0b. BIO_free_all
> follows the next_bio chain, BIO_free does not; I'm not sure if
> BIO_free has any use at all except when you are sure that that
> next_bio == NULL in which case both functions do the same anyway.
Hardly bodes well when one has to sift through the .h file to discover API
design comments that themselves admit to being a tad obscure and, even
after finding and reading, leaves us in some doubt as to how things work
and what the point is.
C'est la vie,
Geoff
----------------------------------------------------------------------
Geoff Thorpe Email: [EMAIL PROTECTED]
Cryptographic Software Engineer, C2Net Europe http://www.int.c2.net
----------------------------------------------------------------------
"It is wrong always, everywhere, and for everyone, to believe
anything upon insufficient evidence." - William James
______________________________________________________________________
OpenSSL Project http://www.openssl.org
Development Mailing List [EMAIL PROTECTED]
Automated List Manager [EMAIL PROTECTED]