There is a self-signed root CA certificate, rootcert.pem, with the following V3 extensions:
X509v3 extensions:
X509v3 Key Usage:
Certificate Sign
X509v3 Basic Constraints:
CA:TRUE
The rootcert.pem has CA flag set to true & its key usage permits certificate signing. The rootcert.pem signs a certificate foocert.pem with the following V3 extensions:
X509v3 extensions:
X509v3 Basic Constraints:
CA:FALSE
X509v3 Key Usage:
Digital Signature, Non Repudiation, Key Encipherment
The foocert.pem has CA flag set to false & its key usage does not permit certificate signing. But lets say, the foocert.pem signs a rougecert.pem.
Form a certificate chain of foocert & roguecert:
cat foocert.pem roguecert.pem > roguechain.pem
Verify using openssl verify. The verification is successful:
$ openssl verify -CAfile rootcert.pem roguechain.pem
roguechain.pem: OK
Verify with x509_strict, still its successful:
$ openssl verify -x509_strict -CAfile rootcert.pem badchain.pem
badchain.pem: OK
Lets say a system trusts just the root CA certificate. A peer gives its certificate chain, where one of the intermediate certificate is not supposed to be a CA (CA set to false & key usage does not permit certificate signing), still the openssl flags the chain is good?
How do I make openssl not trust such chains?
To resolve the chain issue: Search your Certificate Authority's (CA) website to download their intermediate CA file. This file links all of the trusted CA certificates needed to reach the root certificate. When this Intermediate CA file has been downloaded, you must upload it to the LoadMaster.
The lookup first looks in the list of untrusted certificates and if no match is found the remaining lookups are from the trusted certificates. The root CA is always looked up in the trusted certificate list: if the certificate to verify is a root certificate then an exact match must be found in the trusted list.
(edit: just noticed my answer is a longer and more detailed version of Chris Lesner's, I'd vote him up but I don't have the rep here yet :>)
I think you're still on the wrong track here. I think the actual issue is that 'verify' does not verify chains in a single file in this way.
The final argument to 'verify' is listed as [certificates]
and documented thus:
certificates
One or more certificates to verify. If no certificates are given, verify will attempt to read a
certificate from standard input. Certificates must be in PEM format.
You can pass multiple files - but each will be verified as a single leaf certificate, independent of the others. And it's not absolutely explicit, but it implies (and I can tell you that it is in fact the case; see code locations below for details) that one certificate will be read from each file. If you feed it a file containing multiple certificates concatenated together, it will in fact just verify the first certificate from the file as a leaf certificate, and entirely ignore the others.
Thus in your example, what you actually did was verify foocert.pem
as a leaf certificate, because it's the first certificate in your roguechain.pem
. foocert.pem
is valid as a leaf certificate, even with -purpose sslserver
. man x509
section CERTIFICATE EXTENSIONS
documents the conditions for the 'SSL Server' purpose:
SSL Server
The extended key usage extension must be absent or include the "web server authentication" and/or one
of the SGC OIDs. keyUsage must be absent or it must have the digitalSignature, the keyEncipherment set
or both bits set. Netscape certificate type must be absent or have the SSL server bit set.
and you can see that your foocert.pem
has no extended key usage and is not a Netscape type certificate; it does have key usage, with both Digital Signature and Key Encipherment bits set. Therefore, it passed the test.
To do the check you really wanted to do, you have to do this:
openssl verify -CAfile rootcert.pem -untrusted foocert.pem -purpose sslserver roguecert.pem
using the filenames you gave in your initial question. Basically, it's a reasonable simplification to say that you provide root CA certs as -CAfile
, -CApath
, or -trusted
, intermediate CA certs as -untrusted
, and the leaf certificate(s) to be validated as the final argument(s).
Note that the file passed as -untrusted
can contain multiple certificates concatenated together:
-untrusted file
A file of untrusted certificates. The file should contain multiple certificates in PEM format
concatenated together.
If you want to follow the code to confirm this, each leaf certificate file is loaded by load_cert()
in apps/apps.c
. The return for that function is X509
; X509
objects are single certificates. Compare with load_certs()
in the same file, which returns STACK_OF(X509)
- that's what OpenSSL typically uses for raw certificate chains.
The original answer proved to be wrong, so here's another one :)
It looks like openssl verify does only the certificate chain verifications and it doesn't check any flags (even with correct -purpose set). The library however does check the flags when you actually do an ssl/tls connection:
$ openssl s_client -verify 100 -CAfile cacert.pem -connect servername:443
verify depth is 100
CONNECTED(00000003)
depth=1 /CN=middle
verify error:num=24:invalid CA certificate
verify return:1
depth=1 /CN=middle
verify error:num=26:unsupported certificate purpose
verify return:1
depth=2 /CN=root
verify return:1
depth=1 /CN=middle
verify return:1
depth=0 /CN=leaf
verify return:1
---
Certificate chain
0 s:/CN=leaf
i:/CN=middle
1 s:/CN=middle
i:/CN=root
---
...
SSL-Session:
Protocol : TLSv1
...
Verify return code: 26 (unsupported certificate purpose)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With