class SamlTool::ResponseReader

Public Class Methods

new(saml, config = {}, namespaces = {}) click to toggle source
Calls superclass method SamlTool::Reader::new
# File lib/saml_tool/response_reader.rb, line 25
def initialize(saml, config = {}, namespaces = {})
  super(
    saml,
    config.merge(default_config),
    namespaces.merge(default_namespaces)
  )
end

Public Instance Methods

attribute_names() click to toggle source
# File lib/saml_tool/response_reader.rb, line 33
def attribute_names
  @attribute_names ||= saml.xpath("//saml:Attribute/@Name").collect(&:value)
end
attributes() click to toggle source

A hash with the attribute names as keys, and the matching attribute value content as values. Note that if the same Name is assigned to more than one attribute or an attribute contains more than one value, then the value for that key will be an array.

# File lib/saml_tool/response_reader.rb, line 40
def attributes
  @attributes ||= attribute_names.inject({}) do |hash, name|
    attribute_values = saml.xpath("//saml:Attribute[@Name='#{name}']/saml:AttributeValue/text()")
    hash[name] = attribute_values.length > 1 ? attribute_values.collect(&:to_s) : attribute_values.to_s
    hash
  end
end
c14m() click to toggle source
# File lib/saml_tool/response_reader.rb, line 157
def c14m
  'http://www.w3.org/2001/10/xml-exc-c14n#'
end
canonicalization_algorithm() click to toggle source
# File lib/saml_tool/response_reader.rb, line 88
def canonicalization_algorithm
  case canonicalization_method
    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
    else                                                        Nokogiri::XML::XML_C14N_EXCLUSIVE_1_0
  end
end
canonicalized_hashed_element() click to toggle source
# File lib/saml_tool/response_reader.rb, line 100
def canonicalized_hashed_element
  hashed_element.canonicalize(
    canonicalization_algorithm,
    inclusive_namespaces.split(' ')
  )
end
canonicalized_signed_info() click to toggle source
# File lib/saml_tool/response_reader.rb, line 107
def canonicalized_signed_info
  signed_info_element.canonicalize(
    canonicalization_algorithm,
    inclusive_namespaces.split(' ')
  )
end
certificate() click to toggle source
# File lib/saml_tool/response_reader.rb, line 72
def certificate
  @certificate ||= OpenSSL::X509::Certificate.new(raw_cert)
end
clone_saml_and_remove_signature() click to toggle source
# File lib/saml_tool/response_reader.rb, line 144
def clone_saml_and_remove_signature
  cloned_saml = saml.clone
  cloned_saml.xpath('//ds:Signature', namespaces).remove
  return SamlTool::SAML(cloned_saml.to_s)
end
decoded_digest_value() click to toggle source
# File lib/saml_tool/response_reader.rb, line 140
def decoded_digest_value
  Base64.decode64(digest_value)
end
default_config() click to toggle source

On creation, the keys for this hash will be converted into methods that will return the text gathered at the xpath in the matching value.

# File lib/saml_tool/response_reader.rb, line 11
def default_config
  {
    base64_cert:             '//ds:X509Certificate/text()',
    canonicalization_method: '//ds:CanonicalizationMethod/@Algorithm',
    reference_uri:           '//ds:Reference/@URI',
    inclusive_namespaces:    '//ec:InclusiveNamespaces/@PrefixList',
    digest_algorithm:        '//ds:DigestMethod/@Algorithm',
    digest_value:            '//ds:DigestValue/text()',
    signature_value:         '//ds:SignatureValue/text()',
    signature_algorithm:     '//ds:SignatureMethod/@Algorithm',
    signed_info:             '//ds:SignedInfo'
  }
end
default_namespaces() click to toggle source
# File lib/saml_tool/response_reader.rb, line 150
def default_namespaces
  {
    ds: dsig,
    ec: c14m
  }
end
determine_algorithm_class(method_text) click to toggle source
# File lib/saml_tool/response_reader.rb, line 126
def determine_algorithm_class(method_text)
  case method_text.slice(/sha(\d+)\s*$/, 1)
  when '256' then OpenSSL::Digest::SHA256
  when '384' then OpenSSL::Digest::SHA384
  when '512' then OpenSSL::Digest::SHA512
  else
    OpenSSL::Digest::SHA1
  end
end
digest_algorithm_class() click to toggle source
# File lib/saml_tool/response_reader.rb, line 118
def digest_algorithm_class
  @digest_algorithm_class ||= determine_algorithm_class(digest_algorithm)
end
digest_hash() click to toggle source
# File lib/saml_tool/response_reader.rb, line 136
def digest_hash
  @digest_hash ||= digest_algorithm_class.digest(canonicalized_hashed_element)
end
digests_match?() click to toggle source
# File lib/saml_tool/response_reader.rb, line 64
def digests_match?
  digest_hash == decoded_digest_value
end
dsig() click to toggle source
# File lib/saml_tool/response_reader.rb, line 161
def dsig
  'http://www.w3.org/2000/09/xmldsig#'
end
fingerprint() click to toggle source
# File lib/saml_tool/response_reader.rb, line 80
def fingerprint
  @fingerprint ||= Digest::SHA1.hexdigest(certificate.to_der)
end
hashed_element() click to toggle source
# File lib/saml_tool/response_reader.rb, line 96
def hashed_element
  @hashed_element ||= signatureless.at_xpath("//*[@ID='#{reference_uri[1..-1]}']")
end
raw_cert() click to toggle source
# File lib/saml_tool/response_reader.rb, line 76
def raw_cert
  @raw_cert ||= Base64.decode64(base64_cert)
end
signature() click to toggle source
# File lib/saml_tool/response_reader.rb, line 84
def signature
  @signature ||= Base64.decode64(signature_value)
end
signature_algorithm_class() click to toggle source
# File lib/saml_tool/response_reader.rb, line 122
def signature_algorithm_class
  @signature_algorithm_class ||= determine_algorithm_class(signature_algorithm)
end
signature_verified?() click to toggle source
# File lib/saml_tool/response_reader.rb, line 56
def signature_verified?
  certificate.public_key.verify(
    signature_algorithm_class.new,
    signature,
    canonicalized_signed_info
  )
end
signatureless() click to toggle source
# File lib/saml_tool/response_reader.rb, line 68
def signatureless
  @signatureless ||= clone_saml_and_remove_signature
end
signed_info_element() click to toggle source
# File lib/saml_tool/response_reader.rb, line 114
def signed_info_element
  signed_info.source.first
end
structurally_valid?() click to toggle source
# File lib/saml_tool/response_reader.rb, line 52
def structurally_valid?
  Validator.new(saml.to_s).valid?
end
valid?() click to toggle source
# File lib/saml_tool/response_reader.rb, line 48
def valid?
  structurally_valid? && signature_verified? && digests_match?
end