ruby-saml 0.8.11 → 0.8.12

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of ruby-saml might be problematic. Click here for more details.

@@ -1,27 +1,27 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
2
- require 'rexml/document'
3
- require 'responses/logoutresponse_fixtures'
2
+ require File.expand_path(File.join(File.dirname(__FILE__), "responses/logoutresponse_fixtures"))
4
3
 
5
- class LogoutResponseTest < Test::Unit::TestCase
4
+ class LogoutResponseTest < Minitest::Test
6
5
 
7
- context "Logoutresponse" do
8
- context "#new" do
9
- should "raise an exception when response is initialized with nil" do
6
+ describe "Logoutresponse" do
7
+
8
+ describe "#new" do
9
+ it "raise an exception when response is initialized with nil" do
10
10
  assert_raises(ArgumentError) { OneLogin::RubySaml::Logoutresponse.new(nil) }
11
11
  end
12
- should "default to empty settings" do
12
+ it "default to empty settings" do
13
13
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new( valid_response)
14
14
  assert logoutresponse.settings.nil?
15
15
  end
16
- should "accept constructor-injected settings" do
16
+ it "accept constructor-injected settings" do
17
17
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_response, settings)
18
18
  assert !logoutresponse.settings.nil?
19
19
  end
20
- should "accept constructor-injected options" do
20
+ it "accept constructor-injected options" do
21
21
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_response, nil, { :foo => :bar} )
22
22
  assert !logoutresponse.options.empty?
23
23
  end
24
- should "support base64 encoded responses" do
24
+ it "support base64 encoded responses" do
25
25
  expected_response = valid_response
26
26
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(Base64.encode64(expected_response), settings)
27
27
 
@@ -29,8 +29,8 @@ class LogoutResponseTest < Test::Unit::TestCase
29
29
  end
30
30
  end
31
31
 
32
- context "#validate" do
33
- should "validate the response" do
32
+ describe "#validate" do
33
+ it "validate the response" do
34
34
  in_relation_to_request_id = random_id
35
35
 
36
36
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_response({:uuid => in_relation_to_request_id}), settings)
@@ -43,7 +43,7 @@ class LogoutResponseTest < Test::Unit::TestCase
43
43
  assert logoutresponse.success?
44
44
  end
45
45
 
46
- should "invalidate responses with wrong id when given option :matches_uuid" do
46
+ it "invalidate responses with wrong id when given option :matches_uuid" do
47
47
 
48
48
  expected_request_id = "_some_other_expected_uuid"
49
49
  opts = { :matches_request_id => expected_request_id}
@@ -51,10 +51,10 @@ class LogoutResponseTest < Test::Unit::TestCase
51
51
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_response, settings, opts)
52
52
 
53
53
  assert !logoutresponse.validate
54
- assert_not_equal expected_request_id, logoutresponse.in_response_to
54
+ assert expected_request_id != logoutresponse.in_response_to
55
55
  end
56
56
 
57
- should "invalidate responses with wrong request status" do
57
+ it "invalidate responses with wrong request status" do
58
58
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(unsuccessful_response, settings)
59
59
 
60
60
  assert !logoutresponse.validate
@@ -62,8 +62,8 @@ class LogoutResponseTest < Test::Unit::TestCase
62
62
  end
63
63
  end
64
64
 
65
- context "#validate!" do
66
- should "validates good responses" do
65
+ describe "#validate!" do
66
+ it "validates good responses" do
67
67
  in_relation_to_request_id = random_id
68
68
 
69
69
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(valid_response({:uuid => in_relation_to_request_id}), settings)
@@ -71,7 +71,7 @@ class LogoutResponseTest < Test::Unit::TestCase
71
71
  logoutresponse.validate!
72
72
  end
73
73
 
74
- should "raises validation error when matching for wrong request id" do
74
+ it "raises validation error when matching for wrong request id" do
75
75
 
76
76
  expected_request_id = "_some_other_expected_id"
77
77
  opts = { :matches_request_id => expected_request_id}
@@ -81,19 +81,19 @@ class LogoutResponseTest < Test::Unit::TestCase
81
81
  assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate! }
82
82
  end
83
83
 
84
- should "raise validation error for wrong request status" do
84
+ it "raise validation error for wrong request status" do
85
85
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(unsuccessful_response, settings)
86
86
 
87
87
  assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate! }
88
88
  end
89
89
 
90
- should "raise validation error when in bad state" do
90
+ it "raise validation error when in bad state" do
91
91
  # no settings
92
92
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(unsuccessful_response)
93
93
  assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate! }
94
94
  end
95
95
 
