ruby-samlnechotech 0.7.23

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.
Files changed (51) hide show
  1. data/.document +5 -0
  2. data/.gitignore +11 -0
  3. data/.travis.yml +5 -0
  4. data/Gemfile +13 -0
  5. data/LICENSE +19 -0
  6. data/README.md +128 -0
  7. data/Rakefile +41 -0
  8. data/lib/onelogin/ruby-samlnechotech/authrequest.rb +84 -0
  9. data/lib/onelogin/ruby-samlnechotech/logging.rb +26 -0
  10. data/lib/onelogin/ruby-samlnechotech/logoutrequest.rb +82 -0
  11. data/lib/onelogin/ruby-samlnechotech/logoutresponse.rb +154 -0
  12. data/lib/onelogin/ruby-samlnechotech/metadata.rb +66 -0
  13. data/lib/onelogin/ruby-samlnechotech/response.rb +186 -0
  14. data/lib/onelogin/ruby-samlnechotech/settings.rb +27 -0
  15. data/lib/onelogin/ruby-samlnechotech/validation_error.rb +7 -0
  16. data/lib/onelogin/ruby-samlnechotech/version.rb +5 -0
  17. data/lib/ruby-samlnechotech.rb +9 -0
  18. data/lib/schemas/saml20assertion_schema.xsd +283 -0
  19. data/lib/schemas/saml20protocol_schema.xsd +302 -0
  20. data/lib/schemas/xenc_schema.xsd +146 -0
  21. data/lib/schemas/xmldsig_schema.xsd +318 -0
  22. data/lib/xml_security.rb +169 -0
  23. data/ruby-samlnechotech.gemspec +29 -0
  24. data/test/certificates/certificate1 +12 -0
  25. data/test/certificates/r1_certificate2_base64 +1 -0
  26. data/test/logoutrequest_test.rb +111 -0
  27. data/test/logoutresponse_test.rb +116 -0
  28. data/test/request_test.rb +97 -0
  29. data/test/response_test.rb +247 -0
  30. data/test/responses/adfs_response_sha1.xml +46 -0
  31. data/test/responses/adfs_response_sha256.xml +46 -0
  32. data/test/responses/adfs_response_sha384.xml +46 -0
  33. data/test/responses/adfs_response_sha512.xml +46 -0
  34. data/test/responses/logoutresponse_fixtures.rb +67 -0
  35. data/test/responses/no_signature_ns.xml +48 -0
  36. data/test/responses/open_saml_response.xml +56 -0
  37. data/test/responses/r1_response6.xml.base64 +1 -0
  38. data/test/responses/response1.xml.base64 +1 -0
  39. data/test/responses/response2.xml.base64 +79 -0
  40. data/test/responses/response3.xml.base64 +66 -0
  41. data/test/responses/response4.xml.base64 +93 -0
  42. data/test/responses/response5.xml.base64 +102 -0
  43. data/test/responses/response_with_ampersands.xml +139 -0
  44. data/test/responses/response_with_ampersands.xml.base64 +93 -0
  45. data/test/responses/simple_saml_php.xml +71 -0
  46. data/test/responses/starfield_response.xml.base64 +1 -0
  47. data/test/responses/wrapped_response_2.xml.base64 +150 -0
  48. data/test/settings_test.rb +46 -0
  49. data/test/test_helper.rb +75 -0
  50. data/test/xml_security_test.rb +160 -0
  51. metadata +172 -0
