Class: SamlTool::ResponseReader

Inherits:
Reader
  • Object
show all
Defined in:
lib/saml_tool/response_reader.rb

Instance Attribute Summary

Attributes inherited from Reader

#config, #namespaces, #saml

Instance Method Summary collapse

Methods inherited from Reader

#to_hash

Constructor Details

#initialize(saml, config = {}, namespaces = {}) ⇒ ResponseReader



25
26
27
28
29
30
31
# 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

Instance Method Details

#attribute_namesObject



33
34
35
# File 'lib/saml_tool/response_reader.rb', line 33

def attribute_names
  @attribute_names ||= saml.xpath("//saml:Attribute/@Name").collect(&:value)
end

#attributesObject

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.



40
41
42
43
44
45
46
# 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

#c14mObject



157
158
159
# File 'lib/saml_tool/response_reader.rb', line 157

def c14m
  'http://www.w3.org/2001/10/xml-exc-c14n#'
end

#canonicalization_algorithmObject



88
89
90
91
92
93
94
# 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_elementObject



100
101
102
103
104
105
# File 'lib/saml_tool/response_reader.rb', line 100

def canonicalized_hashed_element
  hashed_element.canonicalize(
    canonicalization_algorithm,
    inclusive_namespaces.split(' ')
  )
end

#canonicalized_signed_infoObject



107
108
109
110
111
112
# File 'lib/saml_tool/response_reader.rb', line 107

def canonicalized_signed_info
  signed_info_element.canonicalize(
    canonicalization_algorithm,
    inclusive_namespaces.split(' ')
  )
end

#certificateObject



72
73
74
# File 'lib/saml_tool/response_reader.rb', line 72

def certificate
  @certificate ||= OpenSSL::X509::Certificate.new(raw_cert)
end

#clone_saml_and_remove_signatureObject



144
145
146
147
148
# 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_valueObject



140
141
142
# File 'lib/saml_tool/response_reader.rb', line 140

def decoded_digest_value
  Base64.decode64(digest_value)
end

#default_configObject

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.



11
12
13
14
15
16
17
18
19
20
21
22
23
# 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_namespacesObject



150
151
152
153
154
155
# File 'lib/saml_tool/response_reader.rb', line 150

def default_namespaces
  {
    ds: dsig,
    ec: c14m
  }
end

#determine_algorithm_class(method_text) ⇒ Object



126
127
128
129
130
131
132
133
134
# 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_classObject



118
119
120
# File 'lib/saml_tool/response_reader.rb', line 118

def digest_algorithm_class
  @digest_algorithm_class ||= determine_algorithm_class(digest_algorithm)
end

#digest_hashObject



136
137
138
# File 'lib/saml_tool/response_reader.rb', line 136

def digest_hash
  @digest_hash ||= digest_algorithm_class.digest(canonicalized_hashed_element)
end

#digests_match?Boolean



64
65
66
# File 'lib/saml_tool/response_reader.rb', line 64

def digests_match?
  digest_hash == decoded_digest_value
end

#dsigObject



161
162
163
# File 'lib/saml_tool/response_reader.rb', line 161

def dsig
  'http://www.w3.org/2000/09/xmldsig#'
end

#fingerprintObject



80
81
82
# File 'lib/saml_tool/response_reader.rb', line 80

def fingerprint
  @fingerprint ||= Digest::SHA1.hexdigest(certificate.to_der)
end

#hashed_elementObject



96
97
98
# File 'lib/saml_tool/response_reader.rb', line 96

def hashed_element
  @hashed_element ||= signatureless.at_xpath("//*[@ID='#{reference_uri[1..-1]}']")
end

#raw_certObject



76
77
78
# File 'lib/saml_tool/response_reader.rb', line 76

def raw_cert
  @raw_cert ||= Base64.decode64(base64_cert)
end

#signatureObject



84
85
86
# File 'lib/saml_tool/response_reader.rb', line 84

def signature
  @signature ||= Base64.decode64(signature_value)
end

#signature_algorithm_classObject



122
123
124
# File 'lib/saml_tool/response_reader.rb', line 122

def signature_algorithm_class
  @signature_algorithm_class ||= determine_algorithm_class(signature_algorithm)
end

#signature_verified?Boolean



56
57
58
59
60
61
62
# 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

#signaturelessObject



68
69
70
# File 'lib/saml_tool/response_reader.rb', line 68

def signatureless
  @signatureless ||= clone_saml_and_remove_signature
end

#signed_info_elementObject



114
115
116
# File 'lib/saml_tool/response_reader.rb', line 114

def signed_info_element
  signed_info.source.first
end

#structurally_valid?Boolean



52
53
54
# File 'lib/saml_tool/response_reader.rb', line 52

def structurally_valid?
  Validator.new(saml.to_s).valid?
end

#valid?Boolean



48
49
50
# File 'lib/saml_tool/response_reader.rb', line 48

def valid?
  structurally_valid? && signature_verified? && digests_match?
end