ruby-saml 0.4.7 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


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

@@ -38,6 +38,10 @@ class Test::Unit::TestCase
38
38
  @response_document5 ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response5.xml.base64'))
39
39
  end
40
40
 
41
+ def ampersands_response
42
+ @ampersands_resposne ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response_with_ampersands.xml.base64'))
43
+ end
44
+
41
45
  def response_document_6
42
46
  doc = Base64.decode64(response_document)
43
47
  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")}\"")
@@ -45,6 +49,10 @@ class Test::Unit::TestCase
45
49
  Base64.encode64(doc)
46
50
  end
47
51
 
52
+ def wrapped_response_2
53
+ @wrapped_response_2 ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'wrapped_response_2.xml.base64'))
54
+ end
55
+
48
56
  def signature_fingerprint_1
49
57
  @signature_fingerprint1 ||= "C5:19:85:D9:47:F1:BE:57:08:20:25:05:08:46:EB:27:F6:CA:B7:83"
50
58
  end
metadata CHANGED
@@ -1,13 +1,12 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-saml
3
3
  version: !ruby/object:Gem::Version
4
- hash: 1
5
4
  prerelease: false
6
5
  segments:
7
6
  - 0
8
- - 4
9
- - 7
10
- version: 0.4.7
7
+ - 5
8
+ - 0
9
+ version: 0.5.0
11
10
  platform: ruby
12
11
  authors:
13
12
  - OneLogin LLC
@@ -15,18 +14,16 @@ autorequire:
15
14
  bindir: bin
16
15
  cert_chain: []
17
16
 
18
- date: 2011-06-30 00:00:00 +02:00
17
+ date: 2011-06-30 00:00:00 -07:00
19
18
  default_executable:
20
19
  dependencies:
21
20
  - !ruby/object:Gem::Dependency
22
21
  name: canonix
23
22
  prerelease: false
24
23
  requirement: &id001 !ruby/object:Gem::Requirement
25
- none: false
26
24
  requirements:
27
25
  - - ~>
28
26
  - !ruby/object:Gem::Version
29
- hash: 9
30
27
  segments:
31
28
  - 0
32
29
  - 1
@@ -37,11 +34,9 @@ dependencies:
37
34
  name: uuid
38
35
  prerelease: false
39
36
  requirement: &id002 !ruby/object:Gem::Requirement
40
- none: false
41
37
  requirements:
42
38
  - - ~>
43
39
  - !ruby/object:Gem::Version
44
- hash: 5
45
40
  segments:
46
41
  - 2
47
42
  - 3
@@ -52,11 +47,9 @@ dependencies:
52
47
  name: shoulda
53
48
  prerelease: false
54
49
  requirement: &id003 !ruby/object:Gem::Requirement
55
- none: false
56
50
  requirements:
57
51
  - - ">="
58
52
  - !ruby/object:Gem::Version
59
- hash: 3
60
53
  segments:
61
54
  - 0
62
55
  version: "0"
@@ -66,11 +59,9 @@ dependencies:
66
59
  name: ruby-debug
67
60
  prerelease: false
68
61
  requirement: &id004 !ruby/object:Gem::Requirement
69
- none: false
70
62
  requirements:
71
63
  - - ">="
72
64
  - !ruby/object:Gem::Version
73
- hash: 3
74
65
  segments:
75
66
  - 0
76
67
  version: "0"
@@ -80,11 +71,9 @@ dependencies:
80
71
  name: mocha
81
72
  prerelease: false
82
73
  requirement: &id005 !ruby/object:Gem::Requirement
83
- none: false
84
74
  requirements:
85
75
  - - ">="
86
76
  - !ruby/object:Gem::Version
87
- hash: 3
88
77
  segments:
89
78
  - 0
90
79
  version: "0"
@@ -106,11 +95,13 @@ files:
106
95
  - README.rdoc
107
96
  - Rakefile
108
97
  - VERSION
109
- - lib/onelogin/saml.rb
110
- - lib/onelogin/saml/authrequest.rb
111
- - lib/onelogin/saml/response.rb
112
- - lib/onelogin/saml/settings.rb
113
- - lib/onelogin/saml/validation_error.rb
98
+ - lib/onelogin/ruby-saml/authrequest.rb
99
+ - lib/onelogin/ruby-saml/logging.rb
100
+ - lib/onelogin/ruby-saml/metadata.rb
101
+ - lib/onelogin/ruby-saml/response.rb
102
+ - lib/onelogin/ruby-saml/settings.rb
103
+ - lib/onelogin/ruby-saml/validation_error.rb
104
+ - lib/onelogin/ruby-saml/version.rb
114
105
  - lib/ruby-saml.rb
115
106
  - lib/xml_security.rb
116
107
  - ruby-saml.gemspec
@@ -124,7 +115,10 @@ files:
124
115
  - test/responses/response3.xml.base64
125
116
  - test/responses/response4.xml.base64
