Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SSL Certificate, not authenticating via thrift, but OK via browser

This is how I generate my SSL cert, key, etc:

openssl genrsa -out server.key 1024
openssl rsa -in server.key -out new_key.pem
openssl req -new -key server.key -out server.csr
openssl x509 -req -days 10000 -in server.csr -signkey new_key.pem -out server.crt

This works, i can see the output in chrome, although I get a warning that i'm going to get viruses first.

openssl s_server -cert server.crt -www -key new_key.pem

this is a snippet from the server. I'll be honest, i'm not sure exactly what every line is doing, though I have a good idea:

socketFactory->server(true); // this is the server
socketFactory->authenticate(false); // no auth?
socketFactory->loadCertificate("server.crt"); 
socketFactory->loadPrivateKey("new_key.pem");

client:

socketFactory->loadTrustedCertificates("server.crt");
socketFactory->authenticate(true); //auth? wierd, right? This guy does this:[1]

[1] http://permalink.gmane.org/gmane.comp.lib.thrift.user/1651

If i comment out loadTrustedCertificates in the client, then i get an SSL unverified certificate exception. With that line left in, i get an auth failure exception.

Here are 2 much longer code fragments, that put the above snippets in better perspective.
server:

shared_ptr<SkullduggeryHandler> handler(new SkullduggeryHandler());
shared_ptr<TBufferedTransportFactory> transportFactory =
        shared_ptr<TBufferedTransportFactory>(new TBufferedTransportFactory());
shared_ptr<TProtocolFactory> protocolFactory(new TBinaryProtocolFactory());
shared_ptr<TProcessor> processor(new SkullduggeryProcessor(handler));
shared_ptr<TSSLSocketFactory> socketFactory = 
      shared_ptr<TSSLSocketFactory>(new TSSLSocketFactory());
socketFactory->server(true);
socketFactory->authenticate(false);
socketFactory->loadCertificate("server.crt");
socketFactory->loadPrivateKey("new_key.pem");
shared_ptr<TSSLServerSocket> socket(new TSSLServerSocket(port, socketFactory));
TThreadedServer server(processor,
                               socket,
                               transportFactory,
                               protocolFactory);
server.serve();

client:

shared_ptr <TSSLSocketFactory> socketFactory = shared_ptr<TSSLSocketFactory>(new TSSLSocketFactory());
socketFactory->loadTrustedCertificates("server.crt");
socketFactory->authenticate(false);
shared_ptr <TSSLSocket>socket = socketFactory->createSocket(configuration.ip, configuration.port);
shared_ptr<TBufferedTransport> transport(new TBufferedTransport(socket));
shared_ptr<TProtocol> protocol(new TBinaryProtocol(transport));
SkullduggeryClient client(protocol);
transport->open();

Thanks for taking the time to read this. If there are glaring errors, I'll be glad to hear of it. This has been the bane of my existense for too long now. Too long.

like image 660
demonslayer319 Avatar asked Jun 09 '12 21:06

demonslayer319


People also ask

Why is my WIFI saying the SSL certificate is not trusted?

The SSL error may be because of some malware/virus, and the only thing that can solve it in this case is a Factory Data Reset. You can reset your phone by navigating to Settings >> Backup and Reset >> Factory data reset.

Why am I getting certificate errors on all websites?

You get this error primarily when your web browser cannot verify a website's SSL certificate. The website is a potential risk; hence, the warning ensures that your privacy and security are preserved. Many users reported that they could not access their favorite websites after the error message.


1 Answers

It seems you are generating self-signed certificates (which is fine), but the operations you are making with the openssl utility are confusing.

Line 1 is OK, it generates a private key.
Line 2 is useless: the output key is the same as the input key! (Try to diff the two keys to see).
Line 3 generates a CSR and line 4 actually self-signs it, so they can be merged together in one line as we will see.

Now, let's take a step back and let's try to understand what we are doing :-)

You are using SSL to authenticate and encrypt the communication between a Thrift server and a Thrift client. I assume you want to both:

  1. Protect the client from a rogue server (what your code is attempting to do)
  2. Protect the server from a rogue client (which seems even more important to me).

To make an HTTPS analogy, (1) is the classic server certificate, (2) is normally a username/password for the user. But with Thrift SSL, we will obtain mutual authentication by issuing a certificate also to the client.

The examples I will make will use self-signed certificates. They can easily be adapted to a mini CA managed by openssl, and I leave this as an exercise to the reader.

Generate the server private key:
openssl genrsa -out server-key.pem 2048

Generate the associated public key and self-sign it:
openssl req -new -x509 -key server-key.pem -out server-cert.pem -days 10000

Generate the client private key:
openssl genrsa -out client-key.pem 2048

Generate the associated public key and self-sign it:
openssl req -new -x509 -key client-key.pem -out client-cert.pem -days 10000

Note: when openssl req asks for "Common Name (e.g. server FQDN or YOUR name)", put the FQDN of the host on which the Thrift program will run. This will allow not to customize Thrift's AccessManager class. If on the other hand the FQDN can not be known in advance, one needs to inherit AccessManager and override the verify() methods accordingly. See TSSLSocket.cpp.

Good, now to the code.

On the server side:

socketFactory->server(true); is redundant, remove it.

socketFactory->authenticate(false) is a bit misleading. A better name would have been authenticatePeer. If you say false, it will not authenticate the client, but we decided before we want mutual authentication.

So, a SSL preamble for a server is:

try {
    signal(SIGPIPE, SIG_IGN); // See README.SSL
    shared_ptr<TSSLSocketFactory> sslSocketFactory(new TSSLSocketFactory());
    sslSocketFactory->loadPrivateKey(myKey);
    sslSocketFactory->loadCertificate(myCert);
    sslSocketFactory->authenticate(true);
    sslSocketFactory->loadTrustedCertificates(trustedCerts);
    sslSocketFactory->ciphers("HIGH:!DSS:!aNULL@STRENGTH");
    ...
    } catch (TException& tx) {
        ....
    }

Where myKey is server-key.pem, myCert is server-cert.pem and trustedCerts is... either the cert of a trusted CA, or, in case of a self-signed cert, the cert of the client. You can cat multiple certs one after the other in the same file. In our example, we will put client-cert.pem that we created before.

A SSL preamble for a client is exactly the same, with the correct client private key, client cert and, for trustedCerts, the cert of the peer: server-cert.pem that we created before.

That's all :-) Try to understand before jumping to code it, if you don't have a clear picture of how SSL (mutual) authentication works, it is difficult to understand the error messages. The code I showed is tested to work.

Documentation-wise, unfortunately Thrift is close to nothing. For SSL, you can see: lib/cpp/README.SSL, test/cpp/src/TestServer.cpp and test/cpp/src/TestClient.cpp. Be warned that TestServer.cpp doesn't do mutual authentication, which is an error IMHO.

like image 110
marco.m Avatar answered Oct 20 '22 06:10

marco.m