module EWS # :nodoc: module CertificateHelper EXACT_ISSUER_CERT_FILE = File.dirname(__FILE__)+"/../../certs/valicert_class2_root.crt" unless defined?(EXACT_ISSUER_CERT_FILE) EXACT_SERVER_CERT_FILE = File.dirname(__FILE__)+"/../../certs/e-xact.com.crt" unless defined?(EXACT_SERVER_CERT_FILE) attr_accessor :issuer_cert_file, :server_cert, :client_cert, :client_key def configure_certificates(options) self.issuer_cert_file = (options[:issuer_cert] || EXACT_ISSUER_CERT_FILE) server_cert_file = (options[:server_cert] || EXACT_SERVER_CERT_FILE) self.server_cert = File.new(server_cert_file).read if options[:client_cert] raise ArgumentError.new "Key file not supplied" if options[:client_key].blank? self.client_cert = OpenSSL::X509::Certificate.new(File.new(options[:client_cert]).read) self.client_key = client_cert.public_key.class.send(:new, File.new(options[:client_key]).read) end end private :configure_certificates def validate_certificate(is_ok, ctx) cert = ctx.current_cert return false if cert.nil? # 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 # 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 && self.server_cert == cert.to_pem end private :validate_certificate end end