Browse Source

Fake time for tests

new-scoring
aeris 2 years ago
parent
commit
550171862a

+ 9
- 0
Makefile View File

@@ -100,5 +100,14 @@ lib/openssl.so: $(RUBY_OPENSSL_EXT_DIR)/openssl.so
100 100
 
101 101
 ext: lib/openssl.so
102 102
 
103
+spec/faketime/libfaketime.so: spec/faketime/faketime.c spec/faketime/faketime.h
104
+	$(CC) -shared -fPIC $^ -o $@ -ldl -std=c99 -Werror -Wall
105
+lib/libfaketime.so: spec/faketime/libfaketime.so
106
+	ln -fs ../$< $@
107
+faketime: lib/libfaketime.so
108
+
103 109
 test-material:
104 110
 	bin/generate-test-material.rb
111
+
112
+test: spec/faketime/libfaketime.so
113
+	bin/rspec

+ 2
- 0
bin/rspec View File

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

+ 1
- 0
cryptcheck.gemspec View File

@@ -29,6 +29,7 @@ Gem::Specification.new do |spec|
29 29
 	spec.add_development_dependency 'bundler', '~> 1.9', '>= 1.9.8'
30 30
 	spec.add_development_dependency 'rake', '~> 11.2', '>= 11.2.2'
31 31
 	spec.add_development_dependency 'rspec', '~> 3.2', '>= 3.2.0'
32
+	spec.add_development_dependency 'ffi', '~> 1.9', '>= 1.9.17'
32 33
 	spec.add_development_dependency 'awesome_print', '~> 1.7.0', '>= 1.7.0'
33 34
 
34 35
 	spec.add_dependency 'httparty', '~> 0.13', '>= 0.13.3'

+ 1
- 1
lib/cryptcheck/tls/cert.rb View File

@@ -65,7 +65,7 @@ module CryptCheck
65 65
 
66 66
 			def self.trusted?(cert, chain, roots: DEFAULT_CA_DIRECTORIES)
67 67
 				store         = ::OpenSSL::X509::Store.new
68
-				store.purpose = ::OpenSSL::X509::PURPOSE_SSL_CLIENT
68
+				store.purpose = ::OpenSSL::X509::PURPOSE_SSL_SERVER
69 69
 				store.add_chains roots
70 70
 				chain.each do |cert|
71 71
 					# Never add other self signed certificates than system CA !

+ 30
- 10
spec/cryptcheck/cert_spec.rb View File

@@ -1,32 +1,52 @@
1
+require 'faketime'
2
+
1 3
 describe CryptCheck::Tls::Cert do
2 4
 	def load_chain(chain)
3
-		chain.collect { |f| ::OpenSSL::X509::Certificate.new File.read File.join 'spec/resources', "#{f}.crt" }
5
+		chain.collect { |f| ::OpenSSL::X509::Certificate.new File.read "spec/resources/#{f}.crt" }
4 6
 	end
5 7
 
6 8
 	describe '::trusted?' do
7
-		it 'must accept valid certificat' do
8
-			cert, *chain, ca = load_chain %w(custom intermediate ca)
9
-			trust                  = ::CryptCheck::Tls::Cert.trusted? cert, chain, roots: ca
10
-			expect(trust).to eq :trusted
9
+		it 'must accept valid certificate' do
10
+			FakeTime.freeze_during Time.utc(2000, 1, 1) do
11
+				cert, *chain, ca = load_chain %w(ecdsa-prime256v1 intermediate ca)
12
+				trust            = ::CryptCheck::Tls::Cert.trusted? cert, chain, roots: ca
13
+				expect(trust).to eq :trusted
14
+			end
11 15
 		end
12 16
 
13 17
 		it 'must reject self signed certificate' do
14 18
 			cert, ca = load_chain %w(self-signed ca)
15
-			trust                  = ::CryptCheck::Tls::Cert.trusted? cert, [], roots: ca
19
+			trust    = ::CryptCheck::Tls::Cert.trusted? cert, [], roots: ca
16 20
 			expect(trust).to eq 'self signed certificate'
