ruby-saml 0.8.10 → 0.8.11

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.

checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 1a564ad5fdd002f4648b22638bf51dd7ad029ea633484289c7ce2e8759a3c5d6
4
- data.tar.gz: 15d0f1c459006f4c65fc9cb916b29b55098e68d9e3c5123080737b41b4e5e449
2
+ SHA1:
3
+ metadata.gz: 10ec0e5a4a9fc6a7f65613599597cef7ae8b8293
4
+ data.tar.gz: 0b63798d5d6b78e3073ccb899e355e6aa0134648
5
5
  SHA512:
6
- metadata.gz: 943d65750b9895285e60b24d612c1cce77bef3a262387121ccf9b7f8536ebfea27874d3a68ff095dc1a36e2bc3c53f509de07d2e4e31c02a20437e18015af561
7
- data.tar.gz: ccf1223639a43235641ba2533e61473e4ff248624571cd05177ccd1dd0611f7d8df16f405fd74af2987112a988f5fcb0f2f6c54fe3830f89d3688964780ea333
6
+ metadata.gz: 1883986a5fd1b3925e6745bf7d259a907c656d36958efe50dfb760192c8273a3723b76344ee542a3a07b84da677808fad850b8bd272d949c5ce7fcd8c171a881
7
+ data.tar.gz: 8538b7c75961e99186b320ff1425fb82fa0c759e3e7267eaad76659adf9f0ba98249207122092dbc383f464c1c600b03a37f010d5a3e8bfa7fbb6fba0aaa8915
@@ -2,6 +2,7 @@ require "base64"
2
2
  require "zlib"
3
3
  require "cgi"
4
4
  require "onelogin/ruby-saml/utils"
5
+ require "onelogin/ruby-saml/setting_error"
5
6
 
6
7
  module OneLogin
7
8
  module RubySaml
@@ -25,7 +26,7 @@ module OneLogin
25
26
  params.each_pair do |key, value|
26
27
  request_params << "&#{key.to_s}=#{CGI.escape(value.to_s)}"
27
28
  end
28
- raise "Invalid settings, idp_sso_target_url is not set!" if settings.idp_sso_target_url.nil?
29
+ raise SettingError.new "Invalid settings, idp_sso_target_url is not set!" if settings.idp_sso_target_url.nil? or settings.idp_sso_target_url.empty?
29
30
  @login_url = settings.idp_sso_target_url + request_params
30
31
  end
31
32
 
@@ -101,7 +102,7 @@ module OneLogin
101
102
  root.attributes['ID'] = uuid
102
103
  root.attributes['IssueInstant'] = time
103
104
  root.attributes['Version'] = "2.0"
104
- root.attributes['Destination'] = settings.idp_sso_target_url unless settings.idp_sso_target_url.nil?
105
+ root.attributes['Destination'] = settings.idp_sso_target_url unless settings.idp_sso_target_url.nil? or settings.idp_sso_target_url.empty?
105
106
  root.attributes['IsPassive'] = settings.passive unless settings.passive.nil?
106
107
  root.attributes['ProtocolBinding'] = settings.protocol_binding unless settings.protocol_binding.nil?
107
108
  root.attributes['ForceAuthn'] = settings.force_authn unless settings.force_authn.nil?
@@ -3,6 +3,7 @@ require "zlib"
3
3
  require "cgi"
4
4
  require 'rexml/document'
5
5
  require "onelogin/ruby-saml/utils"
6
+ require "onelogin/ruby-saml/setting_error"
6
7
 
7
8
  module OneLogin
8
9
  module RubySaml
@@ -23,6 +24,7 @@ module OneLogin
23
24
  params.each_pair do |key, value|
24
25
  request_params << "&#{key.to_s}=#{CGI.escape(value.to_s)}"
25
26
  end
27
+ raise SettingError.new "Invalid settings, idp_slo_target_url is not set!" if settings.idp_slo_target_url.nil? or settings.idp_slo_target_url.empty?
26
28
  @logout_url = settings.idp_slo_target_url + request_params
27
29
  end
28
30
 
@@ -103,6 +105,7 @@ module OneLogin
103
105
  root.attributes['ID'] = uuid
104
106
  root.attributes['IssueInstant'] = time
105
107
  root.attributes['Version'] = "2.0"
108
+ root.attributes['Destination'] = settings.idp_slo_target_url unless settings.idp_slo_target_url.nil? or settings.idp_slo_target_url.empty?
106
109
 
107
110
  if settings.sp_entity_id
108
111
  issuer = root.add_element "saml:Issuer", { "xmlns:saml" => "urn:oasis:names:tc:SAML:2.0:assertion" }
@@ -42,6 +42,8 @@ module OneLogin
42
42
  end
43
43
  end
44
44
 
45
+ alias nameid name_id
46
+
45
47
  def sessionindex
46
48
  @sessionindex ||= begin
47
49
  node = xpath_first_from_signed_assertion('/a:AuthnStatement')
@@ -147,6 +149,9 @@ module OneLogin
147
149
  end
148
150
 
149
151
  def validate(soft = true)
