Class: SamlTool::ResponseReader
- Inherits:
-
Reader
- Object
- Reader
- SamlTool::ResponseReader
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_names ⇒ Object
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
|
#attributes ⇒ Object
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
|
#c14m ⇒ Object
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_algorithm ⇒ Object
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_element ⇒ Object
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_info ⇒ Object
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
|
#certificate ⇒ Object
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_signature ⇒ Object
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_value ⇒ Object
140
141
142
|
# File 'lib/saml_tool/response_reader.rb', line 140
def decoded_digest_value
Base64.decode64(digest_value)
end
|
#default_config ⇒ Object
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_namespaces ⇒ Object
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_class ⇒ Object
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_hash ⇒ Object
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
|
#dsig ⇒ Object
161
162
163
|
# File 'lib/saml_tool/response_reader.rb', line 161
def dsig
'http://www.w3.org/2000/09/xmldsig#'
end
|
#fingerprint ⇒ Object
80
81
82
|
# File 'lib/saml_tool/response_reader.rb', line 80
def fingerprint
@fingerprint ||= Digest::SHA1.hexdigest(certificate.to_der)
end
|
#hashed_element ⇒ Object
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_cert ⇒ Object
76
77
78
|
# File 'lib/saml_tool/response_reader.rb', line 76
def raw_cert
@raw_cert ||= Base64.decode64(base64_cert)
end
|
#signature ⇒ Object
84
85
86
|
# File 'lib/saml_tool/response_reader.rb', line 84
def signature
@signature ||= Base64.decode64(signature_value)
end
|
#signature_algorithm_class ⇒ Object
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
|
#signatureless ⇒ Object
68
69
70
|
# File 'lib/saml_tool/response_reader.rb', line 68
def signatureless
@signatureless ||= clone_saml_and_remove_signature
end
|
#signed_info_element ⇒ Object
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
|