17 21
 		end
18 22
 
19 23
 		it 'must reject unknown CA' do
20
-			cert, *chain = load_chain %w(custom intermediate ca)
24
+			cert, *chain = load_chain %w(ecdsa-prime256v1 intermediate ca)
21 25
 			trust        = ::CryptCheck::Tls::Cert.trusted? cert, chain, roots: []
22 26
 			expect(trust).to eq 'unable to get issuer certificate'
23 27
 		end
24 28
 
25 29
 		it 'must reject missing intermediate chain' do
26
-			cert, ca = load_chain %w(custom ca)
27
-			chain   = []
28
-			trust   = ::CryptCheck::Tls::Cert.trusted? cert, chain, roots: ca
30
+			cert, ca = load_chain %w(ecdsa-prime256v1 ca)
31
+			chain    = []
32
+			trust    = ::CryptCheck::Tls::Cert.trusted? cert, chain, roots: ca
29 33
 			expect(trust).to eq 'unable to get local issuer certificate'
30 34
 		end
35
+
36
+		it 'must reject expired certificate' do
37
+			FakeTime.freeze_during Time.utc(2002, 1, 1) do
38
+				cert, *chain, ca = load_chain %w(ecdsa-prime256v1 intermediate ca)
39
+				trust            = ::CryptCheck::Tls::Cert.trusted? cert, chain, roots: ca
40
+				expect(trust).to eq 'certificate has expired'
41
+			end
42
+		end
43
+
44
+		it 'must reject not yet valid certificate' do
45
+			FakeTime.freeze_during Time.utc(1999, 1, 1) do
46
+				cert, *chain, ca = load_chain %w(ecdsa-prime256v1 intermediate ca)
47
+				trust            = ::CryptCheck::Tls::Cert.trusted? cert, chain, roots: ca
48
+				expect(trust).to eq 'certificate is not yet valid'
49
+			end
50
+		end
31 51
 	end
32 52
 end

+ 25
- 0
spec/faketime.rb View File

@@ -0,0 +1,25 @@
1
+require 'ffi'
2
+
3
+module FakeTime
4
+	extend FFI::Library
5
+	ffi_lib 'faketime'
6
+
7
+	def self.freeze(_)
8
+		#This is a stub, used for indexing
9
+	end
10
+	def self.unfreeze
11
+		#This is a stub, used for indexing
12
+	end
13
+
14
+	attach_function :freeze, [:ulong], :void
15
+	attach_function :unfreeze, [], :void
16
+
17
+	def self.freeze_during(time, &block)
18
+		self.freeze time.to_i
19
+		begin
20
+			return block.call
21
+		ensure
22
+			self.unfreeze
23
+		end
24
+	end
25
+end

+ 35
- 0
spec/faketime/faketime.c View File

@@ -0,0 +1,35 @@
1
+#define _GNU_SOURCE
2
+#include <dlfcn.h>
3
+#include "time.h"
4
+#include "faketime.h"
5
+
6
+char frozen = 0;
7
+time_t frozen_time = 0;
8
+
9
+typedef time_t (*orig_time_f_type)(time_t*);
10
+orig_time_f_type orig_time = NULL;
11
+
12
+void freeze(unsigned long time) {
13
+	frozen_time = (time_t)time;
14
+	frozen = 1;
15
+}
16
+
17
+void unfreeze() {
18
+	frozen = 0;
19
+}
20
+
21
+time_t time(time_t *arg) {
22
+	if (orig_time == NULL) {
23
+		orig_time = (orig_time_f_type) dlsym(RTLD_NEXT, "time");
24
+	}
25
+
26
+	if (frozen) {
27
+		if (arg) {
28
+			*arg = frozen_time;
29
+		}
30
+		return frozen_time;
31
+	} else {
32
+		time_t time = orig_time(arg);
33
+		return time;
34
+	}
35
+}

+ 2
- 0
spec/faketime/faketime.h View File

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

BIN
spec/faketime/libfaketime.so View File


Loading…
Cancel
Save