Could you give some advice?
Here is a more detailed answer and how to fix the problem in Ruby with something other than the pathetic OpenSSL::SSL::VERIFY_NONE .
$ openssl s_client -connect 64.103.26.61:443 | openssl x509 -text -noout depth=2 C = BM, O = QuoVadis Limited, CN = QuoVadis Root CA 2 ... Subject: C=US, ST=CA, L=San Jose, O=Cisco Systems, Inc., CN=msesandbox.cisco.com ... X509v3 Subject Alternative Name: DNS:msesandbox.cisco.com
So, the device has the DNS name msesandbox.cisco.com. nslookup tells you a good hostname:
$ nslookup msesandbox.cisco.com Server: 192.168.1.1 Address: 192.168.1.1
So, the first thing you need to do is connect to it by DNS name, not IP address.
If you issue certificates for the cisco.com domain (or you can make a request), you can ask to add the IP address 64.103.26.61 as the Subject Alternative Name (SAN). Thus, the certificate will have two SANs.
Now, if you go back to the openssl command:
$ openssl s_client -connect 64.103.26.61:443 | openssl x509 -text -noout depth=2 C = BM, O = QuoVadis Limited, CN = QuoVadis Root CA 2 verify error:num=19:self signed certificate in certificate chain ... Issuer: C=US, O=HydrantID (Avalanche Cloud Corporation), CN=HydrantID SSL ICA G2 ... Subject: C=US, ST=CA, L=San Jose, O=Cisco Systems, Inc., CN=msesandbox.cisco.com
You will see that the issuer and the entity are different from each other. This means that this is not a self-signed certificate. The certificate was issued by HydrantID (Avalanche Cloud Corporation).
If you look further, you will see that the Issuer's public key (Authorization Key Identifier) ββis different from the Subject public key (Keyword Identifier):
X509v3 Authority Key Identifier: keyid:98:6A:B6:2D:2E:BF:A7:AA:9F:F6:F7:D6:09:AF:D5:8B:57:F9:8A:B7 ... X509v3 Subject Key Identifier: B5:3D:50:53:0A:A2:06:9E:9A:29:89:7A:AB:96:90:FE:9D:6B:57:A0
Again, he is not himself signed.
If you return to the OpenSSL team again, you will see that the issuer has HydrantID SSL ICA G2 , and its issuer is QuoVadis Root CA2 G3 :
depth=2 C = BM, O = QuoVadis Limited, CN = QuoVadis Root CA 2 verify return:1 depth=1 C = US, O = HydrantID (Avalanche Cloud Corporation), CN = HydrantID SSL ICA G2 verify return:1 depth=0 C = US, ST = CA, L = San Jose, O = "Cisco Systems, Inc.", CN = msesandbox.cisco.com verify return:1
This means QuoVadis Root CA2 G3 issued by HydrantID SSL ICA G2 ; and HydrantID SSL ICA G2 issued by msesandbox.cisco.com . QuoVadis Root CA2 G3 is the pinnacle of the food chain.
You can get the QuoVadis Root CA2 G3 from the CA QuoVadis CA Certificate Download :
$ curl -O -J -L https://www.quovadisglobal.bm/Repository/~/media/Files/Roots/quovadis_rca2g3_der.ashx % Total % Received % Xferd Average Speed Time Time Time Current Dload Upload Total Spent Left Speed 100 1380 100 1380 0 0 1808 0 --:--:-- --:--:-- --:--:-- 5726 curl: Saved to filename 'quovadis_rca2g3_der.cer' $ openssl x509 -in quovadis_rca2g3_der.cer -inform DER -out quovadis-ca.pem -outform PEM $ cat quovadis-ca.pem -----BEGIN CERTIFICATE----- MIIFYDCCA0igAwIBAgIURFc0JFuBiZs18s64KztbpybwdSgwDQYJKoZIhvcNAQEL BQAwSDELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxHjAc BgNVBAMTFVF1b1ZhZGlzIFJvb3QgQ0EgMiBHMzAeFw0xMjAxMTIxODU5MzJaFw00 ... -----END CERTIFICATE-----
IF trusts QuoVadis to certify the device, and then:
$ openssl s_client -connect msesandbox.cisco.com:443 -CAfile quovadis-ca.pem CONNECTED(00000003) depth=2 C = BM, O = QuoVadis Limited, CN = QuoVadis Root CA 2 verify return:1 depth=1 C = US, O = HydrantID (Avalanche Cloud Corporation), CN = HydrantID SSL ICA G2 verify return:1 depth=0 C = US, ST = CA, L = San Jose, O = "Cisco Systems, Inc.", CN = msesandbox.cisco.com verify return:1 ... Start Time: 1420616960 Timeout : 300 (sec) Verify return code: 0 (ok)
OpenSSL notification completed with Verify return code: 0 (ok) . This tells you that you have a good chain. OpenSSL does not perform host name matching, but we already know that the host name in the certificate is good.
Now for the Ruby code. All you have to do is connect the CA to Ruby:
#!/usr/bin/ruby require 'net/http' require 'net/https' require 'openssl' uri = URI('https://msesandbox.cisco.com:443') options_mask = OpenSSL::SSL::OP_NO_SSLv2 | OpenSSL::SSL::OP_NO_SSLv3 | OpenSSL::SSL::OP_NO_COMPRESSION http = Net::HTTP.new(uri.host, uri.port) request = Net::HTTP::Get.new(uri.request_uri) if uri.scheme == "https" http.use_ssl = true http.verify_mode = OpenSSL::SSL::VERIFY_PEER http.ca_file = File.join(File.dirname(__FILE__), "quovadis-ca.pem")
And hereβs the run:
$ ./Connect-Test.rb $
There are no exceptions, not OpenSSL::SSL::VERIFY_NONE .
You should try using options_mask as it removes weak / wounded / broken protocols. But Ruby is so broken and undocumented from time to time, I could never get it to work.
I managed to trust both HydrantID SSL ICA G2 and QuoVadis Root CA2 G3 using OpenSSL (which means I got Verify Result 0 (OK) from OpenSSL). But Ruby could only handle QuoVadis Root CA2 G3 (it could not chain to HydrantID SSL ICA G2 ). More ruby ββbreakdown.