./lib/ews/transporter.rb in exact4r-1.1 vs ./lib/ews/transporter.rb in exact4r-1.2

- old
+ new

@@ -29,12 +29,12 @@ # basis, if you choose to do so, by specifying it as a parameter to the <tt>submit</tt> method. def initialize(url = "https://api.e-xact.com", options = {}) @url = URI.parse(url.gsub(/\/$/,'')) @transport_type = options[:transport_type] || :rest - @@issuer_cert ||= File.dirname(__FILE__)+"/../../certs/equifax_ca.cer" - @@server_cert ||= File.new(File.dirname(__FILE__)+"/../../certs/exact.cer").read + @@issuer_cert ||= File.dirname(__FILE__)+"/../../certs/valicert_class2_root.crt" + @@server_cert ||= File.new(File.dirname(__FILE__)+"/../../certs/e-xact.com.crt").read end # Submit a transaction request to the server # # <tt>transaction</tt>:: the Request object to encode for transmission to the server @@ -50,11 +50,11 @@ transport_details = @@transport_types[transport_type] request = build_http_request(transaction, transport_type, transport_details[:suffix]) request.basic_auth(transaction.gateway_id, transaction.password) request.add_field "Accept", transport_details[:content_type] - request.add_field "User-Agent", "exact4r v1.1" + request.add_field "User-Agent", "exact4r v1.2" request.add_field "Content-type", "#{transport_details[:content_type]}; charset=UTF-8" response = get_connection.request(request) case response @@ -111,16 +111,50 @@ @connection end def validate_certificate(is_ok, ctx) cert = ctx.current_cert + return false if cert.nil? - # Only check the server certificate, not the issuer. - unless (cert.subject.to_s == cert.issuer.to_s) - is_ok &&= (@@server_cert == cert.to_pem) + # preverify failed? + return false unless is_ok + + self_signed = false + ca = false + pathlen = nil + server_auth = true + self_signed = (cert.subject.cmp(cert.issuer) == 0) + + # Check extensions for the certificate purpose according to http://www.openssl.org/docs/apps/x509.html (Certificate Extensions) and + # http://www.ietf.org/rfc/rfc3280.txt. + cert.extensions.each do |ex| + case ex.oid + when 'basicConstraints' + /CA:(TRUE|FALSE)(?:, pathlen:)*(\d*)/ =~ ex.value + ca ||= ($1 == 'TRUE') + pathlen = $2.to_i + when 'keyUsage' + usage = ex.value.split(/\s*,\s*/) + # a CA must have + ca &&= !usage.grep(/Certificate Sign/i).empty? + # Server Cert Must have + server_auth &&= !usage.grep(/Key Encipherment/i).empty? + when 'extendedKeyUsage' + usage = ex.value.split(/\s*,\s*/) + # Server Cert Must have + server_auth &&= !usage.grep(/TLS Web Server Authentication/i).empty? + when 'nsCertType' + usage = ex.value.split(/\s*,\s*/) + ca ||= !usage.grep(/SSL CA/i).empty? + server_auth ||= !usage.grep(/SSL Server/i).empty? + end end - is_ok + # We're looking for the server cert, so accept all CAs (which have already passed pre-verification) + return true if self_signed || ca + + # ensure the server cert is the one we're expecting + return server_auth && @@server_cert == cert.to_pem end # what transport types we support, and their corresponding suffixes @@transport_types = { :rest => {:suffix => "xml", :content_type => "application/xml"},