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.
- checksums.yaml +5 -5
- data/.github/workflows/test.yml +4 -44
- data/{changelog.md → CHANGELOG.md} +19 -12
- data/README.md +288 -226
- data/UPGRADING.md +149 -0
- data/lib/onelogin/ruby-saml/authrequest.rb +2 -3
- data/lib/onelogin/ruby-saml/idp_metadata_parser.rb +110 -77
- data/lib/onelogin/ruby-saml/logoutrequest.rb +3 -3
- data/lib/onelogin/ruby-saml/logoutresponse.rb +2 -3
- data/lib/onelogin/ruby-saml/metadata.rb +59 -22
- data/lib/onelogin/ruby-saml/response.rb +16 -25
- data/lib/onelogin/ruby-saml/saml_message.rb +12 -24
- data/lib/onelogin/ruby-saml/settings.rb +76 -70
- data/lib/onelogin/ruby-saml/slo_logoutrequest.rb +13 -6
- data/lib/onelogin/ruby-saml/slo_logoutresponse.rb +2 -2
- data/lib/onelogin/ruby-saml/utils.rb +27 -22
- data/lib/onelogin/ruby-saml/version.rb +1 -1
- data/lib/xml_security.rb +25 -72
- data/ruby-saml.gemspec +1 -9
- metadata +23 -36
- data/.travis.yml +0 -48
@@ -13,9 +13,25 @@ module OneLogin
|
|
13
13
|
class Utils
|
14
14
|
@@uuid_generator = UUID.new if RUBY_VERSION < '1.9'
|
15
15
|
|
16
|
-
|
17
|
-
|
18
|
-
|
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
|
-
|
49
|
-
|
50
|
-
durDays =
|
51
|
-
|
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)
|
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
|
148
|
-
noko =
|
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 =
|
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 =
|
162
|
+
issuer_element = elements["//saml:Issuer"]
|
189
163
|
if issuer_element
|
190
|
-
|
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
|
-
|
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
|
-
|
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
|
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
|
265
|
+
validate_signature(base64_cert, true)
|
296
266
|
end
|
297
267
|
|
298
|
-
def validate_signature(base64_cert, soft = true
|
268
|
+
def validate_signature(base64_cert, soft = true)
|
299
269
|
|
300
|
-
|
301
|
-
|
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(
|
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
|
-
|
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
|
-
|
370
|
-
'
|
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
|
-
"
|
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
|
-
"
|
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
|
-
"
|
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.
|
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:
|
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
|
-
-
|
178
|
+
- CHANGELOG.md
|
193
179
|
- Gemfile
|
194
180
|
- LICENSE
|
195
181
|
- README.md
|
196
182
|
- Rakefile
|
197
|
-
-
|
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
|
-
|
255
|
-
|
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"
|