96
- should "raise validation error when in lack of sp_entity_id setting" do
96
+ it "raise validation error when in lack of sp_entity_id setting" do
97
97
  bad_settings = settings
98
98
  bad_settings.issuer = nil
99
99
  bad_settings.sp_entity_id = nil
@@ -101,7 +101,7 @@ class LogoutResponseTest < Test::Unit::TestCase
101
101
  assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate! }
102
102
  end
103
103
 
104
- should "raise error for invalid xml" do
104
+ it "raise error for invalid xml" do
105
105
  logoutresponse = OneLogin::RubySaml::Logoutresponse.new(invalid_xml_response, settings)
106
106
 
107
107
  assert_raises(OneLogin::RubySaml::ValidationError) { logoutresponse.validate! }
@@ -109,10 +109,4 @@ class LogoutResponseTest < Test::Unit::TestCase
109
109
  end
110
110
 
111
111
  end
112
-
113
- # logoutresponse fixtures
114
- def random_id
115
- "_#{UUID.new.generate}"
116
- end
117
-
118
112
  end
@@ -1,13 +1,13 @@
1
1
  require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
2
2
 
3
- class ResponseTest < Test::Unit::TestCase
3
+ class ResponseTest < Minitest::Test
4
4
 
5
- context "Response" do
6
- should "raise an exception when response is initialized with nil" do
5
+ describe "Response" do
6
+ it "raise an exception when response is initialized with nil" do
7
7
  assert_raises(ArgumentError) { OneLogin::RubySaml::Response.new(nil) }
8
8
  end
9
9
 
10
- should "be able to parse a document which contains ampersands" do
10
+ it "be able to parse a document which contains ampersands" do
11
11
  XMLSecurity::SignedDocument.any_instance.stubs(:digests_match?).returns(true)
12
12
  OneLogin::RubySaml::Response.any_instance.stubs(:validate_conditions).returns(true)
13
13
 
@@ -18,7 +18,7 @@ class ResponseTest < Test::Unit::TestCase
18
18
  response.validate!
19
19
  end
20
20
 
21
- should "adapt namespace" do
21
+ it "adapt namespace" do
22
22
  response = OneLogin::RubySaml::Response.new(response_document)
23
23
  assert !response.name_id.nil?
24
24
  response = OneLogin::RubySaml::Response.new(response_document_2)
@@ -27,14 +27,14 @@ class ResponseTest < Test::Unit::TestCase
27
27
  assert !response.name_id.nil?
28
28
  end
29
29
 
30
- should "default to raw input when a response is not Base64 encoded" do
30
+ it "default to raw input when a response is not Base64 encoded" do
31
31
  decoded = Base64.decode64(response_document_2)
32
32
  response = OneLogin::RubySaml::Response.new(decoded)
33
33
  assert response.document
34
34
  end
35
35
 
36
- context "Assertion" do
37
- should "only retreive an assertion with an ID that matches the signature's reference URI" do
36
+ describe "Assertion" do
37
+ it "only retreive an assertion with an ID that matches the signature's reference URI" do
38
38
  response = OneLogin::RubySaml::Response.new(wrapped_response_2)
39
39
  response.stubs(:conditions).returns(nil)
40
40
  settings = OneLogin::RubySaml::Settings.new
@@ -44,77 +44,89 @@ class ResponseTest < Test::Unit::TestCase
44
44
  end
45
45
  end
46
46
 
47
- context "#validate!" do
48
- should "raise when encountering a condition that prevents the document from being valid" do
47
+ describe "#validate!" do
48
+ it "raise when encountering a condition that prevents the document from being valid" do
49
49
  response = OneLogin::RubySaml::Response.new(response_document)
50
- assert_raise(OneLogin::RubySaml::ValidationError) do
50
+ assert_raises(OneLogin::RubySaml::ValidationError) do
51
51
  response.validate!
52
52
  end
53
53
  end
54
54
  end
55
55
 
56
- context "#is_valid?" do
57
- should "return false when response is initialized with blank data" do
56
+ describe "#is_valid?" do
57
+ it "return false when response is initialized with blank data" do
58
58
  response = OneLogin::RubySaml::Response.new('')
59
59
  assert !response.is_valid?
60
60
  end
61
61
 
62
- should "return false if settings have not been set" do
62
+ it "return false if settings have not been set" do
63
63
  response = OneLogin::RubySaml::Response.new(response_document)
64
64
  assert !response.is_valid?
65
65
  end
66
66
 
