Boost Asio SSL Client Handshake Problems - ssl

I have been trying to implement a very basic Boost SSL implementation to try and learn the basics. The server I want to communicate with had already given me their public key in plain text. I already put a lot of the other code (asynchronous connection, handshaking, etc) in.
I first tried to implement SSL without verification of their certificate using the following setup of the Boost SSL stream:
boost::asio::ssl::context ctxt(boost::asio::ssl::context::sslv23);
ctxt.set_verify_mode(boost::asio::ssl::verify_none);
This implementation worked fine and I was able to connect with the server. When I tried to implement the verification of the peer certificate, however, the handshaking fails. I tried using the following code:
boost::asio::ssl::context ctxt(boost::asio::ssl::context::sslv23);
ctxt.set_verify_mode(boost::asio::ssl::verify_peer);
ctxt.load_verify_file("peer.crt");
I put the "peer.crt" containing the public key (along with the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- tags) in the directory where I am running my executable. For whatever reason the handshake now fails with the error code 336134278: certificate verify failed. I also tried putting the full path to the verify file in there but with no luck.
My questions are the following:
Where should I be specifying the file name for the verify file in load_verify_file? Is it simply in the directory where I am running my executable?
Am I not setting up the handshaking process with peer verification properly? I do not have my own verify callback as I assumed the peer verification would happen automatically if I specified it as such.
Should I be handling the certificate in a certain way by installing it or something like that?
Is there a better way of debugging this functionality? I am using VS10 and can only get to the ipp so I cannot actually view the verification taking place.
Any help is appreciated, thanks!

You should be able to use either a relative or absolute path.
Your use of set_verify_mode() and load_verify_file() looks fine. I have done exactly this in my own code. A default verify callback is used if you do not specify one.
You don't need to "install" the certificate.
I don't know of easy ways to debug boost::asio SSL connections, but you can use OpenSSL command line tools, such as s_client, to test connections. boost::asio uses OpenSSL under the hood.
I suspect that you don't have the entire certificate chain of certificates in your file. You can extract them from your server with (replace www.google.com:443 with your server and port):
openssl s_client -connect www.google.com:443 -showcerts
If you only wish to check some of the certificates, e.g. only the leaf certificate, you can use your own verify callback. An example of a custom callback, as well as a description of the verification modes and options are on this page.

A good place to start is the HTTP Client in asio examples.
Are you calling set_verify_callback on the socket with the callback function to verify the certificate? E.g.:
bool verify_certificate(bool preverified, boost::asio::ssl::verify_context& ctx)
{
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);
return preverified;
}

Related

Solve boost.asio certificate failed error -without- access to source code, to find out what information Philips Hue Bridge shares

This is a bit of a super duper specific question, but who knows there's someone out there that can help me.
I happen to have Philips Hue Bridge and I would love to know what personal information it is sharing with the outside world. Using tcpdump on my router I figured the Hue Bridge has a rather talkative personality. But because it talks over SSL tunnels, I have no idea what it says. So what I did is I setup a SonicWall with SSL-DPI with a CA, got root access to the Hue Bridge and found the application that does the talking to wws://ws.meethue.com (its called websocketcd). I then replaced the root certificate on the Hue Bridge, adjusted the cipher to match the Sonicwall and now I am stuck due to boost.asio trowing an validation error of my certificate:
error:14090086:lib(20):func(144):reason(134)
For those not too familiar with the error codes, this is what they mean:
lib(20) is ERR_LIB_SSL
func(144) is SSL_F_SSL3_GET_SERVER_CERTIFICATE
reason(134) is SSL_R_CERTIFICATE_VERIFY_FAILED
To verify it's not my SonicWall or certificate that is causing the problem, I executed openssl s_client -connect ws.meethue.com:443 -CAfile ca.pem from the Hue Bridge and that validates the chain perfectly fine, the same way as the original certificate. I also verified that the application is loading my root certificate and cipher correctly (because if change the cipher, I get a cipher error error). Also in my browser, I can visit https://ws.meethue.com without certificate errors. Here's my self made certificate chain, in case someone wants to check it: https://gofile.io/d/5msjoJ (password for download/key 1020304050, it's a temporary key that only exists in my local test env. so it's safe to share ;-)
If websocketcd wasn't a binary file, the problem was super easy to solve using set_verify_mode, but unfortunately it is a binary and that makes life significantly more complicated.
Is there anyone who can give me advice how to make this blob called websocketcd with boost.asio in it accept my root certificate? What I tried too: letting it communicate without ssl and with ssl without encryption (eNULL:aNULL ciphers). I am a bit hesitant to share the blob but for those who have a Hue Bridge too, it's located at /usr/bin/websocketcd.
Perhaps you can use strace (or maybe even ltrace) to spot which certificate paths it is using for root authorities.
If it uses a single file, you might be abel to hack it by replacing it with a CA that verifies your MITM certificate.
Sometimes the file can contain multiple certificates, so worth appending/prepending yours.
If you're in luck, there will be a readdir on a directory containing certificates. If so, you should be able to add your root certificate (in PEM form) there and **remember to run c_rehash on that directory.
For those interested: after some 20hrs, I figured that websocketcd requires a certificate revocation list for each CA in the chain (which do not have to have any revoked serials). These CLRs need to be included in the root CA file that is loaded using the ca-filename argument. I was not aware that Boost Asio could demand that a CLR is present for each CA, but apparently, they (Signify) managed to do so.

