Search code examples
c++sslopensslpkipoco-libraries

Poco + OpenSSL + CA PEM : "Unacceptable certificate" error for 1 out of 2 identical sites


I am trying to do a SSL handshake with www1.filemail.com. I am using cURL's cacert.pem, but I am getting this error:

Unacceptable certificate from 188.138.81.30: application verification failure

Making the handshake against any other HTTPS website works - including www2.filemail.com. www1 and www2 should be identically configured - and they both work fine in all browsers. They also test fine here (identical certificates and intermediary certificates are sent out for both sites):

Why am I getting this problem with www1 using OpenSSL and the cacert.pem file?

There has to be a difference in the certificate setup of www1 and www2. I have tested with a myriad of tools (openssl, ssllabs etc.) to try to pinpoint the difference - but I always get the exact same results for both sites (except when running my code)

What am I missing here? What's the difference between the sites?

(It should be noted that we are using a relatively cheap wildcard certificate provided by RapidSSL - so I'm guessing it has something to do with intermediate or cross-root certificates - but everything seems to be in order when testing with the tools mentioned above.)


Code:

Poco::SharedPtr<Poco::Net::InvalidCertificateHandler> pCert = new Poco::Net::ConsoleCertificateHandler(false);
Poco::Net::Context::Ptr pContext = new Poco::Net::Context(Poco::Net::Context::CLIENT_USE, "", "", "C:\\cacert.pem", Poco::Net::Context::VERIFY_RELAXED, 9, false, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");
Poco::Net::SSLManager::instance().initializeClient(0, pCert, pContext);

URI uri("https://www1.filemail.com");
Poco::Net::SecureStreamSocket ss(Poco::Net::SocketAddress(uri.getHost().c_str(), uri.getPort()));
ss.completeHandshake();

Solution

  • Günter Obiltschnig helped me out via POCO@Github and got it working by replacing

    Poco::Net::SecureStreamSocket ss(Poco::Net::SocketAddress(uri.getHost().c_str(), uri.getPort()));
    

    with

    Poco::Net::SecureStreamSocket ss(Poco::Net::SocketAddress(uri.getHost().c_str(), uri.getPort()), uri.getHost());
    

    (including the host name in the constructor of SecureStreamSocket - it is used for certificate verification)

    From the POCO documentation:

    SecureStreamSocket(
        const SocketAddress & address,
        const std::string & hostName
    );
    
    //Creates a secure stream socket using the default client SSL context and connects it to the socket specified by address.
    //The given host name is used for certificate verification <=======
    

    I still do not know the exact difference in config between www1 and www2 are, would love if someone could enlighten me on this.