Generate Certificate for TomatoUSB from Active Directory CA

I wanted to install a cert on my router so that I could stop getting shit for not trusting it when I log in. However, installing the cert on every device that I access it with. Since I've got all my computers on a domain, I can just install the CA role on my DC, so I don't need to fuck around with an untrusted CA like StartCom who offer free certs, but still require you to install the CA chain, or buy a ridiculously overpriced cert from some random CA.
tl;dr

Update 2019-01-09:

Don't bother doing this. Now that LetsEncrypt is a thing, there's no point in trying to do this. If you've got an AD CA, you can set your internal DNS to be something that's publicly resolvable and grab a wildcard. Install that with some scripting magic and be done with what are effectively self-signed certs.

Since I access the router internally with a different hostname than I do externally, it needed to be a SAN/UCC cert, which makes things a bit more tricky, since there's no built in way to create a CSR for one via the OpenSSL CLI, this was a bit harder. So following the instructions from this page, I generated my own OpenSSL configuration settings, and exported the CSR:

openssl req -new -nodes -out CertificateRequest.csr -config UCCSANRequest.conf

I did this in /jffs so that the request and private key would be persistent in case I fuck something up and reboot, I don't lose my shit. So, it saves the new private key in privkey.pem, and the CSR is, obviously CertificateRequest.csr.

With a Windows 2008R2 server, importing CSRs from OpenSSL isn't possible without using the WebGUI. Windows fails to generate the cert with error 0x80094801: Denied by Policy Module, The request does not contain a certificate template extension or the Certificate Template request attribute.

The request contains no certificate template information, 0x80094801 (-2146875391)

So, to the website it is, go to https://yourca/certsrv, and select Request a certificate, then click on advanced certificate request. Paste the contents of the CSR into the Saved Request window, select Web Server from the Certificate Template section, click submit, and then download the DER encoded certificate.

So, now all I should have to do is copy to NVRAM, and all should be well. But not so much. According to this post, all I should need to do is tar up the cert and the private key, set them to an NVRAM field, commit, and done. But that doesn’t work at all. After reboot the cert is gone, and I have to do it over and over again.

Rather than figuring out why everything is stupid and nothing works, I figured kludging would be easier. I saved the files on the router’s jffs, and then set the init script to do:

rm /etc/cert.pem
rm /etc/key.pem
ln -s /jffs/privkey.pem /etc/key.pem
ln -s /jffs/cert.pem /etc/cert.pem
service httpd restart

So, this removes the default private key and certificate, and then symlinks the ones we want and then restarts the webserver, and everything is bingo bango; even after a reboot. Unlike my experience with DD-WRT’s sketchy behaviour with running init scripts, Tomato seems to actually do them properly and reliably.