Install SSL Certificate in WorldClient, MDaemon 12

I have an issue after I installed the SSL Certificate in WorldClient, MDaemon 12.
I followed the link in installing the SSL, SSL installation was fine. Then, I followed the link to use the SSL in WorldClient. I use 888 for TCP port and 443 for https port.
When I call the webmail (http://mail.mydomain.com.sg:888) in browser, it opens properly. But, if https://mail.mydomain.com.sg:888, Secure Connection Failed error message is shown.
Any Ideas, please? Thanks.
I have solved this problem.
If you read all instruction from the link you given in your post carefully until finished, you'll get the answer.
Note: MDaemon will only display certificates that have private keys
using the Personal Information Exchange format (PKCS #12). If your
imported certificate does not appear in the list then you may need to
import a *.PEM file, which contains both a certificate key and private
key. Importing this file using the same process outlined above will
convert it to the PKCS #12 format.
You should make a PKCS#12 file from generating the (certificate) .csr and private key (.key) you have. If you on windows, install the openssl first on your PC. After successful generate the PKCS#12 file, follow the instruction again to install the SSL certification on MDaemon.
If you success, you'll see the certificate appear in the MDaemon.
Remember to restart your server or webserver to apply the changes.
Regards

PJSIP TLS verify error (PJSIP_TLS_ECERTVERIF)

I have recently started to develop a tiny SIP softphone application using the PJ Project and GTK+. My main goal was to create a softphone which supports both TLS and SRTP encryption (and MWI). However I have got stuck right at the part where the library registers an account because the application has failed to verify the server when I asked it for it.
I thought that I misunderstood something while I was coding as I'm a newbie but today I've just tested the library using the PJSUA application which was attached in the source code and it could register my SIP account unless I've started the program with the --tls-verify-server flag.
To make it clear I've created for Asterisk my own certificate authority, keys and certificate and I've installed the CA to my machine.
I must note that this setup works with a commercial software, it can verify the certificate without any problem.
The PJSUA flags I've used:
--use-tls
--tls-ca-file /etc/ssl/certs/ca-certificates.crt
--id=sip:u-kuklinistvan1#kingdom.info.tm;transport=tls
--registrar=sip:kingdom.info.tm;transport=tls
--realm=kingdom.info.tm
--username=u-kuklinistvan1
--password=xxxxxx
--use-srtp=2
--mwi
--tls-verify-server
It says(please follow the link for the long version):
19:21:44.728 pjsua_app.c TLS cert verification result of [94.21.11.229:5061] : The server identity does not match to any identities specified in the certificate
...which could not be true as OpenSSL itself accepts the certificate:
openssl s_client -CAfile /etc/ssl/certs/ca-certificates.crt -connect kingdom.info.tm:5061
(click here for the rest)
Verify return code: 0 (ok)
Extra information
I connect PJSUA as endpoint to registrar by hostname kingdom.info.tm.
Is it possible that I've encountered a bug or I just don't understand something?
Thank you for your help!
... does not match to any identities specified in the certificate
... which could be not true as OpenSSL itself accepts the certificate: ... openssl s_client ...
The error messages refers to checking the identity against the certificate, i.e. the hostname you provide against the names in the certificate (subject alternative names, common name). openssl s_client does not do any identity checks but only checks for a valid trust chain.
Looking at the certificate provided by the server it actually contains contain a common name for kingdom.info.tm. But from the error message it looks that it expects the IP address: TLS cert verification result of [94.21.11.229:5061]: .... Did you specify the SIP URL of the peer with an IP address?

RFC5766-turn-server with TLS

I'm trying to start my TURN server with TLS enabled. I use the following line to start the server:
daemon --user=$USER $TURN $OPTIONS --tls-listening-port 3478 --cert /root/cert_2014_11/my_domain_nl.crt --pkey /root/cert_2014_11/my_domain_nl.key --CA-file /root/cert_2014_11/PositiveSSLCA2.crt
The environment variables in there are set in the config file. The server works fine without TLS using the same startup line, but if I add the three SSL related arguments, the server still isn't reachable over TLS. I tried setting a different port for SLL instead of the standard port, but it still didn't work. Whatever I do, I can reach the server without SLL, but over TLS I can't reach it. The certificate chain I use if fine, I use it for our website as well.
I've run into this exact problem before. Have a look at the documentation for the --CA-file argument:
--CA-file <filename> CA file in OpenSSL format.
Forces TURN server to verify the client SSL certificates.
By default, no CA is set and no client certificate check is performed.
This argument is needed only when you will be verifying client certificates. It's not for the certificate chain for your server certificate.
Drop the --CA-file argument, keeping the --cert and --pkey arguments.
EDIT: FYI, the certificate file you give to the --cert option can contain the entire certificate chain (yours and your CA's).

SSL client authentication returning Bad Certificate error

I was trying to connect to my custom wrote ssl server written in CPP. It has got client authentication features. Its throwing error Bad certificate when watched through Wireshark. At the server side the error returned was
14560:error:140890B2:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:no certificate returned:s3_srvr.c:2619:
I used the following code to force requesting client certificate
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
SSL_CTX_set_verify_depth(ctx, 1);
I could see client returning certificate in Wireshark.
Which function should be used to set the public key used for verifying the client certificate at the server side?
From the error messages it looks like your client does not present a certificate to server and you explicitely requested that a client needs to present one (in server code):
SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, NULL);
What you probably need is to tell your client code to use certificate (along with a private key):
SSL_CTX_use_certificate_chain_file(ctx, pcszCertPath);
SSL_CTX_use_PrivateKey_file(ctx, pcszPrivKeyPath,SSL_FILETYPE_PEM);
I hope that helps.
Also make sure that your server uses the same certificate chain (that it trusts the same CA's). If this is a problem, let me know and I'll help you do that.
With wireshark, you will find out if the server ever requested certificate from the client. The command would be "CertificateRequest".
I was getting a similar error (only line number different):
140671281543104:error:140890B2:SSL routines:SSL3_GET_CLIENT_CERTIFICATE:no certificate returned:s3_srvr.c:3292:
I had generated self-signed certificates using the procedure mentioned in https://help.ubuntu.com/community/OpenSSL.
After juggling with the error for one day, i found that the error was because the self-generated CA was not in the trust chain of the machine I was using.
To add the CA to the trust chain in RHEL-7, one can follow the below procedure:
To add a certificate in the simple PEM or DER file formats to the
list of CAs trusted on the system:
Copy it to the
/etc/pki/ca-trust/source/anchors/
subdirectory, and run the
update-ca-trust
command.
If your certificate is in the extended BEGIN TRUSTED file format,
then place it into the main source/ directory instead.
I think the above procedure can be followed for fedora too.
If "update-ca-trust" command is not available, it might be useful to explore the commands like "update-ca-certificates".
Hope this will be useful to someone.
Difference Between SSLCACertificateFile and SSLCertificateChainFile
SSLCertificateChainFile is generally the correct option to choose, as it has the least impact; it causes the listed file to be sent along with the certificate to any clients that connect.
Provide all the Root CA into the following file to resolve the issue
SSLCACertificateFile (hereafter "CACert") does everything SSLCertificateChainFile does (hereafter "Chain"), and additionally permits the use of the cert in question to sign client certificates. This sort of authentication is quite rare (at least for the moment), and if you aren't using it, there's IMHO no reason to augment its functionality by using CACert instead of Chain. On the flipside, one could argue that there's no harm in the additional functionality, and CACert covers all cases. Both arguments are valid.
Needless to say, if you ask the cert vendor, they'll always push for CACert over Chain, since it gives them another thing (client certs) that they can potentially sell you down the line. ;)
Modify the server code with the below line:
Server code:
SSL_CTX_load_verify_locations(ctx,"client_certificate_ca.pem", NULL);
Here client_certificate_ca.pem is the file which generated the client certificates.
verify your client certificate with the "client_certificate_ca.pem" file using below command.
verify -CAfile client_certificate_ca.pem client_certificate.pem
Client code:
if (SSL_CTX_use_certificate_file(ctx, "client_certificate.pem", SSL_FILETYPE_PEM) <= 0)
{
}
if (SSL_CTX_use_PrivateKey_file(ctx, "client_certificate.ky", SSL_FILETYPE_PEM) <= 0)
{
}
if (!SSL_CTX_check_private_key(ctx))
{
}