libsaml 3.6.0 → 3.9.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9eea4c36aa9fc6f404ff5e6283c2ef39c1cb0e328652edc5e5fda2ceb7b21416
4
- data.tar.gz: d76324210f3fe2863f82f89ac7b7317bc295798ec10982b903f2e3b2700dd62f
3
+ metadata.gz: 80a144ab0df42eeb447e74d6df3f3a19a7d89e72cf5527277403b229eb87216c
4
+ data.tar.gz: cd41e41d4f0492e98c52ea9c6865e958a0896c0522f987b58175c69e2d23eaac
5
5
  SHA512:
6
- metadata.gz: 40a5e18247a43f3e215ce6045d51feeb2774a86e649b4702a64533555b4c5c98b83dad3927b3238929d141f0c49a1078903a278b2ccd76cdf6c29d6188f71839
7
- data.tar.gz: 0eda4d5265000e0da3fc7d2650b69064cda9de9914a287cecb2974e077f42d4c76d05e30e7025a56f6ba7173128c63a652b185f0253424715e6e62227f5bdb45
6
+ metadata.gz: 258f442a035b8e06cb9896ed2faf0c5e88d4d58c63ddfcbcd19b14b937fed2de1482aa89bd92bf3b8bcff20f32e5c65b0f92355eefcb1abe0944f2c14a470b45
7
+ data.tar.gz: faa732f728819578d2e75a73129148da7e74eefca3d5ef7a033b7926d2266c417f9c52666dae8c0eef5f3c6fa06032b6da2bdf7eb5118ba4fb9758d127d8f626
data/README.md CHANGED
@@ -94,10 +94,10 @@ Now you can make a SAML controller in `app/controllers/saml_controller.rb`:
94
94
  ```ruby
95
95
  class SamlController < ApplicationController
96
96
  extend Saml::Rails::ControllerHelper
97
- current_provider "entity_id"
97
+ current_provider "<sp_entity_id>"
98
98
 
99
99
  def request_authentication
100
- provider = Saml.provider("my:very:original:entityid")
100
+ provider = Saml.provider("<idp_enity_id>")
101
101
  destination = provider.single_sign_on_service_url(Saml::ProtocolBinding::HTTP_POST)
102
102
 
103
103
  authn_request = Saml::AuthnRequest.new(destination: destination)
@@ -153,7 +153,7 @@ Below is an example of a very primitive IDP Saml Controller
153
153
  ```ruby
154
154
  class SamlController < ActionController::Base
155
155
  extend Saml::Rails::ControllerHelper
156
- current_provider "entity_id"
156
+ current_provider "<idp_entity_id>"
157
157
 
158
158
  def receive_authn_request
159
159
  authn_request = if request.get?
@@ -227,6 +227,10 @@ class SamlController < ActionController::Base
227
227
  end
