Gist/snippet for Ruby OpenSSL::SSL::VERIFY_NONE alternative?

It seems OpenSSL authentication in Ruby has been broken for some time (see below), resorting many to use the dreaded

“OpenSSL::SSL::VERIFY_PEER = OpenSSL::SSL::VERIFY_NONE”

hack to circumvent authentication. As I develop SketchUp plugins that interact with HTTPS endpoints (including 3D Warehouse), I’d like to handle SSL authentication in a transparent, platform-independent way, without having to resort to the above, dangerous workaround. Does anyone have an idea (or better yet, a code snippet) of how this might be accomplished? A workaround on Windows seems to involve mutating a System Environment Variable (source: Download a cacert.pem for RailsInstaller · GitHub ), but I consider this a last resort, as I’m unsure how this could affect the behavior of other OpenSSL-enabled applications.

Many thanks!

I’ve found HTTPS (The S being OpenSSL) in Ruby to be very troublesome. One thing is the certificate issues they have had. Another is a bad performance problem with OpenSSL under Windows. Under Windows OpenSSL use some extremely slow debug Win32 API functions. They added a time out to work around this - but for some reason there are different code paths for different compilers. And the one used to compile the libs we use in SketchUp didn’t have the time out in the inner most loop - which meant that on a fresh SketchUp start, using OpenSSL for the first time it would spend 3-5secs on generating random seed. That’s best case scenario. If there is a large model loaded this can yield minutes.

We’ve tried some very kludgy workarounds, but they are not something I trust to be reliable. My current recommendation is to build a Ruby C/C++ extension and use C/C++ libs to do the HTTPS communication - without OpenSSL.
We have a sample for Ruby C/C++ extensions on GitHub:

Another argument for going this route is if you want to do these HTTP(S) requests in the background. Ruby threads are now native since Ruby 2.0 - but Ruby still manages the threads so they are not 100% like you’d expect. There is also an issue with Ruby threads inside of SketchUp where they won’t run unless the main thread is busy doing something (UI interaction - or a zero-delay-timer, which is just another kludge…).

Doing a Ruby extension might seem like extra ordeal, but the number of compound issues with HTTPS, OpenSSL and Ruby Threads actually makes it the saner option.

Thank you for the excellent, thoughtful response! It does seem like writing a C/C++ extension may be the best (robust) option. I’ll start from the github sample you’ve listed and go from there. Thanks again!

I think one of the replies (to the Gist,) mentioned that it comes from Mozilla

No need to rebuild.

Distributors of Ruby & RubyGems (such as Trimble does with SketchUp,) in a special distribution, are supposed to copy “Tools/RubyStdLib/rubygems/defaults.rb” and rename it: “Tools/RubyStdLib/rubygems/operating_system.rb”, and make changes to tweak rubygems and their ruby environment.

From: “Tools/RubyStdLib/rubygems.rb:67
# For RubyGems packagers, provide lib/rubygems/operating_system.rb
# and override any defaults from lib/rubygems/defaults.rb.

If you look at “Tools/RubyStdLib/rubygems/defaults.rb” you’ll see quite a few paths and things returned by methods that are for a system Ruby install, not a SketchUp install. These methods need overriding.

Since SketchUp/Ruby is loading RubyGems first, the “operating_system.rb” file would be the perfect place to set ENV["SSL_CERT_FILE"]. This file gets required at the bottom of the “rubygems.rb” loader file.

Also, on an unrelated issue, you and I had discussed a SketchUp gem server for libraries. This override file is also where the url would be added into the array of gem servers.

It is setting the variable,… BUT the examples are all for a system Ruby install.
So they explain how to change the USER’s copy of the environment, or the System’s copy.
Yes this would affect other applications.

However, each application uses it’s OWN copy of the environment, so that changes do not propagate and affect other applications.

Within SketchUp’s Ruby environment, IT’s copy of the environment is accessed via a Hash-like wrapper named ENV.

Some Cert files are provided in the rubygems distributed with SketchUp, here:
Tools\RubyStdLib\rubygems\ssl_certs

