Thread: A successor for PQgetssl

A successor for PQgetssl

From
Martijn van Oosterhout
Date:
There was some discussion about the issues relating to using other SSL
libraries. In a nutshell, it came down to that we couldn't return
anything other than an OpenSSL pointer from PQgetssl because existing
programs simply wouldn't know what to do with it.

So, I was pondering what we might want from an alternative. What I've
come up with is the following:

PGresult *PQgettlsinfo(PGconn *conn);

What it does instead of returning a single pointer is return a PGresult
that has various info depending on the library involved. For example,
if you connected using a libpq compiled with GnuTLS it would contain
the following:
        key         |                 value
---------------------+---------------------------------------tls_library         | GnuTLStls_library_version |
1.0.16tls_sslmode        | prefertls_active          | yestls_verify_server   | yestls_peerdn          |
C=AU,ST=NSW,L=Sydney,O=Home,CN=Myselftls_peercn         | Myselftls_protocol        | TLS 1.0tls_cipher          | AES
256CBCtls_keysize         | 256 bitstls_kx              | DHE RSAtls_mac             | SHAtls_compression     |
NULLtls_certtype       | X.509 
(14 rows)

And when you connected with OpenSSL you would get something like:
        key         |                 value
---------------------+----------------------------------------tls_library         | OpenSSLtls_library_version |
OpenSSL0.9.7e 25 Oct 2004tls_sslmode         | prefertls_active          | yestls_peerdn          |
/C=AU/ST=NSW/L=Sydney/O=Home/CN=Myselftls_peercn         | Myselftls_cipher          | DHE-RSA-AES256-SHAtls_protocol
    | TLSv1/SSLv3tls_keysize         | 256 bits 
(9 rows)

Now, other than for the first time giving users access to the
information like peer DN and CN, it also provides some other
information they might want. And it's done in a way that's extensible.

Do people like this idea?

Note, I don't return a pointer to the GnuTLS session anywhere. I think
that's a bad idea all round and we need to provide another way for
programs to acheive the same effect.

The thing is, it could be extended to include almost anything. One
example would be if the user authenticated using kerberos, we could add
a few rows indicating that. I suppose you would call it
PQgetconninfo().

Thoughts?

*** PostgreSQL with GnuTLS

I've got it almost completely working and have tested interoperability.
You can find it here:

http://svana.org/kleptog/temp/gnutls.patch

The patch does the following:

- Adds configure stuff for gnutls so it checks for the libraries when
you specify --with-gnutls. You may need to run autoconf and autoheader
after patching.

- Both fe-secure.c and be-secure.c have been made TLS library agnostic.
They only refer to functions that implement TLS specific stuff which
are implemented in the files:

src/interfaces/libpq/fe-secure-openssl.c
src/interfaces/libpq/fe-secure-gnutls.c
src/backend/libpq/be-secure-openssl.c
src/backend/libpq/be-secure-gnutls.c

The makefile determines which (if either) is linked in.

- Implements the PQgettlsinfo() as described above and alters psql to
use it. Hence psql is now also TLS library agnostic.

Differences between the two implementations are:

- GnuTLS generates the DH key on the fly on server start, which takes a
few seconds. The OpenSSL versions use hardcoded keys which can be
overridden by the user. Not sure which is best here.

- This breaks psqlODBC when it uses libpq because it wants to use OpenSSL
and when libpq is compiled with GnuTLS that obviously won't work.
Recent thread on -hackers found no resolution for this problem.

- Both support authentication of the server and authentication of the
client, though more testing is need to test all the different
combinations of keys and certificates that are allowed.

- Different output for PQgettlsinfo()

That about it. There's no real difference from the users point of view,
it Just Works either way. In the future we may be able to use the PGP
support in GnuTLS. In other words, provide the server with a pgp
keyring and it accepts any user which a matching key in the keyring.

I hope to post of -patches sometime soon, once some of the kinks have
been ironed out.

Have a nice day,
--
Martijn van Oosterhout   <kleptog@svana.org>   http://svana.org/kleptog/
> Patent. n. Genius is 5% inspiration and 95% perspiration. A patent is a
> tool for doing 5% of the work and then sitting around waiting for someone
> else to do the other 95% so you can sue them.

Re: A successor for PQgetssl

From
Tom Lane
Date:
Martijn van Oosterhout <kleptog@svana.org> writes:
> Do people like this idea?

Not really ...