126
117
  - test/responses/response5.xml.base64
118
+ - test/responses/response_with_ampersands.xml
119
+ - test/responses/response_with_ampersands.xml.base64
127
120
  - test/responses/simple_saml_php.xml
121
+ - test/responses/wrapped_response_2.xml.base64
128
122
  - test/settings_test.rb
129
123
  - test/test_helper.rb
130
124
  - test/xml_security_test.rb
@@ -138,33 +132,41 @@ rdoc_options:
138
132
  require_paths:
139
133
  - lib
140
134
  required_ruby_version: !ruby/object:Gem::Requirement
141
- none: false
142
135
  requirements:
143
136
  - - ">="
144
137
  - !ruby/object:Gem::Version
145
- hash: 3
146
138
  segments:
147
139
  - 0
148
140
  version: "0"
149
141
  required_rubygems_version: !ruby/object:Gem::Requirement
150
- none: false
151
142
  requirements:
152
143
  - - ">="
153
144
  - !ruby/object:Gem::Version
154
- hash: 3
155
145
  segments:
156
146
  - 0
157
147
  version: "0"
158
148
  requirements: []
159
149
 
160
- rubyforge_project:
161
- rubygems_version: 1.3.7
150
+ rubyforge_project: http://www.rubygems.org/gems/ruby-saml
151
+ rubygems_version: 1.3.6
162
152
  signing_key:
163
153
  specification_version: 3
164
154
  summary: SAML Ruby Tookit
165
155
  test_files:
156
+ - test/certificates/certificate1
166
157
  - test/request_test.rb
167
158
  - test/response_test.rb
159
+ - test/responses/adfs_response.xml.base64
160
+ - test/responses/open_saml_response.xml
161
+ - test/responses/response1.xml.base64
162
+ - test/responses/response2.xml.base64
163
+ - test/responses/response3.xml.base64
164
+ - test/responses/response4.xml.base64
165
+ - test/responses/response5.xml.base64
166
+ - test/responses/response_with_ampersands.xml
167
+ - test/responses/response_with_ampersands.xml.base64
168
+ - test/responses/simple_saml_php.xml
169
+ - test/responses/wrapped_response_2.xml.base64
168
170
  - test/settings_test.rb
169
171
  - test/test_helper.rb
170
172
  - test/xml_security_test.rb
@@ -1,5 +0,0 @@
1
- require 'onelogin/saml/authrequest'
2
- require 'onelogin/saml/response'
3
- require 'onelogin/saml/settings'
4
- require 'onelogin/saml/validation_error'
5
-
@@ -1,33 +0,0 @@
1
- require "base64"
2
- require "uuid"
3
- require "zlib"
4
- require "cgi"
5
-
6
- module Onelogin::Saml
7
- class Authrequest
8
- def create(settings, params = {})
9
- uuid = "_" + UUID.new.generate
10
- time = Time.now.utc.strftime("%Y-%m-%dT%H:%M:%SZ")
11
-
12
- request =
13
- "<samlp:AuthnRequest xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" ID=\"#{uuid}\" Version=\"2.0\" IssueInstant=\"#{time}\" ProtocolBinding=\"urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST\" AssertionConsumerServiceURL=\"#{settings.assertion_consumer_service_url}\">" +
14
- "<saml:Issuer xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">#{settings.issuer}</saml:Issuer>\n" +
15
- "<samlp:NameIDPolicy xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" Format=\"#{settings.name_identifier_format}\" AllowCreate=\"true\"></samlp:NameIDPolicy>\n" +
16
- "<samlp:RequestedAuthnContext xmlns:samlp=\"urn:oasis:names:tc:SAML:2.0:protocol\" Comparison=\"exact\">" +
17
- "<saml:AuthnContextClassRef xmlns:saml=\"urn:oasis:names:tc:SAML:2.0:assertion\">urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport</saml:AuthnContextClassRef></samlp:RequestedAuthnContext>\n" +
18
- "</samlp:AuthnRequest>"
19
-
20
- deflated_request = Zlib::Deflate.deflate(request, 9)[2..-5]
21
- base64_request = Base64.encode64(deflated_request)
22
- encoded_request = CGI.escape(base64_request)
23
- request_params = "?SAMLRequest=" + encoded_request
24
-
25
- params.each_pair do |key, value|
26
- request_params << "&#{key}=#{CGI.escape(value.to_s)}"
27
- end
28
-
29
- settings.idp_sso_target_url + request_params
30
- end
31
-
32
- end
33
- end
@@ -1,137 +0,0 @@
1
- require "xml_security"
2
- require "time"
3
-
4
- module Onelogin::Saml
5
-
6
- class Response
7
- ASSERTION = "urn:oasis:names:tc:SAML:2.0:assertion"
8
- PROTOCOL = "urn:oasis:names:tc:SAML:2.0:protocol"
9
- DSIG = "http://www.w3.org/2000/09/xmldsig#"
10
-
11
- attr_accessor :options, :response, :document, :settings
12
-
13
- def initialize(response, options = {})
14
- raise ArgumentError.new("Response cannot be nil") if response.nil?
15
- self.options = options
16
- self.response = response
17
- self.document = XMLSecurity::SignedDocument.new(Base64.decode64(response))
18
- end
19
-
20
- def is_valid?
21
- validate(soft = true)
22
- end
23
-
24
- def validate!
25
- validate(soft = false)
26
- end
27
-
28
- # The value of the user identifier as designated by the initialization request response
29
- def name_id
30
- @name_id ||= begin
31
- node = REXML::XPath.first(document, "/p:Response/a:Assertion[@ID='#{document.signed_element_id[1,document.signed_element_id.size]}']/a:Subject/a:NameID", { "p" => PROTOCOL, "a" => ASSERTION })
32
- node ||= REXML::XPath.first(document, "/p:Response[@ID='#{document.signed_element_id[1,document.signed_element_id.size]}']/a:Assertion/a:Subject/a:NameID", { "p" => PROTOCOL, "a" => ASSERTION })
33
- node.nil? ? nil : node.text
34
- end
35
- end
36
-
37
- # A hash of alle the attributes with the response. Assuming there is only one value for each key
38
- def attributes
39
- @attr_statements ||= begin
40
- result = {}
41
-
42
- stmt_element = REXML::XPath.first(document, "/p:Response/a:Assertion/a:AttributeStatement", { "p" => PROTOCOL, "a" => ASSERTION })
43
- return {} if stmt_element.nil?
44
-
45
- stmt_element.elements.each do |attr_element|
46
- name = attr_element.attributes["Name"]
47
- value = attr_element.elements.first.text
48
-
49
- result[name] = value
50
- end
51
-
52
- result.keys.each do |key|
53
- result[key.intern] = result[key]
54
- end
55
-
56
- result
57
- end
58
- end
59
-
60
- # When this user session should expire at latest
61
- def session_expires_at
62
- @expires_at ||= begin
63
- node = REXML::XPath.first(document, "/p:Response/a:Assertion/a:AuthnStatement", { "p" => PROTOCOL, "a" => ASSERTION })
64
- parse_time(node, "SessionNotOnOrAfter")
65
- end
66
- end
67
-
68
- # Conditions (if any) for the assertion to run
69
- def conditions
70
- @conditions ||= begin
71
- REXML::XPath.first(document, "/p:Response/a:Assertion[@ID='#{document.signed_element_id[1,document.signed_element_id.size]}']/a:Conditions", { "p" => PROTOCOL, "a" => ASSERTION })
72
- end
73
- end
74
-
75
- private
76
-
77
- def validation_error(message)
78
- raise ValidationError.new(message)
79
- end
80
-
81
- def validate(soft = true)
82
- validate_response_state(soft) &&
83
- validate_conditions(soft) &&
84
- document.validate(get_fingerprint, soft)
85
- end
86
-
87
- def validate_response_state(soft = true)
88
- if response.empty?
89
- return soft ? false : validation_error("Blank response")
90
- end
91
-
92
- if settings.nil?
93
- return soft ? false : validation_error("No settings on response")
94
- end
95
-
96
- if settings.idp_cert_fingerprint.nil? && settings.idp_cert.nil?
97
- return soft ? false : validation_error("No fingerprint or certificate on settings")
98
- end
99
-
100
- true
101
- end
102
-
103
- def get_fingerprint
104
- if settings.idp_cert
105
- cert = OpenSSL::X509::Certificate.new(settings.idp_cert)
106
- Digest::SHA1.hexdigest(cert.to_der).upcase.scan(/../).join(":")
107
- else
108
- settings.idp_cert_fingerprint
109
- end
110
- end
111
-
112
- def validate_conditions(soft = true)
113
- return true if conditions.nil?
114
- return true if options[:skip_conditions]
115
-
116
- if not_before = parse_time(conditions, "NotBefore")
117
- if Time.now.utc < not_before
118
- return soft ? false : validation_error("Current time is earlier than NotBefore condition")
119
- end
120
- end
121
-
122
- if not_on_or_after = parse_time(conditions, "NotOnOrAfter")
123
- if Time.now.utc >= not_on_or_after
124
- return soft ? false : validation_error("Current time is on or after NotOnOrAfter condition")
125
- end
126
- end
127
-
128
- true
129
- end
130
-
131
- def parse_time(node, attribute)
132
- if node && node.attributes[attribute]
133
- Time.parse(node.attributes[attribute])
134
- end
135
- end
136
- end
137
- end
@@ -1,6 +0,0 @@
1
- module Onelogin::Saml
2
- class Settings
3
- attr_accessor :assertion_consumer_service_url, :issuer, :sp_name_qualifier
4
- attr_accessor :idp_sso_target_url, :idp_cert_fingerprint, :idp_cert, :name_identifier_format
5
- end
6
- end