228
228
  ```
229
229
 
230
+ ## Caveats
231
+
232
+ - SAMLResponse and Assertions have to be signed as per the SAML security guidelines (Some IDP's don't do this by default and require special configuration)
233
+
230
234
  ## Contributing
231
235
 
232
236
  - Fork the project
data/lib/saml.rb CHANGED
@@ -34,6 +34,8 @@ module Saml
34
34
  end
35
35
  class UnparseableMessage < SamlError
36
36
  end
37
+ class InvalidParams < SamlError
38
+ end
37
39
  class MetadataDownloadFailed < SamlError
38
40
  end
39
41
  class InvalidStore < SamlError
@@ -46,7 +46,8 @@ module Saml
46
46
  @authn_statement = Saml::Elements::AuthnStatement.new(authn_instant: authn_instant,
47
47
  address: options.delete(:address),
48
48
  authn_context_class_ref: options.delete(:authn_context_class_ref),
49
- session_index: options.delete(:session_index))
49
+ session_index: options.delete(:session_index),
50
+ session_not_on_or_after: options.delete(:session_not_on_or_after))
50
51
  super(*(args << options))
51
52
  @_id ||= Saml.generate_id
52
53
  @issue_instant ||= Time.now
@@ -20,7 +20,12 @@ module Saml
20
20
  end
21
21
 
22
22
  def receive_message(request, type)
23
- message = Saml::Encoding.decode_64(request.params["SAMLRequest"] || request.params["SAMLResponse"])
23
+ receive_xml = request.params["SAMLRequest"] || request.params["SAMLResponse"]
24
+ if receive_xml.nil?
25
+ raise Saml::Errors::InvalidParams, 'require params `SAMLRequest` or `SAMLResponse`'
26
+ end
27
+
28
+ message = Saml::Encoding.decode_64(receive_xml)
24
29
  notify('receive_message', message)
25
30
  request_or_response = Saml.parse_message(message, type)
26
31
 
@@ -5,7 +5,7 @@ module Saml
5
5
 
6
6
  class << self
7
7
  def create_url(request_or_response, options = {})
8
- options[:signature_algorithm] ||= 'http://www.w3.org/2000/09/xmldsig#rsa-sha1'
8
+ options[:signature_algorithm] ||= 'http://www.w3.org/2000/09/xmldsig#rsa-sha1' unless options[:exclude_signature]
9
9
  new(request_or_response, options).create_url
10
10
  end
11
11
 
@@ -42,13 +42,14 @@ module Saml
42
42
  end
43
43
  end
44
44
 
45
- attr_accessor :request_or_response, :signature_algorithm, :relay_state, :signature
45
+ attr_accessor :request_or_response, :signature_algorithm, :relay_state, :signature, :exclude_signature
46
46
 
47
47
  def initialize(request_or_response, options = {})
48
48
  @request_or_response = request_or_response
49
49
  @signature_algorithm = options[:signature_algorithm]
50
50
  @relay_state = options[:relay_state]
51
51
  @signature = options[:signature]
52
+ @exclude_signature = options[:exclude_signature]
52
53
  end
53
54
 
54
55
  def verify_signature(query)
@@ -61,7 +62,7 @@ module Saml
61
62
  url = request_or_response.destination
62
63
  delimiter = url.include?('?') ? '&' : '?'
63
64
 
64
- [url, signed_params].join(delimiter)
65
+ [url, exclude_signature ? unsigned_params : signed_params].join(delimiter)
65
66
  end
66
67
 
67
68
  private
@@ -108,6 +109,10 @@ module Saml
108
109
 
109
110
  "#{encoded_params}&Signature=#{encoded_signature}"
110
111
  end
112
+
113
+ def unsigned_params
114
+ encoded_params.to_s
115
+ end
111
116
  end
112
117
  end
113
118
  end
@@ -8,6 +8,7 @@ module Saml
8
8
 
9
9
  attribute :authn_instant, Time, tag: "AuthnInstant", on_save: lambda { |val| val.utc.xmlschema }
10
10
  attribute :session_index, String, tag: "SessionIndex"
11
+ attribute :session_not_on_or_after, Time, tag: "SessionNotOnOrAfter", on_save: lambda { |val| val.utc.xmlschema if val.present?}
11
12
 
12
13
  has_one :subject_locality, Saml::Elements::SubjectLocality, tag: "SubjectLocality"
13
14
  has_one :authn_context, Saml::Elements::AuthnContext, tag: "AuthnContext"
@@ -15,27 +15,9 @@ module Saml
15
15
  validates :encrypted_data, presence: true
16
16
 
17
17
  def encrypt(attribute, encrypted_key_data, encrypted_data_options = {})
18
- self.encrypted_data = Xmlenc::Builder::EncryptedData.new(encrypted_data_options)
19
- self.encrypted_data.set_encryption_method algorithm: 'http://www.w3.org/2001/04/xmlenc#aes256-cbc'
20
- self.encrypted_data.set_key_name key_name
21
-
22
- encrypted_key_data.each do |key_descriptor, key_options|
23
- encrypted_key = self.encrypted_data.encrypt Nokogiri::XML(attribute.to_xml).root.to_xml, key_options
24
- encrypted_key.set_encryption_method algorithm: 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p', digest_method_algorithm: 'http://www.w3.org/2000/09/xmldsig#sha1'
25
- encrypted_key.set_key_name key_descriptor.key_info.key_name
26
- encrypted_key.carried_key_name = key_name
27
- encrypted_key.encrypt key_descriptor.certificate.public_key
28
-
29
- self.encrypted_keys ||= []
30
- self.encrypted_keys << encrypted_key
31
- end
18
+ Saml::Util.encrypt_element(self, attribute, encrypted_key_data, encrypted_data_options)
32
19
  end
33
20
 
34
- private
35
-
36
- def key_name
37
- @key_name ||= Saml.generate_id
38
- end
39
21
  end
40
22
  end
41
23
  end
@@ -28,16 +28,16 @@ module Saml
28
28
 
29
29
  if key_descriptors.any?
30
30
  if key_descriptors.one?
31
- encrypt_for_one_recipient(key_descriptors.first, key_options)
31
+ encrypt_for_one_key_descriptor(key_descriptors.first, key_options)
32
32
  else
33
- encrypt_for_multiple_recipients(key_descriptors, key_options)
33
+ encrypt_for_multiple_key_descriptors(key_descriptors, key_options)
34
34
  end
35
35
  end
36
36
  end
37
37
 
38
38
  private
39
39
 
40
- def encrypt_for_one_recipient(key_descriptor, key_options = {})
40
+ def encrypt_for_one_key_descriptor(key_descriptor, key_options = {})
41
41
  self.encrypted_data = Xmlenc::Builder::EncryptedData.new
42
42
 
43
43
  self.encrypted_data.set_key_retrieval_method Xmlenc::Builder::RetrievalMethod.new(
@@ -47,7 +47,7 @@ module Saml
47
47
  algorithm: 'http://www.w3.org/2001/04/xmlenc#aes256-cbc'
48
48
  )
49
49
 
50
- encrypted_key = self.encrypted_data.encrypt(name_id_xml, key_options)
50
+ encrypted_key = self.encrypted_data.encrypt(Nokogiri::XML(name_id.to_xml).root.to_xml, key_options)
51
51
  encrypted_key.set_encryption_method(
52
52
  algorithm: 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p',
53
53
  digest_method_algorithm: 'http://www.w3.org/2000/09/xmldsig#sha1'
@@ -60,39 +60,18 @@ module Saml
60
60
  self.name_id = nil
61
61
  end
62
62
 
63
- def encrypt_for_multiple_recipients(key_descriptors, key_options = {})
64
- key_name = key_options[:key_name]
65
- encrypted_keys = []
66
-
67
- self.encrypted_data = Xmlenc::Builder::EncryptedData.new
68
- self.encrypted_data.set_key_name key_name
69
- self.encrypted_data.set_encryption_method(
70
- algorithm: 'http://www.w3.org/2001/04/xmlenc#aes256-cbc'
71
- )
72
-
73
- key_descriptors.each do |key_descriptor|
74
- encrypted_key = self.encrypted_data.encrypt(
75
- name_id_xml,
76
- key_options.merge(id: "_#{SecureRandom.uuid}", carried_key_name: key_name)
77
- )
78
- encrypted_key.set_encryption_method(
79
- algorithm: 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p',
80
- digest_method_algorithm: 'http://www.w3.org/2000/09/xmldsig#sha1'
81
- )
82
-
83
- encrypted_key.set_key_name(key_descriptor.key_info.key_name)
84
- encrypted_key.encrypt(key_descriptor.certificate.public_key)
85
-
86
- encrypted_keys << encrypted_key
63
+ def encrypt_for_multiple_key_descriptors(encrypted_key_data, encrypted_data_options = {})
64
+ if encrypted_data_options[:recipient].present? && encrypted_key_data.first.is_a?(Saml::Elements::KeyDescriptor)
65
+ encrypted_key_data.map! do |key_descriptor|
66
+ [ key_descriptor, { recipient: encrypted_data_options[:recipient] } ]
67
+ end
87
68
  end
88
69
 
89
- self.encrypted_keys = encrypted_keys
70
+ Saml::Util.encrypt_element(self, name_id, encrypted_key_data, encrypted_data_options)
71
+
90
72
  self.name_id = nil
91
73
  end
92
74
 
93
- def name_id_xml
94
- Nokogiri::XML(name_id.to_xml).root.to_xml
95
- end
96
75
  end
97
76
  end
98
77
  end
data/lib/saml/response.rb CHANGED
@@ -28,10 +28,14 @@ module Saml
28
28
  !success? && status.status_code.unknown_principal?
29
29
  end
30
30
 
31
- def encrypt_assertions(certificate, include_certificate: false)
31
+ def encrypt_assertions(key_descriptor_or_certificate, include_certificate: false, include_key_retrieval_method: false)
32
32
  @encrypted_assertions = []
33
33
  assertions.each do |assertion|
34
- @encrypted_assertions << Saml::Util.encrypt_assertion(assertion, certificate, include_certificate: include_certificate)
34
+ @encrypted_assertions << Saml::Util.encrypt_assertion(
35
+ assertion, key_descriptor_or_certificate,
36
+ include_certificate: include_certificate,
37
+ include_key_retrieval_method: include_key_retrieval_method
38
+ )
35
39
  end
36
40
  assertions.clear
37
41
  end
data/lib/saml/util.rb CHANGED
@@ -60,7 +60,7 @@ module Saml
60
60
  end
61
61
  end
62
62
 
63
- def encrypt_assertion(assertion, key_descriptor_or_certificate, include_certificate: false)
63
+ def encrypt_assertion(assertion, key_descriptor_or_certificate, include_certificate: false, include_key_retrieval_method: false)
64
64
  case key_descriptor_or_certificate
65
65
  when OpenSSL::X509::Certificate
66
66
  certificate = key_descriptor_or_certificate
@@ -87,6 +87,11 @@ module Saml
87
87
  end
88
88
  encrypted_key.encrypt(certificate.public_key)
89
89
 
90
+ if include_key_retrieval_method
91
+ encrypted_key.id = '_' + SecureRandom.uuid
92
+ encrypted_data.set_key_retrieval_method (Xmlenc::Builder::RetrievalMethod.new(uri: "##{encrypted_key.id}"))
93
+ end
94
+
90
95
  Saml::Elements::EncryptedAssertion.new(encrypted_data: encrypted_data, encrypted_keys: encrypted_key)
91
96
  end
92
97
 
@@ -98,6 +103,32 @@ module Saml
98
103
  Saml::Assertion.parse(encrypted_document.decrypt(private_key), single: true)
99
104
  end
100
105
 
106
+ def encrypt_element(element, target_element, encrypted_key_data, encrypted_data_options)
107
+ key_name = encrypted_data_options.fetch(:key_name, Saml.generate_id)
108
+
109
+ element.encrypted_data = Xmlenc::Builder::EncryptedData.new(encrypted_data_options)
110
+ element.encrypted_data.set_encryption_method(algorithm: 'http://www.w3.org/2001/04/xmlenc#aes256-cbc')
111
+ element.encrypted_data.set_key_name key_name
112
+
113
+ original_encrypted_key = element.encrypted_data.encrypt(Nokogiri::XML(target_element.to_xml).root.to_xml, encrypted_data_options)
114
+
115
+ encrypted_key_data.each do |key_descriptor, key_options = {}|
116
+ encrypted_key_options = key_options.merge(id: Saml.generate_id, data: original_encrypted_key.data)
117
+
118
+ encrypted_key = Xmlenc::Builder::EncryptedKey.new(encrypted_key_options)
119
+ encrypted_key.add_data_reference(element.encrypted_data.id)
120
+ encrypted_key.set_key_name(key_descriptor.key_info.key_name)
121
+ encrypted_key.carried_key_name = key_name
122
+ encrypted_key.set_encryption_method(algorithm: 'http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p', digest_method_algorithm: 'http://www.w3.org/2000/09/xmldsig#sha1')
123
+ encrypted_key.encrypt(key_descriptor.certificate.public_key)
124
+
125
+ element.encrypted_keys ||= []
126
+ element.encrypted_keys << encrypted_key
127
+ end
128
+
129
+ element
130
+ end
131
+
101
132
  def encrypt_name_id(name_id, key_descriptor, key_options = {})
102
133
  encrypted_id = Saml::Elements::EncryptedID.new(name_id: name_id)
103
134
  encrypt_encrypted_id(encrypted_id, key_descriptor, key_options)
data/lib/saml/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Saml
2
- VERSION = '3.6.0'
2
+ VERSION = '3.9.2'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: libsaml
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.6.0
4
+ version: 3.9.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Benoist Claassen
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-10-10 00:00:00.000000000 Z
11
+ date: 2021-02-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -240,7 +240,7 @@ homepage: https://www.digidentity.eu
240
240
  licenses:
241
241
  - MIT
242
242
  metadata: {}
243
- post_install_message:
243
+ post_install_message:
244
244
  rdoc_options: []
245
245
  require_paths:
246
246
  - lib
@@ -256,7 +256,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
256
256
  version: '0'
257
257
  requirements: []
258
258
  rubygems_version: 3.0.3
259
- signing_key:
259
+ signing_key:
260
260
  specification_version: 4
261
261
  summary: A gem to easily create SAML 2.0 messages.
262
262
  test_files: []