ruby-saml-mod 0.1.25 → 0.1.26
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.
- checksums.yaml +7 -0
- data/lib/onelogin/saml/auth_request.rb +1 -1
- data/lib/onelogin/saml/log_out_request.rb +4 -8
- data/lib/onelogin/saml/response.rb +32 -72
- data/lib/xml_sec.rb +0 -46
- data/ruby-saml-mod.gemspec +2 -2
- metadata +5 -12
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.
|
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.
|
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
|
-
@
|
34
|
-
@
|
35
|
-
@
|
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
|
-
|
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
|
-
|
47
|
-
|
48
|
-
|
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
|
-
@
|
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
|
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
|
-
|
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.
|
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 =
|
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
|
data/ruby-saml-mod.gemspec
CHANGED
@@ -1,9 +1,9 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = %q{ruby-saml-mod}
|
3
|
-
s.version = "0.1.
|
3
|
+
s.version = "0.1.26"
|
4
4
|
|
5
5
|
s.authors = ["OneLogin LLC", "Bracken", "Zach", "Cody", "Jeremy", "Paul"]
|
6
|
-
s.date = %q{
|
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.
|
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:
|
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:
|
87
|
+
rubygems_version: 2.0.3
|
94
88
|
signing_key:
|
95
|
-
specification_version:
|
89
|
+
specification_version: 4
|
96
90
|
summary: Ruby library for SAML service providers
|
97
91
|
test_files: []
|
98
|
-
has_rdoc:
|