152
+ validate_success_status &&
153
+ validate_num_assertion &&
154
+ validate_signed_elements &&
150
155
  validate_structure(soft) &&
151
156
  validate_response_state(soft) &&
152
157
  validate_conditions(soft) &&
@@ -155,6 +160,144 @@ module OneLogin
155
160
  success?
156
161
  end
157
162
 
163
+ # Validates that the SAML Response only contains a single Assertion (encrypted or not).
164
+ # @return [Boolean] True if the SAML Response contains one unique Assertion, otherwise False
165
+ #
166
+ def validate_num_assertion(soft = true)
167
+ assertions = REXML::XPath.match(
168
+ document,
169
+ "//a:Assertion",
170
+ { "a" => ASSERTION }
171
+ )
172
+ encrypted_assertions = REXML::XPath.match(
173
+ document,
174
+ "//a:EncryptedAssertion",
175
+ { "a" => ASSERTION }
176
+ )
177
+
178
+ unless assertions.size != 0
179
+ return soft ? false : validation_error("Encrypted assertion is not supported")
180
+ end
181
+
182
+ unless assertions.size + encrypted_assertions.size == 1
183
+ return soft ? false : validation_error("SAML Response must contain 1 assertion")
184
+ end
185
+
186
+ true
187
+ end
188
+
189
+ # Validates the Signed elements
190
+ # @return [Boolean] True if there is 1 or 2 Elements signed in the SAML Response
191
+ # an are a Response or an Assertion Element, otherwise False if soft=True
192
+ #
193
+ def validate_signed_elements
194
+ signature_nodes = REXML::XPath.match(
195
+ document,
196
+ "//ds:Signature",
197
+ {"ds"=>DSIG}
198
+ )
199
+ signed_elements = []
200
+ verified_seis = []
201
+ verified_ids = []
202
+ signature_nodes.each do |signature_node|
203
+ signed_element = signature_node.parent.name
204
+ if signed_element != 'Response' && signed_element != 'Assertion'
205
+ return soft ? false : validation_error("Invalid Signature Element '#{signed_element}'. SAML Response rejected")
206
+ end
207
+
208
+ if signature_node.parent.attributes['ID'].nil?
209
+ return soft ? false : validation_error("Signed Element must contain an ID. SAML Response rejected")
210
+ end
211
+
212
+ id = signature_node.parent.attributes.get_attribute("ID").value
213
+ if verified_ids.include?(id)
214
+ return soft ? false : validation_error("Duplicated ID. SAML Response rejected")
215
+ end
216
+ verified_ids.push(id)
217
+
218
+ # Check that reference URI matches the parent ID and no duplicate References or IDs
219
+ ref = REXML::XPath.first(signature_node, ".//ds:Reference", {"ds"=>DSIG})
220
+ if ref
221
+ uri = ref.attributes.get_attribute("URI")
222
+ if uri && !uri.value.empty?
223
+ sei = uri.value[1..-1]
224
+
225
+ unless sei == id
226
+ return soft ? false : validation_error("Found an invalid Signed Element. SAML Response rejected")
227
+ end
228
+
229
+ if verified_seis.include?(sei)
230
+ return soft ? false : validation_error("Duplicated Reference URI. SAML Response rejected")
231
+ return append_error("Duplicated Reference URI. SAML Response rejected")
232
+ end
233
+
234
+ verified_seis.push(sei)
235
+ end
236
+ end
237
+
238
+ signed_elements << signed_element
239
+ end
240
+
241
+ unless signature_nodes.length < 3 && !signed_elements.empty?
242
+ return soft ? false : validation_error("Found an unexpected number of Signature Element. SAML Response rejected")
243
+ end
244
+
245
+ true
246
+ end
247
+
248
+ # Validates the Status of the SAML Response
249
+ # @return [Boolean] True if the SAML Response contains a Success code, otherwise False if soft == false
250
+ # @raise [ValidationError] if soft == false and validation fails
251
+ #
252
+ def validate_success_status
253
+ return true if success?
254
+
255
+ return false unless soft
256
+
257
+ error_msg = 'The status code of the Response was not Success'
258
+ status_error_msg = OneLogin::RubySaml::Utils.status_error_msg(error_msg, status_code, status_message)
259
+ return validation_error(status_error_msg)
260
+ end
261
+
262
+ # Checks if the Status has the "Success" code
263
+ # @return [Boolean] True if the StatusCode is Sucess
264
+ #
265
+ def success?
266
+ status_code == "urn:oasis:names:tc:SAML:2.0:status:Success"
267
+ end
268
+
269
+ # @return [String] StatusCode value from a SAML Response.
270
+ #
271
+ def status_code
272
+ @status_code ||= begin
273
+ nodes = REXML::XPath.match(
274
+ document,
275
+ "/p:Response/p:Status/p:StatusCode",
276
+ { "p" => PROTOCOL }
277
+ )
278
+ if nodes.size == 1
279
+ node = nodes[0]
280
+ code = node.attributes["Value"] if node && node.attributes
281
+
282
+ unless code == "urn:oasis:names:tc:SAML:2.0:status:Success"
283
+ nodes = REXML::XPath.match(
284
+ document,
285
+ "/p:Response/p:Status/p:StatusCode/p:StatusCode",
286
+ { "p" => PROTOCOL }
287
+ )
288
+ statuses = nodes.collect do |inner_node|
289
+ inner_node.attributes["Value"]
290
+ end
291
+ extra_code = statuses.join(" | ")
292
+ if extra_code
293
+ code = "#{code} | #{extra_code}"
294
+ end
295
+ end
296
+ code
297
+ end
298
+ end
299
+ end
300
+
158
301
  def validate_structure(soft = true)
