Skip to content

Commit 9f52a28

Browse files
committed
Merge pull request SAML-Toolkits#289 from GyldendalDigital/use-secure-random-and-encapsulate-uuid-creation
Use secure random and encapsulate uuid creation
2 parents bf26b30 + 7ce3f3a commit 9f52a28

File tree

10 files changed

+46
-21
lines changed

10 files changed

+46
-21
lines changed

lib/onelogin/ruby-saml/authrequest.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
require "uuid"
21
require "rexml/document"
32

43
require "onelogin/ruby-saml/logging"
54
require "onelogin/ruby-saml/saml_message"
5+
require "onelogin/ruby-saml/utils"
66

77
# Only supports SAML 2.0
88
module OneLogin
@@ -20,7 +20,7 @@ class Authrequest < SamlMessage
2020
# Asigns an ID, a random uuid.
2121
#
2222
def initialize
23-
@uuid = "_" + UUID.new.generate
23+
@uuid = OneLogin::RubySaml::Utils.uuid
2424
end
2525

2626
# Creates the AuthNRequest string.

lib/onelogin/ruby-saml/idp_metadata_parser.rb

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
require "base64"
2-
require "uuid"
32
require "zlib"
43
require "cgi"
54
require "net/http"

lib/onelogin/ruby-saml/logoutrequest.rb

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
require "uuid"
2-
31
require "onelogin/ruby-saml/logging"
42
require "onelogin/ruby-saml/saml_message"
3+
require "onelogin/ruby-saml/utils"
54

65
# Only supports SAML 2.0
76
module OneLogin
@@ -18,7 +17,7 @@ class Logoutrequest < SamlMessage
1817
# Asigns an ID, a random uuid.
1918
#
2019
def initialize
21-
@uuid = "_" + UUID.new.generate
20+
@uuid = OneLogin::RubySaml::Utils.uuid
2221
end
2322

2423
# Creates the Logout Request string.
@@ -108,7 +107,7 @@ def create_logout_request_xml_doc(settings)
108107
nameid.text = settings.name_identifier_value
109108
else
110109
# If no NameID is present in the settings we generate one
111-
nameid.text = "_" + UUID.new.generate
110+
nameid.text = OneLogin::RubySaml::Utils.uuid
112111
nameid.attributes['Format'] = 'urn:oasis:names:tc:SAML:2.0:nameid-format:transient'
113112
end
114113

lib/onelogin/ruby-saml/metadata.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
require "uri"
2-
require "uuid"
32

43
require "onelogin/ruby-saml/logging"
4+
require "onelogin/ruby-saml/utils"
55

66
# Only supports SAML 2.0
77
module OneLogin
@@ -49,7 +49,7 @@ def generate(settings, pretty_print=false)
4949
xc2.text = cert_text
5050
end
5151

52-
root.attributes["ID"] = "_" + UUID.new.generate
52+
root.attributes["ID"] = OneLogin::RubySaml::Utils.uuid
5353
if settings.issuer
5454
root.attributes["entityID"] = settings.issuer
5555
end

lib/onelogin/ruby-saml/slo_logoutresponse.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
require "uuid"
2-
31
require "onelogin/ruby-saml/logging"
2+
43
require "onelogin/ruby-saml/saml_message"
4+
require "onelogin/ruby-saml/utils"
55

66
# Only supports SAML 2.0
77
module OneLogin
@@ -18,7 +18,7 @@ class SloLogoutresponse < SamlMessage
1818
# Asigns an ID, a random uuid.
1919
#
2020
def initialize
21-
@uuid = "_" + UUID.new.generate
21+
@uuid = OneLogin::RubySaml::Utils.uuid
2222
end
2323

2424
# Creates the Logout Response string.

lib/onelogin/ruby-saml/utils.rb

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
1+
if RUBY_VERSION < '1.9'
2+
require 'uuid'
3+
else
4+
require 'securerandom'
5+
end
6+
17
module OneLogin
28
module RubySaml
39

410
# SAML2 Auxiliary class
5-
#
11+
#
612
class Utils
13+
@@uuid_generator = UUID.new if RUBY_VERSION < '1.9'
714

815
DSIG = "http://www.w3.org/2000/09/xmldsig#"
916
XENC = "http://www.w3.org/2001/04/xmlenc#"
@@ -30,7 +37,7 @@ def self.format_cert(cert)
3037
# @return [String] The formatted private key
3138
#
3239
def self.format_private_key(key)
33-
# don't try to format an encoded private key or if is empty
40+
# don't try to format an encoded private key or if is empty
3441
return key if key.nil? || key.empty? || key.match(/\x0d/)
3542

