Skip to content

HTTPSClientSession::sendRequest() fails if server has wildcard cert #1303

@crackajackdev

Description

@crackajackdev

HTTPSClientSession::sendRequest() throws a CertificateValidationException when connecting to a server with a wildcard cert (.example.com) *IF you use the no-argument HTTPSClientSession() constructor. For example:

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"

It took a bit of wading through Poco source to see what was really going on. The problem is that in the no-arg constructor case, the HTTPSClientSession class never calls setPeerHostname on the underlying SecureStreamSocket. As a result, when it comes time to do certificate validation, Poco ends up trying to validate an IP address against the cert CN, which won't work (since any IP addr fails to match against the *.example.com CN).

Several workarounds exist. The easiest is to simply use the HTTPSClientSession(host, port) constructor, since internally that calls SecureStreamSocket::setPeerHostName():

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

The other workaround is to manually create a SecureStreamSocket and call setPeerHostName() yourself: Ugly, but it works:

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

Poco::Net::SecureStreamSocket sss(session.socket());
sss.setPeerHostName(uri.getHost());

Other variations on these themes exist as well, of course (such as creating a SecureStreamSocket yourself and passing that into the HTTPSClientSession constructor, etc.).

This took quite a bit of time to sort through; I'm filing this to hopefully save others the same headache.

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions