FW 3.2.7 breaks custom web certificates
alxwolf opened this issue · 19 comments
my internal CA is as follows:
Root CA
Intermediate CA
Router certificate
the router certificate is signed by my intermediate CA.
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
83:a3:ae:9a:21:e4:00:4c:d2:89:5a:99:f9:41:fb:ad
Signature Algorithm: ecdsa-with-SHA256
Issuer: O = PaulGG Intranet, CN = PaulGG Intranet Intermediate CA
Validity
Not Before: Dec 14 12:04:01 2023 GMT
Not After : Dec 15 12:05:01 2023 GMT
Subject: CN = router.paulgg.int
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
RSA Public-Key: (2048 bit)
Modulus:
00:a2:dc:42:d7:35:b3:dd:5b:96:86:29:4c:64:e7:
32:48:1c:0a:bb:e6:5f:43:ad:63:de:19:12:3e:3f:
a5:52:f3:20:1e:30:23:c4:ac:56:aa:d8:b8:5d:ae:
d8:fe:6b:e8:ce:c5:b6:e6:c8:20:36:e0:98:35:3f:
b5:c3:d3:51:cc:91:ca:1d:38:a7:c8:9c:9e:7b:9a:
5e:41:e1:5b:38:7e:b8:7d:6e:a3:d7:51:11:b9:c7:
1c:be:f7:44:b2:a9:f5:63:1a:f3:43:64:ea:11:f1:
97:4b:6b:a6:e4:95:e1:05:98:45:4f:63:8b:ae:ac:
8d:aa:7d:9b:a5:d8:b8:1d:61:5e:c1:9b:3a:d8:91:
45:57:a0:d6:b7:1c:d4:88:4e:01:e5:c3:61:b4:6d:
68:1d:c8:2c:00:9a:e8:fb:0c:76:f1:f0:b8:d2:22:
3b:35:c8:9c:b9:80:db:7b:d9:ee:b3:af:b0:0d:fc:
70:b8:ef:0b:f6:4c:39:b5:c8:d0:9c:86:b3:71:a1:
a5:42:26:f7:3e:82:4c:23:a0:84:67:f6:0a:a9:34:
eb:ac:f2:f6:bc:a5:f5:6e:1a:34:e8:2a:a6:7e:42:
90:28:b9:db:34:1d:0d:b7:a1:1a:65:d3:61:55:ad:
ec:52:0a:fe:f5:11:41:1d:21:12:25:fc:02:e8:4d:
9d:cd
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Authority Key Identifier:
keyid:58:1E:16:42:18:5A:CF:A5:DA:29:2E:37:50:AF:4E:5D:1B:CE:B9:93
X509v3 Key Usage: critical
Digital Signature, Key Encipherment
X509v3 Extended Key Usage:
TLS Web Server Authentication, TLS Web Client Authentication
X509v3 Subject Key Identifier:
98:41:E0:9B:1A:F8:23:F4:8F:6C:D7:53:37:A4:4E:D6:79:D3:A9:57
X509v3 Subject Alternative Name:
DNS:router.paulgg.int
1.3.6.1.4.1.37476.9000.64.1:
0C.....paul@paul.systems.+V5B126r4pfQJE_PkrMvSvc_gFds2wEs5EhzVSdSF-dQ
Signature Algorithm: ecdsa-with-SHA256
30:45:02:21:00:be:81:ea:60:62:19:71:3e:0b:54:48:43:79:
56:5f:b5:59:23:dc:21:1b:94:16:07:a6:74:f6:5a:24:ff:af:
43:02:20:25:29:02:8e:64:0f:01:b0:4e:b8:3d:47:8c:c5:b1:
f1:80:46:86:fd:48:55:df:65:fb:af:fb:2e:24:eb:8f:a9
I just checked /etc/ssl/certs and looks like there's some stuff that has been deleted, including my root certificate from the keystore.
When I have some more time I'll play around with this...
Originally posted by @therealpaulgg in #61 (comment)
@therealpaulgg opened a new issue, your case is different from the RADIUS issue many people seem to see.
You debugged that your root certificate is gone from keystore - that may be another hint in the direction that UniFiOS says "incorrect / incomplete chain -> trash it, put self-signed in".
but as you wrote, root cause for trust being broken in cert store is unclear...
I assume when you copy the certs manually and restart unifi-core
, they get culled, too?
So I mentioned in my last comment that I ended up trying to fix my cert store manually by both re-adding my Root CA and intermediate CA (I didnt need this previously)
ran openssl verify and it reported OK
Yeah copied the certs manually and they are gone.
Maybe if I try configuring RADIUS (I never bothered) it'll work?
This one is a bit trickier to solve than the RADIUS one. Still not entirely sure what to do.
I did some digging based on what @ouaibe had mentioned in the other issue, and I was only able to find this one entry:
"unifiNetwork": {
"certificate": {
"crt": "CERT_HERE"
},
"controllerURL": "https://192.168.1.1:8443",
"enabled": true,
"informURL": "http://192.168.1.1:8080/inform",
"sitename": "default",
"uciAllowList": []
},
this CERT_HERE is also a base64 encoded value but does not decode the same way that the radius certificates do, so I am a bit confused.
Tried searching for other configuration files and had no luck. There is one called /data/udapi-config/udapi-net-cfg.json
but that appears to just be a subset of the previously mentioned /data/udapi-config/ubios-udapi-server/ubios-udapi-server.state
.
Its like the implementation of RADIUS and the web certs are just completely different, and I'm not able to find where they are configured at.
Looking at it, that certificate is in DER format (binary), not PEM. These are both interchangeable/convertible using the following commands:
DER -> PEM
openssl x509 -inform der -in certificatename.der -out certificatename.pem
PEM->DER
openssl x509 -outform der -in certificatename.pem -out certificatename.der
So in theory, if you already have your local CRT file server.crt
in PEM format, you can do something like this:
jq --arg content "$(openssl x509 -outform der -in server.crt | base64)" '.services.unifiNetwork.certificate.crt = $content' /data/udapi-config/ubios-udapi-server/ubios-udapi-server.state > /data/udapi-config/ubios-udapi-server/ubios-udapi-server.new.state
Then validate the NEW file, the JSON content at .services.unifiNetwork.certificate.crt
and if you're satisified with it (having taken a backup) you can replace the current .state
file with the new one, and finally restart the udapi-server
.
This makes sense... only concern I have is where is the key? previously for web certs it needed both the cert and the key. You should need both pieces, right?
A CRT file for a server can (should?) contain both the cert and the private key. You could try generating a regular CRT file in PEM format, that would contain the two sections:
-----BEGIN CERTIFICATE-----
...
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
...
-----END PRIVATE KEY-----
And then convert that to DER and see if it works?
Alternatively, you could try hacking a key="value"
element in the JSON file similar to how the other certs are setup, and see if udapi-server
breaks while booting?
After digging a bit more, the unifiNetwork
certificate in the JSON config file has the exact same fingerprint than the one in the keystore at /data/unifi/data/keystore
.
Compared the output of openssl x509 -inform der -in unifinetwork.der -noout -fingerprint
and the output of keytool -v -list -keystore /data/unifi/data/keystore -storepass aircontrolenterprise
.
This might mean that the keystore is used to back the signature for that part of the certificate management system.
FWIW you can export the existing private key in PEM
format using the following commands:
keytool -importkeystore -srckeystore /data/unifi/data/keystore -srcstorepass aircontrolenterprise -destkeystore /tmp/keystore.p12 -deststoretype PKCS12 -deststorepass aircontrolenterprise
openssl pkcs12 -in /tmp/keystore.p12 -nodes -nocerts -out /tmp/private_key.pem
But I'm not sure how that private key would be useful for you, instead you could try adding your own private key/certificate to the existing keystore and see how it behaves with udapi-server
.
Good luck!
Unfortunately it seems this certificate is completely different from the one on the web portal. Fingerprints dont match at all and the issuers are totally different (CN = unifi.local
for web cert vs. C = US, ST = New York, L = New York, O = Ubiquiti Inc., OU = UniFi, CN = UniFi
)
I found a log in /data/unifi-core/logs/http.log
saying:
2023-12-18T21:15:19.493Z - info: Self signed certificate needs regenerated, regenerating
2023-12-18T21:15:19.494Z - info: Generating /data/unifi-core/config/unifi-core.crt
wonder if the underlying cert implementations for unifi-core and the other stuff are just totally different.
Ah, reading your message I had assumed the CRT in the JSON file was the right one, sorry to have mis-interpreted that.
It's very likely they combine 3+ certificate management mechanisms, it seems to be all over the place between freeradius, the keystore (that must be used for something, maybe intra-Unifi comms over HTTPS), some certs for Protect and the unifi-core/Web UI stuff...
One thing you "could" try, maybe to get more output out of udapi-server
boot sequence is to chattr +i
the unifi-core.crt
file. It is very likely they're not checking for that so either it makes it immutable across reboots as a temporary solution for you, or crashes udapi-server
and/or you get more info in its journalctl -u
because it cannot replace the file...
Either way, if they are re-generating it, the private key and the cert must be somewhere...
One thing you "could" try, maybe to get more output out of
udapi-server
boot sequence is tochattr +i
theunifi-core.crt
file. It is very likely they're not checking for that so either it makes it immutable across reboots as a temporary solution for you, or crashesudapi-server
and/or you get more info in itsjournalctl -u
because it cannot replace the file...
After being frustrated by 3.2.9's continuation of 3.2.7's bad behavior, I found this thread. I can confirm that marking both the cert and key immutable prevent them from being replaced upon restarting the unifi-core service. It's a kludge, but it'll do until a real fix comes along!
One thing you "could" try, maybe to get more output out of
udapi-server
boot sequence is tochattr +i
theunifi-core.crt
file. It is very likely they're not checking for that so either it makes it immutable across reboots as a temporary solution for you, or crashesudapi-server
and/or you get more info in itsjournalctl -u
because it cannot replace the file...After being frustrated by 3.2.9's continuation of 3.2.7's bad behavior, I found this thread. I can confirm that marking both the cert and key immutable prevent them from being replaced upon restarting the unifi-core service. It's a kludge, but it'll do until a real fix comes along!
Absolutely genius workaround...this totally solves my problem. Finally got around to actually implementing it on my Unifi router and its pretty straightforward. It is a little more complicated since I'm using step-ca
which renews certs daily, but it was easy enough to modify the renewal service to simply make the file temporarily mutable and then make it immutable once renewed.
Thank you very much, I had pretty much given up on the idea of accessing Unifi from a trusted domain at this point.
Not sure this helps, but I'm on EA release v3.2.12 and all I had to do was place move the cert and key to /data/eus_certificates/unifi-os.crt and /data/eus_certificates/unifi-os.key respectively.
@forrestrae interesting observation, have you ever used Glenn R.'s "UniFi Let's Encrypt" before?
That script creates such directory. if you did not use it before, maybe UI has implemented that scripts mechanisms into firmware.