Important Note: The method of validating certificates in my question below is incorrect, and will result in both false positives and false negatives. See my answer for the correct method.
I'm in the process of testing a tool I wrote to test all of the certificates in our environment, and I've run into an issue where OpenSSL doesn't seem to recognize a particular GoDaddy root certificate.
The error text:
$ openssl verify -CAfile bundle.txt cert.txt
cert.txt: C = US, ST = Arizona, L = Scottsdale, O = "GoDaddy.com, Inc.", CN = Go Daddy Root Certificate Authority - G2
error 2 at 2 depth lookup:unable to get issuer certificate
But that certificate is definitely in both /etc/pki/tls/certs/ca-bundle.crt
and ca-bundle.trusted.crt
. I've manually verified that the Issuer and Subject keys in the x509v3 extensions match up back to KeyID D2:C4:B0:D2:91:D4:4C:11:71:B3:61:CB:3D:A1:FE:DD:A8:6A:D4:E3
in the trusted bundles.
Am I missing something?
Certificate details:
Certificate:
Issuer: C=US, ST=Arizona, L=Scottsdale, O=GoDaddy.com, Inc., OU=http://certs.godaddy.com/repository/, CN=Go Daddy Secure Certificate Authority - G2
X509v3 Subject Key Identifier:
28:3C:0E:1A:82:3E:7F:22:A6:DD:22:8C:45:78:BF:F6:40:47:4F:8A
X509v3 Authority Key Identifier:
keyid:40:C2:BD:27:8E:CC:34:83:30:A2:33:D7:FB:6C:B3:F0:B4:2C:80:CE
Bundle1:
Subject: C=US, ST=Arizona, L=Scottsdale, O=GoDaddy.com, Inc., OU=http://certs.godaddy.com/repository/, CN=Go Daddy Secure Certificate Authority - G2
Issuer: C=US, ST=Arizona, L=Scottsdale, O=GoDaddy.com, Inc., CN=Go Daddy Root Certificate Authority - G2
X509v3 Subject Key Identifier:
40:C2:BD:27:8E:CC:34:83:30:A2:33:D7:FB:6C:B3:F0:B4:2C:80:CE
X509v3 Authority Key Identifier:
keyid:3A:9A:85:07:10:67:28:B6:EF:F6:BD:05:41:6E:20:C1:94:DA:0F:DE
Bundle2:
Subject: C=US, ST=Arizona, L=Scottsdale, O=GoDaddy.com, Inc., CN=Go Daddy Root Certificate Authority - G2
Issuer: C=US, O=The Go Daddy Group, Inc., OU=Go Daddy Class 2 Certification Authority
X509v3 Subject Key Identifier:
3A:9A:85:07:10:67:28:B6:EF:F6:BD:05:41:6E:20:C1:94:DA:0F:DE
X509v3 Authority Key Identifier:
keyid:D2:C4:B0:D2:91:D4:4C:11:71:B3:61:CB:3D:A1:FE:DD:A8:6A:D4:E3
Trusted:
Subject: C=US, O=The Go Daddy Group, Inc., OU=Go Daddy Class 2 Certification Authority
X509v3 Subject Key Identifier:
D2:C4:B0:D2:91:D4:4C:11:71:B3:61:CB:3D:A1:FE:DD:A8:6A:D4:E3
X509v3 Authority Key Identifier:
keyid:D2:C4:B0:D2:91:D4:4C:11:71:B3:61:CB:3D:A1:FE:DD:A8:6A:D4:E3
DirName:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
serial:00
To add to the WTFery in play, opening a connection to the server in question using openssl s_client
shows the certificate verifying just fine.
$ openssl s_client -servername www.foo.com -connect www.foo.com:443
Certificate chain
0 s:/OU=Domain Control Validated/CN=*.foo.com
i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy.com/repository//CN=Go Daddy Secure Certificate Authority - G2
1 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./OU=http://certs.godaddy.com/repository//CN=Go Daddy Secure Certificate Authority - G2
i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./CN=Go Daddy Root Certificate Authority - G2
2 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc./CN=Go Daddy Root Certificate Authority - G2
i:/C=US/O=The Go Daddy Group, Inc./OU=Go Daddy Class 2 Certification Authority
...yadda yadda yadda...
Verify return code: 0 (ok)
The naming of the openssl verify
flags can be a bit counter-intuitive, and none of the documentation I found does much to address that. As x539 touched on I was using the -CAfile
option incorrectly, and additionally I was missing the -untrusted
option to specify the intermediate certificates.
I've found that the reason that the validation passed for most certificates is that most CAs have begun including the root certificate in the CA bundle, and the -CAfile
option essentially defines what should comprise the trusted portion of the chain, including the root certificate. It was in the case that the intermediate bundle did not contain the root that my initial, incorrect method of validation failed.
Now I was under the misconception that -untrusted
implied something like "never use these certificates!", but is rather intended to specify a chain of non-trusted certificates that leads back to a root in the "trusted" -CAfile
bundle.
So the correct way to validate a certificate by using its intermediate certificate[s] and a trusted root bundle is:
openssl verify -CAfile /etc/pki/tls/certs/ca-bundle.crt -untrusted bundle.crt certificate.crt