代码:TIdSSLIOHandlerSocketOpenSSL( ASMTP.IOHandler ).SSLOptions.SSLVersions := [sslvSSLv2,sslvSSLv23,sslvSSLv3,sslvTLSv1,sslvTLSv1_1,sslvTLSv1_2]
似乎问题出在方法TIdSSLOptions上。SetSSLVersions,如果您设置除了单个版本之外的任何内容,它将设置fMethod := sslvSSLv23
。如果不可用,则使用TIdSSLContext。SetSSLMethod返回nil,你会得到这个错误。
Indy Dec-2015, TIdSSLContext。SetSSLMethod可以返回nil。解决方案恢复。
什么问题?没有,希望有人觉得有用。
这是一个问答网站。分享知识是可以的,但必须是Q& a格式。我能回答我自己的问题吗?
无论如何,这听起来更像是一个错误报告,应该报告给Indy的问题跟踪器,而不是公共论坛。
也就是说,你永远不应该启用SSLv2或SSLv3协议,因为它们不再安全,甚至在许多OpenSSL版本中都不再可用。并且SSLv23只是一个通配符,它意味着仅在Method
属性中使用,而不是在SSLVersions
属性中使用(事实上,如果您尝试使用任何其他版本指定它,它将被忽略)。您应该在SSLVersions
中只使用TLSv1+协议,让Indy根据需要在内部处理SSLv23。
TIdSSLIOHandlerSocketOpenSSL( ASMTP.IOHandler ).SSLOptions.SSLVersions := [sslvTLSv1,sslvTLSv1_1,sslvTLSv1_2]
似乎问题出在方法TIdSSLOptions上。SetSSLVersions,如果你设置的不是一个版本,它会设置fMethod:= sslvSSLv23。
应该是这样的,因为SSLv23方法是OpenSSL在SSL/TLS握手期间启用动态版本协商的方式,允许客户端和服务器协商它们都支持的最高TLS版本。否则,如果客户端只使用特定版本,而服务器不支持该版本,则TLS握手将失败。
如果不可用,则TIdSSLContext。SetSSLMethod返回nil,你会得到这个错误。
首先,SetSSLMethod()
永远不会将nil
返回给SSL_CTX_new()
。如果所请求的方法不被OpenSSL支持,SetSSLMethod()
会抛出EIdOSSLGetMethodError
异常。
第二,这个条件意味着你不能进行版本协商,所以你必须使用一个特定的TLS版本。例外是故意的,让你知道你要求协商,但你的OpenSSL版本不支持它,所以尝试其他方法。
最简单的解决方法是在设置SSLVersions
之后设置Method
Method
和SSLVersions
属性是互斥的,设置一个属性会更新另一个属性。然而,Method
是不赞成的,你真的应该只使用SSLVersions
,即使是单个TLS版本。
也可能不存在,所以更好的解决方法可能是在indy:
当请求SSLv23时,您的解决方法完全禁用版本协商。对于Indy来说,这不是一个可行的选择。
真正的解决方法是让您自己的代码在SSLv23不可用时捕获EIdOSSLGetMethodError
异常,然后您可以根据需要使用单个TLS版本重新尝试连接。不需要修改Indy的代码。