3

I'm trying to implement certificate pinning over [cpprestsdk][1], so far without success.

I have seen in inside http_client_config object we can call method set_ssl_context_callback and inside that method, link it to custom certificate validation method - set_verify_callback.

When i debugged my code, the method * set_verify_callback* is called after the request is sent, yet my custom validation method is never called.

I have added a sample code below which demonstrate the behaviour described above.

bool verify_certificate(bool preverified, boost::asio::ssl::verify_context& ctx)
{
    // this code is never invoked
    char subject_name[256];
    X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
    X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256);
    std::cout << "Verifying:\n" << subject_name << std::endl;

    return preverified;
}


pplx::task<void> sendRequest()
{
    http_client_config config;
    config.set_validate_certificates(true);
    config.set_ssl_context_callback([](boost::asio::ssl::context& ctx)
                                    {
                                        // this code is invoked right after calling client.request
                                        ctx.set_verify_mode(boost::asio::ssl::context::verify_peer);
                                        ctx.set_verify_callback(&verify_certificate);

                                    });


    http_client client("https://google.com", config);

    http_request request(methods::GET);


    return client.request(request).then([](http_response response)
                                        {
                                            if (response.status_code() == status_codes::OK)
                                            {
                                                return response.extract_json();
                                            }

                                            return pplx::create_task([] { return json::value(); });

                                        }).then([](json::value jsonValue)
                                                {

                                                });

}


int main(int argc, const char * argv[])
{
    try
    {
        sendRequest().wait();
    }
    catch (std::exception& e)
    {
        std::wostringstream ss;
        ss << e.what() << std::endl;
        std::wcout << ss.str();

        // Return an empty task.
    }
    return 0;
}
IdoT
  • 2,831
  • 1
  • 24
  • 35
  • OWASP has a copy/paste example for OpenSSL at [Certificate and Public Key Pinning](https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning). Its real pinning; not the web and browser's rendition from [RFC 7469](https://tools.ietf.org/html/rfc7469). – jww Jun 12 '17 at 17:42
  • @jww - thanks but it's not relevant, since the problem i'm facing is that the callback for verification is not invoked. Also when I tried to access using the native_handle to the SSL* object, the certificate is null using SSL_get_peer_certificate(ssl); (I'm testing it with https://google.com) – IdoT Jun 13 '17 at 08:41
  • btw, by working with boost without cpprest the callback is invoked. – IdoT Jun 13 '17 at 11:14
  • *" native_handle to the SSL* object, the certificate is null..."* - Yeah, something is bent. The only time you would get a NULL server certificate after the handshake completes is when using Anonymous Diffie-Hellman (ADH) or Anonymous Elliptic Curve Diffie-Hellman or (AECDH). ***IF*** your cipher suite list has `!aNULL`, then you are not using them and the certificate should not be NULL. – jww Jun 13 '17 at 12:55
  • thanks for the reply, but do you understand why the callback for verify_certificate is not invoked? according to the specs in boost, the validation should be done in that method. – IdoT Jun 13 '17 at 12:58
  • *" .. do you understand why the callback for verify_certificate is not invoked... "* - Sorry, No. I don't use Boost or CppRest. I'm commenting for the OpenSSL tag. – jww Jun 13 '17 at 13:00

1 Answers1

1

I've found a workaround for using this library with certificate pinning.

This workaround requires to override a method in the library.

In the file https://github.com/Microsoft/cpprestsdk/blob/master/Release/src/http/client/http_client_asio.cpp

override the method

bool handle_cert_verification(bool preverified, boost::asio::ssl::verify_context &verifyCtx)

then recompile the library and replace it in your project.

I have submitted the owners the solution for their main branch, which is calling the set_verify_callback instead of using their own implementation.

IdoT
  • 2,831
  • 1
  • 24
  • 35