ruby-saml 1.12.4 → 1.13.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

@@ -13,9 +13,25 @@ module OneLogin
13
13
  class Utils
14
14
  @@uuid_generator = UUID.new if RUBY_VERSION < '1.9'
15
15
 
16
- DSIG = "http://www.w3.org/2000/09/xmldsig#"
17
- XENC = "http://www.w3.org/2001/04/xmlenc#"
18
- DURATION_FORMAT = %r(^(-?)P(?:(?:(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?)?)|(?:(\d+)W))$)
16
+ BINDINGS = { :post => "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST".freeze,
17
+ :redirect => "urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect".freeze }.freeze
18
+ DSIG = "http://www.w3.org/2000/09/xmldsig#".freeze
19
+ XENC = "http://www.w3.org/2001/04/xmlenc#".freeze
20
+ DURATION_FORMAT = %r(^
21
+ (-?)P # 1: Duration sign
22
+ (?:
23
+ (?:(\d+)Y)? # 2: Years
24
+ (?:(\d+)M)? # 3: Months
25
+ (?:(\d+)D)? # 4: Days
26
+ (?:T
27
+ (?:(\d+)H)? # 5: Hours
28
+ (?:(\d+)M)? # 6: Minutes
29
+ (?:(\d+(?:[.,]\d+)?)S)? # 7: Seconds
30
+ )?
31
+ |
32
+ (\d+)W # 8: Weeks
33
+ )
34
+ $)x.freeze
19
35
 
20
36
  # Checks if the x509 cert provided is expired
21
37
  #
@@ -37,31 +53,20 @@ module OneLogin
37
53
  # current time.
38
54
  #
39
55
  # @return [Integer] The new timestamp, after the duration is applied.
40
- #
56
+ #
41
57
  def self.parse_duration(duration, timestamp=Time.now.utc)
58
+ return nil if RUBY_VERSION < '1.9' # 1.8.7 not supported
59
+
42
60
  matches = duration.match(DURATION_FORMAT)
43
-
61
+
44
62
  if matches.nil?
45
63
  raise Exception.new("Invalid ISO 8601 duration")
46
64
  end
47
65
 
48
- durYears = matches[2].to_i
49
- durMonths = matches[3].to_i
50
- durDays = matches[4].to_i
51
- durHours = matches[5].to_i
52
- durMinutes = matches[6].to_i
53
- durSeconds = matches[7].to_f
54
- durWeeks = matches[8].to_i
55
-
56
- if matches[1] == "-"
57
- durYears = -durYears
58
- durMonths = -durMonths
59
- durDays = -durDays
60
- durHours = -durHours
61
- durMinutes = -durMinutes
62
- durSeconds = -durSeconds
63
- durWeeks = -durWeeks
64
- end
66
+ sign = matches[1] == '-' ? -1 : 1
67
+
68
+ durYears, durMonths, durDays, durHours, durMinutes, durSeconds, durWeeks =
69
+ matches[2..8].map { |match| match ? sign * match.tr(',', '.').to_f : 0.0 }
65
70
 
66
71
  initial_datetime = Time.at(timestamp).utc.to_datetime
67
72
  final_datetime = initial_datetime.next_year(durYears)
@@ -1,5 +1,5 @@
1
1
  module OneLogin
2
2
  module RubySaml
3
- VERSION = '1.12.4'
3
+ VERSION = '1.13.0'
4
4
  end
5
5
  end
data/lib/xml_security.rb CHANGED
@@ -42,36 +42,6 @@ module XMLSecurity
42
42
  NOKOGIRI_OPTIONS = Nokogiri::XML::ParseOptions::STRICT |
43
43
  Nokogiri::XML::ParseOptions::NONET
44
44
 
45
- # Safety load the SAML Message XML
46
- # @param document [REXML::Document] The message to be loaded
47
- # @param check_malformed_doc [Boolean] check_malformed_doc Enable or Disable the check for malformed XML
48
- # @return [Nokogiri::XML] The nokogiri document
49
- # @raise [ValidationError] If there was a problem loading the SAML Message XML
50
- def self.safe_load_xml(document, check_malformed_doc = true)
51
- doc_str = document.to_s
52
- if doc_str.include?("<!DOCTYPE")
53
- raise StandardError.new("Dangerous XML detected. No Doctype nodes allowed")
54
- end
55
-
56
- begin
57
- xml = Nokogiri::XML(doc_str) do |config|
58
- config.options = self::NOKOGIRI_OPTIONS
59
- end
60
- rescue StandardError => error
61
- raise StandardError.new(error.message)
62
- end
63
-
64
- if xml.internal_subset
65
- raise StandardError.new("Dangerous XML detected. No Doctype nodes allowed")
66
- end
67
-
68
- unless xml.errors.empty?
69
- raise StandardError.new("There were XML errors when parsing: #{xml.errors}") if check_malformed_doc
70
- end
71
-
72
- xml
73
- end
74
-
75
45
  def canon_algorithm(element)
