Skip to content

Commit

Permalink
Add support for canonicalization-algorithm detection
Browse files Browse the repository at this point in the history
  • Loading branch information
stouset committed Oct 11, 2012
1 parent 2d3d46c commit 5e7f13e
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 7 deletions.
25 changes: 19 additions & 6 deletions lib/xml_security.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
require "rexml/document"
require "rexml/xpath"
require "openssl"
require "xmlcanonicalizer"
require 'nokogiri'
require 'xmlcanonicalizer'
require "digest/sha1"
require "digest/sha2"
require "onelogin/ruby-saml/validation_error"
Expand Down Expand Up @@ -73,14 +74,18 @@ def validate_doc(base64_cert, soft = true)
element.remove
end

document = Nokogiri.parse(self.to_s)

# check digests
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..-1]}']")
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).gsub('&','&')

hashed_element = document.at_xpath("//*[@ID='#{uri[1..-1]}']")
canon_algorithm = canon_algorithm REXML::XPath.first(ref, '//ds:CanonicalizationMethod').attribute('Algorithm').value
canon_hashed_element = hashed_element.canonicalize(canon_algorithm, inclusive_namespaces).gsub('&','&')

digest_algorithm = algorithm(REXML::XPath.first(ref, "//ds:DigestMethod"))

hash = digest_algorithm.digest(canon_hashed_element)
digest_value = Base64.decode64(REXML::XPath.first(ref, "//ds:DigestValue", {"ds"=>DSIG}).text)

Expand Down Expand Up @@ -122,6 +127,14 @@ def extract_signed_element_id
self.signed_element_id = reference_element.attribute("URI").value[1..-1] unless reference_element.nil?
end

def canon_algorithm(algorithm)
case algorithm
when "http://www.w3.org/2001/10/xml-exc-c14n#" then Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0
when "http://www.w3.org/TR/2001/REC-xml-c14n-20010315" then Nokogiri::XML::XML_C14N_1_0
when "http://www.w3.org/2006/12/xml-c14n11" then Nokogiri::XML::XML_C14N_1_1
end
end

def algorithm(element)
algorithm = element.attribute("Algorithm").value if element
algorithm = algorithm && algorithm =~ /sha(.*?)$/i && $1.to_i
Expand All @@ -133,7 +146,7 @@ def algorithm(element)
OpenSSL::Digest::SHA1
end
end

def extract_inclusive_namespaces
if element = REXML::XPath.first(self, "//ec:InclusiveNamespaces", { "ec" => C14N })
prefix_list = element.attributes.get_attribute("PrefixList").value
Expand Down
2 changes: 1 addition & 1 deletion ruby-saml.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -25,5 +25,5 @@ Gem::Specification.new do |s|

s.add_runtime_dependency("canonix", ["0.1.1"])
s.add_runtime_dependency("uuid", ["~> 2.3"])
s.add_runtime_dependency("nokogiri")
end

0 comments on commit 5e7f13e

Please sign in to comment.