67
- should "return true when the response is initialized with valid data" do
68
- response = OneLogin::RubySaml::Response.new(response_document_4)
67
+ it "return true when the response is initialized with valid data" do
68
+ response = OneLogin::RubySaml::Response.new(response_document_valid_signed)
69
69
  response.stubs(:conditions).returns(nil)
70
70
  assert !response.is_valid?
71
71
  settings = OneLogin::RubySaml::Settings.new
72
72
  assert !response.is_valid?
73
73
  response.settings = settings
74
74
  assert !response.is_valid?
75
- settings.idp_cert_fingerprint = signature_fingerprint_1
76
- assert response.is_valid?
75
+ response.settings.idp_cert_fingerprint = signature_fingerprint_valid_res
76
+ response.validate!
77
77
  end
78
78
 
79
- should "should be idempotent when the response is initialized with invalid data" do
80
- response = OneLogin::RubySaml::Response.new(response_document_4)
79
+ it "should be idempotent when the response is initialized with invalid data" do
80
+ response = OneLogin::RubySaml::Response.new(response_document_valid_signed)
81
81
  response.stubs(:conditions).returns(nil)
82
82
  settings = OneLogin::RubySaml::Settings.new
83
- response.settings = settings
83
+ response.settings = settings
84
84
  assert !response.is_valid?
85
85
  assert !response.is_valid?
86
86
  end
87
87
 
88
- should "should be idempotent when the response is initialized with valid data" do
89
- response = OneLogin::RubySaml::Response.new(response_document_4)
88
+ it "should be idempotent when the response is initialized with valid data" do
89
+ response = OneLogin::RubySaml::Response.new(response_document_valid_signed)
90
90
  response.stubs(:conditions).returns(nil)
91
91
  settings = OneLogin::RubySaml::Settings.new
92
92
  response.settings = settings
93
- settings.idp_cert_fingerprint = signature_fingerprint_1
93
+ response.settings.idp_cert_fingerprint = signature_fingerprint_valid_res
94
94
  assert response.is_valid?
95
95
  assert response.is_valid?
96
96
  end
97
97
 
98
- should "return true when using certificate instead of fingerprint" do
99
- response = OneLogin::RubySaml::Response.new(response_document_4)
98
+ it "return true when using certificate instead of fingerprint" do
99
+ response = OneLogin::RubySaml::Response.new(response_document_valid_signed)
100
100
  response.stubs(:conditions).returns(nil)
101
101
  settings = OneLogin::RubySaml::Settings.new
102
102
  response.settings = settings
103
- settings.idp_cert = signature_1
103
+ settings.idp_cert = valid_cert
104
104
  assert response.is_valid?
105
105
  end
106
106
 
107
- should "not allow signature wrapping attack" do
107
+ it "not allow signature wrapping attack" do
108
108
  response = OneLogin::RubySaml::Response.new(response_document_4)
109
109
  response.stubs(:conditions).returns(nil)
110
110
  settings = OneLogin::RubySaml::Settings.new
111
111
  settings.idp_cert_fingerprint = signature_fingerprint_1
112
112
  response.settings = settings
113
- assert response.is_valid?
113
+ assert !response.is_valid?
114
114
  assert response.name_id == "test@onelogin.com"
115
115
  end
116
116
 
117
- should "support dynamic namespace resolution on signature elements" do
117
+ it "not allow element wrapping attack" do
118
+ response_wrapped = OneLogin::RubySaml::Response.new(response_document_wrapped)
119
+ response_wrapped.stubs(:conditions).returns(nil)
120
+ response_wrapped.stubs(:validate_subject_confirmation).returns(true)
121
+ settings = OneLogin::RubySaml::Settings.new
122
+ response_wrapped.settings = settings
123
+ response_wrapped.settings.idp_cert_fingerprint = signature_fingerprint_1
124
+
125
+ assert !response_wrapped.is_valid?
126
+ assert_nil response_wrapped.name_id
127
+ end
128
+
129
+ it "support dynamic namespace resolution on signature elements" do
118
130
  response = OneLogin::RubySaml::Response.new(fixture("no_signature_ns.xml"))
119
131
  response.stubs(:conditions).returns(nil)
120
132
  settings = OneLogin::RubySaml::Settings.new
@@ -124,7 +136,7 @@ class ResponseTest < Test::Unit::TestCase
124
136
  assert response.validate!
125
137
  end
126
138
 
127
- should "validate ADFS assertions" do
139
+ it "validate ADFS assertions" do
128
140
  response = OneLogin::RubySaml::Response.new(fixture(:adfs_response_sha256))
129
141
  response.stubs(:conditions).returns(nil)
130
142
  settings = OneLogin::RubySaml::Settings.new
