Validate TLS certificates [$155 awarded] #89

Closed
opened 2026-10-05 03:58:13 +02:00 by adam · 18 comments
Owner

What we need to check:

  • The peer name (or alt), wild comparison, could be "*.example.com".
  • If any certificate in the chain has expired.
  • Ensure root certificate is trusted (the OS/distro usually packages a set of CA files to compare this against).
  • Validate the certificate chain (ensure each certificate in the chain is signed correctly by the certificate above).

--- The **[$155 bounty](https://www.bountysource.com/issues/674-validate-tls-certificates?utm_campaign=plugin&utm_content=tracker%2F1759&utm_medium=issues&utm_source=github)** on this issue has been claimed at [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F1759&utm_medium=issues&utm_source=github).
What we need to check: - The peer name (or alt), wild comparison, could be "*.example.com". - If any certificate in the chain has expired. - Ensure root certificate is trusted (the OS/distro usually packages a set of CA files to compare this against). - Validate the certificate chain (ensure each certificate in the chain is signed correctly by the certificate above). ## <bountysource-plugin> --- The **[$155 bounty](https://www.bountysource.com/issues/674-validate-tls-certificates?utm_campaign=plugin&utm_content=tracker%2F1759&utm_medium=issues&utm_source=github)** on this issue has been claimed at [Bountysource](https://www.bountysource.com/?utm_campaign=plugin&utm_content=tracker%2F1759&utm_medium=issues&utm_source=github). </bountysource-plugin> <!-- github-sync-id:3853257 -->
adam closed this issue 2026-10-05 03:58:13 +02:00
Author
Owner

Validate for what? I bet openssl already makes sure that there are no malformed certificates involved :-P

Validate for what? I bet openssl already makes sure that there are no malformed certificates involved :-P <!-- github-comment-id:4767197 -->
Author
Owner

The domain, date, the CA, etc?

The domain, date, the CA, etc? <!-- github-comment-id:4767735 -->
Author
Owner

Yes, OpenSSL can do those things, but you need to make sure you've asked for it.

Yes, OpenSSL _can_ do those things, but you need to make sure you've asked for it. <!-- github-comment-id:5888779 -->
Author
Owner

What exactly do you mean with "those things"? I am pretty sure that, for example, OpenSSL cannot check if a given domain name matches the certificate's subject.
No idea if it verifies the date (= if the cert is yet/still valid), but it definitely checks the issuer chain.
What other properties of a cert would we need to check? How much ugly, ugly code would that take?

What exactly do you mean with "those things"? I am pretty sure that, for example, OpenSSL cannot check if a given domain name matches the certificate's subject. No idea if it verifies the date (= if the cert is yet/still valid), but it definitely checks the issuer chain. What other properties of a cert would we need to check? How much ugly, ugly code would that take? <!-- github-comment-id:5895614 -->
Author
Owner

What we need to check:

  • The peer name, wild comparison, could be "*.example.com".
  • If any certificate in the chain has expired.
  • Ensure root certificate is trusted (the OS/distro usually packages a set of CA files to compare this against).
  • Validate the certificate chain (ensure each certificate in the chain is signed correctly by the certificate above).

SSL_get_verify_result() can be used, but I am not sure what this checks.

What we need to check: - The peer name, wild comparison, could be "*.example.com". - If any certificate in the chain has expired. - Ensure root certificate is trusted (the OS/distro usually packages a set of CA files to compare this against). - Validate the certificate chain (ensure each certificate in the chain is signed correctly by the certificate above). `SSL_get_verify_result()` can be used, but I am not sure what this checks. <!-- github-comment-id:5895818 -->
Author
Owner

I believe this is an important issue. Here's a PDF with an abundance of information on the topic: http://www.cs.utexas.edu/~shmat/shmat_ccs12.pdf

By default, OpenSSL does not throw a run-time exception if the certificate is self-signed or has an invalid chain of trust. Instead, it sets flags. Furthermore, OpenSSL does not provide any hostname verification.
I believe this is an important issue. Here's a PDF with an abundance of information on the topic: http://www.cs.utexas.edu/~shmat/shmat_ccs12.pdf <blockquote>By default, OpenSSL does not throw a run-time exception if the certificate is self-signed or has an invalid chain of trust. Instead, it sets flags. Furthermore, OpenSSL does not provide any hostname verification.</blockquote> <!-- github-comment-id:14518082 -->
Author
Owner

Some old code that I once wrote for something like this:

https://github.com/psychon/znc/commits/openssl-experiments

However, this is security-sensitive stuff and I have no clue about what exactly the rules for this kind of things are. In other words: I feel really unsure about this and have no clue if it is correct. (Also, I didn't look at the branch in years...)

Some old code that I once wrote for something like this: https://github.com/psychon/znc/commits/openssl-experiments However, this is security-sensitive stuff and I have no clue about what exactly the rules for this kind of things are. In other words: I feel really unsure about this and have no clue if it is correct. (Also, I didn't look at the branch in years...) <!-- github-comment-id:14666204 -->
Author
Owner

Given that very few IRC servers have valid certificates, "trust on first use" in addition to the chain validation would be more useful...

Given that very few IRC servers have valid certificates, "trust on first use" in addition to the chain validation would be more useful... <!-- github-comment-id:15695220 -->
Author
Owner

User should be presented an option to allow cert, if the cert is invalid. User should explicitly allow this particular invalid cert. "trust on first use" is bad if you want security

User should be presented an option to allow cert, if the cert is invalid. User should explicitly allow this particular invalid cert. "trust on first use" is bad if you want security <!-- github-comment-id:15695289 -->
Author
Owner

User should be presented an option to allow cert, if the cert is invalid. User should explicitly allow this particular invalid cert.

"trust on first use" is bad if you want security

Isn't that exactly what "trust on first use" usually means?

> User should be presented an option to allow cert, if the cert is invalid. User should explicitly allow this particular invalid cert. > > "trust on first use" is bad if you want security Isn't that exactly what "trust on first use" usually means? <!-- github-comment-id:15695306 -->
Author
Owner

Hm, if it means that, ok... For me it sounded like "if we connect to the server for the first time, trust it anyway".
Good that I've mistaken.

Hm, if it means that, ok... For me it sounded like "if we connect to the server for the first time, trust it anyway". Good that I've mistaken. <!-- github-comment-id:15701525 -->
Author
Owner

Just for reference, here is how HexChat implements it: https://github.com/hexchat/hexchat/blob/master/src/common/server.c#L624 Though I don't see that they would validate the CN, too… :-)

grawity, DarthGandalf: Looking at how other programs handle invalid certificates, I'd say there could be two approaches:

  • Just have a "Accept invalid certificates" checkbox in the network settings (the easiest to implement, the easiest to use)
  • When connecting to a server for the first time, halt the connection, PRIVMSG the user the certificate info, fingerprint and validation error message, and then ask to answer "AcceptOnce", "AcceptAlways" or "Reject" (though the IRC server might drop the connection while waiting). To account for the situation where this might be happening without a user client connected, the bouncer could wait for a couple of minutes and reconnect then. Note that this is different from "Trust on first use", as the user takes the initiative to accept/reject the certificate. Perhaps there could be also an option to enter the certificate (path) manually in the config/web interface.

In the mean time, https://www.stunnel.org/ can be used to establish a secure SSL connection from the bouncer to the IRC server (thanks to a friend of mine for recommending me this).

Just for reference, here is how HexChat implements it: https://github.com/hexchat/hexchat/blob/master/src/common/server.c#L624 Though I don't see that they would validate the CN, too… :-) grawity, DarthGandalf: Looking at how other programs handle invalid certificates, I'd say there could be two approaches: - Just have a "Accept invalid certificates" checkbox in the network settings (the easiest to implement, the easiest to use) - When connecting to a server for the first time, halt the connection, PRIVMSG the user the certificate info, fingerprint and validation error message, and then ask to answer "AcceptOnce", "AcceptAlways" or "Reject" (though the IRC server might drop the connection while waiting). To account for the situation where this might be happening without a user client connected, the bouncer could wait for a couple of minutes and reconnect then. Note that this is different from "Trust on first use", as the user takes the initiative to accept/reject the certificate. Perhaps there could be also an option to enter the certificate (path) manually in the config/web interface. In the mean time, https://www.stunnel.org/ can be used to establish a secure SSL connection from the bouncer to the IRC server (thanks to a friend of mine for recommending me this). <!-- github-comment-id:15715911 -->
Author
Owner

I added a bounty to this :)

I'd love for ZNC to verify that:

  • There is a valid trust chain for the certificate
  • The certificate itself is valid (hasn't expired, isn't in the future)
  • The CN or SAN matches the hostname of the server in question
  • Allow a way to put a fingerprint in the config file that the server certificate must match on
    • This could be used to still securely connect when the certificate cannot be validated usin the above.
I added a bounty to this :) I'd love for ZNC to verify that: - There is a valid trust chain for the certificate - The certificate itself is valid (hasn't expired, isn't in the future) - The CN or SAN matches the hostname of the server in question - RFC 6125 can help with rules here, especially http://tools.ietf.org/html/rfc6125#section-6.4.3 for wildcards - Allow a way to put a fingerprint in the config file that the server certificate must match on - This could be used to still securely connect when the certificate cannot be validated usin the above. <!-- github-comment-id:37912313 -->
Author
Owner

