Sunday, March 05, 2006

Using SSL with Ruby http-access2

Expanding on my Ruby scripts, I wanted to download information from my yahoo account. Using Ruby to get HTTP is super easy. For example, the following will print the contents of http://www.w3.org/
require 'http-access2'
client = HTTPAccess2::Client.new()
puts client.get('http://www.w3.org/').content


Sometime later, I may post some examples of parsing HTML which is also super easy. For now I will talk about getting SSL to work.

Ruby http-access2 is a great library for writting web servers and clients. In this instance I am writting a simple client to login to yahoo and download information like my bookmarks. To login to yahoo, Ruby must use SSL.

It turns out that calling SSL from ruby is pretty easy. Just add the SSL configuration information. [Also, I changed the URL in this example.]
require 'http-access2'
client = HTTPAccess2::Client.new()
client.ssl_config.set_trust_ca('ca.cert')
puts client.get('https://login.yahoo.com/config/login?').content


This works great, if you have the correct certificate. If you don't (which happened to me), you get the message:
at depth 0 - 20: unable to get local issuer certificate
http-access2.rb:1001:in `connect': certificate verify failed (OpenSSL::SSL::SSLError)
from c:/codetiger/ruby/tools/ruby/lib/ruby/site_ruby/1.8/http-access2.rb:1001:in `ssl_connect'
from c:/codetiger/ruby/tools/ruby/lib/ruby/site_ruby/1.8/http-access2.rb:1363:in `connect'
...

Figuring out what caused this error was a little confusing because of the "unable to get local issuer certificate" message. It really means "Unable to validate the certificate of the host because the trusted root certificate was not found locally." Unfortunately http-access2's docs are almost non-existent. I eventually found this information from the cURL faq! cURL and http-access2 both use OpenSSL, so the faq about this error is correct. The error message in the stack trace was from OpenSSL.

To solve this error, I had to get the correct root certificate. This is easily accomplished. First, check the web page properties in your browser. For the yahoo page, you will find yahoo is signed by "Equifax Secure Certificate Authority". I'm using Windows XP, so all I had to do was go into Control Panel -> Internet Options -> Content tab -> Certificates -> Trusted Root Certificates -> select "Equifax Secure Certificate Authority" -> Export -> select Base 64 Encoding -> save to file (EquifaxSecureCertificateAuthority.cer). [Firefox did not have an export option.]

Now that the trusted root cert is in a file, Ruby can use it...
require 'http-access2'
client = HTTPAccess2::Client.new()
client.ssl_config.set_trust_ca('EquifaxSecureCertificateAuthority.cer')
puts client.get('https://login.yahoo.com/config/login?').content


Yahoo!!!

No comments: