ruby-saml 0.4.1 → 0.4.2

Sign up to get free protection for your applications and to get access to all the features.

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