./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"},