@@ -133,7 +145,7 @@ class ResponseTest < Test::Unit::TestCase
133
145
  assert response.validate!
134
146
  end
135
147
 
136
- should "validate the digest" do
148
+ it "validate the digest" do
137
149
  response = OneLogin::RubySaml::Response.new(r1_response_document_6)
138
150
  response.stubs(:conditions).returns(nil)
139
151
  settings = OneLogin::RubySaml::Settings.new
@@ -142,8 +154,8 @@ class ResponseTest < Test::Unit::TestCase
142
154
  assert response.validate!
143
155
  end
144
156
 
145
- should "validate SAML 2.0 XML structure" do
146
- resp_xml = Base64.decode64(response_document_4).gsub(/emailAddress/,'test')
157
+ it "validate SAML 2.0 XML structure" do
158
+ resp_xml = Base64.decode64(response_document_valid_signed).gsub(/emailAddress/,'test')
147
159
  response = OneLogin::RubySaml::Response.new(Base64.encode64(resp_xml))
148
160
  response.stubs(:conditions).returns(nil)
149
161
  settings = OneLogin::RubySaml::Settings.new
@@ -152,7 +164,7 @@ class ResponseTest < Test::Unit::TestCase
152
164
  assert_raises(OneLogin::RubySaml::ValidationError, 'Digest mismatch'){ response.validate! }
153
165
  end
154
166
 
155
- should "Prevent node text with comment (VU#475445) attack" do
167
+ it "Prevent node text with comment (VU#475445) attack" do
156
168
  response_doc = File.read(File.join(File.dirname(__FILE__), "responses", 'response_node_text_attack.xml.base64'))
157
169
  response = OneLogin::RubySaml::Response.new(response_doc)
158
170
 
@@ -160,42 +172,42 @@ class ResponseTest < Test::Unit::TestCase
160
172
  assert_equal "smith", response.attributes["surname"]
161
173
  end
162
174
 
163
- context '#validate_audience' do
164
- should "return true when sp_entity_id not set or empty" do
165
- response = OneLogin::RubySaml::Response.new(response_document_4)
175
+ describe '#validate_audience' do
176
+ it "return true when sp_entity_id not set or empty" do
177
+ response = OneLogin::RubySaml::Response.new(response_document_valid_signed)
166
178
  response.stubs(:conditions).returns(nil)
167
179
  settings = OneLogin::RubySaml::Settings.new
168
180
  response.settings = settings
169
- settings.idp_cert_fingerprint = signature_fingerprint_1
181
+ settings.idp_cert_fingerprint = signature_fingerprint_valid_res
170
182
  assert response.is_valid?
171
183
  settings.sp_entity_id = ''
172
184
  assert response.is_valid?
173
185
  end
174
186
 
175
- should "return false when sp_entity_id set to incorrectly" do
176
- response = OneLogin::RubySaml::Response.new(response_document_4)
187
+ it "return false when sp_entity_id set to incorrectly" do
188
+ response = OneLogin::RubySaml::Response.new(response_document_valid_signed)
177
189
  response.stubs(:conditions).returns(nil)
178
190
  settings = OneLogin::RubySaml::Settings.new
179
191
  response.settings = settings
180
- settings.idp_cert_fingerprint = signature_fingerprint_1
192
+ settings.idp_cert_fingerprint = signature_fingerprint_valid_res
181
193
  settings.sp_entity_id = 'wrong_audience'
182
194
  assert !response.is_valid?
183
195
  end
184
196
 
185
- should "return true when sp_entity_id set to correctly" do
186
- response = OneLogin::RubySaml::Response.new(response_document_4)
197
+ it "return true when sp_entity_id set to correctly" do
198
+ response = OneLogin::RubySaml::Response.new(response_document_valid_signed)
187
199
  response.stubs(:conditions).returns(nil)
188
200
  settings = OneLogin::RubySaml::Settings.new
189
201
  response.settings = settings
190
- settings.idp_cert_fingerprint = signature_fingerprint_1
191
- settings.sp_entity_id = 'audience'
202
+ settings.idp_cert_fingerprint = signature_fingerprint_valid_res
203
+ settings.sp_entity_id = 'https://someone.example.com/audience'
192
204
  assert response.is_valid?
193
205
  end
194
206
  end
195
207
  end
196
208
 
197
- context "#name_id" do
198
- should "extract the value of the name id element" do
209
+ describe "#name_id" do
210
+ it "extract the value of the name id element" do
199
211
  response = OneLogin::RubySaml::Response.new(response_document)
200
212
  assert_equal "support@onelogin.com", response.name_id
201
213
 
