(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.
badchain.pem
come from? Was it supposed to berougechain.pem
again? – Greg Dubickiopenssl s_client
, but below @paulus said he was usingopenssl s_client
and didn't see the problem. So I don't know what's going on. – Mark Doliner