@@ -0,0 +1,46 @@
1
+ require File.expand_path(File.join(File.dirname(__FILE__), "test_helper"))
2
+
3
+ class SettingsTest < Test::Unit::TestCase
4
+
5
+ context "Settings" do
6
+ setup do
7
+ @settings = Onelogin::Saml::Settings.new
8
+ end
9
+ should "should provide getters and settings" do
10
+ accessors = [
11
+ :assertion_consumer_service_url, :issuer, :sp_name_qualifier,
12
+ :idp_sso_target_url, :idp_cert_fingerprint, :name_identifier_format,
13
+ :idp_slo_target_url, :name_identifier_value, :sessionindex,
14
+ :assertion_consumer_logout_service_url,
15
+ :passive
16
+ ]
17
+
18
+ accessors.each do |accessor|
19
+ value = Kernel.rand
20
+ @settings.send("#{accessor}=".to_sym, value)
21
+ assert_equal value, @settings.send(accessor)
22
+ end
23
+ end
24
+
25
+ should "create settings from hash" do
26
+
27
+ config = {
28
+ :assertion_consumer_service_url => "http://app.muda.no/sso",
29
+ :issuer => "http://muda.no",
30
+ :sp_name_qualifier => "http://sso.muda.no",
31
+ :idp_sso_target_url => "http://sso.muda.no/sso",
32
+ :idp_slo_target_url => "http://sso.muda.no/slo",
33
+ :idp_cert_fingerprint => "00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00",
34
+ :name_identifier_format => "urn:oasis:names:tc:SAML:2.0:nameid-format:transient",
35
+ :passive => true,
36
+ }
37
+ @settings = Onelogin::Saml::Settings.new(config)
38
+
39
+ config.each do |k,v|
40
+ assert_equal v, @settings.send(k)
41
+ end
42
+ end
43
+
44
+ end
45
+
46
+ end
@@ -0,0 +1,75 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+ require 'mocha'
5
+ require 'ruby-debug'
6
+ require 'timecop'
7
+
8
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
9
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
10
+ require 'ruby-samlnechotech'
11
+
12
+ ENV["ruby-samlnechotech/testing"] = "1"
13
+
14
+ class Test::Unit::TestCase
15
+ def fixture(document, base64 = true)
16
+ response = Dir.glob(File.join(File.dirname(__FILE__), "responses", "#{document}*")).first
17
+ if base64 && response =~ /\.xml$/
18
+ Base64.encode64(File.read(response))
19
+ else
20
+ File.read(response)
21
+ end
22
+ end
23
+
24
+ def response_document
25
+ @response_document ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response1.xml.base64'))
26
+ end
27
+
28
+ def response_document_2
29
+ @response_document2 ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response2.xml.base64'))
30
+ end
31
+
32
+ def response_document_3
33
+ @response_document3 ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response3.xml.base64'))
34
+ end
35
+
36
+ def response_document_4
37
+ @response_document4 ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response4.xml.base64'))
38
+ end
39
+
40
+ def response_document_5
41
+ @response_document5 ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response5.xml.base64'))
42
+ end
43
+
44
+ def r1_response_document_6
45
+ @response_document6 ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'r1_response6.xml.base64'))
46
+ end
47
+
48
+ def ampersands_response
49
+ @ampersands_resposne ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response_with_ampersands.xml.base64'))
50
+ end
51
+
52
+ def response_document_6
53
+ doc = Base64.decode64(response_document)
54
+ doc.gsub!(/NotBefore=\"(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z\"/, "NotBefore=\"#{(Time.now-300).getutc.strftime("%Y-%m-%dT%XZ")}\"")
55
+ doc.gsub!(/NotOnOrAfter=\"(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z\"/, "NotOnOrAfter=\"#{(Time.now+300).getutc.strftime("%Y-%m-%dT%XZ")}\"")
56
+ Base64.encode64(doc)
57
+ end
58
+
59
+ def wrapped_response_2
60
+ @wrapped_response_2 ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'wrapped_response_2.xml.base64'))
61
+ end
62
+
63
+ def signature_fingerprint_1
64
+ @signature_fingerprint1 ||= "C5:19:85:D9:47:F1:BE:57:08:20:25:05:08:46:EB:27:F6:CA:B7:83"
65
+ end
66
+
67
+ def signature_1
68
+ @signature1 ||= File.read(File.join(File.dirname(__FILE__), 'certificates', 'certificate1'))
69
+ end
70
+
71
+ def r1_signature_2
72
+ @signature2 ||= File.read(File.join(File.dirname(__FILE__), 'certificates', 'r1_certificate2_base64'))
73
+ end
74
+
75
+ end
@@ -0,0 +1,160 @@
1
+ require 'test_helper'
2
+ require 'xml_security'
3
+
4
+ class XmlSecurityTest < Test::Unit::TestCase
5
+ include XMLSecurity
6
+
7
+ context "XmlSecurity" do
8
+ setup do
9
+ @document = XMLSecurity::SignedDocument.new(Base64.decode64(response_document))
10
+ @base64cert = @document.elements["//ds:X509Certificate"].text
11
+ end
12
+
13
+ should "should run validate without throwing NS related exceptions" do
14
+ assert !@document.validate_doc(@base64cert, true)
15
+ end
16
+
17
+ should "should run validate with throwing NS related exceptions" do
18
+ assert_raise(Onelogin::Saml::ValidationError) do
19
+ @document.validate_doc(@base64cert, false)
20
+ end
21
+ end
22
+
23
+ should "not raise an error when softly validating the document multiple times" do
24
+ assert_nothing_raised do
25
+ 2.times { @document.validate_doc(@base64cert, true) }
26
+ end
27
+ end
28
+
29
+ should "should raise Fingerprint mismatch" do
30
+ exception = assert_raise(Onelogin::Saml::ValidationError) do
31
+ @document.validate("no:fi:ng:er:pr:in:t", false)
32
+ end
33
+ assert_equal("Fingerprint mismatch", exception.message)
34
+ end
35
+
36
+ should "should raise Digest mismatch" do
37
+ exception = assert_raise(Onelogin::Saml::ValidationError) do
38
+ @document.validate_doc(@base64cert, false)
39
+ end
40
+ assert_equal("Digest mismatch", exception.message)
41
+ end
42
+
43
+ should "should raise Key validation error" do
44
+ response = Base64.decode64(response_document)
45
+ response.sub!("<ds:DigestValue>pJQ7MS/ek4KRRWGmv/H43ReHYMs=</ds:DigestValue>",
46
+ "<ds:DigestValue>b9xsAXLsynugg3Wc1CI3kpWku+0=</ds:DigestValue>")
47
+ document = XMLSecurity::SignedDocument.new(response)
48
+ base64cert = document.elements["//ds:X509Certificate"].text
49
+ exception = assert_raise(Onelogin::Saml::ValidationError) do
50
+ document.validate_doc(base64cert, false)
51
+ end
52
+ assert_equal("Key validation error", exception.message)
53
+ end
54
+
55
+ should "raise validation error when the X509Certificate is missing" do
56
+ response = Base64.decode64(response_document)
57
+ response.sub!(/<ds:X509Certificate>.*<\/ds:X509Certificate>/, "")
58
+ document = XMLSecurity::SignedDocument.new(response)
59
+ exception = assert_raise(Onelogin::Saml::ValidationError) do
60
+ document.validate("a fingerprint", false) # The fingerprint isn't relevant to this test
61
+ end
62
+ assert_equal("Certificate element missing in response (ds:X509Certificate)", exception.message)
63
+ end
64
+ end
65
+
66
+ context "Algorithms" do
67
+ should "validate using SHA1" do
68
+ @document = XMLSecurity::SignedDocument.new(fixture(:adfs_response_sha1, false))
69
+ assert @document.validate("F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72")
70
+ end
71
+
72
+ should "validate using SHA256" do
73
+ @document = XMLSecurity::SignedDocument.new(fixture(:adfs_response_sha256, false))
74
+ assert @document.validate("28:74:9B:E8:1F:E8:10:9C:A8:7C:A9:C3:E3:C5:01:6C:92:1C:B4:BA")
75
+ end
76
+
77
+ should "validate using SHA384" do
78
+ @document = XMLSecurity::SignedDocument.new(fixture(:adfs_response_sha384, false))
79
+ assert @document.validate("F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72")
80
+ end
81
+
82
+ should "validate using SHA512" do
83
+ @document = XMLSecurity::SignedDocument.new(fixture(:adfs_response_sha512, false))
84
+ assert @document.validate("F1:3C:6B:80:90:5A:03:0E:6C:91:3E:5D:15:FA:DD:B0:16:45:48:72")
85
+ end
86
+ end
87
+
88
+ context "XmlSecurity::SignedDocument" do
89
+
90
+ context "#extract_inclusive_namespaces" do
91
+ should "support explicit namespace resolution for exclusive canonicalization" do
92
+ response = fixture(:open_saml_response, false)
93
+ document = XMLSecurity::SignedDocument.new(response)
94
+ inclusive_namespaces = document.send(:extract_inclusive_namespaces)
95
+
96
+ assert_equal %w[ xs ], inclusive_namespaces
97
+ end
98
+
99
+ should "support implicit namespace resolution for exclusive canonicalization" do
100
+ response = fixture(:no_signature_ns, false)
101
+ document = XMLSecurity::SignedDocument.new(response)
102
+ inclusive_namespaces = document.send(:extract_inclusive_namespaces)
103
+
104
+ assert_equal %w[ #default saml ds xs xsi ], inclusive_namespaces
105
+ end
106
+
107
+ should_eventually 'support inclusive canonicalization' do
108
+
109
+ response = Onelogin::Saml::Response.new(fixture("tdnf_response.xml"))
110
+ response.stubs(:conditions).returns(nil)
111
+ assert !response.is_valid?
112
+ settings = Onelogin::Saml::Settings.new
113
+ assert !response.is_valid?
114
+ response.settings = settings
115
+ assert !response.is_valid?
116
+ settings.idp_cert_fingerprint = "e6 38 9a 20 b7 4f 13 db 6a bc b1 42 6a e7 52 1d d6 56 d4 1b".upcase.gsub(" ", ":")
117
+ assert response.validate!
118
+ end
119
+
120
+ should "return an empty list when inclusive namespace element is missing" do
121
+ response = fixture(:no_signature_ns, false)
122
+ response.slice! %r{<InclusiveNamespaces xmlns="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="#default saml ds xs xsi"/>}
123
+
124
+ document = XMLSecurity::SignedDocument.new(response)
125
+ inclusive_namespaces = document.send(:extract_inclusive_namespaces)
126
+
127
+ assert inclusive_namespaces.empty?
128
+ end
129
+ end
130
+
131
+ context "StarfieldTMS" do
132
+ setup do
133
+ @response = Onelogin::Saml::Response.new(fixture(:starfield_response))
134
+ @response.settings = Onelogin::Saml::Settings.new(
135
+ :idp_cert_fingerprint => "8D:BA:53:8E:A3:B6:F9:F1:69:6C:BB:D9:D8:BD:41:B3:AC:4F:9D:4D"
136
+ )
137
+ end
138
+
139
+ should "be able to validate a good response" do
140
+ Timecop.freeze Time.parse('2012-11-28 17:55:00 UTC') do
141
+ assert @response.validate!
142
+ end
143
+ end
144
+
145
+ should "fail before response is valid" do
146
+ Timecop.freeze Time.parse('2012-11-20 17:55:00 UTC') do
147
+ assert ! @response.is_valid?
148
+ end
149
+ end
150
+
151
+ should "fail after response expires" do
152
+ Timecop.freeze Time.parse('2012-11-30 17:55:00 UTC') do
153
+ assert ! @response.is_valid?
154
+ end
155
+ end
156
+ end
157
+
158
+ end
159
+
160
+ end
metadata ADDED
@@ -0,0 +1,172 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ruby-samlnechotech
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.7.23
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - OneLogin LLC, beekermememe
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-04-05 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: canonix
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - '='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.1.1
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - '='
28
+ - !ruby/object:Gem::Version
29
+ version: 0.1.1
30
+ - !ruby/object:Gem::Dependency
31
+ name: uuid
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: '2.3'
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: '2.3'
46
+ - !ruby/object:Gem::Dependency
47
+ name: nokogiri
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: 1.5.0
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 1.5.0
62
+ description: SAML toolkit for Ruby on Rails forked and modified by beekermememe
63
+ email: nechotech@gmail.com
64
+ executables: []
65
+ extensions: []
66
+ extra_rdoc_files:
67
+ - LICENSE
68
+ - README.md
69
+ files:
70
+ - .document
71
+ - .gitignore
72
+ - .travis.yml
73
+ - Gemfile
74
+ - LICENSE
75
+ - README.md
76
+ - Rakefile
77
+ - lib/onelogin/ruby-samlnechotech/authrequest.rb
78
+ - lib/onelogin/ruby-samlnechotech/logging.rb
79
+ - lib/onelogin/ruby-samlnechotech/logoutrequest.rb
80
+ - lib/onelogin/ruby-samlnechotech/logoutresponse.rb
81
+ - lib/onelogin/ruby-samlnechotech/metadata.rb
82
+ - lib/onelogin/ruby-samlnechotech/response.rb
83
+ - lib/onelogin/ruby-samlnechotech/settings.rb
84
+ - lib/onelogin/ruby-samlnechotech/validation_error.rb
85
+ - lib/onelogin/ruby-samlnechotech/version.rb
86
+ - lib/ruby-samlnechotech.rb
87
+ - lib/schemas/saml20assertion_schema.xsd
88
+ - lib/schemas/saml20protocol_schema.xsd
89
+ - lib/schemas/xenc_schema.xsd
90
+ - lib/schemas/xmldsig_schema.xsd
91
+ - lib/xml_security.rb
92
+ - ruby-samlnechotech.gemspec
93
+ - test/certificates/certificate1
94
+ - test/certificates/r1_certificate2_base64
95
+ - test/logoutrequest_test.rb
96
+ - test/logoutresponse_test.rb
97
+ - test/request_test.rb
98
+ - test/response_test.rb
99
+ - test/responses/adfs_response_sha1.xml
100
+ - test/responses/adfs_response_sha256.xml
101
+ - test/responses/adfs_response_sha384.xml
102
+ - test/responses/adfs_response_sha512.xml
103
+ - test/responses/logoutresponse_fixtures.rb
104
+ - test/responses/no_signature_ns.xml
105
+ - test/responses/open_saml_response.xml
106
+ - test/responses/r1_response6.xml.base64
107
+ - test/responses/response1.xml.base64
108
+ - test/responses/response2.xml.base64
109
+ - test/responses/response3.xml.base64
110
+ - test/responses/response4.xml.base64
111
+ - test/responses/response5.xml.base64
112
+ - test/responses/response_with_ampersands.xml
113
+ - test/responses/response_with_ampersands.xml.base64
114
+ - test/responses/simple_saml_php.xml
115
+ - test/responses/starfield_response.xml.base64
116
+ - test/responses/wrapped_response_2.xml.base64
117
+ - test/settings_test.rb
118
+ - test/test_helper.rb
119
+ - test/xml_security_test.rb
120
+ homepage: https://github.com/beekermememe/ruby-saml
121
+ licenses: []
122
+ post_install_message:
123
+ rdoc_options:
124
+ - --charset=UTF-8
125
+ require_paths:
126
+ - lib
127
+ required_ruby_version: !ruby/object:Gem::Requirement
128
+ none: false
129
+ requirements:
130
+ - - ! '>='
131
+ - !ruby/object:Gem::Version
132
+ version: '0'
133
+ required_rubygems_version: !ruby/object:Gem::Requirement
134
+ none: false
135
+ requirements:
136
+ - - ! '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ requirements: []
140
+ rubyforge_project: http://www.rubygems.org/gems/ruby-samlnechotech
141
+ rubygems_version: 1.8.24
142
+ signing_key:
143
+ specification_version: 3
144
+ summary: SAML Ruby Tookit
145
+ test_files:
146
+ - test/certificates/certificate1
147
+ - test/certificates/r1_certificate2_base64
148
+ - test/logoutrequest_test.rb
149
+ - test/logoutresponse_test.rb
150
+ - test/request_test.rb
151
+ - test/response_test.rb
152
+ - test/responses/adfs_response_sha1.xml
153
+ - test/responses/adfs_response_sha256.xml
154
+ - test/responses/adfs_response_sha384.xml
155
+ - test/responses/adfs_response_sha512.xml
156
+ - test/responses/logoutresponse_fixtures.rb
157
+ - test/responses/no_signature_ns.xml
158
+ - test/responses/open_saml_response.xml
159
+ - test/responses/r1_response6.xml.base64
160
+ - test/responses/response1.xml.base64
161
+ - test/responses/response2.xml.base64
162
+ - test/responses/response3.xml.base64
163
+ - test/responses/response4.xml.base64
164
+ - test/responses/response5.xml.base64
165
+ - test/responses/response_with_ampersands.xml
166
+ - test/responses/response_with_ampersands.xml.base64
167
+ - test/responses/simple_saml_php.xml
168
+ - test/responses/starfield_response.xml.base64
169
+ - test/responses/wrapped_response_2.xml.base64
170
+ - test/settings_test.rb
171
+ - test/test_helper.rb
172
+ - test/xml_security_test.rb