ruby-saml 0.4.1 → 0.4.2

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.

Potentially problematic release.


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

data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.1
1
+ 0.4.2
@@ -8,18 +8,20 @@ module Onelogin::Saml
8
8
  DSIG = "http://www.w3.org/2000/09/xmldsig#"
9
9
 
10
10
  attr_accessor :response, :document, :logger, :settings, :original
11
+ attr_accessor :bypass_conditions_check # for testing only
11
12
 
12
13
  def initialize(response)
13
14
  raise ArgumentError.new("Response cannot be nil") if response.nil?
14
- self.response = response
15
- self.document = XMLSecurity::SignedDocument.new(Base64.decode64(response))
16
- self.original = XMLSecurity::SignedDocument.new(Base64.decode64(response))
15
+ self.bypass_conditions_check = false
16
+ self.response = response
17
+ self.document = XMLSecurity::SignedDocument.new(Base64.decode64(response))
17
18
  end
18
19
 
19
20
  def is_valid?
20
21
  return false if response.empty?
21
22
  return false if settings.nil?
22
23
  return false if settings.idp_cert_fingerprint.nil?
24
+ return false if !check_conditions
23
25
 
24
26
  document.validate(settings.idp_cert_fingerprint, logger)
25
27
  end
@@ -27,12 +29,21 @@ module Onelogin::Saml
27
29
  # The value of the user identifier as designated by the initialization request response
28
30
  def name_id
29
31
  @name_id ||= begin
30
- uri = REXML::XPath.first(original, "//ds:Signature/ds:SignedInfo/ds:Reference", {"ds"=>DSIG}).attribute("URI").value
31
- node = REXML::XPath.first(document, "/p:Response/a:Assertion[@ID='#{uri[1,uri.size]}']/a:Subject/a:NameID", { "p" => PROTOCOL, "a" => ASSERTION })
32
+ 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
33
  node.text
33
34
  end
34
35
  end
35
36
 
37
+ def check_conditions
38
+ return true if self.bypass_conditions_check
39
+
40
+ cond_element = 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 })
41
+ return false unless cond_element
42
+ return false unless parseXsDateTime(cond_element.attribute('NotBefore').to_s) < Time.now.utc
43
+ return false unless parseXsDateTime(cond_element.attribute('NotOnOrAfter').to_s) >= Time.now.utc
44
+ true
45
+ end
46
+
36
47
  # A hash of alle the attributes with the response. Assuming there is only one value for each key
37
48
  def attributes
38
49
  @attr_statements ||= begin
@@ -62,5 +73,11 @@ module Onelogin::Saml
62
73
  end
63
74
  end
64
75
 
76
+ private
77
+
78
+ def parseXsDateTime(xsDatetime)
79
+ return nil unless xsDatetime =~ /^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z$/
80
+ Time.utc($1, $2, $3, $4, $5, $6)
81
+ end
65
82
  end
66
83
  end
data/lib/xml_security.rb CHANGED
@@ -32,6 +32,14 @@ require "digest/sha1"
32
32
  module XMLSecurity
33
33
 
34
34
  class SignedDocument < REXML::Document
35
+ DSIG = "http://www.w3.org/2000/09/xmldsig#"
36
+
37
+ attr_accessor :signed_element_id
38
+
39
+ def initialize(response)
40
+ super(response)
41
+ extract_signed_element_id
42
+ end
35
43
 
36
44
  def validate (idp_cert_fingerprint, logger = nil)
37
45
  # get cert from response
@@ -87,5 +95,11 @@ module XMLSecurity
87
95
  return valid_flag
88
96
  end
89
97
 
98
+ private
99
+
100
+ def extract_signed_element_id
101
+ reference_element = REXML::XPath.first(self, "//ds:Signature/ds:SignedInfo/ds:Reference", {"ds"=>DSIG})
102
+ self.signed_element_id = reference_element.attribute("URI").value unless reference_element.nil?
103
+ end
90
104
  end
