ruby-samlnechotech 0.7.23

Sign up to get free protection for your applications and to get access to all the features.
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