test/response_test.rb in ruby-saml-1.7.2 vs test/response_test.rb in ruby-saml-1.8.0
- old
+ new
@@ -21,11 +21,13 @@
let(:response_valid_signed_without_x509certificate) { OneLogin::RubySaml::Response.new(response_document_valid_signed_without_x509certificate) }
let(:response_no_id) { OneLogin::RubySaml::Response.new(read_invalid_response("no_id.xml.base64")) }
let(:response_no_version) { OneLogin::RubySaml::Response.new(read_invalid_response("no_saml2.xml.base64")) }
let(:response_multi_assertion) { OneLogin::RubySaml::Response.new(read_invalid_response("multiple_assertions.xml.base64")) }
let(:response_no_conditions) { OneLogin::RubySaml::Response.new(read_invalid_response("no_conditions.xml.base64")) }
+ let(:response_no_conditions_with_skip) { OneLogin::RubySaml::Response.new(read_invalid_response("no_conditions.xml.base64"), { :skip_conditions => true }) }
let(:response_no_authnstatement) { OneLogin::RubySaml::Response.new(read_invalid_response("no_authnstatement.xml.base64")) }
+ let(:response_no_authnstatement_with_skip) { OneLogin::RubySaml::Response.new(read_invalid_response("no_authnstatement.xml.base64"), {:skip_authnstatement => true}) }
let(:response_empty_destination) { OneLogin::RubySaml::Response.new(read_invalid_response("empty_destination.xml.base64")) }
let(:response_empty_destination_with_skip) { OneLogin::RubySaml::Response.new(read_invalid_response("empty_destination.xml.base64"), {:skip_destination => true}) }
let(:response_no_status) { OneLogin::RubySaml::Response.new(read_invalid_response("no_status.xml.base64")) }
let(:response_no_statuscode) { OneLogin::RubySaml::Response.new(read_invalid_response("no_status_code.xml.base64")) }
let(:response_statuscode_responder) { OneLogin::RubySaml::Response.new(read_invalid_response("status_code_responder.xml.base64")) }
@@ -52,14 +54,26 @@
let(:response_invalid_subjectconfirmation_nb) { OneLogin::RubySaml::Response.new(read_invalid_response("invalid_subjectconfirmation_nb.xml.base64")) }
let(:response_invalid_subjectconfirmation_noa) { OneLogin::RubySaml::Response.new(read_invalid_response("invalid_subjectconfirmation_noa.xml.base64")) }
let(:response_invalid_signature_position) { OneLogin::RubySaml::Response.new(read_invalid_response("invalid_signature_position.xml.base64")) }
let(:response_encrypted_nameid) { OneLogin::RubySaml::Response.new(response_document_encrypted_nameid) }
+ def generate_audience_error(expected, actual)
+ s = actual.count > 1 ? 's' : '';
+ return "Invalid Audience#{s}. The audience#{s} #{actual.join(',')}, did not match the expected audience #{expected}"
+ end
+
it "raise an exception when response is initialized with nil" do
assert_raises(ArgumentError) { OneLogin::RubySaml::Response.new(nil) }
end
+ it "not filter available options only" do
+ options = { :skip_destination => true, :foo => :bar }
+ response = OneLogin::RubySaml::Response.new(response_document_valid_signed, options)
+ assert_includes response.options.keys, :skip_destination
+ assert_includes response.options.keys, :foo
+ end
+
it "be able to parse a document which contains ampersands" do
XMLSecurity::SignedDocument.any_instance.stubs(:digests_match?).returns(true)
OneLogin::RubySaml::Response.any_instance.stubs(:validate_conditions).returns(true)
ampersands_response = OneLogin::RubySaml::Response.new(ampersands_document)
@@ -80,13 +94,38 @@
end
it "receives the full AttributeValue when there is an injected comment" do
assert_equal "smith", @response.attributes["surname"]
end
+ end
+ describe "Another test to prevent with comment attack (VU#475445)" do
+ before do
+ @response = OneLogin::RubySaml::Response.new(read_response('response_node_text_attack2.xml.base64'), {:skip_recipient_check => true })
+ @response.settings = settings
+ @response.settings.idp_cert_fingerprint = ruby_saml_cert_fingerprint
+ end
+
+ it "receives the full NameID when there is an injected comment, validates the response" do
+ assert_equal "test@onelogin.com", @response.name_id
+ end
end
+ describe "Another test with CDATA injected" do
+ before do
+ @response = OneLogin::RubySaml::Response.new(read_response('response_node_text_attack3.xml.base64'), {:skip_recipient_check => true })
+ @response.settings = settings
+ @response.settings.idp_cert_fingerprint = ruby_saml_cert_fingerprint
+ end
+
+ it "it normalizes CDATA but reject SAMLResponse due signature invalidation" do
+ assert_equal "test@onelogin.com.evil.com", @response.name_id
+ assert !@response.is_valid?
+ assert_includes @response.errors, "Invalid Signature on SAML Response"
+ end
+ end
+
describe "Prevent XEE attack" do
before do
@response = OneLogin::RubySaml::Response.new(fixture(:attackxee))
end
@@ -221,11 +260,11 @@
it "raise when there is no valid audience" do
settings.idp_cert_fingerprint = signature_fingerprint_1
settings.issuer = 'invalid'
response_valid_signed.settings = settings
response_valid_signed.soft = false
- error_msg = "#{response_valid_signed.settings.issuer} is not a valid audience for this Response - Valid audiences: https://someone.example.com/audience"
+ error_msg = generate_audience_error(response_valid_signed.settings.issuer, ['https://someone.example.com/audience'])
assert_raises(OneLogin::RubySaml::ValidationError, error_msg) do
response_valid_signed.is_valid?
end
assert_includes response_valid_signed.errors, error_msg
end
@@ -377,11 +416,12 @@
it "return false when there is no valid audience" do
settings.idp_cert_fingerprint = signature_fingerprint_1
settings.issuer = 'invalid'
response_valid_signed.settings = settings
response_valid_signed.is_valid?
- assert_includes response_valid_signed.errors, "#{response_valid_signed.settings.issuer} is not a valid audience for this Response - Valid audiences: https://someone.example.com/audience"
+
+ assert_includes response_valid_signed.errors, generate_audience_error(response_valid_signed.settings.issuer, ['https://someone.example.com/audience'])
end
it "return false when no ID present in the SAML Response" do
settings.idp_cert_fingerprint = signature_fingerprint_1
response_no_id.settings = settings
@@ -413,11 +453,11 @@
settings.idp_cert = ruby_saml_cert_text
settings.issuer = 'invalid'
response_invalid_subjectconfirmation_recipient.settings = settings
collect_errors = true
response_invalid_subjectconfirmation_recipient.is_valid?(collect_errors)
- assert_includes response_invalid_subjectconfirmation_recipient.errors, "invalid is not a valid audience for this Response - Valid audiences: http://stuff.com/endpoints/metadata.php"
+ assert_includes response_invalid_subjectconfirmation_recipient.errors, generate_audience_error('invalid', ['http://stuff.com/endpoints/metadata.php'])
assert_includes response_invalid_subjectconfirmation_recipient.errors, "Invalid Signature on SAML Response"
end
end
end
@@ -438,11 +478,11 @@
it "return false when the audience is valid" do
response.settings = settings
response.settings.issuer = 'invalid_audience'
assert !response.send(:validate_audience)
- assert_includes response.errors, "#{response.settings.issuer} is not a valid audience for this Response - Valid audiences: {audience}"
+ assert_includes response.errors, generate_audience_error(response.settings.issuer, ['{audience}'])
end
end
describe "#validate_destination" do
it "return true when the destination of the SAML Response matches the assertion consumer service url" do
@@ -624,11 +664,11 @@
it "return false when there is no valid audience" do
response_invalid_audience.settings = settings
response_invalid_audience.settings.issuer = "https://invalid.example.com/audience"
assert !response_invalid_audience.send(:validate_audience)
- assert_includes response_invalid_audience.errors, "#{response_invalid_audience.settings.issuer} is not a valid audience for this Response - Valid audiences: http://invalid.audience.com"
+ assert_includes response_invalid_audience.errors, generate_audience_error(response_invalid_audience.settings.issuer, ['http://invalid.audience.com'])
end
end
describe "#validate_issuer" do
it "return true when the issuer of the Message/Assertion matches the IdP entityId or it was empty" do
@@ -956,10 +996,15 @@
it "return true when one conditions element" do
response.soft = true
assert response.send(:validate_one_conditions)
end
+
+ it "return true when no conditions are present and skip_conditions is true" do
+ response_no_conditions_with_skip.soft = true
+ assert response_no_conditions_with_skip.send(:validate_one_conditions)
+ end
end
describe "#check_one_authnstatement" do
it "return false when none or more than one authnstatement element" do
response_no_authnstatement.soft = true
@@ -968,9 +1013,15 @@
end
it "return true when one authnstatement element" do
response.soft = true
assert response.send(:validate_one_authnstatement)
+ end
+
+ it "return true when SAML Response is empty but skip_authstatement option is used" do
+ response_no_authnstatement_with_skip.soft = true
+ assert response_no_authnstatement_with_skip.send(:validate_one_authnstatement)
+ assert_empty response_empty_destination_with_skip.errors
end
end
describe "#check_conditions" do
it "check time conditions" do