Websocket++ with tls: more verbosity of error messages

1,026 views
Skip to first unread message

Dmitry Liman

unread,
May 18, 2016, 10:06:33 AM5/18/16
to WebSocket++
I am using websocket++ with boost and tls. I have implemented tls_init callback and passed it to websockets handler. Everything works fine except error messages getting at on_fail handler when something goes wrong with tls handshake (wrong certificate, etc). Anything I cat get is:
"websocketpp.transport.asio.socket:8 - TLS handshake failed".
Is there a way to get more verbose error information? Something like "wrong peer certificate" and so on?
Here is my tls_init callback:

context_ptr tls_init_handler(websocketpp::connection_hdl) {
    context_ptr ctx = websocketpp::lib::make_shared<boost::asio::ssl::context>(boost::asio::ssl::context::sslv23);  // use ssl23 and higher

    try {
        ctx->set_options(boost::asio::ssl::context::default_workarounds |
                         boost::asio::ssl::context::no_sslv2 |
                         boost::asio::ssl::context::no_sslv3 |
                         boost::asio::ssl::context::single_dh_use);
        ctx->set_verify_mode(boost::asio::ssl::verify_peer |
                             boost::asio::ssl::verify_fail_if_no_peer_cert);
        ctx->load_verify_file("/home/liman_da/workspace/shield_ssl/ca.crt");
    } catch (std::exception& e) {
        LOGE("tls_init_handler exception: " << e.what());
    }

    return ctx;

}


Brian Hamon

unread,
May 18, 2016, 12:58:20 PM5/18/16
to WebSocket++
Because Websocket++ uses Asio, this is actually a question about how to use Asio. This Boost::asio example demonstrates how to use Asio to verify a peer's certificate using the verify callback method. I'll come back to this point in a moment.

Because Asio uses OpenSSL, this actually is a question about how to use OpenSSL to verify client certificates. We eventually need to call X509_verify_cert_error_string() to get the error code as a C string. But first we need to get a X509_STORE_CTX*.

The way Asio wraps OpenSSL, the way to obtain the X509_STORE_CTX* is via one of the parameters Asio passes to your verify callback:

bool Your_class::verify_certificate(bool preverified,
        boost::asio::ssl::verify_context& ssl_verify_ctx);

Now, call ssl_verify_ctx.native_handle() to get the X509_STORE_CTX*:

std::string errstr(
    X509_verify_cert_error_string(
        X509_STORE_CTX_get_error(ssl_verify_ctx.native_handle())));

The callback you set with boost::asio::ssl::stream<boost::asio::ip::tcp::socket>::set_verify_callback is called once for each certificate in the certificate chain, starting from the root certificate authority.

Refer back to the X509_STORE_CTX_get_error man page for more information. RFC 2818 describes the steps involved in doing this for HTTPS. 

Brian Hamon

unread,
May 19, 2016, 1:34:50 PM5/19/16
to WebSocket++
Although the RFC reference which I provided yesterday (RFC2818, particularly section 3.1) remains the canonical reference, there is a newer IETF document, RFC6125 which generalizes the best practices employed by common application-level protocols that use TLS, including HTTP.  Since you are using WebSockets, you may find RFC6125 more updated and circumspect as to the most effective and secure implementation of server identity verification for your application.

Again, working example code would be really useful, and I regret that I don't have any to share; however, I'd like to reiterate that the best place for such a sample would probably be in an OpenSSL developer's forum. 

I'll keep my eye out for something appropriate, and others who have links or sources are welcome to chime in.

--
You received this message because you are subscribed to the Google Groups "WebSocket++" group.
To unsubscribe from this group and stop receiving emails from it, send an email to websocketpp...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Message has been deleted

Dmitry Liman

unread,
May 21, 2016, 9:12:12 AM5/21/16
to WebSocket++
Thanks for the answer. I have implemented verify_certificate as you said and seems it works as I need.

By the way, it seems a little messy compared to other libs utilizing TLS I used. 
Reply all
Reply to author
Forward
0 new messages