@@ -203,19 +215,19 @@ class ResponseTest < Test::Unit::TestCase
203
215
  assert_equal "someone@example.com", response.name_id
204
216
  end
205
217
 
206
- should "be extractable from an OpenSAML response" do
218
+ it "be extractable from an OpenSAML response" do
207
219
  response = OneLogin::RubySaml::Response.new(fixture(:open_saml))
208
220
  assert_equal "someone@example.org", response.name_id
209
221
  end
210
222
 
211
- should "be extractable from a Simple SAML PHP response" do
223
+ it "be extractable from a Simple SAML PHP response" do
212
224
  response = OneLogin::RubySaml::Response.new(fixture(:simple_saml_php))
213
225
  assert_equal "someone@example.com", response.name_id
214
226
  end
215
227
  end
216
228
 
217
- context "#check_conditions" do
218
- should "check time conditions" do
229
+ describe "#check_conditions" do
230
+ it "check time conditions" do
219
231
  response = OneLogin::RubySaml::Response.new(response_document)
220
232
  assert !response.send(:validate_conditions, true)
221
233
  response = OneLogin::RubySaml::Response.new(response_document_6)
@@ -226,75 +238,74 @@ class ResponseTest < Test::Unit::TestCase
226
238
  assert response.send(:validate_conditions, true)
227
239
  end
228
240
 
229
- should "optionally allow for clock drift" do
241
+ it "optionally allow for clock drift" do
230
242
  # The NotBefore condition in the document is 2011-06-14T18:21:01.516Z
231
- Time.stubs(:now).returns(Time.parse("2011-06-14T18:21:01Z"))
243
+ expected_time = Time.parse("2011-06-14T18:21:01Z")
244
+ Time.stubs(:now).returns(expected_time)
232
245
  response = OneLogin::RubySaml::Response.new(response_document_5, :allowed_clock_drift => 0.515)
233
246
  assert !response.send(:validate_conditions, true)
234
247
 
235
- Time.stubs(:now).returns(Time.parse("2011-06-14T18:21:01Z"))
248
+ expected_time = Time.parse("2011-06-14T18:21:01Z")
249
+ Time.stubs(:now).returns(expected_time)
236
250
  response = OneLogin::RubySaml::Response.new(response_document_5, :allowed_clock_drift => 0.516)
237
251
  assert response.send(:validate_conditions, true)
238
252
  end
239
253
  end
240
254
 
241
- context "#attributes" do
242
- should "extract the first attribute in a hash accessed via its symbol" do
243
- response = OneLogin::RubySaml::Response.new(response_document)
244
- assert_equal "demo", response.attributes[:uid]
255
+ describe "#attributes" do
256
+ before do
257
+ @response = OneLogin::RubySaml::Response.new(response_document)
245
258
  end
246
259
 
247
- should "extract the first attribute in a hash accessed via its name" do
248
- response = OneLogin::RubySaml::Response.new(response_document)
249
- assert_equal "demo", response.attributes["uid"]
260
+ it "extract the first attribute in a hash accessed via its symbol" do
261
+ assert_equal "demo", @response.attributes[:uid]
250
262
  end
251
263
 
252
- should "extract all attributes" do
253
- response = OneLogin::RubySaml::Response.new(response_document)
254
- assert_equal "demo", response.attributes[:uid]
255
- assert_equal "value", response.attributes[:another_value]
264
+ it "extract the first attribute in a hash accessed via its name" do
265
+ assert_equal "demo", @response.attributes["uid"]
256
266
  end
257
267
 
258
- should "work for implicit namespaces" do
259
- response = OneLogin::RubySaml::Response.new(response_document_3)
260
- assert_equal "someone@example.com", response.attributes["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"]
268
+ it "extract all attributes" do
269
+ assert_equal "demo", @response.attributes[:uid]
270
+ assert_equal "value", @response.attributes[:another_value]
261
271
  end
262
272
 
263
- should "not raise on responses without attributes" do
264
- response = OneLogin::RubySaml::Response.new(response_document_4)
265
- assert_equal OneLogin::RubySaml::Attributes.new, response.attributes
273
+ it "work for implicit namespaces" do
274
+ response_3 = OneLogin::RubySaml::Response.new(response_document_3)
275
+ assert_equal "someone@example.com", response_3.attributes["http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress"]
266
276
  end
267
277
 
268
- should "extract attributes from all AttributeStatement tags" do
278
+ it "not raise on responses without attributes" do
279
+ response_4 = OneLogin::RubySaml::Response.new(response_document_4)
280
+ assert_equal OneLogin::RubySaml::Attributes.new, response_4.attributes
281
+ end
282
+
283
+ it "extract attributes from all AttributeStatement tags" do
269
284
  assert_equal "smith", response_with_multiple_attribute_statements.attributes[:surname]
