SecureSocket CertificateVerificationFailed not working?

Hey everyone! I’m relatively new to Haiku development, but I’m writing some code that needs to negotiate a TLS connection and I’m using SecureSocket for it.

I’ve noticed, though, that SecureSocket never seems to reject a cert - whether expired, unsigned, a wrong host, etc, it happily negotiates a TLS connection anyway. I figured “okay, weird default behavior, but I probably just need to subclass SecureSocket and implement CertificateVerificationFailed()” - but no dice; CertificateVerificationFailed() never seems to be called.

Am I missing something obvious? I’ve been pulling some hair out on this one today!

Maybe related: There’s a open ticket about mail_daemon,which uses SecureSocket,not validating SSL certificates:

On the other hand,the libnetservices HttpRequest and libnetservices2 HttpSession also uses SecureSocket and it seems the validation works there,at least there’s no open ticket saying otherwise.
Might be a bug in either SecureSocket itself or the way it’s used here and in mail_daemon.

I looked over the libnetservices2 implementation of HttpSession, and I’d guess it probably exhibits the same behavior I’m running into. It also has a TODO item for cert checking in the code (“To do: secure socket with callbacks to check certificates.”)

I’m pretty new to Haiku and don’t know what, if any, apps currently use HttpSession and would allow for a quick and dirty test, though.

Would it be useful for me to post some sample code exhibiting the problem? It’s entirely possible I’m doing something wrong.

Looking closer - I’m not actually seeing anywhere in SecureSocket.cpp where SSL_CTX_set_cert_verify_callback is invoked to set up a call to VerifyCallback(), which is where execution is handed off to CertificateVerificationFailed implementations. Either I’m missing something obvious, or SecureSocket’s cert verification looks a bit incomplete!

What’s less clear to me is why it’s still able to negotiate a connection with a bad cert at all, since that’s not default OpenSSL behavior.

I’m wondering if it would be helpful for me to debug this further and maybe submit a patch to register the callback (from OpenSSL to SecureSocket) correctly. I have no idea what the process for getting code merged into Haiku is like, but this seems like it might be useful to resolve?

This is a thing that would be absolutely useful to solve.
Sending patches and getting them merged isn’t too hard either.
It’s documented here:

I’ve not looked at the code here, but you are probably correct in that it is “just broken”. In addition to not validating stuff correctly, haiku is also missing a UI for a cert store (so users can add or blacklist CA roots they don’t want) and a UI for allowing/disallowing exceptions that could be used for mail, WebPositive and whoever else uses the libservices kit.

I suppose most prominentl would be HaikuDepot and pkgman which both use the netservices directly.

If you want you can work on some of these issues :smiley:

I learned about mail_server beeing broken because I have my own CA for my mail, and while we did add a way to (cumbersomly) add user root certs, my mail continued to work after i only migrated my mail config, and forgot to migrate the cert, to a new computer…

Thanks for the reply, nephele! I created a ticket (19980 on Trac) and I’m looking into fixing it myself. The OpenSSL behavior (failing unsafe for no obvious reason) is scary and I’m still not sure why it’s doing that, but hopefully I’ll figure it out and have a fix in the next week or two.

Keep in mind that Haiku is sitll explicitly marked as a beta, and it is among other things stuff like this that make it so :slight_smile:

Of course! I wasn’t intending to blame Haiku, and I’m sorry if it came across that way - just noticing something weird. I’ll get to the bottom of it. :slight_smile:

1 Like

As far as I know this is how OpenSSL behaves by default on all platforms, and it’s been that way for decades.

Scary? Yes, probably, but it seems no one really cares enough to run away from OpenSSL and write some clean and no-nonsense cryptography library.

LibreSSL, mbed TLS, gnuTLS, wolfSSL, … ?

It did not come across that way, don’t worry!

Thanks for working on this

I think SSL_CTX_set_cert_verify_callback() is to define a callback that will do its own implementation of the certificate verification procedure. Which we don’t really want to do here.

What seem to be needed here is more using SSL_CTX_set_verify() to define a callback to be called after the OpenSSL builtin preverification certificate procedure.

There is an example of such callback which implement user-defined behavior on certificates verification, which run above the builtin preverify procedure:

You’re right - I had actually forgotten that SSL_VERIFY_NONE is the default behavior. So all that really needs to be done is wiring up the callback.

1 Like

I guess the verify mode should be configurable via a BSecureSocket method so that it could be still possible to do TLS connections without failing in case of peer certificate verification.

It’s a socket API, a low level API. While for higher, more abstract API like BHttpRequest it make perfect sense to always verify by default, at socket API level it should be up to the API user.

With, by default, a SSL_VERIFY_PEER | SSL_VERIFY_CLIENT_ONCE mode, just to be on the safe side, contrary to even lower OpenSSL API.

Wouldn’t the trivial way to do unverified TLS connections just be to do an override of CertificateVerificationFailed that returns true? That would seem to be the intended behavior of the current BSecureSocket implementation, even though the callback isn’t working - fail on unverified certs by default, but with a simple built-in way to provide your own verification behavior.

Indeed, it loks that was the way initially planned but due to the callback not being wired to OpenSSL API, never worked that way.

Yes, that’s how it was designed. I’m not sure when the callback setup was lost, maybe during one of the openssl version changes.