Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SSLError: hostname "W.X.Y.Z" does not match the server certificate

I just started to learn Ruby and after some basic things, I'm trying to understand making REST calls to a service in ruby. I can make get requests to foursquare API without any trouble. On the other hand calls to Cisco CMX API give error. My ruby version is 2.1.2. I searched many solutions on the web but still got problem. This my shell command that I run.

Working One

$resclient
>> RestClient.get 'https://api.foursquare.com/v2/venues/search?ll=40.7,-74&oauth_token=0ZDO1JMJ0PW2QTCDK50OGZ21UENHZ0Y3KIDQZJLLURTQNRQ2&v=20150106'

This gives error

$restclient
>> RestClient.get 'https://learning:[email protected]/api/contextaware/v1/maps/.json'

My error log:

OpenSSL::SSL::SSLError: hostname "64.103.26.61" does not match the server certificate
from /Users/apple/.rbenv/versions/2.1.2/lib/ruby/2.1.0/openssl/ssl.rb:139:in `post_connection_check'
from /Users/apple/.rbenv/versions/2.1.2/lib/ruby/2.1.0/net/http.rb:922:in `connect'
from /Users/apple/.rbenv/versions/2.1.2/lib/ruby/2.1.0/net/http.rb:863:in `do_start'
from /Users/apple/.rbenv/versions/2.1.2/lib/ruby/2.1.0/net/http.rb:852:in `start'
from /Users/apple/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/rest-client-1.7.2/lib/restclient/request.rb:413:in `transmit'
from /Users/apple/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/rest-client-1.7.2/lib/restclient/request.rb:176:in `execute'
from /Users/apple/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/rest-client-1.7.2/lib/restclient/request.rb:41:in `execute'
from /Users/apple/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/rest-client-1.7.2/lib/restclient.rb:65:in `get'
from (irb):3
from /Users/apple/.rbenv/versions/2.1.2/lib/ruby/gems/2.1.0/gems/rest-client-1.7.2/bin/restclient:93:in `<top (required)>'
from /Users/apple/.rbenv/versions/2.1.2/bin/restclient:23:in `load'
from /Users/apple/.rbenv/versions/2.1.2/bin/restclient:23:in `<main>'

Could you please give some advise? Thank you

like image 826
Ahmet Tanakol Avatar asked Jan 06 '15 09:01

Ahmet Tanakol


1 Answers

Could you please give some advise?

Here's 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 appliance has a DNS name of msesandbox.cisco.com. nslookup tells you its a good hostname:

$ nslookup msesandbox.cisco.com
Server:     192.168.1.1
Address:    192.168.1.1#53

Non-authoritative answer:
Name:   msesandbox.cisco.com
Address: 64.103.26.61

So the first thing you have to do is connect to it by its DNS name, and not an IP address.

If you issue certificates for the cisco.com domain (or can make a request), then you can ask that the IP address 64.103.26.61 be added as a Subject Alternative Name (SAN). So there will be two SANs in the certificate.


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 the issuer and subject are different. That means this is not a self signed certificate. The certificate was issued by HydrantID (Avalanche Cloud Corporation).

If you look further, you will see the Issuer's public key (Authority Key Identifier) is different than the Subject's public key (Subject Key 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, its not self signed.


If you go back to the OpenSSL command again, you will see the issuer is 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

That means QuoVadis Root CA2 G3 issued HydrantID SSL ICA G2; and HydrantID SSL ICA G2 issued msesandbox.cisco.com. QuoVadis Root CA2 G3 is the top of the food chain.

You can fetch QuoVadis Root CA2 G3 from 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 you trust QuoVadis to certify the appliance, 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)

Notice OpenSSL finished with Verify return code: 0 (ok). That tells you you got a good chain. OpenSSL does not perform hostname matching, but we already know that the hostname in the certificate is good.


Now, for Ruby code. All you need to do is plug the CA into 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")
  # http.ssl_options = options_mask
end

response = http.request request

And here's a run:

$ ./Connect-Test.rb 
$ 

No exceptions, and no OpenSSL::SSL::VERIFY_NONE.

You should try to use options_mask since it removes weak/wounded/broken protocols. But Ruby's so broken and undocumented at times, I have never been able to get it to work.


I was able to root trust in both HydrantID SSL ICA G2 and QuoVadis Root CA2 G3 with OpenSSL (meaning I got a Verify Result 0 (OK) from OpenSSL). But Ruby could only handle QuoVadis Root CA2 G3 (it could not build a chain to HydrantID SSL ICA G2). More Ruby broken-ness.

like image 140
jww Avatar answered Oct 05 '22 23:10

jww