Commit a5952bc

mo <mo.khan@gmail.com>
2018-02-15 18:03:13
add specs for certificate verification.
1 parent 0fa1190
Changed files (3)
lib
saml
spec
lib/saml/kit/locales/en.yml
@@ -28,6 +28,7 @@ en:
         unregistered: "must originate from registered identity provider."
       Signature:
         digest_value: "is invalid."
+        empty: "is missing."
       SPSSODescriptor:
         invalid: "must contain SPSSODescriptor."
         invalid_signature: "invalid signature."
lib/saml/kit/signature.rb
@@ -9,24 +9,25 @@ module Saml
 
       attr_reader :name
 
-      def initialize(xml_hash)
+      def initialize(item)
         @name = "Signature"
-        if xml_hash.is_a?(Hash)
-          @xml_hash = xml_hash
+        if item.is_a?(Hash)
+          @xml_hash = item
         else
-          @document = xml_hash
+          @node = item
         end
       end
 
       # Returns the embedded X509 Certificate
       def certificate
-        if @document
-          item = @document.at_xpath("//ds:KeyInfo/ds:X509Data/ds:X509Certificate", "ds": ::Xml::Kit::Namespaces::XMLDSIG)
-          ::Xml::Kit::Certificate.new(item.text, use: :signing)
-        else
+        if @xml_hash
           value = to_h.fetch('KeyInfo', {}).fetch('X509Data', {}).fetch('X509Certificate', nil)
           return if value.nil?
           ::Xml::Kit::Certificate.new(value, use: :signing)
+        else
+          return if @node.nil?
+          item = @node.at_xpath("//ds:KeyInfo/ds:X509Data/ds:X509Certificate", "ds": ::Xml::Kit::Namespaces::XMLDSIG)
+          ::Xml::Kit::Certificate.new(item.text, use: :signing)
         end
       end
 
@@ -44,9 +45,9 @@ module Saml
       private
 
       def validate_signature
-        return errors[:base].push("is missing") if certificate.nil?
+        return errors[:base].push(error_message(:empty)) if certificate.nil?
 
-        signature = Xmldsig::Signature.new(@document, 'ID=$uri or @Id')
+        signature = Xmldsig::Signature.new(@node, 'ID=$uri or @Id')
         unless signature.valid?(certificate.x509)
           signature.errors.each do |attribute|
             errors.add(attribute, error_message(attribute))
spec/saml/signature_spec.rb
@@ -19,10 +19,46 @@ RSpec.describe Saml::Kit::Signature do
     end
 
     it 'is invalid when the signature is missing' do
-      unsigned_document = Saml::Kit::AuthenticationRequest.build
-      subject = described_class.new(Hash.from_xml(unsigned_document.to_xml))
+      subject = described_class.new(nil)
       expect(subject).to_not be_valid
-      expect(subject.errors[:base]).to be_present
+      expect(subject.errors[:base]).to match_array(['is missing.'])
+    end
+
+    describe "certificate validation" do
+      let(:key_pair) { ::Xml::Kit::KeyPair.new(expired_certificate, private_key, nil, :signing) }
+      let(:private_key) { OpenSSL::PKey::RSA.new(2048) }
+      let(:expired_certificate) do
+        certificate = OpenSSL::X509::Certificate.new
+        certificate.not_before = not_before
+        certificate.not_after = not_after
+        certificate.public_key = private_key.public_key
+        certificate.sign(private_key, OpenSSL::Digest::SHA256.new)
+        certificate
+      end
+
+      context "when the certificate is expired" do
+        let(:not_before) { 10.minutes.ago }
+        let(:not_after) { 1.minute.ago }
+
+        it 'is invalid' do
+          expect(subject).to be_invalid
+          expect(subject.errors[:certificate]).to match_array([
+            "Not valid before #{expired_certificate.not_before}. Not valid after #{expired_certificate.not_after}."
+          ])
+        end
+      end
+
+      context "when the certificate is not active yet" do
+        let(:not_before) { 10.minutes.from_now }
+        let(:not_after) { 20.minute.from_now }
+
+        it 'it invalid' do
+          expect(subject).to be_invalid
+          expect(subject.errors[:certificate]).to match_array([
+            "Not valid before #{expired_certificate.not_before}. Not valid after #{expired_certificate.not_after}."
+          ])
+        end
+      end
     end
   end
 end