Fake time for tests
parent
9abcc3365a
commit
550171862a
9
Makefile
9
Makefile
|
@ -100,5 +100,14 @@ lib/openssl.so: $(RUBY_OPENSSL_EXT_DIR)/openssl.so
|
|||
|
||||
ext: lib/openssl.so
|
||||
|
||||
spec/faketime/libfaketime.so: spec/faketime/faketime.c spec/faketime/faketime.h
|
||||
$(CC) -shared -fPIC $^ -o $@ -ldl -std=c99 -Werror -Wall
|
||||
lib/libfaketime.so: spec/faketime/libfaketime.so
|
||||
ln -fs ../$< $@
|
||||
faketime: lib/libfaketime.so
|
||||
|
||||
test-material:
|
||||
bin/generate-test-material.rb
|
||||
|
||||
test: spec/faketime/libfaketime.so
|
||||
bin/rspec
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
#!/bin/bash
|
||||
LD_PRELOAD=${PWD}/lib/libfaketime.so LD_LIBRARY_PATH=${PWD}/lib bundle exec rspec $@
|
|
@ -29,6 +29,7 @@ Gem::Specification.new do |spec|
|
|||
spec.add_development_dependency 'bundler', '~> 1.9', '>= 1.9.8'
|
||||
spec.add_development_dependency 'rake', '~> 11.2', '>= 11.2.2'
|
||||
spec.add_development_dependency 'rspec', '~> 3.2', '>= 3.2.0'
|
||||
spec.add_development_dependency 'ffi', '~> 1.9', '>= 1.9.17'
|
||||
spec.add_development_dependency 'awesome_print', '~> 1.7.0', '>= 1.7.0'
|
||||
|
||||
spec.add_dependency 'httparty', '~> 0.13', '>= 0.13.3'
|
||||
|
|
|
@ -65,7 +65,7 @@ module CryptCheck
|
|||
|
||||
def self.trusted?(cert, chain, roots: DEFAULT_CA_DIRECTORIES)
|
||||
store = ::OpenSSL::X509::Store.new
|
||||
store.purpose = ::OpenSSL::X509::PURPOSE_SSL_CLIENT
|
||||
store.purpose = ::OpenSSL::X509::PURPOSE_SSL_SERVER
|
||||
store.add_chains roots
|
||||
chain.each do |cert|
|
||||
# Never add other self signed certificates than system CA !
|
||||
|
|
|
@ -1,32 +1,52 @@
|
|||
require 'faketime'
|
||||
|
||||
describe CryptCheck::Tls::Cert do
|
||||
def load_chain(chain)
|
||||
chain.collect { |f| ::OpenSSL::X509::Certificate.new File.read File.join 'spec/resources', "#{f}.crt" }
|
||||
chain.collect { |f| ::OpenSSL::X509::Certificate.new File.read "spec/resources/#{f}.crt" }
|
||||
end
|
||||
|
||||
describe '::trusted?' do
|
||||
it 'must accept valid certificat' do
|
||||
cert, *chain, ca = load_chain %w(custom intermediate ca)
|
||||
trust = ::CryptCheck::Tls::Cert.trusted? cert, chain, roots: ca
|
||||
expect(trust).to eq :trusted
|
||||
it 'must accept valid certificate' do
|
||||
FakeTime.freeze_during Time.utc(2000, 1, 1) do
|
||||
cert, *chain, ca = load_chain %w(ecdsa-prime256v1 intermediate ca)
|
||||
trust = ::CryptCheck::Tls::Cert.trusted? cert, chain, roots: ca
|
||||
expect(trust).to eq :trusted
|
||||
end
|
||||
end
|
||||
|
||||
it 'must reject self signed certificate' do
|
||||
cert, ca = load_chain %w(self-signed ca)
|
||||
trust = ::CryptCheck::Tls::Cert.trusted? cert, [], roots: ca
|
||||
trust = ::CryptCheck::Tls::Cert.trusted? cert, [], roots: ca
|
||||
expect(trust).to eq 'self signed certificate'
|
||||
end
|
||||
|
||||
it 'must reject unknown CA' do
|
||||
cert, *chain = load_chain %w(custom intermediate ca)
|
||||
cert, *chain = load_chain %w(ecdsa-prime256v1 intermediate ca)
|
||||
trust = ::CryptCheck::Tls::Cert.trusted? cert, chain, roots: []
|
||||
expect(trust).to eq 'unable to get issuer certificate'
|
||||
end
|
||||
|
||||
it 'must reject missing intermediate chain' do
|
||||
cert, ca = load_chain %w(custom ca)
|
||||
chain = []
|
||||
trust = ::CryptCheck::Tls::Cert.trusted? cert, chain, roots: ca
|
||||
cert, ca = load_chain %w(ecdsa-prime256v1 ca)
|
||||
chain = []
|
||||
trust = ::CryptCheck::Tls::Cert.trusted? cert, chain, roots: ca
|
||||
expect(trust).to eq 'unable to get local issuer certificate'
|
||||
end
|
||||
|
||||
it 'must reject expired certificate' do
|
||||
FakeTime.freeze_during Time.utc(2002, 1, 1) do
|
||||
cert, *chain, ca = load_chain %w(ecdsa-prime256v1 intermediate ca)
|
||||
trust = ::CryptCheck::Tls::Cert.trusted? cert, chain, roots: ca
|
||||
expect(trust).to eq 'certificate has expired'
|
||||
end
|
||||
end
|
||||
|
||||
it 'must reject not yet valid certificate' do
|
||||
FakeTime.freeze_during Time.utc(1999, 1, 1) do
|
||||
cert, *chain, ca = load_chain %w(ecdsa-prime256v1 intermediate ca)
|
||||
trust = ::CryptCheck::Tls::Cert.trusted? cert, chain, roots: ca
|
||||
expect(trust).to eq 'certificate is not yet valid'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
require 'ffi'
|
||||
|
||||
module FakeTime
|
||||
extend FFI::Library
|
||||
ffi_lib 'faketime'
|
||||
|
||||
def self.freeze(_)
|
||||
#This is a stub, used for indexing
|
||||
end
|
||||
def self.unfreeze
|
||||
#This is a stub, used for indexing
|
||||
end
|
||||
|
||||
attach_function :freeze, [:ulong], :void
|
||||
attach_function :unfreeze, [], :void
|
||||
|
||||
def self.freeze_during(time, &block)
|
||||
self.freeze time.to_i
|
||||
begin
|
||||
return block.call
|
||||
ensure
|
||||
self.unfreeze
|
||||
end
|
||||
end
|
||||
end
|
|
@ -0,0 +1,35 @@
|
|||
#define _GNU_SOURCE
|
||||
#include <dlfcn.h>
|
||||
#include "time.h"
|
||||
#include "faketime.h"
|
||||
|
||||
char frozen = 0;
|
||||
time_t frozen_time = 0;
|
||||
|
||||
typedef time_t (*orig_time_f_type)(time_t*);
|
||||
orig_time_f_type orig_time = NULL;
|
||||
|
||||
void freeze(unsigned long time) {
|
||||
frozen_time = (time_t)time;
|
||||
frozen = 1;
|
||||
}
|
||||
|
||||
void unfreeze() {
|
||||
frozen = 0;
|
||||
}
|
||||
|
||||
time_t time(time_t *arg) {
|
||||
if (orig_time == NULL) {
|
||||
orig_time = (orig_time_f_type) dlsym(RTLD_NEXT, "time");
|
||||
}
|
||||
|
||||
if (frozen) {
|
||||
if (arg) {
|
||||
*arg = frozen_time;
|
||||
}
|
||||
return frozen_time;
|
||||
} else {
|
||||
time_t time = orig_time(arg);
|
||||
return time;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,2 @@
|
|||
void freeze(unsigned long time);
|
||||
void unfreeze();
|
Binary file not shown.
Loading…
Reference in New Issue