ruby-saml-mod 0.1.25 → 0.1.26

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: 5884860b076f35e491df0c3d402a03d60da78778
4
+ data.tar.gz: f4ef94c69230b9799cbae69c2ba6cb5b21a9ef95
5
+ !binary "U0hBNTEy":
6
+ metadata.gz: 2284ac2e714c3bc981de6ac2e2a87b9da238f6f7053561eab6fa30724d36eff99a43590c5d191b329fe064ca02b2540352e732569bfd67e72d1f586624f92049
7
+ data.tar.gz: 000451843ab8775c51367a6d409f1c763e2fd4cd1cb6fb3d04a8e77de07ce93ce611279dd7b1e4594f176f74336a9c8b7cf943f7e55227fecacfee5906f0c241
@@ -30,7 +30,7 @@ module Onelogin::Saml
30
30
  @request_xml += "</samlp:AuthnRequest>"
31
31
 
32
32
  deflated_request = Zlib::Deflate.deflate(@request_xml, 9)[2..-5]
33
- base64_request = Base64.strict_encode64(deflated_request)
33
+ base64_request = Base64.encode64(deflated_request)
34
34
  encoded_request = CGI.escape(base64_request)
35
35
 
36
36
  @forward_url = @settings.idp_sso_target_url + (@settings.idp_sso_target_url.include?("?") ? "&" : "?") + "SAMLRequest=" + encoded_request
@@ -11,11 +11,11 @@ module Onelogin::Saml
11
11
  ar = LogOutRequest.new(settings, session)
12
12
  ar.generate_request
13
13
  end
14
-
14
+
15
15
  def generate_request
16
16
  @id = Onelogin::Saml::AuthRequest.generate_unique_id(42)
17
17
  issue_instant = Onelogin::Saml::AuthRequest.get_timestamp
18
-
18
+
19
19
  @request_xml = <<-REQUEST_XML
20
20
  <samlp:LogoutRequest xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" ID="#{@id}" Version="2.0" IssueInstant="#{issue_instant}" Destination="#{@settings.idp_slo_target_url}">
21
21
  <saml:Issuer xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion">#{@settings.issuer}</saml:Issuer>
@@ -24,12 +24,8 @@ module Onelogin::Saml
24
24
  </samlp:LogoutRequest>
25
25
  REQUEST_XML
26
26
 
27
- if settings.sign?
28
- @request_xml = XMLSecurity.sign(@id, @request_xml, @settings.xmlsec_privatekey, @settings.xmlsec_certificate)
29
- end
30
-
31
27
  deflated_logout_request = Zlib::Deflate.deflate(@request_xml, 9)[2..-5]
32
- base64_logout_request = Base64.strict_encode64(deflated_logout_request)
28
+ base64_logout_request = Base64.encode64(deflated_logout_request)
33
29
 
34
30
  url, existing_query_string = @settings.idp_slo_target_url.split('?')
35
31
  query_string = _query_string_append(existing_query_string, 'SAMLRequest', base64_logout_request)
@@ -41,7 +37,7 @@ module Onelogin::Saml
41
37
  end
42
38
 
43
39
  @forward_url = [url, query_string].join("?")
44
-
40
+
45
41
  @forward_url
46
42
  end
47
43
 
@@ -2,7 +2,7 @@ module Onelogin::Saml
2
2
  class Response
3
3
 
4
4
  attr_accessor :settings
5
- attr_reader :document, :xml, :response
5
+ attr_reader :document, :decrypted_document, :xml, :response
6
6
  attr_reader :name_id, :name_qualifier, :session_index, :saml_attributes
7
7
  attr_reader :status_code, :status_message
8
8
  attr_reader :in_response_to, :destination, :issuer
@@ -14,14 +14,14 @@ module Onelogin::Saml
14
14
  @xml = Base64.decode64(@response)
15
15
  @document = LibXML::XML::Document.string(@xml)
16
16
  @document.extend(XMLSecurity::SignedDocument)
17
- rescue
17
+ rescue => e
18
18
  # could not parse document, everything is invalid
19
19
  @response = nil
20
20
  return
21
21
  end
22
22
 
23
- @issuer = document.find_first("/samlp:Response/saml:Issuer", Onelogin::NAMESPACES).content rescue nil
24
- @status_code = document.find_first("/samlp:Response/samlp:Status/samlp:StatusCode", Onelogin::NAMESPACES)["Value"] rescue nil
23
+ @issuer = @document.find_first("/samlp:Response/saml:Issuer", Onelogin::NAMESPACES).content rescue nil
24
+ @status_code = @document.find_first("/samlp:Response/samlp:Status/samlp:StatusCode", Onelogin::NAMESPACES)["Value"] rescue nil
25
25
 
26
26
  process(settings) if settings
27
27
  end
