I'm currently testing an mTLS scenario server and client using boost asio. Each party has its own certificate and key, using self signed CA root (OpenSSL).
It works as expected, however there is a major issue which after searching quite a lot, came to a dead end. I need to be able to revoke client side certificates at any point in time.
So the question is, how to revoke certificates from clients? (make asio server refuse them)
I tried several options in the boost asio context without success, I could not find a way to revoke the client side certificate.
Related
I need a snippet of code for a program i am writing with Boost Asio SSL.
I have a system of two clients, that connect with each other. I require them to do a mutual authentication, so, that at the end of the handshake() command, both clients can be certain that the other client has the private key to the certificate they supplied.
Both clients have a context object, lets call them ctx1and ctx2 and each client has a public certificate and a private key.
Is it possible to set up the context objects so, that when i call socket.handshake() the clients will do a two-way authentication. If not, what would be the correct way to go about to achieve my goal ?
It looks like boost just uses the OpenSSL interface.
I don't know boost much but I've implemented lots of OpenSSL internals for Perl and came to the following conclusions after reading the relevant parts of the boost source code:
To have mutual authentication with OpenSSL you have to use SSL_VERIFY_PEER on the client side and SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT on the server side. If you use only SSL_VERIFY_PEER on the server side it will only send the certificate request to the client, but silently accept if the client sends no certificate back.
With boost this would probably be:
ctx.set_verify_mode(ssl::verify_peer); // client side
ctx.set_verify_mode(ssl::verify_peer|ssl::verify_fail_if_no_peer_cert); // server side
If you set verify_mode this way it will verify the certificates against the configured trusted CAs (set with ctx.load_verify_file or ctx.load_verify_path).
If you have full control over the CA which signed the certificates (i.e. its your own CA) it might be enough for you to accept any certificates signed by this CA. But if you use a CA which also signed certificates you don't want to accept, like typically the case with public CAs, you also need to verify the contents of the certificate. Details how to do this depends on your protocol, but for the usual internet protocols like HTTP or SMTP this involves checking commonName and/or subjectAltNames of the certificate. Details like wildcard handling vary between the protocols.
Boost provides rfc2818_verification to help you with HTTP-style validation, although from reading the code I think the implementation is slightly wrong (multiple wildcards accepted, IDN wildcards allowed - see RFC6125 for requirements).
I don't know of any standards for verifying client certificates. Often just any certificate signed by a specific (private) CA will be accepted. Other times certificates from a public CA matching a specific e-mail pattern. It looks like boost does not help you much in this case, so you probably have to get OpenSSL SSL* handle with sock.native_handle() and then use OpenSSL functions to extract certificate (SSL_get_peer_certificate) and to check the contents of the certificate (various X509_* functions).
At least if public CAs are involved you should also check the revocation status of the certificates. It looks like boost does not provide a direct interface to CRL (certificate revocation list) so you have to use ctx.native_handle() with the appropriate OpenSSL functions (X509_STORE_add_crl etc). Using OCSP (online status revocation protocol) is way more complex and relevant OpenSSL functions are mostly undocumented, which means you have to read the OpenSSL source code to use them :(
One cant force other side to authenticate against you, it is up to protocol, Ieach side autenticate only against other side. Just follow manuals as http://www.boost.org/doc/libs/1_47_0/doc/html/boost_asio/overview/ssl.html
ssl::context ctx(ssl::context::sslv23);
ctx.set_verify_mode(ssl::verify_peer);
ctx.load_verify_file("ca.pem");
I am trying to figure out how to tell Boost Beast to use a client authentication certificate during the SSL handshake.
I have looked at the Boost Beast documentation, but have been unable to find any hint on client side certificates. The examples also do not cover this case.
I'm still learning to program in C++ using OpenSSL, and trying to build and application where the client initiates the connections to the server. I have
Generated a certificate/key pair using OpenSSL (as .pem)
Called the SSL_use_certificate_file/PrivateKey_file in the server's initialization
Store the server's certificate with the clien and verify the certificate on client side when trying to connect to server
I noticed that even when I passed an incorrect certificate to the client and (correctly) failed 3., the connection still goes through, and the client and server continue doing whatever they were originally supposed to do.
What I would like to ask is,
Is there something wrong with how I'm using the certificate?
How can I make it such that the connection will fail if the client does not have the server's certificate?
You seem to have a design flaw.
The point of a server certificate is to protect the client. If you control the client, you should use the (detected) failure to abort the connection from the client side.
If you don't control the client, but need to trust it, you need to use client certificates. These are much less common, but definitely allowed in the SSL/TLS protocol underlying HTTPS. The effect of a client certificate is reversed: when the server detects a failure with a client certificate, the server can disconnect.
I have a SOAP webserver developed in Delphi XE2 that exposes some methods and it uses SSL. I built my client also in Delphi XE2, and I use THTTPRIO to connect to webserver. My question is related to the use of SSL certificatest with THTTPRIO. If I call my webservice it works without having a certificate installed, but I think that it shouldn't.
Second scenario :I have a self signed certificate which I installed it and after I made a call to my webservice it works also.
When I inspected my events: HTTPRIOAfterExecute and HTTPRIOBeforeExecute, I converted SoapRequest and SOAPResponse to string from TStream and seems that it isn't encrypted in both cases. I also found on another forum the same question but with no response.
I searched for info about SOAP SSL Clients with Delphi but couldn't find any new info. Could any of you guys give me some advices regarding this issue?
If I call my webservice it works without having a certificate
installed, but I think that it shouldn't.
Not many web services require client certificates (with exceptions like banking and other high risk environments). It is more common that clients want to verify the server identity, and this is done with server certificates.
So I would say this web service does work in a normal, expected way.
HTTPRIOAfterExecute and HTTPRIOBeforeExecute, I converted SoapRequest
and SOAPResponse to string from TStream and seems that it isn't
encrypted in both cases
This is correct, the message payload will appear unencrypted because SSL / TLS does encryption on the transport layer. Your application will not see the encrypted data, which actually makes things easier.
You can add encryption for the message payload, there are generic libraries for this (however I have no experience with using encryption HTTPRio).
I'm attempting to write a simple HTTP/HTTPS proxy using Boost ASIO. HTTP is working fine, but I'm having some issues with HTTPS. For the record this is a local proxy. Anyway so here is an example of how a transaction works with my setup.
Browser asks for Google.com
I lie to the browser and tell it to go to 127.0.0.1:443
Browser socket connects to my local server on 443I attempt to read the headers so I can do a real host lookup and open a second upstream socket so I can simply forward out the requests.
This is where things fail immediately. When I try to print out the headers of the incoming socket, it appears that they are already encrypted by the browser making the request. I thought at first that perhaps the jumbled console output was just that the headers were compressed, but after some thorough testing this is not the case.
So I'm wondering if anyone can point me in the right direction, perhaps to some reading material where I can better understand what is happening here. Why are the headers immediately encrypted before the connection to the "server" (my proxy) even completes and has a chance to communicate with the client? Is it a temp key? Do I need to ignore the initial headers and send some command back telling the client what temporary key to use or not to compress/encrypt at all? Thanks so much in advance for any help, I've been stuck on this for a while.
HTTPS passes all HTTP traffic, headers and all, over a secure SSL connection. This is by design to prevent exactly what you're trying to do which is essentially a man-in-the-middle attack. In order to succeed, you'll have to come up with a way to defeat SSL security.
One way to do this is to provide an SSL certificate that the browser will accept. There are a couple common reasons the browser complains about a certificate: (1) the certificate is not signed by an authority that the browser trusts and (2) the certificate common name (CN) does not match the URL host.
As long as you control the browser environment then (1) is easily fixed by creating your own certificate authority (CA) and installing its certificate as trusted in your operating system and/or browser. Then in your proxy you supply a certificate signed by your CA. You're basically telling the browser that it's okay to trust certificates that your proxy provides.
(2) will be more difficult because you have to supply the certificate with the correct CN before you can read the HTTP headers to determine the host the browser was trying to reach. Furthermore, unless you already know the hosts that might be requested you will have to generate (and sign) a matching certificate dynamically. Perhaps you could use a pool of IP addresses for your proxy and coordinate with your spoofing DNS service so that you know which certificate should be presented on which connection.
Generally HTTPS proxies are not a good idea. I would discourage it because you'll really be working against the grain of browser security.
I liked this book as a SSL/TLS reference. You can use a tool like OpenSSL to create and sign your own certificates.