> Note, I don't return a pointer to the GnuTLS session anywhere. I think
> that's a bad idea all round and we need to provide another way for
> programs to acheive the same effect.

No, failing to provide that is the bad idea, because then you're buying
into the notion that libpq will provide a universal API that will
incorporate anything anyone could possibly want to do with the
underlying SSL library.  The above is *not* that, prima facie because
it is read-only access.  Even if this was a feasible goal, it would absorb
a lot of time on our part that could be better spent elsewhere, plus a
lot of time on the part of app programmers rewriting existing
OpenSSL-aware or GnuTLS-aware code to instead use whatever random API we
tell them they ought to use.  They have better things to do with their
time, too.

> I've got it almost completely working and have tested interoperability.
> ...
> - This breaks psqlODBC when it uses libpq because it wants to use OpenSSL
> and when libpq is compiled with GnuTLS that obviously won't work.

That alone is sufficient reason why we're not going down that path.
If we expose a GnuTLS-handle-fetching API then it's up to the ODBC
guys to extend their code to handle that SSL library when they feel
like it.  But telling them that we're simply going to break their
code and not provide them a path to fix it is not happening.
        regards, tom lane


Re: A successor for PQgetssl

From
Martijn van Oosterhout
Date:
On Sun, Apr 16, 2006 at 05:29:04PM -0400, Tom Lane wrote:
> No, failing to provide that is the bad idea, because then you're buying
> into the notion that libpq will provide a universal API that will
> incorporate anything anyone could possibly want to do with the
> underlying SSL library.  The above is *not* that, prima facie because
> it is read-only access.  Even if this was a feasible goal, it would absorb

The intention is not to provide access to everything. If people want to
know more about the certificate, we simply export the certificate to
them and they can do with it what they like, including sending it to
another program. I wasn't expecting that list to grow much because
there's not much to export.

Besides, what's wrong with read-only access? What parameters were you
expecting them to want to change? After a session is setup there are no
parameters to change anymore. All you need is read and write.

> a lot of time on our part that could be better spent elsewhere, plus a
> lot of time on the part of app programmers rewriting existing
> OpenSSL-aware or GnuTLS-aware code to instead use whatever random API we
> tell them they ought to use.  They have better things to do with their
> time, too.

The whole point is that app writers should not be aware at all which
library we're using. At the moment psqlODBC requires openssl because we
force them to. They only use three OpenSSL functions, SSL_read,
SSL_write, and SSL_get_error.

If we provided a hook to allow people read/write directly, they
wouldn't need to know about the SSL connection at all. I think that's a
much better way to go than adding a new library specific function for
every little feature we add.

You objected to this on the grounds of a problem with the COPY
functions, except I can't see any problem that's relevent. The problem
with copy was that data didn't have a length. Given the user is sending
their own packets, we always have a length.

> > - This breaks psqlODBC when it uses libpq because it wants to use OpenSSL
> > and when libpq is compiled with GnuTLS that obviously won't work.
>
> That alone is sufficient reason why we're not going down that path.
> If we expose a GnuTLS-handle-fetching API then it's up to the ODBC
> guys to extend their code to handle that SSL library when they feel
> like it.  But telling them that we're simply going to break their
> code and not provide them a path to fix it is not happening.

By going down this path you're saying that psql will never be able
display the cipher of an SSL connection if the libpq was compiled with
a different library. If we provide a read/write than psqlODBC can
remove code and it will work with GnuTLS. Isn't that much better?

Have a nice day,
--
Martijn van Oosterhout   <kleptog@svana.org>   http://svana.org/kleptog/
> Patent. n. Genius is 5% inspiration and 95% perspiration. A patent is a
> tool for doing 5% of the work and then sitting around waiting for someone
> else to do the other 95% so you can sue them.

Re: A successor for PQgetssl

From
Tom Lane
Date:
Martijn van Oosterhout <kleptog@svana.org> writes:
> On Sun, Apr 16, 2006 at 05:29:04PM -0400, Tom Lane wrote:
>> No, failing to provide that is the bad idea, because then you're buying
>> into the notion that libpq will provide a universal API that will
>> incorporate anything anyone could possibly want to do with the
>> underlying SSL library. ...
> [ snip ]
> Besides, what's wrong with read-only access?