@@ -30,119 +30,79 @@ module Onelogin::Saml
30
30
  @settings = settings
31
31
  return unless @response
32
32
 
33
- @in_response_to = untrusted_find_first("/samlp:Response")['InResponseTo'] rescue nil
34
- @destination = untrusted_find_first("/samlp:Response")['Destination'] rescue nil
35
- @status_message = untrusted_find_first("/samlp:Response/samlp:Status/samlp:StatusCode").content rescue nil
36
-
37
- @name_id = trusted_find_first("saml:Assertion/saml:Subject/saml:NameID").content rescue nil
38
- @name_qualifier = trusted_find_first("saml:Assertion/saml:Subject/saml:NameID")["NameQualifier"] rescue nil
39
- @session_index = trusted_find_first("saml:Assertion/saml:AuthnStatement")["SessionIndex"] rescue nil
33
+ @decrypted_document = LibXML::XML::Document.document(@document)
34
+ @decrypted_document.extend(XMLSecurity::SignedDocument)
35
+ @decrypted_document.decrypt!(@settings)
40
36
 
37
+ @in_response_to = @decrypted_document.find_first("/samlp:Response", Onelogin::NAMESPACES)['InResponseTo'] rescue nil
38
+ @destination = @decrypted_document.find_first("/samlp:Response", Onelogin::NAMESPACES)['Destination'] rescue nil
39
+ @name_id = @decrypted_document.find_first("/samlp:Response/saml:Assertion/saml:Subject/saml:NameID", Onelogin::NAMESPACES).content rescue nil
41
40
  @saml_attributes = {}
42
- trusted_find("saml:Attribute").each do |attr|
41
+ @decrypted_document.find("//saml:Attribute", Onelogin::NAMESPACES).each do |attr|
43
42
  attrname = attr['FriendlyName'] || Onelogin::ATTRIBUTES[attr['Name']] || attr['Name']
44
43
  @saml_attributes[attrname] = attr.content.strip rescue nil
45
44
  end
46
- end
47
-
48
- def disable_signature_validation!(settings)
49
- @settings = settings
50
- @is_valid = true
51
- @trusted_roots = [decrypted_document.root]
52
- end
53
-
54
- def decrypted_document
55
- @decrypted_document ||= LibXML::XML::Document.document(document).tap do |doc|
56
- doc.extend(XMLSecurity::SignedDocument)
57
- doc.decrypt!(settings)
58
- end
59
- end
60
-
61
- def untrusted_find_first(xpath)
62
- decrypted_document.find(xpath, Onelogin::NAMESPACES).first
63
- end
64
-
65
- def trusted_find_first(xpath)
66
- trusted_find(xpath).first
67
- end
68
-
69
- def trusted_find(xpath)
70
- trusted_roots.map do |trusted_root|
71
- trusted_root.find("descendant-or-self::#{xpath}", Onelogin::NAMESPACES).to_a
72
- end.flatten.compact
45
+ @name_qualifier = @decrypted_document.find_first("/samlp:Response/saml:Assertion/saml:Subject/saml:NameID", Onelogin::NAMESPACES)["NameQualifier"] rescue nil
46
+ @session_index = @decrypted_document.find_first("/samlp:Response/saml:Assertion/saml:AuthnStatement", Onelogin::NAMESPACES)["SessionIndex"] rescue nil
47
+ @status_message = @decrypted_document.find_first("/samlp:Response/samlp:Status/samlp:StatusCode", Onelogin::NAMESPACES).content rescue nil
73
48
  end
74
49
 
75
50
  def logger=(val)
76
51
  @logger = val
77
52
  end
78
-
53
+
79
54
  def is_valid?
80
- @is_valid ||= validate
81
- end
82
-
83
- def validate
84
- if response.nil? || response == ""
55
+ if @response.nil? || @response == ""
85
56
  @validation_error = "No response to validate"
86
57
  return false
87
58
  end
88
-
89
- if !settings.idp_cert_fingerprint
59
+
60
+ if !@settings.idp_cert_fingerprint
90
61
  @validation_error = "No fingerprint configured in SAML settings"
91
62
  return false
92
63
  end
93
-
64
+
94
65
  # Verify the original document if it has a signature, otherwise verify the signature
95
66
  # in the encrypted portion. If there is no signature, then we can't verify.
96
67
  verified = false
97
-
98
- if document.has_signature?
99
- verified = document.validate(settings.idp_cert_fingerprint, @logger)
68
+ if @document.find_first("//ds:Signature", Onelogin::NAMESPACES)
69
+ verified = @document.validate(@settings.idp_cert_fingerprint, @logger)
100
70
  if !verified
101
- @validation_error = document.validation_error
71
+ @validation_error = @document.validation_error
102
72
  return false
103
73
  end
104
74
  end
105
75
 
106
- if !verified && decrypted_document.has_signature?
107
- verified = decrypted_document.validate(settings.idp_cert_fingerprint, @logger)
76
+ if !verified && @decrypted_document.find_first("//ds:Signature", Onelogin::NAMESPACES)
77
+ verified = @decrypted_document.validate(@settings.idp_cert_fingerprint, @logger)
108
78
  if !verified
109
- @validation_error = decrypted_document.validation_error
79
+ @validation_error = @document.validation_error
110
80
  return false
111
81
  end
112
82
  end
113
-
83
+
114
84
  if !verified
115
85
  @validation_error = "No signature found in the response"
116
86
  return false
117
87
  end
118
-
119
- # If we get here, validation has succeeded, and we can trust all
120
- # <ds:Signature> elements. Each of those has a <ds:Reference> which
121
- # points to the root of the root of the NodeSet it signs.
122
- @trusted_roots = decrypted_document.signed_roots
123
-
88
+
124
89
  true
125
90
  end
126
-
127
- # triggers validation
128
- def trusted_roots
129
- is_valid? ? @trusted_roots : []
130
- end
131
-
91
+
132
92
  def success_status?
133
93
  @status_code == Onelogin::Saml::StatusCodes::SUCCESS_URI
134
94
  end
135
-
95
+
136
96
  def auth_failure?
137
97
  @status_code == Onelogin::Saml::StatusCodes::AUTHN_FAILED_URI
138
98
  end
139
-
99
+
140
100
  def no_authn_context?
141
101
  @status_code == Onelogin::Saml::StatusCodes::NO_AUTHN_CONTEXT_URI
142
102
  end
143
-
103
+
144
104
  def fingerprint_from_idp
145
- if base64_cert = decrypted_document.find_first("//ds:X509Certificate", Onelogin::NAMESPACES)
105
+ if base64_cert = @decrypted_document.find_first("//ds:X509Certificate", Onelogin::NAMESPACES)
146
106
  cert_text = Base64.decode64(base64_cert.content)
147
107
  cert = OpenSSL::X509::Certificate.new(cert_text)
148
108
  Digest::SHA1.hexdigest(cert.to_der)
data/lib/xml_sec.rb CHANGED
@@ -79,9 +79,6 @@ module XMLSecurity
79
79
  :xmlSecDSigStatusInvalid
80
80
  ]
81
81
 
82
- XMLSEC_ERRORS_R_INVALID_DATA = 12
83
- class XmlSecError < ::RuntimeError; end
84
-
85
82
  class XmlSecPtrList < FFI::Struct
86
83
  layout \
87
84
  :id, :string,
@@ -173,12 +170,6 @@ module XMLSecurity
173
170
  :reserved1, :pointer
174
171
  end
175
172
 
176
- ErrorCallback = FFI::Function.new(:void,
177
- [ :string, :int, :string, :string, :string, :int, :string ]
178
- ) do |file, line, func, errorObject, errorSubject, reason, msg |
179
- XMLSecurity.handle_xmlsec_error_callback(file, line, func, errorObject, errorSubject, reason, msg)
180
- end
181
-
182
173
  # xmlsec functions
183
174
  attach_function :xmlSecInit, [], :int
184
175
  attach_function :xmlSecParseMemory, [ :pointer, :uint, :int ], :pointer
@@ -202,9 +193,7 @@ module XMLSecurity
202
193
  attach_function :xmlSecEncCtxDecrypt, [ :pointer, :pointer ], :int
203
194
  attach_function :xmlSecEncCtxDestroy, [ :pointer ], :void
204
195
 
205
- attach_function :xmlSecErrorsDefaultCallback, [ :string, :int, :string, :string, :string, :int, :string ], :void
206
196
  attach_function :xmlSecErrorsDefaultCallbackEnableOutput, [ :bool ], :void
207
- attach_function :xmlSecErrorsSetCallback, [:pointer], :void
208
197
 
209
198
  attach_function :xmlSecTransformExclC14NGetKlass, [], :pointer
210
199
  attach_function :xmlSecOpenSSLTransformRsaSha1GetKlass, [], :pointer
@@ -249,18 +238,6 @@ module XMLSecurity
249
238
  raise "Failed initializing XMLSec" if self.xmlSecInit < 0
250
239
  raise "Failed initializing app crypto" if self.xmlSecOpenSSLAppInit(nil) < 0
251
240
  raise "Failed initializing crypto" if self.xmlSecOpenSSLInit < 0
252
- self.xmlSecErrorsSetCallback(ErrorCallback)
253
-
254
- def self.handle_xmlsec_error_callback(*args)
255
- raise_exception_if_necessary(*args)
256
- xmlSecErrorsDefaultCallback(*args)
257
- end
258
-
259
- def self.raise_exception_if_necessary(file, line, func, errorObject, errorSubject, reason, msg)
260
- if reason == XMLSEC_ERRORS_R_INVALID_DATA
261
- raise XmlSecError.new(msg)
262
- end
263
- end
264
241
 