159
302
  Dir.chdir(File.expand_path(File.join(File.dirname(__FILE__), '..', '..', 'schemas'))) do
160
303
  @schema = Nokogiri::XML::Schema(IO.read('saml20protocol_schema.xsd'))
@@ -0,0 +1,6 @@
1
+ module OneLogin
2
+ module RubySaml
3
+ class SettingError < StandardError
4
+ end
5
+ end
6
+ end
@@ -2,6 +2,7 @@ require "base64"
2
2
  require "zlib"
3
3
  require "cgi"
4
4
  require "onelogin/ruby-saml/utils"
5
+ require "onelogin/ruby-saml/setting_error"
5
6
 
6
7
  module OneLogin
7
8
  module RubySaml
@@ -35,7 +36,7 @@ module OneLogin
35
36
  params.each_pair do |key, value|
36
37
  response_params << "&#{key.to_s}=#{CGI.escape(value.to_s)}"
37
38
  end
38
-
39
+ raise SettingError.new "Invalid settings, idp_slo_target_url is not set!" if settings.idp_slo_target_url.nil? or settings.idp_slo_target_url.empty?
39
40
  @logout_url = settings.idp_slo_target_url + response_params
40
41
  end
41
42
 
@@ -119,7 +120,7 @@ module OneLogin
119
120
  root.attributes['IssueInstant'] = time
120
121
  root.attributes['Version'] = '2.0'
121
122
  root.attributes['InResponseTo'] = request_id unless request_id.nil?
122
- root.attributes['Destination'] = settings.idp_slo_target_url unless settings.idp_slo_target_url.nil?
123
+ root.attributes['Destination'] = settings.idp_slo_target_url unless settings.idp_slo_target_url.nil? or settings.idp_slo_target_url.empty?
123
124
 
124
125
  if settings.sp_entity_id != nil
125
126
  issuer = root.add_element "saml:Issuer"
@@ -89,6 +89,31 @@ module OneLogin
89
89
  def self.uuid
90
90
  RUBY_VERSION < '1.9' ? "_#{@@uuid_generator.generate}" : "_#{SecureRandom.uuid}"
91
91
  end
92
+
93
+ # Build the status error message
94
+ # @param status_code [String] StatusCode value
95
+ # @param status_message [Strig] StatusMessage value
96
+ # @return [String] The status error message
97
+ def self.status_error_msg(error_msg, raw_status_code = nil, status_message = nil)
98
+ unless raw_status_code.nil?
99
+ if raw_status_code.include? "|"
100
+ status_codes = raw_status_code.split(' | ')
101
+ values = status_codes.collect do |status_code|
102
+ status_code.split(':').last
103
+ end
104
+ printable_code = values.join(" => ")
105
+ else
106
+ printable_code = raw_status_code.split(':').last
107
+ end
108
+ error_msg << ', was ' + printable_code
109
+ end
110
+
111
+ unless status_message.nil?
112
+ error_msg << ' -> ' + status_message
113
+ end
114
+
115
+ error_msg
116
+ end
92
117
  end
93
118
  end
94
119
  end
@@ -1,5 +1,5 @@
1
1
  module OneLogin
2
2
  module RubySaml
3
- VERSION = '0.8.10'
3
+ VERSION = '0.8.11'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-saml
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.10
4
+ version: 0.8.11
5
5
  platform: ruby
6
6
  authors:
7
7
  - OneLogin LLC
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-07-25 00:00:00.000000000 Z
11
+ date: 2019-11-05 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: uuid
@@ -61,6 +61,7 @@ files:
61
61
  - lib/onelogin/ruby-saml/logoutresponse.rb
62
62
  - lib/onelogin/ruby-saml/metadata.rb
63
63
  - lib/onelogin/ruby-saml/response.rb
64
+ - lib/onelogin/ruby-saml/setting_error.rb
64
65
  - lib/onelogin/ruby-saml/settings.rb
65
66
  - lib/onelogin/ruby-saml/slo_logoutresponse.rb
66
67
  - lib/onelogin/ruby-saml/utils.rb
@@ -127,7 +128,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
127
128
  - !ruby/object:Gem::Version
128
129
  version: '0'
129
130
  requirements: []
130
- rubygems_version: 3.0.4
131
+ rubyforge_project: http://www.rubygems.org/gems/ruby-saml
132
+ rubygems_version: 2.5.1
131
133
  signing_key:
132
134
  specification_version: 4
133
135
  summary: SAML Ruby Tookit