Well, psqlODBC seems a sufficient counterexample.  But the problem
with this is that you're asking a bunch of non-SSL-experts to design,
evaluate, and then maintain an API for an SSL library.  The real
answer to the above is "I don't know, and I doubt you do either."
This is the sort of problem that we should be avoiding, rather than
going out of our way to get involved in.  PQgetssl made it possible
for us to stay out of the way for SSL-using applications, and I think
we should continue to follow that philosophy for other SSL libraries.
        regards, tom lane


Re: A successor for PQgetssl

From
Stephen Frost
Date:
* Martijn van Oosterhout (kleptog@svana.org) wrote:
> The intention is not to provide access to everything. If people want to
> know more about the certificate, we simply export the certificate to
> them and they can do with it what they like, including sending it to
> another program. I wasn't expecting that list to grow much because
> there's not much to export.
>
> Besides, what's wrong with read-only access? What parameters were you
> expecting them to want to change? After a session is setup there are no
> parameters to change anymore. All you need is read and write.

I have to agree with this...  Certificate handling isn't growing new
things in leaps and bounds these days and as long as the certificates
are available to the user then the other things are really just
nicities for people who don't want to decode the certs themselves.

> > a lot of time on our part that could be better spent elsewhere, plus a
> > lot of time on the part of app programmers rewriting existing
> > OpenSSL-aware or GnuTLS-aware code to instead use whatever random API we
> > tell them they ought to use.  They have better things to do with their
> > time, too.
>
> The whole point is that app writers should not be aware at all which
> library we're using. At the moment psqlODBC requires openssl because we
> force them to. They only use three OpenSSL functions, SSL_read,
> SSL_write, and SSL_get_error.
>
> If we provided a hook to allow people read/write directly, they
> wouldn't need to know about the SSL connection at all. I think that's a
> much better way to go than adding a new library specific function for
> every little feature we add.

I have to agree with Martijn here too.  It's not all that expensive to
provide read/write calls to abstract away the specific library being
used (since psqlODBC, at least, couldn't care less which library is
being used, really) rather than ask for application developers to write
their apps to support multiple SSL libraries to handle the case where
libpq is compiled with one library vs. compiled with another...

> > > - This breaks psqlODBC when it uses libpq because it wants to use OpenSSL
> > > and when libpq is compiled with GnuTLS that obviously won't work.
> >
> > That alone is sufficient reason why we're not going down that path.
> > If we expose a GnuTLS-handle-fetching API then it's up to the ODBC
> > guys to extend their code to handle that SSL library when they feel
> > like it.  But telling them that we're simply going to break their
> > code and not provide them a path to fix it is not happening.
>
> By going down this path you're saying that psql will never be able
> display the cipher of an SSL connection if the libpq was compiled with
> a different library. If we provide a read/write than psqlODBC can
> remove code and it will work with GnuTLS. Isn't that much better?

I didn't really understand Tom's point here either...  In order to not
break psqlODBC when libpq is compiled with GnuTLS we'd have to code up
support for returning an SSL* from the GnuTLS library that would work
for all the OpenSSL functions which just isn't going to happen...  I
agree that we probably shouldn't go out of our way to break psqlODBC
when libpq is compiled with OpenSSL (and so we shouldn't really change
PQgetssl but mark it obsolete and ask that people don't use it and
provide some other way for psqlODBC to do what it wants, or not, perhaps
return NULL when using GnuTLS or '0x1', or not define it when libpq is
compiled with GnuTLS...).
Thanks,
    Stephen

Re: A successor for PQgetssl

From
Tom Lane
Date:
Stephen Frost <sfrost@snowman.net> writes:
> I have to agree with Martijn here too.  It's not all that expensive to
> provide read/write calls to abstract away the specific library being
> used (since psqlODBC, at least, couldn't care less which library is
> being used, really)

You're failing to consider async applications.  AFAICS, the *minimum*
API would bereadwriteread ready?write ready?get socket so I can use it in select()
(very possibly there's some stuff I missed, considering I haven't
consumed any caffeine yet today...).  And that's just considering
the data transport aspect of it.  I'm still concerned that SSL-using
apps may wish to twiddle the SSL library in ways we don't even know
about.
        regards, tom lane


Re: A successor for PQgetssl