76
46
  algorithm = element
77
47
  if algorithm.is_a?(REXML::Element)
@@ -144,8 +114,10 @@ module XMLSecurity
144
114
  #<KeyInfo />
145
115
  #<Object />
146
116
  #</Signature>
147
- def sign_document(private_key, certificate, signature_method = RSA_SHA1, digest_method = SHA1, check_malformed_doc = true)
148
- noko = XMLSecurity::BaseDocument.safe_load_xml(self.to_s, check_malformed_doc)
117
+ def sign_document(private_key, certificate, signature_method = RSA_SHA1, digest_method = SHA1)
118
+ noko = Nokogiri::XML(self.to_s) do |config|
119
+ config.options = XMLSecurity::BaseDocument::NOKOGIRI_OPTIONS
120
+ end
149
121
 
150
122
  signature_element = REXML::Element.new("ds:Signature").add_namespace('ds', DSIG)
151
123
  signed_info_element = signature_element.add_element("ds:SignedInfo")
@@ -167,7 +139,9 @@ module XMLSecurity
167
139
  reference_element.add_element("ds:DigestValue").text = compute_digest(canon_doc, algorithm(digest_method_element))
168
140
 
169
141
  # add SignatureValue
170
- noko_sig_element = XMLSecurity::BaseDocument.safe_load_xml(signature_element.to_s, check_malformed_doc)
142
+ noko_sig_element = Nokogiri::XML(signature_element.to_s) do |config|
143
+ config.options = XMLSecurity::BaseDocument::NOKOGIRI_OPTIONS
144
+ end
171
145
 
172
146
  noko_signed_info_element = noko_sig_element.at_xpath('//ds:Signature/ds:SignedInfo', 'ds' => DSIG)
173
147
  canon_string = noko_signed_info_element.canonicalize(canon_algorithm(C14N))
@@ -185,15 +159,13 @@ module XMLSecurity
185
159
  x509_cert_element.text = Base64.encode64(certificate.to_der).gsub(/\n/, "")
186
160
 
187
161
  # add the signature
188
- issuer_element = self.elements["//saml:Issuer"]
162
+ issuer_element = elements["//saml:Issuer"]
189
163
  if issuer_element
190
- self.root.insert_after issuer_element, signature_element
164
+ root.insert_after(issuer_element, signature_element)
165
+ elsif first_child = root.children[0]
166
+ root.insert_before(first_child, signature_element)
191
167
  else
192
- if sp_sso_descriptor = self.elements["/md:EntityDescriptor"]
193
- self.root.insert_before sp_sso_descriptor, signature_element
194
- else
195
- self.root.add_element(signature_element)
196
- end
168
+ root.add_element(signature_element)
197
169
  end
198
170
  end
199
171
 
@@ -263,12 +235,10 @@ module XMLSecurity
263
235
  end
264
236
  end
265
237
  end
266
- check_malformed_doc = true
267
- check_malformed_doc = options[:check_malformed_doc] if options.key?(:check_malformed_doc)
268
- validate_signature(base64_cert, soft, check_malformed_doc)
238
+ validate_signature(base64_cert, soft)
269
239
  end
270
240
 
271
- def validate_document_with_cert(idp_cert, soft = true, check_malformed_doc = true)
241
+ def validate_document_with_cert(idp_cert, soft = true)
272
242
  # get cert from response
