SSL doesn't work on 1.9.2

1,274 views
Skip to first unread message

Nick Klauer

unread,
Sep 16, 2011, 2:36:44 PM9/16/11
to rubyin...@googlegroups.com
I think I incorrectly reported a bug on the RubyInstaller issue tracker for this instead of reading Luis' comment on reporting issues, so I'll repost here (sorry).

See this StackOverflow post, but the gist of it is this:

PS C:\> C:\Ruby192\bin\pry.bat
pry(main)> require 'open-uri'
=> true
pry(main)> open('https://www.gmail.com')
OpenSSL::SSL::SSLError: SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed
from C:/RailsInstaller/Ruby1.9.2/lib/ruby/1.9.1/net/http.rb:678:in `connect'
pry(main)>

This also affects things like the savon gem and httparty, or really, any SSL URL. Is there something I'm missing on my end to make this work?

Luis Lavena

unread,
Sep 16, 2011, 3:10:14 PM9/16/11
to rubyin...@googlegroups.com
Hello Nick, see my comment below

This is happening because your system is lacking a cert bundle, this
will happen also if you try to use curl from the command line.

If you look at RubyInstaller own code, we manage to connect to SSL
connections setting the proper SSL cert:

https://github.com/oneclick/rubyinstaller/blob/master/rake/contrib/uri_ext.rb#L287-295

You can download cURL pem certs from here:
http://curl.haxx.se/docs/caextract.html

Then, you should try setting SSL_CERT_FILE environment variable to
point to the full path of the file.

I've seen some threads about this on the web with links to things like:

https://gist.github.com/867550

And

https://gist.github.com/767249

Let us know if that solves your issue.
--
Luis Lavena
AREA 17
-
Perfection in design is achieved not when there is nothing more to add,
but rather when there is nothing more to take away.
Antoine de Saint-Exupéry

Nick Klauer

unread,
Sep 16, 2011, 5:22:17 PM9/16/11
to rubyin...@googlegroups.com
It would appear that it does something, but for one use case it's a different error, and another, I'm not sure this fix will work.

For instance, the simple open-uri bit:

pry(main)> require 'open-uri'
=> true
pry(main)> open("https://www.gmail.com")
OpenSSL::SSL::SSLError: hostname was not match with the server certificate
from C:/RailsInstaller/Ruby1.9.2/lib/ruby/1.9.1/openssl/ssl-internal.rb:121:in `post_connection_check'

That seems to fail in a different way, but maybe that's supposed to fail the check?

For another application, I need to define the CA cert, certificate and key files, as I would do from cURL on the command-line.  This can be done in savon like so:

require 'savon'

$client = Savon::Client.new do
  wsdl.document = "my-awesome-wsdl.wsdl"
end
  $client.http.proxy = ENV['http_proxy']
  $client.http.auth.ssl.cert_key_file = "key.pem"
  $client.http.auth.ssl.cert_key_password = "password"
  $client.http.auth.ssl.ca_cert_file = "ca.pem"
  $client.http.auth.ssl.cert_file = "client.pem"
  $client.http.auth.ssl.verify_mode = :none

$client.request :query_request

But this throws the same error as was given originally:

PS C:\mydocs\Work\PCI_Projects\dart-mui\src\main\resources> ruby .\savon_testing.rb
D, [2011-09-16T16:16:15.890625 #4524] DEBUG -- : SOAP request: https://thing.somewhere.com/xml/query
D, [2011-09-16T16:16:15.890625 #4524] DEBUG -- : SOAPAction: "/xml/query", Content-Type: text/xml;charset=UTF-8, Content-Length: 322
D, [2011-09-16T16:16:15.906250 #4524] DEBUG -- : <?xml version="1.0" encoding="UTF-8"?><env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:wsdl="https://thing.somewhere.com/xml/" xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"><env:Body><QueryRequest></QueryRequest></env:Body></env:Envelope>
D, [2011-09-16T16:16:16.515625 #4524] DEBUG -- : HTTPI executes HTTP POST using the httpclient adapter
C:/RailsInstaller/Ruby1.9.2/lib/ruby/gems/1.9.1/gems/httpclient-2.1.7.2/lib/httpclient/session.rb:276:in `connect': SSL_connect returned=1 errno=0 state=SSLv3 read finished A: sslv3 alert handshake failure (OpenSSL::SSL::SSLError)
        from C:/RailsInstaller/Ruby1.9.2/lib/ruby/gems/1.9.1/gems/httpclient-2.1.7.2/lib/httpclient/session.rb:276:in `ssl_connect'
        from C:/RailsInstaller/Ruby1.9.2/lib/ruby/gems/1.9.1/gems/httpclient-2.1.7.2/lib/httpclient/session.rb:712:in `block in connect'
        from C:/RailsInstaller/Ruby1.9.2/lib/ruby/1.9.1/timeout.rb:58:in `timeout'
        from C:/RailsInstaller/Ruby1.9.2/lib/ruby/1.9.1/timeout.rb:89:in `timeout'
        from C:/RailsInstaller/Ruby1.9.2/lib/ruby/gems/1.9.1/gems/httpclient-2.1.7.2/lib/httpclient/session.rb:704:in `connect'
        from C:/RailsInstaller/Ruby1.9.2/lib/ruby/gems/1.9.1/gems/httpclient-2.1.7.2/lib/httpclient/session.rb:568:in `query'
        from C:/RailsInstaller/Ruby1.9.2/lib/ruby/gems/1.9.1/gems/httpclient-2.1.7.2/lib/httpclient/session.rb:158:in `query'
        from C:/RailsInstaller/Ruby1.9.2/lib/ruby/gems/1.9.1/gems/httpclient-2.1.7.2/lib/httpclient.rb:991:in `do_get_block'
        from C:/RailsInstaller/Ruby1.9.2/lib/ruby/gems/1.9.1/gems/httpclient-2.1.7.2/lib/httpclient.rb:800:in `block in do_request'
        from C:/RailsInstaller/Ruby1.9.2/lib/ruby/gems/1.9.1/gems/httpclient-2.1.7.2/lib/httpclient.rb:887:in `protect_keep_alive_disconnected'
        from C:/RailsInstaller/Ruby1.9.2/lib/ruby/gems/1.9.1/gems/httpclient-2.1.7.2/lib/httpclient.rb:799:in `do_request'
        from C:/RailsInstaller/Ruby1.9.2/lib/ruby/gems/1.9.1/gems/httpclient-2.1.7.2/lib/httpclient.rb:697:in `request'
        from C:/RailsInstaller/Ruby1.9.2/lib/ruby/gems/1.9.1/gems/httpclient-2.1.7.2/lib/httpclient.rb:619:in `post'
        from C:/RailsInstaller/Ruby1.9.2/lib/ruby/gems/1.9.1/gems/httpi-0.9.5/lib/httpi/adapter/httpclient.rb:32:in `block in post'
        from C:/RailsInstaller/Ruby1.9.2/lib/ruby/gems/1.9.1/gems/httpi-0.9.5/lib/httpi/adapter/httpclient.rb:64:in `do_request'
        from C:/RailsInstaller/Ruby1.9.2/lib/ruby/gems/1.9.1/gems/httpi-0.9.5/lib/httpi/adapter/httpclient.rb:31:in `post'
        from C:/RailsInstaller/Ruby1.9.2/lib/ruby/gems/1.9.1/gems/httpi-0.9.5/lib/httpi.rb:96:in `block in post'
        from C:/RailsInstaller/Ruby1.9.2/lib/ruby/gems/1.9.1/gems/httpi-0.9.5/lib/httpi.rb:194:in `with_adapter'
        from C:/RailsInstaller/Ruby1.9.2/lib/ruby/gems/1.9.1/gems/httpi-0.9.5/lib/httpi.rb:94:in `post'
        from C:/RailsInstaller/Ruby1.9.2/lib/ruby/gems/1.9.1/gems/savon-0.9.7/lib/savon/soap/request.rb:31:in `block in response'
        from C:/RailsInstaller/Ruby1.9.2/lib/ruby/gems/1.9.1/gems/savon-0.9.7/lib/savon/soap/request.rb:51:in `with_logging'
        from C:/RailsInstaller/Ruby1.9.2/lib/ruby/gems/1.9.1/gems/savon-0.9.7/lib/savon/soap/request.rb:31:in `response'
        from C:/RailsInstaller/Ruby1.9.2/lib/ruby/gems/1.9.1/gems/savon-0.9.7/lib/savon/client.rb:79:in `request'
        from ./savon_testing.rb:13:in `<main>'

So is the SSL_CERT_FILE supposed to fix things across the board, or just for general uses?  I've even applied a change to set the SSL_CERT_FILE to be the same .pem that I use for this service (set SSL_CERT_FILE=.....ca.pem), but that doesn't seem to change anything.

Jon

unread,
Sep 16, 2011, 5:53:10 PM9/16/11
to rubyin...@googlegroups.com
> It would appear that it does *something*, but for one use case it's a
> different error, and another, I'm not sure this fix will work.
>
> For instance, the simple open-uri bit:
>
> pry(main)> require 'open-uri'
> => true
> pry(main)> open("https://www.gmail.com")
> OpenSSL::SSL::SSLError: hostname was not match with the server certificate
> from
> C:/RailsInstaller/Ruby1.9.2/lib/ruby/1.9.1/openssl/ssl-internal.rb:121:in
> `post_connection_check'
>
> That seems to fail in a different way, but maybe that's supposed to fail the
> check?

I get the same thing when I try the following on a freshly downloaded 1.9.2-p290:

C:\Users\Jon\Documents>irb
irb(main):001:0> p RUBY_DESCRIPTION
"ruby 1.9.2p290 (2011-07-09) [i386-mingw32]"
=> "ruby 1.9.2p290 (2011-07-09) [i386-mingw32]"
irb(main):002:0> ENV['SSL_CERT_FILE'] = 'C:/tools/cacert.pem'
=> "C:/tools/cacert.pem"
irb(main):003:0> require 'open-uri'
=> true
irb(main):004:0> f = open 'https://www.gmail.com'


OpenSSL::SSL::SSLError: hostname was not match with the server certificate

from C:/ruby192/lib/ruby/1.9.1/openssl/ssl-internal.rb:121:in `post_connection_check'
from C:/ruby192/lib/ruby/1.9.1/net/http.rb:680:in `connect'
...
irb(main):005:0> OpenSSL::OPENSSL_VERSION
=> "OpenSSL 1.0.0d 8 Feb 2011"


...but on a recently built 1.9.3 from our master branch I get:

C:\Users\Jon\Documents\RubyDev>ripl
>> p RUBY_DESCRIPTION
"ruby 1.9.3dev (2011-09-16 revision 33281) [i386-mingw32]"
=> "ruby 1.9.3dev (2011-09-16 revision 33281) [i386-mingw32]"
>> ENV['SSL_CERT_FILE'] = 'C:/tools/cacert.pem'
=> "C:/tools/cacert.pem"
>> require 'open-uri'
=> true
>> f = open 'https://www.gmail.com'
=> #<File:C:/Users/Jon/AppData/Local/Temp/open-uri20110916-4256-1dirmt1>
>> f.read(100)
=> "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"utf-8\">\n <title>Gmail: Email from Google"
>> OpenSSL::OPENSSL_VERSION
=> "OpenSSL 1.0.0e 6 Sep 2011"


Jon

---
blog: http://jonforums.github.com/
twitter: @jonforums

"Anyone who can only think of one way to spell a word obviously lacks imagination." - Mark Twain

Luis Lavena

unread,
Sep 16, 2011, 6:56:54 PM9/16/11
to rubyin...@googlegroups.com
On Fri, Sep 16, 2011 at 6:22 PM, Nick Klauer <kla...@gmail.com> wrote:
> It would appear that it does something, but for one use case it's a
> different error, and another, I'm not sure this fix will work.
> For instance, the simple open-uri bit:
> pry(main)> require 'open-uri'
> => true
> pry(main)> open("https://www.gmail.com")
> OpenSSL::SSL::SSLError: hostname was not match with the server certificate
> from

That will fail, www.gmail.com redirects you to mail.google.com, so the
cert is not for gmail.com but for mail.google.com:

>> r = open("https://www.gmail.com"); nil


OpenSSL::SSL::SSLError: hostname was not match with the server certificate

>> r = open("https://mail.google.com"); nil
=> nil
>> r.read
=> "<html><head><meta http-equiv=\"Refresh\"
content=\"0;URL=https://mail.google.com/mail/\" /></hea
d><body><script type=\"text/javascript\"
language=\"javascript\"><!--\nlocation.replace(\"https://ma
il.google.com/mail/\")\n--></script></body></html>"

> That seems to fail in a different way, but maybe that's supposed to fail the
> check?

Correct.

> For another application, I need to define the CA cert, certificate and key
> files, as I would do from cURL on the command-line.  This can be done in
> savon like so:

For cURL, I've placed curl-ca-bundle.crt in the same directory of
cURL, and that allows me to use cURL without indicating the
certificate file every time.

> require 'savon'
> $client = Savon::Client.new do
>   wsdl.document = "my-awesome-wsdl.wsdl"
>   wsdl.endpoint = "https://thing.somewhere.com/xml/query"
> end
>   $client.http.proxy = ENV['http_proxy']
>   $client.http.auth.ssl.cert_key_file = "key.pem"
>   $client.http.auth.ssl.cert_key_password = "password"
>   $client.http.auth.ssl.ca_cert_file = "ca.pem"
>   $client.http.auth.ssl.cert_file = "client.pem"
>   $client.http.auth.ssl.verify_mode = :none
> $client.request :query_request

Can you indicate *full path* to the ca_cert_file?

Also, if you set SSL_CERT_FILE, it needs to be with full path.

> So is the SSL_CERT_FILE supposed to fix things across the board, or just for
> general uses?  I've even applied a change to set the SSL_CERT_FILE to be the
> same .pem that I use for this service (set SSL_CERT_FILE=.....ca.pem), but
> that doesn't seem to change anything.
>

Hmn, works for me for open-uri, and I bet will do for Savon if you use
the full path too.

Can you try? don't have a SOAP service around to connect to for trying, sorry.

Nick Klauer

unread,
Sep 16, 2011, 8:42:41 PM9/16/11
to rubyin...@googlegroups.com
So here's a couple different things I've tried, all which don't appear to do anything differently

  1. I set ENV['SSL_CERT_FILE'] in the first line of a script before anything else runs (with a full path to the cert)
  2. Changed all paths to be full paths (see below)
  3. In Savon's (or really HTTPI's that performs the calls) settings, I've set all paths to the files as full paths
ENV['SSL_CERT_FILE'] = "C:/Certificates/ca.pem" # No different with or without this line
require 'savon'
require 'pry'

cert_dir = "C:/Certificates/"

$client = Savon::Client.new do
  wsdl.document = "my-awesome-wsdl.wsdl"
  wsdl.endpoint = "https://thing.somewhere.com/xml/query"
  http.auth.ssl.cert_key_file = "#{cert_dir}/key.pem" 
  http.auth.ssl.cert_key_password = "password"
  http.auth.ssl.ca_cert_file = "#{cert_dir}/ca.pem"
  http.auth.ssl.cert_file = "${cert_dir}/client.pem" 
  http.auth.ssl.verify_mode = :none
end

$client.request :query_request
binding.pry

Still throws the same exception as above.  I'm not terribly familiar with how certificates work, so I'm truly confused what I'm even reading in the exception.  I need to find another gem/lib to test this against, but I had a hard enough time finding this one, so I'll get back to you if I can reproduce this somewhere else with another gem.

Luis Lavena

unread,
Sep 16, 2011, 8:57:27 PM9/16/11
to rubyin...@googlegroups.com
On Fri, Sep 16, 2011 at 9:42 PM, Nick Klauer <kla...@gmail.com> wrote:
> So here's a couple different things I've tried, all which don't appear to do
> anything differently
>
> I set ENV['SSL_CERT_FILE'] in the first line of a script before anything
> else runs (with a full path to the cert)
> Changed all paths to be full paths (see below)
> In Savon's (or really HTTPI's that performs the calls) settings, I've set
> all paths to the files as full paths
>
> ENV['SSL_CERT_FILE'] = "C:/Certificates/ca.pem" # No different with or
> without this line

Please do "SET SSL_CERT_FILE=" from outside your script, in your
environment prior anything.

I'm not sure how that works with OpenSSL.

> require 'savon'
> require 'pry'
> cert_dir = "C:/Certificates/"
> $client = Savon::Client.new do
>   wsdl.document = "my-awesome-wsdl.wsdl"
>   wsdl.endpoint = "https://thing.somewhere.com/xml/query"
>   http.auth.ssl.cert_key_file = "#{cert_dir}/key.pem"
>   http.auth.ssl.cert_key_password = "password"
>   http.auth.ssl.ca_cert_file = "#{cert_dir}/ca.pem"
>   http.auth.ssl.cert_file = "${cert_dir}/client.pem"
>   http.auth.ssl.verify_mode = :none
> end

Are you sure this code is correct? you're doing ${cert_dir} for your
client certificate.

Why are you having a client certificate in the first place? is not
enough verify the authenticity of the remote?

Does the ca cert bundle you have include the certificate of the remote
server you're trying to connect? It is worthless specify the CA cert
file if doesn't contain it.

> Still throws the same exception as above.  I'm not terribly familiar with
> how certificates work, so I'm truly confused what I'm even reading in the
> exception.  I need to find another gem/lib to test this against, but I had a
> hard enough time finding this one, so I'll get back to you if I can
> reproduce this somewhere else with another gem.
>

I'm not familiar with either Savon or Pry (which is what you're
using), what I can tell you is that OpenSSL and the lookup of certs
from the ca cert bundle by SSL_CERT_FILE doest work, as you noted
before with your open-uri attempt.

So, we can discard that is the problem.

Now, I don't know any SOAP server/service to connect with that I can
try this out and help you better, nor does Savon documentation mention
anything about SSL in their README [1] or their website [2]

I've tried to follow the method call in your example from auth here:
https://github.com/rubiii/httpi/blob/master/lib/httpi/request.rb#L67

To here:
https://github.com/rubiii/httpi/blob/master/lib/httpi/auth/config.rb#L57

And here:
https://github.com/rubiii/httpi/blob/master/lib/httpi/auth/ssl.rb#L31

Have you tried only specifying ca_cert_file?

Sorry that I'm not able to answer your questions and still ask more,
but without access to a SOAP server to help you, I'm useless.

[1] https://github.com/rubiii/savon
[2] http://savonrb.com/

Nick Klauer

unread,
Sep 16, 2011, 11:03:11 PM9/16/11
to rubyin...@googlegroups.com
That's understandable.  I did set the environment in the command prompt with all of this too, so that rules that being the issue.

I know that with cURL, I had issues just using the certificate itself, and had to pull out the pieces for it and specify those individually, following something I found on cURL's website: http://curl.haxx.se/mail/archive-2005-09/0138.html

That worked (at least on the command-line), and since I don't have curb working on Ruby (yet), I decided to go with whatever adapter Savon's HTTPI library picked for me (httpclient and net_http were alternatives)

---

Trying rubinius on my Mac with the same code had produced a different error that I could troubleshoot a minor mistake (I had accidentally switched cert_key_file and cert_file), which worked..for Rubinius on my Mac.  Taking that same code back to the Windows side does not.

require 'rubygems'
require 'savon'

cert_dir = "."
$client = Savon::Client.new do
  wsdl.document = "my-awesome-wsdl.wsdl"
  http.proxy = ENV['http_proxy'] if ENV['http_proxy']
  http.auth.ssl.cert_key_file = "#{cert_dir}/key.pem" 
  http.auth.ssl.cert_key_password = "password"
  #http.auth.ssl.ca_cert_file = "#{cert_dir}/ca.pem"  # I didn't need this line in rbx
  http.auth.ssl.cert_file = "#{cert_dir}/client.pem" 
  http.auth.ssl.verify_mode = :none
end

$client.request :query_request

I'm going to keep digging, but I'm feeling stumped, too.  Thanks for offering the tips, though.  Tried everything you said, (set SSL_CERT_FILE, exclude ca_cert, various matrices of yes/no things) but still coming up short.  I'll see if I can find a way to emulate a self-signed cert against a server expecting it.

Uraki66

unread,
Sep 17, 2011, 7:20:29 AM9/17/11
to RubyInstaller
Not to confuse things, but I've found that with RubyInstaller and
Windows, you're better off going to http://www.slproweb.com/products/Win32OpenSSL.html
and installing the pre-compiled OpenSSL binaries they offer.

Note there are 32-bit/64-bit versions and the associated 32/64-bit
Visual C++ 2008 redistributable that you will probably have to
install.

I generally couldn't get curl/curb to work under Windows 7 until I
installed the OpenSSL binaries and after that things worked as
expected.

I now just install these as part of any new RubyInstaller/DevKit
installation on Windows and then the curl libraries and then the curb
gem to be sure the installation works.

If you are doing anything with Ruby on Windows, be sure to visit
http://rubyonwindows.blogspot.com/ as there are a lot of good Windows-
specific tips & hints there. This is generally not the kind of stuff
that Luis is probably concerned with, but sometimes if you can't get
something to work with gem, etc, you may be able to use something
Windows-specific (yes, that's bad, I know!) to work around the
problem.

Robert

Luis Lavena

unread,
Sep 17, 2011, 8:01:33 AM9/17/11
to rubyin...@googlegroups.com
On Sat, Sep 17, 2011 at 8:20 AM, Uraki66 <ura...@gmail.com> wrote:
> Not to confuse things, but I've found that with RubyInstaller and
> Windows, you're better off going to http://www.slproweb.com/products/Win32OpenSSL.html
> and installing the pre-compiled OpenSSL binaries they offer.
>
> Note there are 32-bit/64-bit versions and the associated 32/64-bit
> Visual C++ 2008 redistributable that you will probably have to
> install.
>
> I generally couldn't get curl/curb to work under Windows 7 until I
> installed the OpenSSL binaries and after that things worked as
> expected.
>

Hello, you're confusing things out.

First:

RubyInstaller links against a private copy of OpenSSL, so require
"openssl" works.

The OpenSSL libs you mention above can generate segmentation fault for
programs that are linked against MSVCRT, simply because these
libraries are linked against a different version of MSVCR

See:
http://msdn.microsoft.com/en-us/library/abx4dbyh(v=vs.80).aspx
http://msdn.microsoft.com/en-us/library/ms235460(v=vs.80).aspx

If you use that approach, be warned.

> I now just install these as part of any new RubyInstaller/DevKit
> installation on Windows and then the curl libraries and then the curb
> gem to be sure the installation works.
>

The curb gem and the curl headers and development libraries are tricky
but lot of developers did manage to solve, search the group.

Thank you for sharing your approach, but these comments has nothing to
solve the issue since is SOAP/SSL related and not OpenSSL related.

Nick Klauer

unread,
Sep 20, 2011, 3:00:16 PM9/20/11
to rubyin...@googlegroups.com
OK, I figured out what I did wrong, and instead of sitting quietly in shame, I'm going to publicize it.

$client = Savon::Client.new do
  wsdl.document = "my-awesome-wsdl.wsdl"
  wsdl.endpoint = "https://thing.somewhere.com/xml/query"
  http.auth.ssl.cert_key_file = "#{cert_dir}/key.pem" 
  http.auth.ssl.cert_key_password = "password"
  http.auth.ssl.ca_cert_file = "#{cert_dir}/ca.pem"
  http.auth.ssl.cert_file = "${cert_dir}/client.pem" 
# http.auth.ssl.verify_mode = :none  # Take this out
end

HTTPI's verify_mode works in that if you set it to :none, you ignore important SSL cert settings, like client and key cert files:


So I feel stupid, but I want to clarify that SSL works GREAT in Windows and you don't need curb or OpenSSL installed outside of it to get what you need working, even if you're doing Client cert over SSL. :)
Reply all
Reply to author
Forward
0 new messages