libsaml 2.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +15 -0
  2. data/MIT-LICENSE +20 -0
  3. data/README.rdoc +91 -0
  4. data/Rakefile +33 -0
  5. data/lib/saml.rb +142 -0
  6. data/lib/saml/artifact.rb +51 -0
  7. data/lib/saml/artifact_resolve.rb +10 -0
  8. data/lib/saml/artifact_response.rb +9 -0
  9. data/lib/saml/assertion.rb +67 -0
  10. data/lib/saml/authn_request.rb +34 -0
  11. data/lib/saml/base.rb +47 -0
  12. data/lib/saml/bindings/http_artifact.rb +44 -0
  13. data/lib/saml/bindings/http_post.rb +29 -0
  14. data/lib/saml/bindings/http_redirect.rb +100 -0
  15. data/lib/saml/bindings/soap.rb +31 -0
  16. data/lib/saml/complex_types/endpoint_type.rb +17 -0
  17. data/lib/saml/complex_types/indexed_endpoint_type.rb +15 -0
  18. data/lib/saml/complex_types/request_abstract_type.rb +57 -0
  19. data/lib/saml/complex_types/sso_descriptor_type.rb +48 -0
  20. data/lib/saml/complex_types/status_response_type.rb +29 -0
  21. data/lib/saml/config.rb +49 -0
  22. data/lib/saml/elements/attribute.rb +24 -0
  23. data/lib/saml/elements/attribute_statement.rb +26 -0
  24. data/lib/saml/elements/audience_restriction.rb +12 -0
  25. data/lib/saml/elements/authn_context.rb +13 -0
  26. data/lib/saml/elements/authn_statement.rb +25 -0
  27. data/lib/saml/elements/conditions.rb +24 -0
  28. data/lib/saml/elements/contact_person.rb +33 -0
  29. data/lib/saml/elements/entities_descriptor.rb +27 -0
  30. data/lib/saml/elements/entity_descriptor.rb +37 -0
  31. data/lib/saml/elements/idp_sso_descriptor.rb +23 -0
  32. data/lib/saml/elements/key_descriptor.rb +34 -0
  33. data/lib/saml/elements/key_descriptor/key_info.rb +30 -0
  34. data/lib/saml/elements/key_descriptor/key_info/x509_data.rb +34 -0
  35. data/lib/saml/elements/name_id.rb +14 -0
  36. data/lib/saml/elements/organization.rb +16 -0
  37. data/lib/saml/elements/requested_authn_context.rb +28 -0
  38. data/lib/saml/elements/signature.rb +33 -0
  39. data/lib/saml/elements/signature/canonicalization_method.rb +19 -0
  40. data/lib/saml/elements/signature/digest_method.rb +19 -0
  41. data/lib/saml/elements/signature/inclusive_namespaces.rb +20 -0
  42. data/lib/saml/elements/signature/key_info.rb +14 -0
  43. data/lib/saml/elements/signature/reference.rb +23 -0
  44. data/lib/saml/elements/signature/signature_method.rb +19 -0
  45. data/lib/saml/elements/signature/signed_info.rb +24 -0
  46. data/lib/saml/elements/signature/transform.rb +19 -0
  47. data/lib/saml/elements/signature/transforms.rb +21 -0
  48. data/lib/saml/elements/sp_sso_descriptor.rb +27 -0
  49. data/lib/saml/elements/status.rb +15 -0
  50. data/lib/saml/elements/status_code.rb +42 -0
  51. data/lib/saml/elements/sub_status_code.rb +14 -0
  52. data/lib/saml/elements/subject.rb +38 -0
  53. data/lib/saml/elements/subject_confirmation.rb +30 -0
  54. data/lib/saml/elements/subject_confirmation_data.rb +23 -0
  55. data/lib/saml/elements/subject_locality.rb +12 -0
  56. data/lib/saml/encoding.rb +35 -0
  57. data/lib/saml/logout_request.rb +10 -0
  58. data/lib/saml/logout_response.rb +11 -0
  59. data/lib/saml/provider.rb +85 -0
  60. data/lib/saml/provider_stores/file.rb +33 -0
  61. data/lib/saml/response.rb +21 -0
  62. data/lib/saml/util.rb +51 -0
  63. data/lib/saml/version.rb +3 -0
  64. data/lib/saml/xml_helpers.rb +34 -0
  65. data/lib/tasks/saml_tasks.rake +4 -0
  66. metadata +195 -0