How should it be handled with different fingerprints?
Id guess some networks that have different servers run independently that are connected where they have a different cert for each server use different fingerprints? Maybe a list of trusted fingerprints?

How should it be handled with different fingerprints? Id guess some networks that have different servers run independently that are connected where they have a different cert for each server use different fingerprints? Maybe a list of trusted fingerprints? <!-- github-comment-id:37915992 -->
Author
Owner

Hmm, I'm not sure, a list of fingerprints sounds reasonable to me.

Hmm, I'm not sure, a list of fingerprints sounds reasonable to me. <!-- github-comment-id:37916454 -->
Author
Owner

You could orientate yourself by the IRC-client Irssi. It provides the following options:

  • -ssl: use SSL when connecting
  • -ssl_verify: Verify servers SSL certificate
  • -ssl_cafile <cafile>: File with list of CA certificates (implies -ssl_verify)
  • -ssl_capath <capath>: Directory with CA certificates (implies -ssl_verify)

For ZNC a -ssl_verify-like option could check if the certificate send by the server matches with the certificates installed on the system. And an optional -ssl_capath <capath>-like option could provide a path containing manually downloaded/already accepted certificates.

Not being able to verify the servers certificate is currently stopping me from using ZNC, so I would gladly see this feature in future versions.

You could orientate yourself by the IRC-client Irssi. It provides the following options: - <code>-ssl</code>: use SSL when connecting - <code>-ssl_verify</code>: Verify servers SSL certificate - <code>-ssl_cafile &lt;cafile&gt;</code>: File with list of CA certificates (implies <code>-ssl_verify</code>) - <code>-ssl_capath &lt;capath&gt;</code>: Directory with CA certificates (implies <code>-ssl_verify</code>) For ZNC a <code>-ssl_verify</code>-like option could check if the certificate send by the server matches with the certificates installed on the system. And an optional <code>-ssl_capath &lt;capath&gt;</code>-like option could provide a path containing manually downloaded/already accepted certificates. Not being able to verify the servers certificate is currently stopping me from using ZNC, so I would gladly see this feature in future versions. <!-- github-comment-id:44624131 -->
Author
Owner

Yup, I hope to fix this by next release... -ssl_capath can't work for us, because ZNC user doesn't have access to file system. But list of explicitly accepted certificates need to be stored somewhere, in some form, of course.

Yup, I hope to fix this by next release... `-ssl_capath` can't work for us, because ZNC user doesn't have access to file system. But list of explicitly accepted certificates need to be stored somewhere, in some form, of course. <!-- github-comment-id:44683631 -->
Author
Owner

How about -ssl_cafile instead? Default to the OS-wide /etc/ssl/certs/ca-certificates.crt bundle, and let the user upload their own. That way it also remains compatible with GnuTLS and such, in case ZNC ever wants to use that.

Not sure what's better – should the user CAs override, or extend, the global CAs? Option would be nice, as both are useful.

How about `-ssl_cafile` instead? Default to the OS-wide `/etc/ssl/certs/ca-certificates.crt` bundle, and let the user upload their own. That way it also remains compatible with GnuTLS and such, in case ZNC ever wants to use that. Not sure what's better &ndash; should the user CAs override, or extend, the global CAs? Option would be nice, as both are useful. <!-- github-comment-id:47792328 -->
Sign in to join this conversation.
No labels
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: adam/znc#89