270
285
  assert_equal "bob", response_with_multiple_attribute_statements.attributes[:firstname]
271
286
  end
272
287
 
273
- should "be manipulable by hash methods such as #merge and not raise an exception" do
274
- response = OneLogin::RubySaml::Response.new(response_document)
275
- response.attributes.merge({ :testing_attribute => "test" })
288
+ it "be manipulable by hash methods such as #merge and not raise an exception" do
289
+ @response.attributes.merge({ :testing_attribute => "test" })
276
290
  end
277
291
 
278
- should "be manipulable by hash methods such as #shift and not raise an exception" do
279
- response = OneLogin::RubySaml::Response.new(response_document)
280
- response.attributes.shift
292
+ it "be manipulable by hash methods such as #shift and not raise an exception" do
293
+ @response.attributes.shift
281
294
  end
282
295
 
283
- should "be manipulable by hash methods such as #merge! and actually contain the value" do
284
- response = OneLogin::RubySaml::Response.new(response_document)
285
- response.attributes.merge!({ :testing_attribute => "test" })
286
- assert response.attributes[:testing_attribute]
296
+ it "be manipulable by hash methods such as #merge! and actually contain the value" do
297
+ @response.attributes.merge!({ :testing_attribute => "test" })
298
+ assert @response.attributes[:testing_attribute]
287
299
  end
288
300
 
289
- should "be manipulable by hash methods such as #shift and actually remove the value" do
290
- response = OneLogin::RubySaml::Response.new(response_document)
291
- removed_value = response.attributes.shift
292
- assert_nil response.attributes[removed_value[0]]
301
+ it "be manipulable by hash methods such as #shift and actually remove the value" do
302
+ removed_value = @response.attributes.shift
303
+ assert_nil @response.attributes[removed_value[0]]
293
304
  end
294
305
  end
295
306
 
296
- context "#session_expires_at" do
297
- should "extract the value of the SessionNotOnOrAfter attribute" do
307
+ describe "#session_expires_at" do
308
+ it "extract the value of the SessionNotOnOrAfter attribute" do
298
309
  response = OneLogin::RubySaml::Response.new(response_document)
299
310
  assert response.session_expires_at.is_a?(Time)
300
311
 
@@ -303,124 +314,162 @@ class ResponseTest < Test::Unit::TestCase
303
314
  end
304
315
  end
305
316
 
306
- context "#issuer" do
307
- should "return the issuer inside the response assertion" do
317
+ describe "#issuer" do
318
+ it "return the issuer inside the response assertion" do
308
319
  response = OneLogin::RubySaml::Response.new(response_document)
309
320
  assert_equal "https://app.onelogin.com/saml/metadata/13590", response.issuer
310
321
  end
311
322
 
312
- should "return the issuer inside the response" do
323
+ it "return the issuer inside the response" do
313
324
  response = OneLogin::RubySaml::Response.new(response_document_2)
314
325
  assert_equal "wibble", response.issuer
315
326
  end
316
327
  end
317
328
 
318
- context "#success" do
319
- should "find a status code that says success" do
329
+ describe "#success" do
330
+ it "find a status code that says success" do
320
331
  response = OneLogin::RubySaml::Response.new(response_document)
321
- response.success?
332
+ assert response.send(:success?)
322
333
  end
323
334
  end
324
335
 
325
- context '#xpath_first_from_signed_assertion' do
326
- should 'not allow arbitrary code execution' do
336
+ describe '#xpath_first_from_signed_assertion' do
337
+ it 'not allow arbitrary code execution' do
327
338
  malicious_response_document = fixture('response_eval', false)
328
339
  response = OneLogin::RubySaml::Response.new(malicious_response_document)
329
340
  response.send(:xpath_first_from_signed_assertion)
330
- assert_equal($evalled, nil)
341
+ assert_nil $evalled
331
342
  end
332
343
  end
333
344
 
334
- context "#multiple values" do
335
- should "extract single value as string" do
345
+ describe "#multiple values" do
346
+ it "extract single value as string" do
336
347
  assert_equal "demo", response_multiple_attr_values.attributes[:uid]
337
348
  end
338
349
 
339
- should "extract single value as string in compatibility mode off" do
350
+ it "extract single value as string in compatibility mode off" do
340
351
  OneLogin::RubySaml::Attributes.single_value_compatibility = false
341
352
  assert_equal ["demo"], response_multiple_attr_values.attributes[:uid]
342
353
  # classes are not reloaded between tests so restore default
343
354
  OneLogin::RubySaml::Attributes.single_value_compatibility = true
344
355
  end
345
356
 
346
- should "extract first of multiple values as string for b/w compatibility" do
357
+ it "extract first of multiple values as string for b/w compatibility" do
347
358
  assert_equal 'value1', response_multiple_attr_values.attributes[:another_value]
348
359
  end
349
360
 
350
- should "extract first of multiple values as string for b/w compatibility in compatibility mode off" do
361
+ it "extract first of multiple values as string for b/w compatibility in compatibility mode off" do
351
362
  OneLogin::RubySaml::Attributes.single_value_compatibility = false
352
363
  assert_equal ['value1', 'value2'], response_multiple_attr_values.attributes[:another_value]
353
364
  OneLogin::RubySaml::Attributes.single_value_compatibility = true
354
365
  end
355
366
 
356
- should "return array with all attributes when asked in XML order" do
367
+ it "return array with all attributes when asked in XML order" do
357
368
  assert_equal ['value1', 'value2'], response_multiple_attr_values.attributes.multi(:another_value)
358
369
  end
359
370
 
360
- should "return array with all attributes when asked in XML order in compatibility mode off" do
371
+ it "return array with all attributes when asked in XML order in compatibility mode off" do
361
372
  OneLogin::RubySaml::Attributes.single_value_compatibility = false
362
373
  assert_equal ['value1', 'value2'], response_multiple_attr_values.attributes.multi(:another_value)
363
374
  OneLogin::RubySaml::Attributes.single_value_compatibility = true
364
375
  end
365
376
 
366
- should "return first of multiple values when multiple Attribute tags in XML" do
377
+ it "return first of multiple values when multiple Attribute tags in XML" do
367
378
  assert_equal 'role1', response_multiple_attr_values.attributes[:role]
368
379
  end
369
380
 
370
- should "return first of multiple values when multiple Attribute tags in XML in compatibility mode off" do
381
+ it "return first of multiple values when multiple Attribute tags in XML in compatibility mode off" do
371
382
  OneLogin::RubySaml::Attributes.single_value_compatibility = false
372
383
  assert_equal ['role1', 'role2', 'role3'], response_multiple_attr_values.attributes[:role]
373
384
  OneLogin::RubySaml::Attributes.single_value_compatibility = true
374
385
  end
375
386
 
376
- should "return all of multiple values in reverse order when multiple Attribute tags in XML" do
387
+ it "return all of multiple values in reverse order when multiple Attribute tags in XML" do
377
388
  assert_equal ['role1', 'role2', 'role3'], response_multiple_attr_values.attributes.multi(:role)
378
389
  end
379
390
 
380
- should "return all of multiple values in reverse order when multiple Attribute tags in XML in compatibility mode off" do
391
+ it "return all of multiple values in reverse order when multiple Attribute tags in XML in compatibility mode off" do
381
392
  OneLogin::RubySaml::Attributes.single_value_compatibility = false
382
393
  assert_equal ['role1', 'role2', 'role3'], response_multiple_attr_values.attributes.multi(:role)
383
394
  OneLogin::RubySaml::Attributes.single_value_compatibility = true
384
395
  end
385
396
 
386
- should "return all of multiple values when multiple Attribute tags in multiple AttributeStatement tags" do
397
+ it "return all of multiple values when multiple Attribute tags in multiple AttributeStatement tags" do
387
398
  OneLogin::RubySaml::Attributes.single_value_compatibility = false
388
399
  assert_equal ['role1', 'role2', 'role3'], response_with_multiple_attribute_statements.attributes.multi(:role)
389
400
  OneLogin::RubySaml::Attributes.single_value_compatibility = true
390
401
  end
391
402
 
392
- should "return nil value correctly" do
403
+ it "return nil value correctly" do
393
404
  assert_nil response_multiple_attr_values.attributes[:attribute_with_nil_value]
394
405
  end
395
406
 
396
- should "return nil value correctly when not in compatibility mode off" do
407
+ it "return nil value correctly when not in compatibility mode off" do
397
408
  OneLogin::RubySaml::Attributes.single_value_compatibility = false
398
- assert_equal [nil], response_multiple_attr_values.attributes[:attribute_with_nil_value]
409
+ assert [nil] == response_multiple_attr_values.attributes[:attribute_with_nil_value]
399
410
  OneLogin::RubySaml::Attributes.single_value_compatibility = true
400
411
  end
401
412
 
402
- should "return multiple values including nil and empty string" do
413
+ it "return multiple values including nil and empty string" do
403
414
  response = OneLogin::RubySaml::Response.new(fixture(:response_with_multiple_attribute_values))
404
415
  assert_equal ["", "valuePresent", nil, nil], response.attributes.multi(:attribute_with_nils_and_empty_strings)
405
416
  end
406
417
 
407
- should "return multiple values from [] when not in compatibility mode off" do
418
+ it "return multiple values from [] when not in compatibility mode off" do
408
419
  OneLogin::RubySaml::Attributes.single_value_compatibility = false
409
420
  assert_equal ["", "valuePresent", nil, nil], response_multiple_attr_values.attributes[:attribute_with_nils_and_empty_strings]
410
421
  OneLogin::RubySaml::Attributes.single_value_compatibility = true
411
422
  end
412
423
 
413
- should "check what happens when trying retrieve attribute that does not exists" do
414
- assert_equal nil, response_multiple_attr_values.attributes[:attribute_not_exists]
415
- assert_equal nil, response_multiple_attr_values.attributes.single(:attribute_not_exists)
416
- assert_equal nil, response_multiple_attr_values.attributes.multi(:attribute_not_exists)
424
+ it "check what happens when trying retrieve attribute that does not exists" do
425
+ assert_nil response_multiple_attr_values.attributes[:attribute_not_exists]
426
+ assert_nil response_multiple_attr_values.attributes.single(:attribute_not_exists)
427
+ assert_nil response_multiple_attr_values.attributes.multi(:attribute_not_exists)
417
428
 
418
429
  OneLogin::RubySaml::Attributes.single_value_compatibility = false
419
- assert_equal nil, response_multiple_attr_values.attributes[:attribute_not_exists]
420
- assert_equal nil, response_multiple_attr_values.attributes.single(:attribute_not_exists)
421
- assert_equal nil, response_multiple_attr_values.attributes.multi(:attribute_not_exists)
430
+ assert_nil response_multiple_attr_values.attributes[:attribute_not_exists]
431
+ assert_nil response_multiple_attr_values.attributes.single(:attribute_not_exists)
432
+ assert_nil response_multiple_attr_values.attributes.multi(:attribute_not_exists)
422
433
  OneLogin::RubySaml::Attributes.single_value_compatibility = true
423
434
  end
424
435
  end
436
+
437
+ describe "signature wrapping attack with encrypted assertion" do
438
+ it "should not be valid" do
439
+ settings = OneLogin::RubySaml::Settings.new
440
+ settings.private_key = valid_key
441
+ signature_wrapping_attack = read_response("encrypted_new_attack.xml.base64")
442
+ response_wrapped = OneLogin::RubySaml::Response.new(signature_wrapping_attack, :settings => settings)
443
+ response_wrapped.stubs(:conditions).returns(nil)
444
+ response_wrapped.stubs(:validate_subject_confirmation).returns(true)
445
+ settings.idp_cert_fingerprint = "385b1eec71143f00db6af936e2ea12a28771d72c"
446
+ assert !response_wrapped.is_valid?
447
+ end
448
+ end
449
+
450
+ describe "signature wrapping attack - concealed SAML response body" do
451
+ it "should not be valid" do
452
+ settings = OneLogin::RubySaml::Settings.new
453
+ signature_wrapping_attack = read_response("response_with_concealed_signed_assertion.xml")
454
+ response_wrapped = OneLogin::RubySaml::Response.new(signature_wrapping_attack, :settings => settings)
455
+ settings.idp_cert_fingerprint = '4b68c453c7d994aad9025c99d5efcf566287fe8d'
456
+ response_wrapped.stubs(:conditions).returns(nil)
457
+ response_wrapped.stubs(:validate_subject_confirmation).returns(true)
458
+ assert !response_wrapped.is_valid?
459
+ assert_raises(OneLogin::RubySaml::ValidationError, "SAML Response must contain 1 assertion"){ response_wrapped.validate! }
460
+ end
461
+ end
462
+
463
+ describe "signature wrapping attack - doubled signed assertion SAML response" do
464
+ it "should not be valid" do
465
+ settings = OneLogin::RubySaml::Settings.new
466
+ signature_wrapping_attack = read_response("response_with_doubled_signed_assertion.xml")
467
+ response_wrapped = OneLogin::RubySaml::Response.new(signature_wrapping_attack, :settings => settings)
468
+ settings.idp_cert_fingerprint = '4b68c453c7d994aad9025c99d5efcf566287fe8d'
469
+ response_wrapped.stubs(:conditions).returns(nil)
470
+ response_wrapped.stubs(:validate_subject_confirmation).returns(true)
471
+ assert !response_wrapped.is_valid?
472
+ end
473
+ end
425
474
  end
426
475
  end