265
242
 
266
243
  def self.mute(&block)
@@ -290,29 +267,6 @@ module XMLSecurity
290
267
  "-----BEGIN PUBLIC KEY-----\n#{base64}-----END PUBLIC KEY-----"
291
268
  end
292
269
 
293
- def has_signature?
294
- signatures.any?
295
- end
296
-
297
- def signed_roots
298
- signatures.map do |sig|
299
- ref = sig.find('.//ds:Reference', Onelogin::NAMESPACES).first
300
- signed_element_id = ref['URI'].sub(/^#/, '')
301
-
302
- if signed_element_id.empty?
303
- self.root
304
- else
305
- xpath_id_query = %Q(ancestor::*[@ID = "#{signed_element_id}"])
306
-
307
- ref.find(xpath_id_query, Onelogin::NAMESPACES).first
308
- end
309
- end.compact
310
- end
311
-
312
- def signatures
313
- @signatures ||= self.find("//ds:Signature", Onelogin::NAMESPACES)
314
- end
315
-
316
270
  def validate(idp_cert_fingerprint, logger = nil)
317
271
  # get cert from response
318
272
  base64_cert = self.find_first("//ds:X509Certificate", Onelogin::NAMESPACES).content
@@ -1,9 +1,9 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = %q{ruby-saml-mod}
3
- s.version = "0.1.25"
3
+ s.version = "0.1.26"
4
4
 
5
5
  s.authors = ["OneLogin LLC", "Bracken", "Zach", "Cody", "Jeremy", "Paul"]
6
- s.date = %q{2014-03-12}
6
+ s.date = %q{2013-05-07}
7
7
  s.extra_rdoc_files = [
8
8
  "LICENSE"
9
9
  ]
metadata CHANGED
@@ -1,8 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-saml-mod
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.25
5
- prerelease:
4
+ version: 0.1.26
6
5
  platform: ruby
7
6
  authors:
8
7
  - OneLogin LLC
@@ -14,12 +13,11 @@ authors:
14
13
  autorequire:
15
14
  bindir: bin
16
15
  cert_chain: []
17
- date: 2014-03-12 00:00:00.000000000 Z
16
+ date: 2013-05-07 00:00:00.000000000 Z
18
17
  dependencies:
19
18
  - !ruby/object:Gem::Dependency
20
19
  name: libxml-ruby
21
20
  requirement: !ruby/object:Gem::Requirement
22
- none: false
23
21
  requirements:
24
22
  - - ! '>='
25
23
  - !ruby/object:Gem::Version
@@ -27,7 +25,6 @@ dependencies:
27
25
  type: :runtime
28
26
  prerelease: false
29
27
  version_requirements: !ruby/object:Gem::Requirement
30
- none: false
31
28
  requirements:
32
29
  - - ! '>='
33
30
  - !ruby/object:Gem::Version
@@ -35,7 +32,6 @@ dependencies:
35
32
  - !ruby/object:Gem::Dependency
36
33
  name: ffi
37
34
  requirement: !ruby/object:Gem::Requirement
38
- none: false
39
35
  requirements:
40
36
  - - ! '>='
41
37
  - !ruby/object:Gem::Version
@@ -43,7 +39,6 @@ dependencies:
43
39
  type: :runtime
44
40
  prerelease: false
45
41
  version_requirements: !ruby/object:Gem::Requirement
46
- none: false
47
42
  requirements:
48
43
  - - ! '>='
49
44
  - !ruby/object:Gem::Version
@@ -72,27 +67,25 @@ files:
72
67
  - ruby-saml-mod.gemspec
73
68
  homepage: http://github.com/bracken/ruby-saml
74
69
  licenses: []
70
+ metadata: {}
75
71
  post_install_message:
76
72
  rdoc_options: []
77
73
  require_paths:
78
74
  - lib
79
75
  required_ruby_version: !ruby/object:Gem::Requirement
80
- none: false
81
76
  requirements:
82
77
  - - ! '>='
83
78
  - !ruby/object:Gem::Version
84
79
  version: '0'
85
80
  required_rubygems_version: !ruby/object:Gem::Requirement
86
- none: false
87
81
  requirements:
88
82
  - - ! '>='
89
83
  - !ruby/object:Gem::Version
90
84
  version: '0'
91
85
  requirements: []
92
86
  rubyforge_project:
93
- rubygems_version: 1.8.23
87
+ rubygems_version: 2.0.3
94
88
  signing_key:
95
- specification_version: 3
89
+ specification_version: 4
96
90
  summary: Ruby library for SAML service providers
97
91
  test_files: []
98
- has_rdoc: