diff --git a/lib/win32/certstore.rb b/lib/win32/certstore.rb index 328d071..d530851 100644 --- a/lib/win32/certstore.rb +++ b/lib/win32/certstore.rb @@ -71,8 +71,8 @@ def search(certificate_name) end # Validate certificate from open certificate store and return boolean - def verify(certificate_name) - cert_verify(certstore_handler, certificate_name) + def valid_certificate?(certificate_thumbprint) + cert_validate(certificate_thumbprint) end # To close and destroy pointer of open certificate store handler diff --git a/lib/win32/certstore/mixin/helper.rb b/lib/win32/certstore/mixin/helper.rb index f2b0671..1bdac82 100644 --- a/lib/win32/certstore/mixin/helper.rb +++ b/lib/win32/certstore/mixin/helper.rb @@ -15,6 +15,8 @@ # See the License for the specific language governing permissions and # limitations under the License. +require 'date' + module Win32 class Certstore module Mixin @@ -38,11 +40,11 @@ def cert_ps_cmd(thumbprint) end # validate certificate not_before and not_after date in UTC - def valid_duration(cert_obj) + def valid_duration?(cert_obj) cert_obj.not_before < Time.now.utc && cert_obj.not_after > Time.now.utc end + end end end end - diff --git a/lib/win32/certstore/store_base.rb b/lib/win32/certstore/store_base.rb index cb192fa..c4766f7 100644 --- a/lib/win32/certstore/store_base.rb +++ b/lib/win32/certstore/store_base.rb @@ -102,7 +102,7 @@ def cert_delete(store_handler, certificate_thumbprint) # Verify certificate from open certificate store and return boolean or exceptions # store_handler => Open certificate store handler # certificate_thumbprint => thumbprint is a hash. which could be sha1 or md5. - def cert_verify(store_handler, certificate_thumbprint) + def cert_validate(certificate_thumbprint) validate_thumbprint(certificate_thumbprint) thumbprint = update_thumbprint(certificate_thumbprint) cert_pem = get_cert_pem(thumbprint) @@ -127,6 +127,12 @@ def update_thumbprint(certificate_thumbprint) certificate_thumbprint.gsub(/[^A-Za-z0-9]/, '') end + # Verify OpenSSL::X509::Certificate object + def verify_certificate(cert_pem) + return "Certificate not found" if cert_pem.empty? + valid_duration?(build_openssl_obj(cert_pem)) + end + # Convert OpenSSL::X509::Certificate object in .der formate def der_cert(cert_obj) FFI::MemoryPointer.from_string(cert_obj.to_der) @@ -138,12 +144,6 @@ def get_cert_pem(thumbprint) get_data.stdout end - # Verify OpenSSL::X509::Certificate object - def verify_certificate(cert_pem) - return "Certificate not found" if cert_pem.empty? - valid_duration(build_openssl_obj(cert_pem)) - end - # Format pem def format_pem(cert_pem) cert_pem.delete("\r") diff --git a/spec/win32/unit/certstore_spec.rb b/spec/win32/unit/certstore_spec.rb index ed533a8..8d6d8d0 100644 --- a/spec/win32/unit/certstore_spec.rb +++ b/spec/win32/unit/certstore_spec.rb @@ -128,7 +128,7 @@ let (:store_name) { "root" } let (:thumbprint) { "b1bc968bd4f49d622aa89a81f2150152a41d829c" } before(:each) do - allow_any_instance_of(certbase).to receive(:get_cert_pem).and_return([]) + allow_any_instance_of(certbase).to receive(:get_cert_pem).and_return("") end it "returns nil" do store = certstore.open(store_name) @@ -142,7 +142,7 @@ let (:thumbprint) { "b1bc968bd4f49d622aa89a81f2150152a41d829909c" } let (:cert_pem) { File.read('.\spec\win32\unit\assets\GlobalSignRootCA.pem') } before(:each) do - allow_any_instance_of(certbase).to receive(:get_cert_pem).and_return([cert_pem]) + allow_any_instance_of(certbase).to receive(:get_cert_pem).and_return(cert_pem) end it "returns OpenSSL::X509::Certificate Object" do store = certstore.open(store_name) @@ -158,7 +158,7 @@ let (:thumbprint) { "b1 bc 96 8b d4 f4 9d 62 2a a8 9a 81 f2 15 01 52 a4 1d 82 9c" } let (:cert_pem) { File.read('.\spec\win32\unit\assets\GlobalSignRootCA.pem') } before(:each) do - allow_any_instance_of(certbase).to receive(:get_cert_pem).and_return([cert_pem]) + allow_any_instance_of(certbase).to receive(:get_cert_pem).and_return(cert_pem) end it "returns OpenSSL::X509::Certificate Object" do store = certstore.open(store_name) @@ -174,7 +174,7 @@ let (:thumbprint) { "b1:bc:96:8b:d4:f4:9d:62:2a:a8:9a:81:f2:15:01:52:a4:1d:82:9c" } let (:cert_pem) { File.read('.\spec\win32\unit\assets\GlobalSignRootCA.pem') } before(:each) do - allow_any_instance_of(certbase).to receive(:get_cert_pem).and_return([cert_pem]) + allow_any_instance_of(certbase).to receive(:get_cert_pem).and_return(cert_pem) end it "returns OpenSSL::X509::Certificate Object" do store = certstore.open(store_name) @@ -186,7 +186,7 @@ end end - describe "#cert_verify" do + describe "#cert_validate" do context "When passing empty certificate store name" do let (:store_name) { "" } it "raises ArgumentError" do @@ -199,7 +199,7 @@ let (:thumbprint) { " " } it "raises ArgumentError" do store = certstore.open(store_name) - expect { store.verify(thumbprint) }.to raise_error(ArgumentError, "Invalid certificate thumbprint.") + expect { store.valid_certificate?(thumbprint) }.to raise_error(ArgumentError, "Invalid certificate thumbprint.") end end @@ -208,7 +208,7 @@ let (:thumbprint) { nil } it "raises ArgumentError" do store = certstore.open(store_name) - expect { store.verify(thumbprint) }.to raise_error(ArgumentError, "Invalid certificate thumbprint.") + expect { store.valid_certificate?(thumbprint) }.to raise_error(ArgumentError, "Invalid certificate thumbprint.") end end @@ -216,54 +216,50 @@ let (:store_name) { "root" } let (:thumbprint) { "b1bc968bd4f49d622aa89a81f2150152a41d829c" } before(:each) do - allow_any_instance_of(certbase).to receive(:get_cert_pem).and_return([]) + allow_any_instance_of(certbase).to receive(:get_cert_pem).and_return("") end it "returns Certificate not found" do store = certstore.open(store_name) - cert_obj = store.verify(thumbprint) - expect(cert_obj).to eql("Certificate not found") + expect(store.valid_certificate?(thumbprint)).to eql("Certificate not found") end end - context "When passing valid thumbprint" do + context "When passing valid certificate's thumbprint" do let (:store_name) { "root" } let (:thumbprint) { "b1bc968bd4f49d622aa89a81f2150152a41d829909c" } let (:cert_pem) { File.read('.\spec\win32\unit\assets\GlobalSignRootCA.pem') } before(:each) do - allow_any_instance_of(certbase).to receive(:get_cert_pem).and_return([cert_pem]) + allow_any_instance_of(certbase).to receive(:get_cert_pem).and_return(cert_pem) end - it "returns OpenSSL::X509::Certificate Object" do + it "returns true" do store = certstore.open(store_name) - cert_obj = store.verify(thumbprint) - expect(cert_obj).to eql(true) + expect(store.valid_certificate?(thumbprint)).to eql(true) end end - context "When passing valid thumbprint with spaces" do + context "When passing valid certificate's thumbprint with spaces" do let (:store_name) { "root" } let (:thumbprint) { "b1 bc 96 8b d4 f4 9d 62 2a a8 9a 81 f2 15 01 52 a4 1d 82 9c" } let (:cert_pem) { File.read('.\spec\win32\unit\assets\GlobalSignRootCA.pem') } before(:each) do - allow_any_instance_of(certbase).to receive(:get_cert_pem).and_return([cert_pem]) + allow_any_instance_of(certbase).to receive(:get_cert_pem).and_return(cert_pem) end - it "returns OpenSSL::X509::Certificate Object" do + it "returns true" do store = certstore.open(store_name) - cert_obj = store.verify(thumbprint) - expect(cert_obj).to eql(true) + expect(store.valid_certificate?(thumbprint)).to eql(true) end end - context "When passing valid thumbprint with :" do + context "When passing valid certificate's thumbprint with :" do let (:store_name) { "root" } let (:thumbprint) { "b1:bc:96:8b:d4:f4:9d:62:2a:a8:9a:81:f2:15:01:52:a4:1d:82:9c" } let (:cert_pem) { File.read('.\spec\win32\unit\assets\GlobalSignRootCA.pem') } before(:each) do - allow_any_instance_of(certbase).to receive(:get_cert_pem).and_return([cert_pem]) + allow_any_instance_of(certbase).to receive(:get_cert_pem).and_return(cert_pem) end - it "returns OpenSSL::X509::Certificate Object" do + it "returns true" do store = certstore.open(store_name) - cert_obj = store.verify(thumbprint) - expect(cert_obj).to eql(true) + expect(store.valid_certificate?(thumbprint)).to eql(true) end end end