273
243
  cert_element = REXML::XPath.first(
274
244
  self,
@@ -292,17 +262,13 @@ module XMLSecurity
292
262
  else
293
263
  base64_cert = Base64.encode64(idp_cert.to_pem)
294
264
  end
295
- validate_signature(base64_cert, true, check_malformed_doc)
265
+ validate_signature(base64_cert, true)
296
266
  end
297
267
 
298
- def validate_signature(base64_cert, soft = true, check_malformed_doc = true)
268
+ def validate_signature(base64_cert, soft = true)
299
269
 
300
- begin
301
- document = XMLSecurity::BaseDocument.safe_load_xml(self, check_malformed_doc)
302
- rescue StandardError => error
303
- @errors << error.message
304
- return false if soft
305
- raise ValidationError.new("XML load failed: #{error.message}")
270
+ document = Nokogiri::XML(self.to_s) do |config|
271
+ config.options = XMLSecurity::BaseDocument::NOKOGIRI_OPTIONS
306
272
  end
307
273
 
308
274
  # create a rexml document
@@ -344,30 +310,17 @@ module XMLSecurity
344
310
  canon_string = noko_signed_info_element.canonicalize(canon_algorithm)
345
311
  noko_sig_element.remove
346
312
 
347
- # get signed info
348
- signed_info_element = REXML::XPath.first(
349
- sig_element,
350
- "./ds:SignedInfo",
351
- { "ds" => DSIG }
352
- )
353
-
354
313
  # get inclusive namespaces
355
314
  inclusive_namespaces = extract_inclusive_namespaces
356
315
 
357
316
  # check digests
358
- ref = REXML::XPath.first(signed_info_element, "./ds:Reference", {"ds"=>DSIG})
359
-
360
- reference_nodes = document.xpath("//*[@ID=$id]", nil, { 'id' => extract_signed_element_id })
317
+ ref = REXML::XPath.first(sig_element, "//ds:Reference", {"ds"=>DSIG})
361
318
 
362
- if reference_nodes.length > 1 # ensures no elements with same ID to prevent signature wrapping attack.
363
- return append_error("Duplicated IDs found", soft)
364
- end
365
-
366
- hashed_element = reference_nodes[0]
319
+ hashed_element = document.at_xpath("//*[@ID=$id]", nil, { 'id' => extract_signed_element_id })
367
320
 
368
321
  canon_algorithm = canon_algorithm REXML::XPath.first(
369
- signed_info_element,
370
- './ds:CanonicalizationMethod',
322
+ ref,
323
+ '//ds:CanonicalizationMethod',
371
324
  { "ds" => DSIG }
372
325
  )
373
326
 
@@ -377,13 +330,13 @@ module XMLSecurity
377
330
 
378
331
  digest_algorithm = algorithm(REXML::XPath.first(
379
332
  ref,
380
- "./ds:DigestMethod",
333
+ "//ds:DigestMethod",
381
334
  { "ds" => DSIG }
382
335
  ))
383
336
  hash = digest_algorithm.digest(canon_hashed_element)
384
337
  encoded_digest_value = REXML::XPath.first(
385
338
  ref,
386
- "./ds:DigestValue",
339
+ "//ds:DigestValue",
387
340
  { "ds" => DSIG }
388
341
  )
389
342
  digest_value = Base64.decode64(OneLogin::RubySaml::Utils.element_text(encoded_digest_value))
@@ -409,7 +362,7 @@ module XMLSecurity
409
362
  def process_transforms(ref, canon_algorithm)
410
363
  transforms = REXML::XPath.match(
411
364
  ref,
412
- "./ds:Transforms/ds:Transform",
365
+ "//ds:Transforms/ds:Transform",
413
366
  { "ds" => DSIG }
414
367
  )
415
368
 
data/ruby-saml.gemspec CHANGED
@@ -47,20 +47,12 @@ Gem::Specification.new do |s|
47
47
  s.add_runtime_dependency('rexml')
48
48
  end
49
49
 
50
- s.add_development_dependency('simplecov', '<0.22.0')
51
- if RUBY_VERSION < '2.4.1'
52
- s.add_development_dependency('simplecov-lcov', '<0.8.0')
53
- s.add_development_dependency('term-ansicolor', '1.2.2')
54
- s.add_development_dependency('mime-types', '<3.6.0')
55
- else
56
- s.add_development_dependency('simplecov-lcov', '>0.7.0')
57
- end
58
-
59
50
  s.add_development_dependency('coveralls')
60
51
  s.add_development_dependency('minitest', '~> 5.5')
61
52
  s.add_development_dependency('mocha', '~> 0.14')
62
53
  s.add_development_dependency('rake', '~> 10')
63
54
  s.add_development_dependency('shoulda', '~> 2.11')
55
+ s.add_development_dependency('simplecov')
64
56
  s.add_development_dependency('systemu', '~> 2')
65
57
  s.add_development_dependency('timecop', '<= 0.6.0')
66
58
 
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: 1.12.4
4
+ version: 1.13.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - OneLogin LLC
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-03-12 00:00:00.000000000 Z
11
+ date: 2021-09-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nokogiri
@@ -38,34 +38,6 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: simplecov
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "<"
46
- - !ruby/object:Gem::Version
47
- version: 0.22.0
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "<"
53
- - !ruby/object:Gem::Version
54
- version: 0.22.0
55
- - !ruby/object:Gem::Dependency
56
- name: simplecov-lcov
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - ">"
60
- - !ruby/object:Gem::Version
61
- version: 0.7.0
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - ">"
67
- - !ruby/object:Gem::Version
68
- version: 0.7.0
69
41
  - !ruby/object:Gem::Dependency
70
42
  name: coveralls
71
43
  requirement: !ruby/object:Gem::Requirement
@@ -136,6 +108,20 @@ dependencies:
136
108
  - - "~>"
137
109
  - !ruby/object:Gem::Version
138
110
  version: '2.11'
111
+ - !ruby/object:Gem::Dependency
112
+ name: simplecov
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
139
125
  - !ruby/object:Gem::Dependency
140
126
  name: systemu
141
127
  requirement: !ruby/object:Gem::Requirement
@@ -189,12 +175,12 @@ files:
189
175
  - ".document"
190
176
  - ".github/workflows/test.yml"
191
177
  - ".gitignore"
192
- - ".travis.yml"
178
+ - CHANGELOG.md
193
179
  - Gemfile
194
180
  - LICENSE
195
181
  - README.md
196
182
  - Rakefile
197
- - changelog.md
183
+ - UPGRADING.md
198
184
  - gemfiles/nokogiri-1.5.gemfile
199
185
  - lib/onelogin/ruby-saml.rb
200
186
  - lib/onelogin/ruby-saml/attribute_service.rb
@@ -235,7 +221,7 @@ homepage: https://github.com/onelogin/ruby-saml
235
221
  licenses:
236
222
  - MIT
237
223
  metadata: {}
238
- post_install_message:
224
+ post_install_message:
239
225
  rdoc_options:
240
226
  - "--charset=UTF-8"
241
227
  require_paths:
@@ -251,8 +237,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
251
237
  - !ruby/object:Gem::Version
252
238
  version: '0'
253
239
  requirements: []
254
- rubygems_version: 3.5.18
255
- signing_key:
240
+ rubyforge_project:
241
+ rubygems_version: 2.5.2.1
242
+ signing_key:
256
243
  specification_version: 4
257
244
  summary: SAML Ruby Tookit
258
245
  test_files: []
data/.travis.yml DELETED
@@ -1,48 +0,0 @@
1
- language: ruby
2
- rvm:
3
- - 1.9.3
4
- - 2.0.0
5
- - 2.1.10
6
- - 2.2.10
7
- - 2.3.8
8
- - 2.4.6
9
- - 2.5.8
10
- - 2.6.6
11
- - 2.7.2
12
- - 3.0.0
13
- - jruby-1.7.27
14
- - jruby-9.1.17.0
15
- - jruby-9.2.13.0
16
- gemfile:
17
- - Gemfile
18
- - gemfiles/nokogiri-1.5.gemfile
19
- before_install:
20
- - gem update bundler
21
- matrix:
22
- exclude:
23
- - rvm: jruby-1.7.27
24
- gemfile: gemfiles/nokogiri-1.5.gemfile
25
- - rvm: jruby-9.1.17.0
26
- gemfile: gemfiles/nokogiri-1.5.gemfile
27
- - rvm: jruby-9.2.13.0
28
- gemfile: gemfiles/nokogiri-1.5.gemfile
29
- - rvm: 2.1.5
30
- gemfile: gemfiles/nokogiri-1.5.gemfile
31
- - rvm: 2.1.10
32
- gemfile: gemfiles/nokogiri-1.5.gemfile
33
- - rvm: 2.2.10
34
- gemfile: gemfiles/nokogiri-1.5.gemfile
35
- - rvm: 2.3.8
36
- gemfile: gemfiles/nokogiri-1.5.gemfile
37
- - rvm: 2.4.6
38
- gemfile: gemfiles/nokogiri-1.5.gemfile
39
- - rvm: 2.5.8
40
- gemfile: gemfiles/nokogiri-1.5.gemfile
41
- - rvm: 2.6.6
42
- gemfile: gemfiles/nokogiri-1.5.gemfile
43
- - rvm: 2.7.2
44
- gemfile: gemfiles/nokogiri-1.5.gemfile
45
- - rvm: 3.0.0
46
- gemfile: gemfiles/nokogiri-1.5.gemfile
47
- env:
48
- - JRUBY_OPTS="--debug"