will / crystal-pg

a postgres driver for crystal
BSD 3-Clause "New" or "Revised" License
463 stars 78 forks source link

Add scram support, switch to circle ci #176

Closed will closed 5 years ago

will commented 5 years ago

This doesn't yet do the channel binding, but that can be added later. Fixes #154

will commented 5 years ago

I looked into the channel binding today, but I can't figure out how to get the peer cert from either the OpenSSL::SSL::Context::Client or the OpenSSL::SSL::Socket::Client. I imagine new functions need to be mapped out of openssl, but I'm not sure where to start.

For channel binding to work, you need to need to

Then comes tls-server-end-point, which needs more routines from OpenSSL, first to get the server certificate and hash it:

SSL_get_peer_certificate() to get the peer certificate data, which needs to be used on the client side in this case. Once this information is fetched, hashing it it first necessary. In this process comes a detail of RFC 5929: if the signature algorithm of a certificate is MD5 or SHA-1, then the hashing needs to be done with SHA-256. For anything above, use the same hashing. Getting a hash from a certificate is a matter of using X509_digest(), but the algorithm type to specify depends on the signature algorithm the certificate is using. Digging through the code of OpenSSL, I have found an answer of how to do that in crypto/asn1/a_verify.c:

Use X509_get_signature_nid() to find the signature algorithm, note that this may not be the hash itself. Then apply OBJ_find_sigid_algs() to find out the real algorithm. from: https://paquier.xyz/postgresql-2/channel-binding-openssl/

libpq: https://github.com/postgres/postgres/blob/a806b14a1139d3443a7c2c263abb9ff8e4a65694/src/interfaces/libpq/fe-secure-openssl.c#L374

@asterite do you know? Or I'm not sure who has done the most ssl/tls stuff with crystal

asterite commented 5 years ago

Unfortunately I'm clueless regarding openssl (I think I didn't touch a single code of it in Crystal).

will commented 5 years ago

Mayyyybe @ysbaddaden can you point me in the right direction?

straight-shoota commented 5 years ago

There is currently no support to retrieve the certificate from SSL::Context. The implementation is pretty limited, it only allows to specify a file or director path where the certificates are to be found.

But it should probably not be too complicated to add SSL_get_peer_certificate. It receives the value from OpenSSL::SSL::Context#@handle and returns an X509 pointer. There is already a OpenSSL::X509::Certificate class, but it doesn't provide any access to the actual certificate data. So you'd have to use X509_digest directly.

will commented 5 years ago

@straight-shoota sounds good, thanks!

Neustradamus commented 2 years ago

Linked to: