After running into a few hurdles, I managed to get rust openssl bindings to work, which means that this is now the time to actually wire things properly in my network protocol, let’s see how that works, shall we?
First, we have the OpenSSL setup:
As you can see, this is pretty easy and there isn’t really anything there that is of actual interest. It does feel a whole lot easier than dealing with OpenSSL directly in C, though.
That said, when I started actually dealing with the client certificate, things got a lot more complicated. The first thing that I wanted to do is to do my authentication, which is defined as:
- Client present a client certificate (can be any client certificate).
- If a client doesn’t give a certificate, we accept the connection, send a message (using the encrypted tunnel) and abort.
- If the client provide an certificate, it must be one that was previously registered in the server. That is what allowed_certs_thumbprints is for. If it isn’t, we accept the connection, write an error and abort.
- If the client certificate has expired or is not yet valid, accept, write error & abort.
You get the gist. Here is what I had to do to implement the first part:
Most of the code, actually, is about generating proper and clear error messages, more than anything else. I’m not sure how to get the friendly name from the certificate, but this seems to be a good enough stand-in for now.
We validate that we have a certificate, or send an error back. We validate that the certificate presented is known to us, or we send an error back.
The next part I wanted to implement was… really far too hard than it should be. I just wanted to verify that the certificate not before/not after dates are valid. And the problem is that the rust bindings for OpenSSL do not expose that information. Luckily, because it is using OpenSSL, I can just call to OpenSSL directly. That led me to some interesting search into how Rust calls out to C, how foreign types work and a lot of “fun” like that. Given that I’m doing this to learn, I suppose that this is a good thing, though.
Here is what I ended up with (take a deep breath):
Notice that I’m doing all of this (defining external function, defining helper functions) inside the authenticate_certificate function. Coming up with that was harder than expected, but I really liked the fact that it was possible, and that I can just shove this into a corner of my code and not have to make a Big Thing out of it.
And with that, I the authentication portion of my network protocol in Rust done.
The next stage is going to be implementing a server that can handle more than a single connection at a time .