使用SSL通配符证书验证主机

时间:2015-07-02 21:55:27

标签: c++ https ssl-certificate poco-libraries

我的HTTPS客户端使用Poco C ++连接我们的服务器,该服务器使用通配符证书(*.example.com)。连接失败并显示CertificateValidationException,错误消息为“来自x.y.z.w的不可接受的证书:应用程序验证失败”

奇怪的是,大多数时候它并不总是失败。经过多次调试后,我的预感是它与拓扑(例如跨子网)或主机名转换为I.P.的方式/时间有关。地址。

我认为这是因为在一切按预期工作的情况下,本地DNS正在路由主机名。但是如果它不起作用(上面的错误信息),主机名转换就像我的PC一样在本地盒子上。

有没有办法缩小这里发生的事情?这是一个常见的或已知的问题吗?

感谢。

1 个答案:

答案 0 :(得分:1)

我自己也遇到了同样的症状。使用Poco :: Net :: HTTPSClientSession,我可以很好地连接到非通配符站点,但在连接到* .example.com通配符站点时,上述异常和消息失败了。但请注意,我观察到的行为是100%一致,从不间断。

通过Poco源代码调试后,我发现了HTTPSClientConnection类如何设置自己执行证书验证的问题。我在pocoproject.org上提交了Poco issue #1303,但是如果你使用no-arg构造函数创建一个HTTPSClientSession,,当使用通配符证书连接到服务器时,你总是会遇到这个异常。例如:

Poco::URI uri("http://blah.example.com");   // SSL cert is for *.example.com
Poco::Net::HTTPSClientSession session;      // Note no-arg constructor
session.setHost(uri.getHost());
session.setPort(uri.getPort());

Poco::Net::HTTPRequest req;
// Populate req...

session.sendRequest(req);      // Throws CertificateValidationException:
                               // "Unacceptable certificate from x.x.x.x,
                               // application verification failure"

问题是,在验证证书时,如果尚未设置主机名,各种Poco :: Net类会将对等名称查找为IP地址,然后尝试将该IP地址与通配符匹配cert CN(显然,xyzw将无法与* .example.com匹配)。

好消息是有几个简单的解决方法。最简单的方法是使用HTTPSClientSession(主机,端口)构造函数,它将在底层SecureStreamSocket上设置正确的主机名,以便后续证书验证与真实主机名(blah.example.com)匹配证书(CN = *。 example.com),而不是IP地址:

Poco::URI uri("http://blah.example.com");
Poco::Net::HTTPSClientSession session(uri.getHost(), uri.getPort());      // Calls SecureStreamSocket::setPeerHostName() internally

还有其他解决方法:首先创建自己的SecureStreamSocket,在其上调用setPeerHostName(),然后将其传递到相应的HTTPSClientSession构造函数等。如果需要,请参阅上面的问题跟踪链接以获取更多想法。< / p>