From
Martijn van Oosterhout
Date:
On Mon, Apr 17, 2006 at 11:07:26AM -0400, Stephen Frost wrote:
> I didn't really understand Tom's point here either...  In order to not
> break psqlODBC when libpq is compiled with GnuTLS we'd have to code up
> support for returning an SSL* from the GnuTLS library that would work
> for all the OpenSSL functions which just isn't going to happen...  I
> agree that we probably shouldn't go out of our way to break psqlODBC
> when libpq is compiled with OpenSSL (and so we shouldn't really change
> PQgetssl but mark it obsolete and ask that people don't use it and
> provide some other way for psqlODBC to do what it wants, or not, perhaps
> return NULL when using GnuTLS or '0x1', or not define it when libpq is
> compiled with GnuTLS...).

Just mark PQgetssl() obsolete. We have to return a NULL or a valid
pointer, otherwise existing programs will just crash. The major reason
for this PQgettlsinfo() function is so people can actually *know* which
library is active. Consider stuff like this:

PQgetssl()     not NULL -> using openssl
PQgetgnutls    not NULL -> using gnutls
else not using ssl OR using some unknown library

That's not a way to design an interface. This PQgettlsinfo() would tell
you, one way or the other, if there is a TLS library in use. Give the
user the certificates and the cipher and if the user wants more info,
they can use the SSL library of their choice to get the information
they want.

Note, some of the info there is not stuff you can actually get from
the PQgetssl() function currently anyway. You can't ask the SSL library
easily if we provided a certificate during authentication. libpq knows
this easily.

Have a nice day,
--
Martijn van Oosterhout   <kleptog@svana.org>   http://svana.org/kleptog/
> Patent. n. Genius is 5% inspiration and 95% perspiration. A patent is a
> tool for doing 5% of the work and then sitting around waiting for someone
> else to do the other 95% so you can sue them.

Re: A successor for PQgetssl

From
Stephen Frost
Date:
* Tom Lane (tgl@sss.pgh.pa.us) wrote:
> Stephen Frost <sfrost@snowman.net> writes:
> > I have to agree with Martijn here too.  It's not all that expensive to
> > provide read/write calls to abstract away the specific library being
> > used (since psqlODBC, at least, couldn't care less which library is
> > being used, really)
>
> You're failing to consider async applications.  AFAICS, the *minimum*

You're assuming I intended just 'read()' and 'write()', I suppose I
should have been more explicit but I certainly understand there's more
than just read() and write() involved, though not by much.  I'm not sure
I see a reason we wouldn't just use the existing PQsocket() for the same
socket back to the user for select()-based systems (don't we do this for
SSL-enabled connections too anyway?)...  There's not a whole lot special
when it comes to handling data transport, or much that has changed
lately or is likely to change anytime soon.

> consumed any caffeine yet today...).  And that's just considering
> the data transport aspect of it.  I'm still concerned that SSL-using
> apps may wish to twiddle the SSL library in ways we don't even know
> about.

SSL is all about the certificates, really.  As long as we provide
that back to the user in a library-agnostic way they'll be able to
do whatever they like with it, such as compare it to a CRL or use OCSP
to check the current status.  Of course, these are usually things you're
more concerned about on the *server* side, which we don't currently
support anyway.  With supporting multiple SSL libraries we'll have to
deal with these issues on the *server* side, should we decide to
implement them someday (which would be nice...) anyway so trying to
play like we don't want to or don't care to know about them doesn't
really work.  Just saying we won't do CRLs or OCSP ever would just mean
we don't get run in some environments.

Of course, in either case we can play the "if you want it, write the
code" card but I'd really expect to get complaints from admins who want
to use X.509 but need CRL/OCSP support before getting complaints from
application developers that they need libpq to provide something more
for them...
Thanks,
    Stephen

Re: A successor for PQgetssl

From
Martijn van Oosterhout
Date:
On Mon, Apr 17, 2006 at 11:25:26AM -0400, Tom Lane wrote:
> You're failing to consider async applications.  AFAICS, the *minimum*
> API would be
>     read
>     write
>     read ready?
>     write ready?
>     get socket so I can use it in select()

Actually, you only need two functions:

read
write

The "get socket" already exists as PQsocket().

Both SSL libraries work perfectly fine if the user sets the connection
to non-blocking via PQsetnonblocking(). They just return -EAGAIN. I was
actually thinking of the two functions as follows:

typedef PostgresPollingStatusType pq_read_func( PGconn *conn, void *buf, int *len);
typedef PostgresPollingStatusType pq_write_func( PGconn *conn, const void *buf, int *len);

The existing PostgresPollingStatusType seems to handle both blocking
and non-blocking states just fine.