91
105
  end
data/ruby-saml.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{ruby-saml}
8
- s.version = "0.4.1"
8
+ s.version = "0.4.2"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["OneLogin LLC"]
12
- s.date = %q{2011-06-03}
12
+ s.date = %q{2011-06-04}
13
13
  s.description = %q{SAML toolkit for Ruby on Rails}
14
14
  s.email = %q{support@onelogin.com}
15
15
  s.extra_rdoc_files = [
@@ -39,13 +39,11 @@ class RubySamlTest < Test::Unit::TestCase
39
39
  assert !response.name_id.nil?
40
40
  end
41
41
 
42
- should "not allow signature wrapping attack" do
43
- response = Onelogin::Saml::Response.new(response_document_4)
44
- settings = Onelogin::Saml::Settings.new
45
- response.settings = settings
46
- settings.idp_cert_fingerprint = signature_fingerprint_1
47
- assert response.is_valid?
48
- assert response.name_id == "test@onelogin.com"
42
+ should "check time conditions" do
43
+ response = Onelogin::Saml::Response.new(response_document)
44
+ assert !response.check_conditions
45
+ response = Onelogin::Saml::Response.new(response_document_5)
46
+ assert response.check_conditions
49
47
  end
50
48
 
51
49
  context "#is_valid?" do
@@ -60,15 +58,25 @@ class RubySamlTest < Test::Unit::TestCase
60
58
  end
61
59
 
62
60
  should "return true when the response is initialized with valid data" do
63
- response = Onelogin::Saml::Response.new(response_document)
61
+ response = Onelogin::Saml::Response.new(response_document_4)
62
+ response.bypass_conditions_check = true
63
+ assert !response.is_valid?
64
64
  settings = Onelogin::Saml::Settings.new
65
- settings.idp_cert_fingerprint = 'hello'
65
+ assert !response.is_valid?
66
66
  response.settings = settings
67
67
  assert !response.is_valid?
68
- document = stub()
69
- document.stubs(:validate).returns(true)
70
- response.document = document
68
+ settings.idp_cert_fingerprint = signature_fingerprint_1
69
+ assert response.is_valid?
70
+ end
71
+
72
+ should "not allow signature wrapping attack" do
73
+ response = Onelogin::Saml::Response.new(response_document_4)
74
+ response.bypass_conditions_check = true
75
+ settings = Onelogin::Saml::Settings.new
76
+ settings.idp_cert_fingerprint = signature_fingerprint_1
77
+ response.settings = settings
71
78
  assert response.is_valid?
79
+ assert response.name_id == "test@onelogin.com"
72
80
  end
73
81
  end
74
82
 
data/test/test_helper.rb CHANGED
@@ -24,6 +24,13 @@ class Test::Unit::TestCase
24
24
  @response_document4 ||= File.read(File.join(File.dirname(__FILE__), 'responses', 'response4.xml.base64'))
25
25
  end
26
26
 
27
+ def response_document_5
28
+ doc = Base64.decode64(response_document)
29
+ 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")}\"")
30
+ doc.gsub!(/NotOnOrAfter=\"(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})Z\"/, "NotOnOrAfter=\"#{(Time.now+300).getutc.strftime("%Y-%m-%dT%XZ")}\"")
31
+ Base64.encode64(doc)
32
+ end
33
+
27
34
  def signature_fingerprint_1
28
35
  @signature_fingerprint1 ||= "C5:19:85:D9:47:F1:BE:57:08:20:25:05:08:46:EB:27:F6:CA:B7:83"
29
36
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-saml
3
3
  version: !ruby/object:Gem::Version
4
- hash: 13
4
+ hash: 11
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 4
9
- - 1
10
- version: 0.4.1
9
+ - 2
10
+ version: 0.4.2
11
11
  platform: ruby
12
12
  authors:
13
13
  - OneLogin LLC
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-06-03 00:00:00 -06:00
18
+ date: 2011-06-04 00:00:00 -06:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency