So is there a way to know which protocol a server is running before establishing a connection?
No. But you should now presume its "TLS 1.0 and above".
As Steffen pointed out, you use SSLv23_method
and context options to realize "TLS 1.0 and above". Here's the full code. You can use it in a client or a server:
const SSL_METHOD* method = SSLv23_method();
if(method == NULL) handleFailure();
SSL_CTX* ctx = SSL_CTX_new(method);
if(ctx == NULL) handleFailure();
const long flags = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;
SSL_CTX_set_options(ctx, flags);
Now, there's an implicit assumption here that's not readily apparent; and that assumption is wrong. That assumption is there is a "TLS min" and "TLS max" version.
What happens is there's a underlying SSL/TLS record layer that carries the protocol payloads. The TLS record layer is independent from the protocol layer, and it has its own version. People interpret TLS record layer version as "TLS min" version; and the protocol version as the "TLS max" version. Most clients servers, sites and services use it that way.
However, the IETF does not specify it that way, and browser's don't use it that way. Because of that, we recently got TLS Fallback Signaling Cipher Suite Value (SCSV).
The browser are correct. Here's how its supposed to be done:
- try TLS 1.2, use Fallback Signalling to detect downgrade attacks
- if TLS 1.2 fails, then try TLS 1.1, use Fallback Signalling to detect downgrade attacks
- if TLS 1.1 fails, then try TLS 1.0, use Fallback Signalling to detect downgrade attacks
Many give up after TLS 1.0 fails. Some user agents may continue with SSLv3.
Why has the IETF not moved to give us "TLS min" and "TLS max"? That's still a mystery. I think the effective argument given is "suppose a client want to use TLS 1.0, 1.2 and 1.3, but not 1.1". I don't know anyone who drops a protocol version like that, so its just a strawman to me. (This is one of those times when I wonder if law enforcement or a national interest, like the NSA, is tampering with standards).
The issue was recently brought up again on the TLS Working Group. From TLS: prohibit <1.2 support on 1.3+ servers (but allow clients) (May 21, 2015):
Now might be a good time to add a (3) for TLS 1.3: have a client
specify both the least TLS version they are willing to use, and the
greatest TLS they desire to use. And MAC or derive from it it so it
can't be tampered or downgraded.
You can still provide the the TLS record layer version, and you can
keep it un-MAC'd so it can be tampered with to cause a disclosure or
crash :)
Effectively, that's how the versions in the record layer and client
protocol are being used. It stops those silly dances the browsers and
other user agents perform without the need for TLS Fallback SCSV.
If part of the IETF's mission is to document existing practices, then the IETF is not fulfilling its mission.