> (very possibly there's some stuff I missed, considering I haven't
> consumed any caffeine yet today...).  And that's just considering
> the data transport aspect of it.  I'm still concerned that SSL-using
> apps may wish to twiddle the SSL library in ways we don't even know
> about.

Well, I checked a few libs like libcurl and libldap. They generally
allow you to configure the files containing the certificates but that's
about it.

Seriously, if people want to do really sophisticated things with the
SSL library, they should setup s_tunnel instead. If we wanted to let
users control everything we'd allow Anonymous DH key transfers. The
README.SSL lists the situations were SSL makes sense and if you fall
outside of that you shouldn't be using SSL.

All I'm asking for is that libpq be made SSL-library *agnostic* so that
users like psqlODBC can just *use* the connection with having to jump
through hoops.

Have a nice day,
--
Martijn van Oosterhout   <kleptog@svana.org>   http://svana.org/kleptog/
> Patent. n. Genius is 5% inspiration and 95% perspiration. A patent is a
> tool for doing 5% of the work and then sitting around waiting for someone
> else to do the other 95% so you can sue them.

Re: A successor for PQgetssl

From
Stephen Frost
Date:
* Martijn van Oosterhout (kleptog@svana.org) wrote:
> Seriously, if people want to do really sophisticated things with the
> SSL library, they should setup s_tunnel instead. If we wanted to let

I certainly agree with all the rest but I'm just not sure I can agree
with you here.  While s_tunnel is nice it's not always an option and I
think it *would* be nice to have Postgres support things like CRLs and
OCSP but more from the server-side of things than the client-side.
Thanks,
    Stephen

Re: A successor for PQgetssl

From
Martijn van Oosterhout
Date:
On Mon, Apr 17, 2006 at 12:24:40PM -0400, Stephen Frost wrote:
> * Martijn van Oosterhout (kleptog@svana.org) wrote:
> > Seriously, if people want to do really sophisticated things with the
> > SSL library, they should setup s_tunnel instead. If we wanted to let
>
> I certainly agree with all the rest but I'm just not sure I can agree
> with you here.  While s_tunnel is nice it's not always an option and I
> think it *would* be nice to have Postgres support things like CRLs and
> OCSP but more from the server-side of things than the client-side.

CRLs are easy, almost a one line change. I was actually surprised it
wasn't done but I didn't add it because I figured someone had left it
out for a reason.

OCSP is something else. And in any case, you don't need a result of
PQgetssl() to use it since it's a completely seperate part of the
library.

But neither of these are what I considered "sophisticated". I don't
think either of these require any API changes either.

Have a nice day,
--
Martijn van Oosterhout   <kleptog@svana.org>   http://svana.org/kleptog/
> Patent. n. Genius is 5% inspiration and 95% perspiration. A patent is a
> tool for doing 5% of the work and then sitting around waiting for someone
> else to do the other 95% so you can sue them.

Re: A successor for PQgetssl

From
Stephen Frost
Date:
* Martijn van Oosterhout (kleptog@svana.org) wrote:
> On Mon, Apr 17, 2006 at 12:24:40PM -0400, Stephen Frost wrote:
> > I certainly agree with all the rest but I'm just not sure I can agree
> > with you here.  While s_tunnel is nice it's not always an option and I
> > think it *would* be nice to have Postgres support things like CRLs and
> > OCSP but more from the server-side of things than the client-side.
>
> CRLs are easy, almost a one line change. I was actually surprised it
> wasn't done but I didn't add it because I figured someone had left it
> out for a reason.

I doubt there was a reason it was left out...

> OCSP is something else. And in any case, you don't need a result of
> PQgetssl() to use it since it's a completely seperate part of the
> library.

Right, I mentioned you'd just need the certificate, and that I was
talking about it on the server-side...

> But neither of these are what I considered "sophisticated". I don't
> think either of these require any API changes either.

Right, they don't require API changes (at least, not libpq) and wouldn't
provided the certificate is available.  What I was getting at is that
they're more complicated SSL issues that the server *should* be able to
deal with (imv) and would require additional configuration parameters
and more of the SSL libraries than we're currently using.

Mainly I was trying to point out that trying to claim that "we don't do
anything with SSL, it's all up to the application to decide what they
want to do, and we give the application the SSL pointer so we don't have
to worry about it" doesn't really fly- we have an SSL-using application
ourselves which is the postmaster and we really should be able to
properly support it and be at least somewhat knowledgable about how it
works because SSL is a Good Thing for us to have.
Thanks,
    Stephen