3643
# is this an rsa key?
@@ -114,7 +121,7 @@ def self.decrypt_data(encrypted_node, private_key)
114121
{ 'xenc' => XENC }
115122
)
116123
algorithm = encrypt_method.attributes['Algorithm']
117-
retrieve_plaintext(node, symmetric_key, algorithm)
124+
retrieve_plaintext(node, symmetric_key, algorithm)
118125
end
119126

120127
# Obtains the symmetric key from the EncryptedData element
@@ -140,7 +147,7 @@ def self.retrieve_symmetric_key(encrypt_data, private_key)
140147
{"ds" => DSIG, "xenc" => XENC }
141148
)
142149
algorithm = encrypt_method.attributes['Algorithm']
143-
retrieve_plaintext(cipher_text, private_key, algorithm)
150+
retrieve_plaintext(cipher_text, private_key, algorithm)
144151
end
145152

146153
# Obtains the deciphered text
@@ -158,7 +165,7 @@ def self.retrieve_plaintext(cipher_text, symmetric_key, algorithm)
158165
when 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p' then oaep = symmetric_key
159166
end
160167

161-
if cipher
168+
if cipher
162169
iv_len = cipher.iv_len
163170
data = cipher_text[iv_len..-1]
164171
cipher.padding, cipher.key, cipher.iv = 0, symmetric_key, cipher_text[0..iv_len-1]
@@ -173,6 +180,9 @@ def self.retrieve_plaintext(cipher_text, symmetric_key, algorithm)
173180
end
174181
end
175182

183+
def self.uuid
184+
RUBY_VERSION < '1.9' ? "_#{@@uuid_generator.generate}" : "_#{SecureRandom.uuid}"
185+
end
176186
end
177187
end
178188
end

ruby-saml.gemspec

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,17 @@ Gem::Specification.new do |s|
2525
s.summary = %q{SAML Ruby Tookit}
2626
s.test_files = `git ls-files test/*`.split("\n")
2727

28-
s.add_runtime_dependency('uuid', '~> 2.3')
28+
2929

3030
# Because runtime dependencies are determined at build time, we cannot make
3131
# Nokogiri's version dependent on the Ruby version, even though we would
3232
# have liked to constrain Ruby 1.8.7 to install only the 1.5.x versions.
3333
if defined?(JRUBY_VERSION)
3434
s.add_runtime_dependency('nokogiri', '>= 1.6.0')
3535
s.add_runtime_dependency('jruby-openssl', '>= 0.9.8')
36+
elsif RUBY_VERSION < '1.9'
37+
s.add_runtime_dependency('uuid')
38+
s.add_runtime_dependency('nokogiri', '<= 1.5.11')
3639
else
3740
s.add_runtime_dependency('nokogiri', '>= 1.5.10')
3841
end

test/logoutrequest_test.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ class RequestTest < Minitest::Test
2929
end
3030

3131
it "set sessionindex" do
32-
sessionidx = UUID.new.generate
32+
settings.idp_slo_target_url = "http://example.com"
33+
sessionidx = OneLogin::RubySaml::Utils.uuid
3334
settings.sessionindex = sessionidx
3435

3536
unauth_url = OneLogin::RubySaml::Logoutrequest.new.create(settings, { :nameid => "there" })

test/test_helper.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ def ruby_saml_key_text
203203
# logoutresponse fixtures
204204
#
205205
def random_id
206-
"_#{UUID.new.generate}"
206+
"_#{OneLogin::RubySaml::Utils.uuid}"
207207
end
208208

209209
#

test/utils_test.rb

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,4 +142,17 @@ class UtilsTest < Minitest::Test
142142
assert_equal = "The status code of the Logout Response was not Success", status_error_msg3
143143
end
144144
end
145-
end
145+
146+
describe "Utils" do
147+
148+
describe ".uuid" do
149+
it "returns a uuid starting with an underscore" do
150+
assert_match /^_[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/, OneLogin::RubySaml::Utils.uuid
151+
end
152+
153+
it "doesn't return the same value twice" do
154+
refute_equal OneLogin::RubySaml::Utils.uuid, OneLogin::RubySaml::Utils.uuid
155+
end
156+
end
157+
end
158+
end

0 commit comments

Comments
 (0)