The code:
TIdSSLIOHandlerSocketOpenSSL( ASMTP.IOHandler ).SSLOptions.SSLVersions := [sslvSSLv2,sslvSSLv23,sslvSSLv3,sslvTLSv1,sslvTLSv1_1,sslvTLSv1_2]
Seems like the problem lies down in method TIdSSLOptions.SetSSLVersions, if you set anything but a single version, it sets fMethod := sslvSSLv23
. If not available, TIdSSLContext.SetSSLMethod returns nil and you get this error.
Indy Dec-2015, TIdSSLContext.SetSSLMethod can return nil. Solution reverted.
CodePudding user response:
What's the question? None, hope someone finds this useful.
This is a Q&A site. Sharing knowledge is fine, but it must be in a Q&A format. See Can I answer my own question?
In any case, this sounds more like a bug report that should have been reported to Indy's issue tracker instead of a public forum.
That being said, you should NEVER enable the SSLv2 or SSLv3 protocols at all, as they are no longer secure, and are not even available in many OpenSSL releases anymore. And SSLv23 is just a wildcard, it is meant to be used only in the Method
property, not in the SSLVersions
property (in fact, if you try to specify it with any other version, it will just be ignored). You should be using only the TLSv1 protocols in SSLVersions
, let Indy deal with SSLv23 internally as needed.
TIdSSLIOHandlerSocketOpenSSL( ASMTP.IOHandler ).SSLOptions.SSLVersions := [sslvTLSv1,sslvTLSv1_1,sslvTLSv1_2]
Seems like the problem lies down in method TIdSSLOptions.SetSSLVersions, if you set anything but a single version, it sets fMethod := sslvSSLv23.
As it should be, because the SSLv23 method is how OpenSSL enables dynamic version negotiation during the SSL/TLS handshake, allowing client and server to negotiate the highest TLS version they both support. Otherwise, if the client uses just a specific version, and if the server doesn't support that version, the TLS handshake Wil fail.
If not available, TIdSSLContext.SetSSLMethod returns nil and you get this error.
First off, SetSSLMethod()
will never return nil
to SSL_CTX_new()
. If the requested method is not supported by OpenSSL, SetSSLMethod()
raises an EIdOSSLGetMethodError
exception instead.
Second, this condition means you can't perform version negotiation, so you must use a specific TLS version instead. The exception is by design, letting you know that you asked for negotiation but your OpenSSL release doesn't support it, so try something else.
The simplest workaround is to set Method after setting SSLVersions
The Method
and SSLVersions
properties are mutually exclusive, setting one updates the other. However, Method
is deprecated, you really should be using only SSLVersions
, even for single TLS versions.
That might not exist either, so a better workaround might be in indy:
Your workaround disables version negotiation altogether when SSLv23 is requested. That is not a viable option for Indy to implement.
The real workaround would be for your own code to catch the EIdOSSLGetMethodError
exception when SSLv23 is not available, and then you can re-attempt your connection using single TLS versions as needed. No changes to Indy's code are needed for that.