代码:TIdSSLIOHandlerSocketOpenSSL( ASMTP.IOHandler ).SSLOptions.SSLVersions := [sslvSSLv2,sslvSSLv23,sslvSSLv3,sslvTLSv1,sslvTLSv1_1,sslvTLSv1_2]
看起来问题出在方法TidSSLOptions.SetSSLVersions中,如果您设置了除单个版本之外的任何内容,它将设置fMethod := sslvSSLv23
。如果不可用,TidSSLContext.SetSSLMethod将返回nil,您将得到此错误。
Indy 2015年12月,TIdSSLContext.SetSSLMethod可以返回nil。解决方案已恢复。
1条答案
按热度按时间svdrlsy41#
有什么问题吗?没有,希望有人觉得这个有用。
这是一个问答网站。可以分享知识,但必须采用问答格式。请参阅Can I answer my own question?
在任何情况下,这听起来更像是一个错误报告,应该报告给Indy's issue tracker,而不是一个公共论坛。
也就是说,您根本不应该启用SSLv 2或SSLv 3协议,因为它们不再安全,甚至在许多OpenSSL发行版中不再可用。SSLv 23只是一个通配符,它只用于
Method
属性,而不是SSLVersions
属性(事实上,如果您尝试使用任何其他版本指定它,它将被忽略)。您应该只在SSLVersions
中使用TLSv 1+协议,让Indy根据需要在内部处理SSLv 23。看起来问题出在方法TIdSSLOptions.SetSSLVersions中,如果你设置了除单个版本之外的任何内容,它会设置fMethod:= sslvSSLv 23。
这是理所当然的,因为SSLv 23方法是OpenSSL在SSL/TLS握手过程中实现动态版本协商的方式,允许客户端和服务器协商它们都支持的最高TLS版本。否则,如果客户端只使用特定版本,而服务器不支持该版本,TLS握手将失败。
如果不可用,TidSSLContext.SetSSLMethod将返回nil,并出现此错误。
首先,
SetSSLMethod()
永远不会将nil
返回到SSL_CTX_new()
。如果OpenSSL不支持所请求的方法,SetSSLMethod()
会引发EIdOSSLGetMethodError
异常。第二,这种情况意味着你不能进行版本协商,所以你必须使用特定的TLS版本来代替。这个例外是设计好的,让你知道你要求协商,但是你的OpenSSL版本不支持它,所以尝试其他的方法。
最简单的解决方法是在设置SSL版本后设置方法
Method
和SSLVersions
属性是互斥的,设定其中一个会更新另一个。但是,Method
已过时,您应该只使用SSLVersions
,即使是单一TLS版本。这可能也不存在,所以更好的解决方案可能是在indy:
您的解决方法在请求SSLv 23时完全禁用版本协商。这不是Indy实现的可行选项。
真实的的解决方案是当SSLv 23不可用时,您自己的代码捕获
EIdOSSLGetMethodError
异常,然后您可以根据需要使用单个TLS版本重新尝试连接。