So (using that as an example,) you’d set it thus:

certs = Sketchup::find_support_file("Tools/RubyStdLib/rubygems/ssl_certs")
ENV["SSL_CERT_FILE"]= File::join( certs, "ca-bundle.pem" )

:smile:


Luis Lavena has a really important Gist out that says we need to update rubygems, and the cert file it uses:
howto-manually-add-trust-cert-to-rubygems.md

Rubygems is up to at least 2.0.15, … but SketchUp 2015 was re-released with rubygems veer 2.0.3 again.

Yes - for normal Ruby devs that deploy Ruby on the server this works easily for them. For extension developers this is more tricky to deploy as a fix. We tried to patch the issue in SU by shipping with updates certificate. Though my memory is a bit fuzzy on the details. I think we ran into some other issues later on.

Though, that was before luislavena’s post which provided better insight to what was going on. I saw that a few weeks ago when I realized that even my standalone Ruby installation failed.

Hmm… need to look into that file. Thanks.

The SSL cert issues is just the tip of the iceberg though. Even if that was fixed there is still the problem with the severe performance issue.

I’d still recommend developers to not use Net::HTTPS and do something like A Ruby C extensions instead until all these items has been fixed in Ruby and implemented in SketchUp:

  • SSL certificate (This seems to be fixed in Ruby by now - but with SketchUp we’d need a new release with the new fixes.)
  • OpenSSL performance issue which might easily freeze up SketchUp for minutes when larger models are loaded.
  • If you also want to do background HTTP(S) communication the threading is a problem.

Sure, but fix what ya’ can, when ya’ can, is my motto.

Everybody having to do the same thing is inefficient. Maybe there could be some collaboration on a GitHub project ?

Some responders suggested using 3rd-party gems instead of Net::HTTPS. Looked into those ?

Often they build upon Net::HTTP and would inherit the same issues. And so far all of them used OpenSSL.

Recent OpenSSL patch to Ruby:
CVE-2015-1855: Ruby OpenSSL Hostname Verification

Thomas mentioned this above (and in posts elsewhere.) I’m hoping the next SketchUp version includes a Ruby with working OpenSSL.

EDIT (“mentioned this” meant): Thomas has said in the past, specifically that (as of SU2017) all versions of OpenSSL distributed with SketchUp’s Ruby are flawed. (Not meaning anything specific about Ruby 2.4, nor OpenSSL 1.1.0, as I say below.)

As we noted above, we think it came from Mozilla, and was added to the SketchUp package during the SketchUp 2015 development cycle, which was summer & fall of 2014. It just has not changed since in the two succeeding cycles.

Given that this thread had it’s previous post in 2015-Apr, just I’d point this out.

The first release of OpenSSL 1.1.0 was openssl-1.1.0-pre1, which occurred 2015-Dec. The first normal release was 1.1.0, which occurred 2016-Aug. See Old 1.1.0 Releases.

Also, Ruby 2.4 wasn’t in existence before 2015-Dec, and that was as trunk. It was officially released in 2016-Dec.

Thomas may have been discussing Ruby and OpenSSL versions, but not Ruby 2.4 and OpenSSL 1.1.0…

Yes, I meant he was discussing the issues we’ve had with OpenSSL
(which you’ve subsequently noted the fixes for were not pushed until v1.1.0.)

For the general readership, so far (as of SketchUp 2017 w/ Trimble Ruby 2.2.4,) no version of SketchUp yet uses the fixed OpenSSL library.

But it makes one wonder if a patch could be created (perhaps in the form of a SketchUp extension RBZ package,) to allow SketchUp extensions to use the latest OpenSSL ? (I’ve done this before, and had an example of doing it with the RubyZip library.)

I don’t think I’ve ever seen those PR’s. BTW, just because it says ‘Windows’ doesn’t clarify which compiler the PR affects. That PR is for msvc/mswin builds, Ruby (and SU) typically use MinGW builds. Some of the Ruby Core guys build and test mswin, but I don’t think you’d have any luck installing a gem extension in them…

I never said, nor meant a gem.