@@ -0,0 +1,12 @@
1
+ module Saml
2
+ module Elements
3
+ class SubjectLocality
4
+ include Saml::Base
5
+
6
+ tag "SubjectLocality"
7
+ namespace 'saml'
8
+
9
+ attribute :address, String, :tag => "Address"
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,35 @@
1
+ require 'zlib'
2
+ require 'base64'
3
+
4
+ module Saml
5
+ class Encoding
6
+
7
+ def self.encode_64 string
8
+ Base64.encode64(string).chomp
9
+ end
10
+
11
+ def self.decode_64 base64_string
12
+ Base64.decode64 base64_string
13
+ end
14
+
15
+ def self.encode_gzip string
16
+ Zlib::Deflate.deflate(string, 9)[2..-5]
17
+ end
18
+
19
+ def self.decode_gzip gzip_binary_string
20
+ # Adding a - sign to MAX_WBITS makes zlib ignore the zlib headers
21
+ inflate(gzip_binary_string, -Zlib::MAX_WBITS)
22
+ rescue ::Zlib::DataError
23
+ inflate(gzip_binary_string) rescue nil
24
+ end
25
+
26
+ def self.inflate gzip_binary_string, max_bits=nil
27
+ zstream = Zlib::Inflate.new(max_bits)
28
+ begin
29
+ zstream.inflate(gzip_binary_string)
30
+ ensure
31
+ zstream.close
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,10 @@
1
+ module Saml
2
+ class LogoutRequest
3
+ include Saml::ComplexTypes::RequestAbstractType
4
+
5
+ tag "LogoutRequest"
6
+ element :name_id, String, :tag => "NameID", :namespace => 'saml'
7
+
8
+ validates :name_id, :presence => true
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ module Saml
2
+ class LogoutResponse
3
+ include Saml::ComplexTypes::StatusResponseType
4
+
5
+ tag "LogoutResponse"
6
+
7
+ def partial_logout?
8
+ !success? && status.status_code.partial_logout?
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,85 @@
1
+ module Saml
2
+ module Provider
3
+ extend ActiveSupport::Concern
4
+
5
+ def assertion_consumer_service_url(index = nil)
6
+ find_indexed_service(descriptor.assertion_consumer_services, index)
7
+ end
8
+
9
+ def artifact_resolution_service_url(index = nil)
10
+ find_indexed_service(descriptor.artifact_resolution_services, index)
11
+ end
12
+
13
+ def entity_descriptor
14
+ @entity_descriptor
15
+ end
16
+
17
+ def entity_id
18
+ entity_descriptor.entity_id
19
+ end
20
+
21
+ def certificate(use = "signing")
22
+ key_descriptor = descriptor.key_descriptors.find { |key| key.use == use || key.use == "" }
23
+ key_descriptor.certificate if key_descriptor
24
+ end
25
+
26
+ def private_key
27
+ @private_key
28
+ end
29
+
30
+ def sign(signature_algorithm, data)
31
+ private_key.sign(digest_method(signature_algorithm).new, data)
32
+ end
33
+
34
+ def single_sign_on_service_url(binding)
35
+ find_binding_service(descriptor.single_sign_on_services, binding)
36
+ end
37
+
38
+ def single_logout_service_url(binding)
39
+ find_binding_service(descriptor.single_logout_services, binding)
40
+ end
41
+
42
+ def type
43
+ descriptor.is_a?(Saml::Elements::SPSSODescriptor) ? "service_provider" : "identity_provider"
44
+ end
45
+
46
+ def verify(signature_algorithm, signature, data)
47
+ certificate.public_key.verify(digest_method(signature_algorithm).new, signature, data) rescue nil
48
+ end
49
+
50
+ def authn_requests_signed?
51
+ descriptor.authn_requests_signed
52
+ end
53
+
54
+ private
55
+
56
+ def digest_method(signature_algorithm)
57
+ digest = signature_algorithm && signature_algorithm =~ /sha(.*?)$/i && $1.to_i
58
+ case digest
59
+ when 256 then
60
+ OpenSSL::Digest::SHA256
61
+ else
62
+ OpenSSL::Digest::SHA1
63
+ end
64
+ end
65
+
66
+ # @return [Saml::ComplexTypes::SSODescriptorType]
67
+ def descriptor
68
+ entity_descriptor.sp_sso_descriptor || entity_descriptor.idp_sso_descriptor
69
+ end
70
+
71
+ def find_indexed_service(service_list, index)
72
+ service = if index
73
+ service_list.find { |service| service.index == index }
74
+ else
75
+ service_list.find { |service| service.is_default }
76
+ end
77
+ service.location if service
78
+ end
79
+
80
+ def find_binding_service(service_list, binding)
81
+ service = service_list.find { |service| service.binding == binding }
82
+ service.location if service
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,33 @@
1
+ module Saml
2
+ module ProviderStores
3
+ class File
4
+ class Provider
5
+ include Saml::Provider
6
+ attr_accessor :entity_descriptor, :private_key, :type
7
+
8
+ def initialize(entity_descriptor, private_key, type)
9
+ @entity_descriptor = entity_descriptor
10
+ @private_key = private_key
11
+ @type = type
12
+ end
13
+ end
14
+
15
+ attr_accessor :providers
16
+
17
+ def initialize(metadata_dir = "config/metadata", key_file = "config/ssl/key.pem")
18
+ self.providers = []
19
+ Dir[::File.join(metadata_dir, "*.xml")].each do |file|
20
+ entity_descriptor = Saml::Elements::EntityDescriptor.parse(::File.read(file), single: true)
21
+ private_key = OpenSSL::PKey::RSA.new(::File.read(key_file))
22
+ type = entity_descriptor.sp_sso_descriptor.present? ? "service_provider" : "identity_provider"
23
+
24
+ self.providers << Provider.new(entity_descriptor, private_key, type)
25
+ end
26
+ end
27
+
28
+ def find_by_entity_id(entity_id)
29
+ self.providers.find { |provider| provider.entity_id == entity_id }
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,21 @@
1
+ module Saml
2
+ class Response
3
+ include Saml::ComplexTypes::StatusResponseType
4
+
5
+ tag "Response"
6
+ has_one :assertion, Saml::Assertion, :tag => "Assertion"
7
+ has_many :assertions, Saml::Assertion, :tag => "Assertion"
8
+
9
+ def authn_failed?
10
+ !success? && status.status_code.authn_failed?
11
+ end
12
+
13
+ def request_denied?
14
+ !success? && status.status_code.request_denied?
15
+ end
16
+
17
+ def no_authn_context?
18
+ !success? && status.status_code.no_authn_context?
19
+ end
20
+ end
21
+ end
data/lib/saml/util.rb ADDED
@@ -0,0 +1,51 @@
1
+ module Saml
2
+ class Util
3
+ class << self
4
+ def parse_params(url)
5
+ query = URI.parse(url).query
6
+ return {} unless query
7
+
8
+ params = {}
9
+ query.split(/[&;]/).each do |pairs|
10
+ key, value = pairs.split('=',2)
11
+ params[key] = value
12
+ end
13
+
14
+ params
15
+ end
16
+
17
+ def post(location, message)
18
+ request = HTTPI::Request.new
19
+
20
+ request.url = location
21
+ request.headers['Content-Type'] = 'text/xml'
22
+ request.body = message
23
+ request.auth.ssl.cert_file = Saml::Config.ssl_certificate_file
24
+ request.auth.ssl.cert_key_file = Saml::Config.ssl_private_key_file
25
+
26
+ HTTPI.post request
27
+ end
28
+
29
+ def sign_xml(message, format = :xml)
30
+ message.add_signature
31
+
32
+ document = Xmldsig::SignedDocument.new(message.send("to_#{format}"))
33
+ document.sign do |data, signature_algorithm|
34
+ message.provider.sign(signature_algorithm, data)
35
+ end
36
+ end
37
+
38
+ def verify_xml(message, raw_body)
39
+ document = Xmldsig::SignedDocument.new(raw_body)
40
+
41
+ signature_valid = document.validate do |signature, data, signature_algorithm|
42
+ message.provider.verify(signature_algorithm, signature, data)
43
+ end
44
+
45
+ raise Saml::Errors::SignatureInvalid.new unless signature_valid
46
+
47
+ message.class.parse(document.signed_nodes.first.to_xml, single: true)
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,3 @@
1
+ module Saml
2
+ VERSION = "2.0.5"
3
+ end
@@ -0,0 +1,34 @@
1
+ module Saml
2
+ module XMLHelpers
3
+ extend ActiveSupport::Concern
4
+
5
+ def to_xml(builder = nil, default_namespace = nil, instruct = true)
6
+ write_xml = builder.nil? ? true : false
7
+ builder ||= Nokogiri::XML::Builder.new
8
+ builder.doc.encoding = "UTF-8"
9
+ result = super(builder, default_namespace)
10
+ if write_xml
11
+ instruct ? result.to_xml : result.doc.root
12
+ else
13
+ result
14
+ end
15
+
16
+ end
17
+
18
+ def to_soap
19
+ builder = Nokogiri::XML::Builder.new
20
+ body = self.to_xml(builder)
21
+
22
+ builder = Nokogiri::XML::Builder.new(:encoding => "UTF-8")
23
+ builder.Envelope(:'xmlns:soapenv' => "http://schemas.xmlsoap.org/soap/envelope/",
24
+ :'xmlns:xsd' => "http://www.w3.org/2001/XMLSchema",
25
+ :'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance") do |xml|
26
+ builder.parent.namespace = builder.parent.namespace_definitions.find { |n| n.prefix == 'soapenv' }
27
+ builder.Body do
28
+ builder.parent.add_child body.doc.root
29
+ end
30
+ end
31
+ builder.to_xml
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :saml do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,195 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: libsaml
3
+ version: !ruby/object:Gem::Version
4
+ version: 2.0.5
5
+ platform: ruby
6
+ authors:
7
+ - Benoist Claassen
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-08-12 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activesupport
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 3.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 3.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: activemodel
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: 3.0.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: 3.0.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: nokogiri-happymapper
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: 0.5.7
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 0.5.7
55
+ - !ruby/object:Gem::Dependency
56
+ name: xmldsig
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 0.2.1
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: 0.2.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: curb
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: httpi
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: Libsaml makes the creation of SAML 2.0 messages easy. The object structure
98
+ is modeled after the SAML Core 2.0 specification from OASIS. Supported bindings
99
+ are HTTP-Post, HTTP-Redirect, HTTP-Artifact and SOAP. Features include XML signing,
100
+ XML verification and a pluggable backend for providers (FileStore backend included).
101
+ email:
102
+ - bclaassen@digidentity.eu
103
+ executables: []
104
+ extensions: []
105
+ extra_rdoc_files: []
106
+ files:
107
+ - lib/saml/artifact.rb
108
+ - lib/saml/artifact_resolve.rb
109
+ - lib/saml/artifact_response.rb
110
+ - lib/saml/assertion.rb
111
+ - lib/saml/authn_request.rb
112
+ - lib/saml/base.rb
113
+ - lib/saml/bindings/http_artifact.rb
114
+ - lib/saml/bindings/http_post.rb
115
+ - lib/saml/bindings/http_redirect.rb
116
+ - lib/saml/bindings/soap.rb
117
+ - lib/saml/complex_types/endpoint_type.rb
118
+ - lib/saml/complex_types/indexed_endpoint_type.rb
119
+ - lib/saml/complex_types/request_abstract_type.rb
120
+ - lib/saml/complex_types/sso_descriptor_type.rb
121
+ - lib/saml/complex_types/status_response_type.rb
122
+ - lib/saml/config.rb
123
+ - lib/saml/elements/attribute.rb
124
+ - lib/saml/elements/attribute_statement.rb
125
+ - lib/saml/elements/audience_restriction.rb
126
+ - lib/saml/elements/authn_context.rb
127
+ - lib/saml/elements/authn_statement.rb
128
+ - lib/saml/elements/conditions.rb
129
+ - lib/saml/elements/contact_person.rb
130
+ - lib/saml/elements/entities_descriptor.rb
131
+ - lib/saml/elements/entity_descriptor.rb
132
+ - lib/saml/elements/idp_sso_descriptor.rb
133
+ - lib/saml/elements/key_descriptor/key_info/x509_data.rb
134
+ - lib/saml/elements/key_descriptor/key_info.rb
135
+ - lib/saml/elements/key_descriptor.rb
136
+ - lib/saml/elements/name_id.rb
137
+ - lib/saml/elements/organization.rb
138
+ - lib/saml/elements/requested_authn_context.rb
139
+ - lib/saml/elements/signature/canonicalization_method.rb
140
+ - lib/saml/elements/signature/digest_method.rb
141
+ - lib/saml/elements/signature/inclusive_namespaces.rb
142
+ - lib/saml/elements/signature/key_info.rb
143
+ - lib/saml/elements/signature/reference.rb
144
+ - lib/saml/elements/signature/signature_method.rb
145
+ - lib/saml/elements/signature/signed_info.rb
146
+ - lib/saml/elements/signature/transform.rb
147
+ - lib/saml/elements/signature/transforms.rb
148
+ - lib/saml/elements/signature.rb
149
+ - lib/saml/elements/sp_sso_descriptor.rb
150
+ - lib/saml/elements/status.rb
151
+ - lib/saml/elements/status_code.rb
152
+ - lib/saml/elements/sub_status_code.rb
153
+ - lib/saml/elements/subject.rb
154
+ - lib/saml/elements/subject_confirmation.rb
155
+ - lib/saml/elements/subject_confirmation_data.rb
156
+ - lib/saml/elements/subject_locality.rb
157
+ - lib/saml/encoding.rb
158
+ - lib/saml/logout_request.rb
159
+ - lib/saml/logout_response.rb
160
+ - lib/saml/provider.rb
161
+ - lib/saml/provider_stores/file.rb
162
+ - lib/saml/response.rb
163
+ - lib/saml/util.rb
164
+ - lib/saml/version.rb
165
+ - lib/saml/xml_helpers.rb
166
+ - lib/saml.rb
167
+ - lib/tasks/saml_tasks.rake
168
+ - MIT-LICENSE
169
+ - Rakefile
170
+ - README.rdoc
171
+ homepage: https://www.digidentity.eu
172
+ licenses:
173
+ - MIT
174
+ metadata: {}
175
+ post_install_message:
176
+ rdoc_options: []
177
+ require_paths:
178
+ - lib
179
+ required_ruby_version: !ruby/object:Gem::Requirement
180
+ requirements:
181
+ - - ! '>='
182
+ - !ruby/object:Gem::Version
183
+ version: '0'
184
+ required_rubygems_version: !ruby/object:Gem::Requirement
185
+ requirements:
186
+ - - ! '>='
187
+ - !ruby/object:Gem::Version
188
+ version: '0'
189
+ requirements: []
190
+ rubyforge_project:
191
+ rubygems_version: 2.0.6
192
+ signing_key:
193
+ specification_version: 4
194
+ summary: A gem to easily create SAML 2.0 messages.
195
+ test_files: []