Fake time for tests

new-scoring
aeris 2017-01-29 23:54:21 +01:00
parent 9abcc3365a
commit 550171862a
9 changed files with 105 additions and 11 deletions

View File

@ -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

2
bin/rspec 100755
View File

@ -0,0 +1,2 @@
#!/bin/bash
LD_PRELOAD=${PWD}/lib/libfaketime.so LD_LIBRARY_PATH=${PWD}/lib bundle exec rspec $@

View File

@ -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'

View File

@ -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 !

View File

@ -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

25
spec/faketime.rb 100644
View File

@ -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

View File

@ -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;
}
}

View File

@ -0,0 +1,2 @@
void freeze(unsigned long time);
void unfreeze();

Binary file not shown.