class OmniAuth::Strategies::WSFed::XMLSecurity::SignedDocument
Constants
- DSIG
Attributes
settings[RW]
signed_element_id[RW]
Public Class Methods
new(response, settings = {})
click to toggle source
Calls superclass method
# File lib/omniauth/strategies/wsfed/xml_security.rb, line 44 def initialize(response, settings = {}) super(response) extract_signed_element_id self.settings = settings end
Public Instance Methods
validate(idp_cert_fingerprint, soft = true)
click to toggle source
# File lib/omniauth/strategies/wsfed/xml_security.rb, line 51 def validate(idp_cert_fingerprint, soft = true) # get cert from response base64_cert = self.elements["//ds:X509Certificate"].text cert_text = Base64.decode64(base64_cert) cert = OpenSSL::X509::Certificate.new(cert_text) # check cert matches registered idp cert fingerprint = Digest::SHA1.hexdigest(cert.to_der) if fingerprint != idp_cert_fingerprint.gsub(/[^a-zA-Z0-9]/,"").downcase return soft ? false : (raise OmniAuth::Strategies::WSFed::ValidationError.new("Fingerprint mismatch")) end validate_doc(base64_cert, soft) end
validate_doc(base64_cert, soft = true)
click to toggle source
# File lib/omniauth/strategies/wsfed/xml_security.rb, line 67 def validate_doc(base64_cert, soft = true) # validate references # check for inclusive namespaces inclusive_namespaces = [] inclusive_namespace_element = REXML::XPath.first(self, "//ec:InclusiveNamespaces") if inclusive_namespace_element prefix_list = inclusive_namespace_element.attributes.get_attribute('PrefixList').value inclusive_namespaces = prefix_list.split(" ") end # remove signature node sig_element = REXML::XPath.first(self, "//ds:Signature", {"ds"=>DSIG}) sig_element.remove # check digests saml_version = settings[:saml_version] REXML::XPath.each(sig_element, "//ds:Reference", {"ds"=>DSIG}) do |ref| uri = ref.attributes.get_attribute("URI").value hashed_element = REXML::XPath.first(self, "//*[@ID='#{uri[1,uri.size]}']") || REXML::XPath.first(self, "//*[@AssertionID='#{uri[1,uri.size]}']") canoner = XML::Util::XmlCanonicalizer.new(false, true) canoner.inclusive_namespaces = inclusive_namespaces if canoner.respond_to?(:inclusive_namespaces) && !inclusive_namespaces.empty? canon_hashed_element = canoner.canonicalize(hashed_element) digest_algorithm = algorithm(REXML::XPath.first(ref, "//ds:DigestMethod")) hash = Base64.encode64(digest_algorithm.digest(canon_hashed_element)).chomp digest_value = REXML::XPath.first(ref, "//ds:DigestValue", {"ds"=>"http://www.w3.org/2000/09/xmldsig#"}).text unless digests_match?(hash, digest_value) return soft ? false : (raise OmniAuth::Strategies::WSFed::ValidationError.new("Digest mismatch")) end end # verify signature canoner = XML::Util::XmlCanonicalizer.new(false, true) signed_info_element = REXML::XPath.first(sig_element, "//ds:SignedInfo", {"ds"=>DSIG}) canon_string = canoner.canonicalize(signed_info_element) base64_signature = REXML::XPath.first(sig_element, "//ds:SignatureValue", {"ds"=>DSIG}).text signature = Base64.decode64(base64_signature) # get certificate object cert_text = Base64.decode64(base64_cert) cert = OpenSSL::X509::Certificate.new(cert_text) # signature method signature_algorithm = algorithm(REXML::XPath.first(signed_info_element, "//ds:SignatureMethod", {"ds"=>DSIG})) unless cert.public_key.verify(signature_algorithm.new, signature, canon_string) return soft ? false : (raise OmniAuth::Strategies::WSFed::ValidationError.new("Key validation error")) end return true end
Private Instance Methods
algorithm(element)
click to toggle source
# File lib/omniauth/strategies/wsfed/xml_security.rb, line 135 def algorithm(element) algorithm = element.attribute("Algorithm").value if element algorithm = algorithm && algorithm =~ /sha(.*?)$/i && $1.to_i case algorithm when 256 then OpenSSL::Digest::SHA256 when 384 then OpenSSL::Digest::SHA384 when 512 then OpenSSL::Digest::SHA512 else OpenSSL::Digest::SHA1 end end
digests_match?(hash, digest_value)
click to toggle source
# File lib/omniauth/strategies/wsfed/xml_security.rb, line 126 def digests_match?(hash, digest_value) hash == digest_value end
extract_signed_element_id()
click to toggle source
# File lib/omniauth/strategies/wsfed/xml_security.rb, line 130 def extract_signed_element_id reference_element = REXML::XPath.first(self, "//ds:Signature/ds:SignedInfo/ds:Reference", {"ds"=>DSIG}) self.signed_element_id = reference_element.attribute("URI").value unless reference_element.nil? end