tlspretense 0.6.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +6 -0
- data/.gitignore +7 -0
- data/.rspec +1 -0
- data/Gemfile +2 -0
- data/Gemfile.lock +41 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +231 -0
- data/Rakefile +44 -0
- data/bin/makeder.sh +6 -0
- data/bin/tlspretense +7 -0
- data/bin/view.sh +3 -0
- data/doc/general_setup.rdoc +288 -0
- data/doc/linux_setup.rdoc +64 -0
- data/lib/certmaker.rb +61 -0
- data/lib/certmaker/certificate_factory.rb +106 -0
- data/lib/certmaker/certificate_suite_generator.rb +120 -0
- data/lib/certmaker/ext_core/hash_indifferent_fetch.rb +12 -0
- data/lib/certmaker/runner.rb +27 -0
- data/lib/certmaker/tasks.rb +20 -0
- data/lib/packetthief.rb +167 -0
- data/lib/packetthief/handlers.rb +14 -0
- data/lib/packetthief/handlers/abstract_ssl_handler.rb +249 -0
- data/lib/packetthief/handlers/proxy_redirector.rb +26 -0
- data/lib/packetthief/handlers/ssl_client.rb +87 -0
- data/lib/packetthief/handlers/ssl_server.rb +174 -0
- data/lib/packetthief/handlers/ssl_smart_proxy.rb +143 -0
- data/lib/packetthief/handlers/ssl_transparent_proxy.rb +225 -0
- data/lib/packetthief/handlers/transparent_proxy.rb +183 -0
- data/lib/packetthief/impl.rb +11 -0
- data/lib/packetthief/impl/ipfw.rb +140 -0
- data/lib/packetthief/impl/manual.rb +54 -0
- data/lib/packetthief/impl/netfilter.rb +109 -0
- data/lib/packetthief/impl/pf_divert.rb +168 -0
- data/lib/packetthief/impl/pf_rdr.rb +192 -0
- data/lib/packetthief/logging.rb +49 -0
- data/lib/packetthief/redirect_rule.rb +29 -0
- data/lib/packetthief/util.rb +36 -0
- data/lib/ssl_test.rb +21 -0
- data/lib/ssl_test/app_context.rb +17 -0
- data/lib/ssl_test/certificate_manager.rb +33 -0
- data/lib/ssl_test/config.rb +79 -0
- data/lib/ssl_test/ext_core/io_raw_input.rb +31 -0
- data/lib/ssl_test/input_handler.rb +35 -0
- data/lib/ssl_test/runner.rb +110 -0
- data/lib/ssl_test/runner_options.rb +68 -0
- data/lib/ssl_test/ssl_test_case.rb +46 -0
- data/lib/ssl_test/ssl_test_report.rb +24 -0
- data/lib/ssl_test/ssl_test_result.rb +30 -0
- data/lib/ssl_test/test_listener.rb +140 -0
- data/lib/ssl_test/test_manager.rb +116 -0
- data/lib/tlspretense.rb +13 -0
- data/lib/tlspretense/app.rb +52 -0
- data/lib/tlspretense/init_runner.rb +115 -0
- data/lib/tlspretense/skel/ca/goodcacert.pem +19 -0
- data/lib/tlspretense/skel/ca/goodcakey.pem +27 -0
- data/lib/tlspretense/skel/config.yml +523 -0
- data/lib/tlspretense/version.rb +3 -0
- data/packetthief_examples/em_ssl_test.rb +73 -0
- data/packetthief_examples/redirector.rb +29 -0
- data/packetthief_examples/setup_iptables.sh +24 -0
- data/packetthief_examples/ssl_client_simple.rb +27 -0
- data/packetthief_examples/ssl_server_simple.rb +44 -0
- data/packetthief_examples/ssl_smart_proxy.rb +115 -0
- data/packetthief_examples/ssl_transparent_proxy.rb +97 -0
- data/packetthief_examples/transparent_proxy.rb +56 -0
- data/spec/packetthief/impl/ipfw_spec.rb +98 -0
- data/spec/packetthief/impl/manual_spec.rb +65 -0
- data/spec/packetthief/impl/netfilter_spec.rb +66 -0
- data/spec/packetthief/impl/pf_divert_spec.rb +82 -0
- data/spec/packetthief/impl/pf_rdr_spec.rb +133 -0
- data/spec/packetthief/logging_spec.rb +78 -0
- data/spec/packetthief_spec.rb +47 -0
- data/spec/spec_helper.rb +53 -0
- data/spec/ssl_test/certificate_manager_spec.rb +222 -0
- data/spec/ssl_test/config_spec.rb +76 -0
- data/spec/ssl_test/runner_spec.rb +360 -0
- data/spec/ssl_test/ssl_test_case_spec.rb +113 -0
- data/spec/ssl_test/test_listener_spec.rb +199 -0
- data/spec/ssl_test/test_manager_spec.rb +324 -0
- data/tlspretense.gemspec +35 -0
- metadata +262 -0
@@ -0,0 +1,116 @@
|
|
1
|
+
module SSLTest
|
2
|
+
# Tracks testing state and handles reporting for the TestListener.
|
3
|
+
class TestManager
|
4
|
+
include PacketThief::Logging
|
5
|
+
|
6
|
+
attr_accessor :current_test
|
7
|
+
attr_reader :remaining_tests
|
8
|
+
|
9
|
+
attr_accessor :listener
|
10
|
+
|
11
|
+
attr_accessor :goodcacert
|
12
|
+
attr_accessor :goodcakey
|
13
|
+
|
14
|
+
def initialize(context, testlist, report, logger=nil)
|
15
|
+
@appctx = context
|
16
|
+
@testlist = testlist
|
17
|
+
@report = report
|
18
|
+
@logger = logger
|
19
|
+
@remaining_tests = @testlist.dup
|
20
|
+
|
21
|
+
@goodcacert = @appctx.cert_manager.get_cert("goodca")
|
22
|
+
@goodcakey = @appctx.cert_manager.get_key("goodca")
|
23
|
+
|
24
|
+
@pause = false
|
25
|
+
prepare_next_test(true)
|
26
|
+
end
|
27
|
+
|
28
|
+
# grabs the next test. Returns it, or nil if we are out of tests.
|
29
|
+
def prepare_next_test(first=false)
|
30
|
+
@current_test = @remaining_tests.shift
|
31
|
+
|
32
|
+
if current_test == nil
|
33
|
+
stop_testing
|
34
|
+
elsif @appctx.config.pause? and not first
|
35
|
+
pause
|
36
|
+
else
|
37
|
+
loginfo "Starting test: #{current_test.id}"
|
38
|
+
end
|
39
|
+
|
40
|
+
@start_time = Time.now
|
41
|
+
end
|
42
|
+
|
43
|
+
# Called when a test completes or is skipped. It adds an SSLTestResult to
|
44
|
+
# the report, and it cleans up after itself.
|
45
|
+
#
|
46
|
+
# :connected, :rejected, :sentdata
|
47
|
+
def test_completed(test, actual_result)
|
48
|
+
logdebug "test_completed", :actual_result => actual_result, :expected_result => test.expected_result, :test => test.id
|
49
|
+
return if actual_result == :running
|
50
|
+
|
51
|
+
passed = if @appctx.config.testing_method == 'tlshandshake'
|
52
|
+
case test.expected_result.to_s
|
53
|
+
when 'connected', :connected
|
54
|
+
%w{connected sentdata}.include? actual_result.to_s
|
55
|
+
when 'rejected', :rejected
|
56
|
+
actual_result == :rejected
|
57
|
+
else
|
58
|
+
raise "Unknown expected_result: #{test.expected_result}"
|
59
|
+
end
|
60
|
+
else # senddata, which requires data to be sent for it to pass.
|
61
|
+
case test.expected_result
|
62
|
+
when 'connected'
|
63
|
+
actual_result == :sentdata
|
64
|
+
when 'rejected'
|
65
|
+
%w{rejected connected}.include? actual_result.to_s
|
66
|
+
else
|
67
|
+
raise "Unknown expected_result: #{test.expected_result}"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
str = SSLTestResult.new(test.id, passed)
|
72
|
+
str.description = test.description
|
73
|
+
str.expected_result = test.expected_result
|
74
|
+
str.actual_result = actual_result.to_s
|
75
|
+
str.start_time = @start_time
|
76
|
+
str.stop_time = Time.now
|
77
|
+
|
78
|
+
@report.add_result(str)
|
79
|
+
|
80
|
+
if actual_result == :skipped
|
81
|
+
loginfo "#{test.id}: Skipping test"
|
82
|
+
else
|
83
|
+
loginfo "#{test.id}: Finished test"
|
84
|
+
end
|
85
|
+
|
86
|
+
prepare_next_test if current_test == test
|
87
|
+
end
|
88
|
+
|
89
|
+
def stop_testing
|
90
|
+
loginfo "Stopping"
|
91
|
+
@listener.stop_server if @listener
|
92
|
+
EM.stop_event_loop
|
93
|
+
end
|
94
|
+
|
95
|
+
def paused?
|
96
|
+
@pause
|
97
|
+
end
|
98
|
+
|
99
|
+
def pause
|
100
|
+
@pause = true
|
101
|
+
loginfo "Press Enter to continue."
|
102
|
+
end
|
103
|
+
|
104
|
+
def unpause
|
105
|
+
if paused?
|
106
|
+
loginfo "Starting test: #{current_test.id}"
|
107
|
+
@pause = false
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
def testing_method
|
112
|
+
@appctx.config.testing_method
|
113
|
+
end
|
114
|
+
|
115
|
+
end
|
116
|
+
end
|
data/lib/tlspretense.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'fileutils'
|
2
|
+
|
3
|
+
require 'ssl_test'
|
4
|
+
require 'certmaker'
|
5
|
+
require 'certmaker/runner'
|
6
|
+
|
7
|
+
module TLSPretense
|
8
|
+
class CleanExitError < StandardError ; end
|
9
|
+
|
10
|
+
autoload :App, 'tlspretense/app'
|
11
|
+
autoload :InitRunner, 'tlspretense/init_runner'
|
12
|
+
autoload :VERSION, 'tlspretense/version'
|
13
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
module TLSPretense
|
2
|
+
class App
|
3
|
+
def initialize(args, stdin, stdout)
|
4
|
+
@args = args
|
5
|
+
@stdin = stdin
|
6
|
+
@stdout = stdout
|
7
|
+
@action_args = args.dup
|
8
|
+
@action = @action_args.shift
|
9
|
+
end
|
10
|
+
|
11
|
+
def usage
|
12
|
+
@stdout.puts <<-QUOTE
|
13
|
+
Usage: #{0} action arguments...
|
14
|
+
|
15
|
+
Actions:
|
16
|
+
init PATH Creates a new TLSPretense working directory. This includes
|
17
|
+
configuration files and test certificates.
|
18
|
+
run Run all or some of the test cases. Call `run -h` for more
|
19
|
+
information.
|
20
|
+
list, ls List all or some of the test cases (equivalent to `run -l`).
|
21
|
+
ca Checks for a ca, and generates it if needed.
|
22
|
+
certs (Re)generate a suite of test certificates.
|
23
|
+
cleancerts Remove the certs directory.
|
24
|
+
QUOTE
|
25
|
+
end
|
26
|
+
|
27
|
+
def run
|
28
|
+
begin
|
29
|
+
case @action
|
30
|
+
when 'init'
|
31
|
+
InitRunner.new(@action_args, @stdin, @stdout).run
|
32
|
+
when 'run'
|
33
|
+
SSLTest::Runner.new(@action_args, @stdin, @stdout).run
|
34
|
+
when 'list', 'ls'
|
35
|
+
SSLTest::Runner.new(['--list'] + @action_args, @stdin, @stdout).run
|
36
|
+
when 'ca'
|
37
|
+
CertMaker::Runner.new.ca
|
38
|
+
when 'certs'
|
39
|
+
CertMaker::Runner.new.certs
|
40
|
+
when 'cleancerts'
|
41
|
+
CertMaker::Runner.new.clean
|
42
|
+
else
|
43
|
+
usage
|
44
|
+
end
|
45
|
+
rescue CleanExitError => e
|
46
|
+
@stdout.puts ""
|
47
|
+
@stdout.puts "#{e.class}: #{e}"
|
48
|
+
exit 1
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
module TLSPretense
|
2
|
+
class InitRunner
|
3
|
+
include FileUtils
|
4
|
+
|
5
|
+
class InitError < CleanExitError ; end
|
6
|
+
|
7
|
+
def initialize(args, stdin, stdout)
|
8
|
+
@args = args
|
9
|
+
@stdin = stdin
|
10
|
+
@stdout = stdout
|
11
|
+
end
|
12
|
+
|
13
|
+
def run
|
14
|
+
if @args.length != 1
|
15
|
+
usage
|
16
|
+
return
|
17
|
+
end
|
18
|
+
path = @args[0]
|
19
|
+
check_environment
|
20
|
+
init_project(path)
|
21
|
+
end
|
22
|
+
|
23
|
+
def check_environment
|
24
|
+
@stdout.puts "Ruby and OpenSSL compatibility check..."
|
25
|
+
# Ruby check:
|
26
|
+
# TODO: detect non-MRI versions of Ruby such as jruby, ironruby
|
27
|
+
if ruby_version[:major] < 1 or ruby_version[:minor] < 9 or ruby_version[:patch] < 3
|
28
|
+
@stdout.puts <<-QUOTE.gsub(/^ /,'')
|
29
|
+
Warning: You are running TLSPretense on an unsupported version of Ruby:
|
30
|
+
|
31
|
+
RUBY_DESCRIPTION: #{RUBY_DESCRIPTION}
|
32
|
+
|
33
|
+
Use it at your own risk! TLSPretense was developed and tested on MRI Ruby
|
34
|
+
1.9.3. However, bug reports are welcome for Ruby 1.8.7 and later to try and
|
35
|
+
improve compatibility.
|
36
|
+
|
37
|
+
QUOTE
|
38
|
+
end
|
39
|
+
unless openssl_supports_sni?
|
40
|
+
@stdout.puts <<-QUOTE.gsub(/^ /,'')
|
41
|
+
|
42
|
+
Warning: Your version of Ruby and/or OpenSSL does not have the ability to set
|
43
|
+
the SNI hostname on outgoing SSL/TLS connections.
|
44
|
+
|
45
|
+
Testing might work fine, but if the client being tested sends the SNI TLS
|
46
|
+
extension to request the certificate for a certain hostname, TLSPretense will
|
47
|
+
be unable to request the correct certificate from the destination, which may
|
48
|
+
adversely affect testing.
|
49
|
+
|
50
|
+
QUOTE
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def ruby_version
|
55
|
+
@ruby_version ||= (
|
56
|
+
v = {}
|
57
|
+
m = /^(.+)\.(.+)\.(.+)$/.match(RUBY_VERSION)
|
58
|
+
v[:major] = m[1].to_i
|
59
|
+
v[:minor] = m[2].to_i
|
60
|
+
v[:patch] = m[3].to_i
|
61
|
+
v
|
62
|
+
)
|
63
|
+
end
|
64
|
+
|
65
|
+
def openssl_supports_sni?
|
66
|
+
OpenSSL::SSL::SSLSocket.public_instance_methods.include? :hostname=
|
67
|
+
end
|
68
|
+
|
69
|
+
def init_project(path)
|
70
|
+
@stdout.print "Creating #{path}... "
|
71
|
+
raise InitError, "#{path} already exists!" if File.exist? path
|
72
|
+
mkdir_p path
|
73
|
+
@stdout.puts "Done"
|
74
|
+
|
75
|
+
@stdout.puts "Populating #{path}... "
|
76
|
+
skeldir = File.join(File.dirname(__FILE__), 'skel')
|
77
|
+
@stdout.print ' ' ; cp_r Dir.glob(File.join(skeldir,'*')), path, :verbose => true
|
78
|
+
@stdout.puts "Done"
|
79
|
+
|
80
|
+
@stdout.puts <<-QUOTE.gsub(/^ /,'')
|
81
|
+
Finished!
|
82
|
+
|
83
|
+
Now cd to #{path} and edit config.yml to suit your needs.
|
84
|
+
|
85
|
+
If you have an existing CA certificate and key you would like to use, you
|
86
|
+
should copy the PEM encoded certificate to:
|
87
|
+
|
88
|
+
#{path}/ca/goodcacert.pem
|
89
|
+
|
90
|
+
And you should copy the PEM encoded private key to:
|
91
|
+
|
92
|
+
#{path}/ca/goodcakey.pem
|
93
|
+
|
94
|
+
Otherwise you can use the preinstalled CA certificate or delete the ca
|
95
|
+
directory and run:
|
96
|
+
|
97
|
+
tlspretense ca
|
98
|
+
|
99
|
+
to generate a new CA (which you will then need to install so that the software
|
100
|
+
you are testing will trust it).
|
101
|
+
|
102
|
+
Refer to the guides on http://isecpartners.github.com/tlspretense/ for more
|
103
|
+
information on configuring your host to run TLSPretense.
|
104
|
+
QUOTE
|
105
|
+
end
|
106
|
+
|
107
|
+
def usage
|
108
|
+
@stdout.puts <<-QUOTE.gsub(/^ /,'')
|
109
|
+
Usage: #{0} init PATH
|
110
|
+
|
111
|
+
Creates a new TLSPretense working directory at PATH.
|
112
|
+
QUOTE
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
-----BEGIN CERTIFICATE-----
|
2
|
+
MIIDJTCCAg2gAwIBAgIECy0y7TANBgkqhkiG9w0BAQUFADAiMQswCQYDVQQGEwJV
|
3
|
+
UzETMBEGA1UEAwwKVHJ1c3RlZCBDQTAeFw0xMjEwMDUyMjIwMjFaFw0xMzEwMDUy
|
4
|
+
MjIwMjFaMCIxCzAJBgNVBAYTAlVTMRMwEQYDVQQDDApUcnVzdGVkIENBMIIBIjAN
|
5
|
+
BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA6clG32L98j4S9CqddFeup+NyxZmd
|
6
|
+
SPuEqJpIJHPQn/oGDmqXg8qmDr+DayAKa2ZHVD0+p0ymBJ74kZlFg6apcE55WWet
|
7
|
+
VfE6L491zfAyIqgVET//OPmDd0pgiBo78NXgwVoThMZ/79/fa0BddV02xqqLNuD5
|
8
|
+
0lXYB918wEoN909y7kOtldcqSL0N8Ts0SHxXrT3zmh+t2Oz007khsq99W50VrYO+
|
9
|
+
qzmeUpf1lJopFwRkBpkw1JoXwUL36Kfzqp0KgjEcgdxJU2DsfDIIcqcZEkCFEU9x
|
10
|
+
dkaEq6pIAVT4Qegqb7oeLbMEyvRc253cMd5PkjITMa4DgbBeWrrm1QFm7wIDAQAB
|
11
|
+
o2MwYTAOBgNVHQ8BAf8EBAMCAgQwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU
|
12
|
+
DmhEoCTfJPfISxh9gBtZNVTDZikwHwYDVR0jBBgwFoAUDmhEoCTfJPfISxh9gBtZ
|
13
|
+
NVTDZikwDQYJKoZIhvcNAQEFBQADggEBAEoG5up12jtiNII8MU4dziExht/xnJCa
|
14
|
+
ZwlVfsnY9coJ8BDw26T3Qk4qYZuWlQz/XVl3ERquHqRITE5ltcLpjgADWIIa09AT
|
15
|
+
eZC2lay/Bprevo4DbSRw+nfHF1YOECIRSPfIiA15/f3XsNoB/8kV+vvLxZbQ1Sfi
|
16
|
+
C3YXgiqXBtN72kxCfMwpekBXO77p+//Fu2UYiqbyd+W5U79l7B+U6c6CfqfGLhhW
|
17
|
+
Up6KBNu9znx9FJUMtQi3qGqb3JFgKZKAdusb3DYDvssWiXRsjFKtswQXwuBH97f1
|
18
|
+
cEr7mv5mLsBfgQrAJCZXwpaUIxLMHwAsRfgktiO5iqFalB9Gf4q7YIo=
|
19
|
+
-----END CERTIFICATE-----
|
@@ -0,0 +1,27 @@
|
|
1
|
+
-----BEGIN RSA PRIVATE KEY-----
|
2
|
+
MIIEpAIBAAKCAQEA6clG32L98j4S9CqddFeup+NyxZmdSPuEqJpIJHPQn/oGDmqX
|
3
|
+
g8qmDr+DayAKa2ZHVD0+p0ymBJ74kZlFg6apcE55WWetVfE6L491zfAyIqgVET//
|
4
|
+
OPmDd0pgiBo78NXgwVoThMZ/79/fa0BddV02xqqLNuD50lXYB918wEoN909y7kOt
|
5
|
+
ldcqSL0N8Ts0SHxXrT3zmh+t2Oz007khsq99W50VrYO+qzmeUpf1lJopFwRkBpkw
|
6
|
+
1JoXwUL36Kfzqp0KgjEcgdxJU2DsfDIIcqcZEkCFEU9xdkaEq6pIAVT4Qegqb7oe
|
7
|
+
LbMEyvRc253cMd5PkjITMa4DgbBeWrrm1QFm7wIDAQABAoIBAAZIK0hbX5l/w4Ce
|
8
|
+
GIcEyCOov+/BVfGdGI5zPtcD6aoyzLDcel/HNTkWOlDJlp4WLHp9/s3+CEP9hY5c
|
9
|
+
APstokXrReV6HLU/eyHGCBNVjfNScuZ4wsHkKn0tGXTux4eMJ7LqWbXqo4tth5JZ
|
10
|
+
M2mw7ITgFkeOOghF2D013WFJXCC2C6jgJ/QIK2RYehNlPFUbjWrBFIh3Jg1nbfg9
|
11
|
+
WuextjpQqB8dA+1t5FzqhaWXmubIvBvYMjdRuYa63WgCN3VOaI6qqi+bVIbE2SyE
|
12
|
+
KNOAT0Lj4F/svJ3O8J1a28eaLKJ370K8x3FLfAgu+NzZG7JI1o3bdsDXmPm3yMwF
|
13
|
+
HP8K6lECgYEA+oXOhGFo9X6zph7EFLik9XRZkOTwM2E/FjaaObwuQll84e/3mx/G
|
14
|
+
CsPc3+Oc+bhbUn94lAqSNFROASukE1/4yHr8lJdABOmarJpOXm7luSPl/dug85XR
|
15
|
+
gpz2u9/lVtiXc/4iLM0UENrTWgmZ9rhh1PSD8ZbA5EXxGNnFfAzqqWcCgYEA7uXL
|
16
|
+
iWno1qieyWKhB6vE/ZSMrz1MxKwWoOD2U4futPixgrX32oDdlS889yWKajBW8upf
|
17
|
+
Qkr7/YbGtzqr27WCZ/WVOYWAe1lwMpm8gmCg2I+NFD/XaG2IR/A/9QWtO9krPv7j
|
18
|
+
p874BLQ8MFkR6xZDzq9pt7rbacNqAjmYFgHQeTkCgYBgFNeKwA1QMkLWUHBlfheO
|
19
|
+
KAx93MAfBIn8i/6EbB7VxZp20OEG9p2u3UWl/Jbk04b60fa92HwQY9Dy8/jekW1J
|
20
|
+
/plGp+eeurVew2ORJjkm05TO0uAc6/XJgUfD8G/16eXUT8BtrE2o1TRAEPSiwj6L
|
21
|
+
PSgpjOb35bc9D7CFDjMluwKBgQDN2ZabjnYCWYORNfpZmMoCUzkyWtjGcx6Ae7fl
|
22
|
+
XDD1IYIbhl7OmdHVFcIrl96AB600XX29qs0dtT+PbO/fPrTijXuK+B0wrG2APHZx
|
23
|
+
xX9ze6Zt92DOa+tNSZhisgSGmGeqPYm+9BlEPGXMp0NIVYQSGZY3qbwckzTKPARv
|
24
|
+
mhqgCQKBgQCGQMrlWCb/mEvoroQ8JsTltsXuB1qbVtYudlkOWTMTGdw82lQQFVQ8
|
25
|
+
r9rIDSOoTS/70aCvpQg3jFipJ5vFkPucYspM2jE22LvwqncaUg3KJ0hWcbzZJSxE
|
26
|
+
tPLj+I5PQWOR8Gljsik4OhstpU9GOumOyL+EL1MG1+8woArH3P0cTA==
|
27
|
+
-----END RSA PRIVATE KEY-----
|
@@ -0,0 +1,523 @@
|
|
1
|
+
---
|
2
|
+
# This hostname is the one that the test runner will actually perform its test
|
3
|
+
# against. All other intercepted SSL connections will use the original
|
4
|
+
# certificate, but doctored to use the goodca. For this hostname, the SSL
|
5
|
+
# interceptor will present the configured certificate chain of generated
|
6
|
+
# certificates.
|
7
|
+
#
|
8
|
+
# Additionally, the defaultsubject and defaultsubjectwithnull strings will
|
9
|
+
# replace %HOSTNAME% with this value during certificate generation.
|
10
|
+
#hostname: my.hostname.com
|
11
|
+
hostname: www.isecpartners.com
|
12
|
+
|
13
|
+
# Configuration options to pass to PacketThief to configure your firewall.
|
14
|
+
packetthief:
|
15
|
+
# Explicitly declare what firewall implementation to use for intercepting
|
16
|
+
# traffic. It is also needed to discover the original destination of
|
17
|
+
# intercepted network traffic. There are two special implementations: the
|
18
|
+
# 'manual' implementation is meant for when you don't use a firewall at all.
|
19
|
+
# In this case, you must explicitly provide an original destination for the
|
20
|
+
# proxy to forward all intercepted traffic to.
|
21
|
+
#
|
22
|
+
# The second special implementation is 'external'. This means that you are
|
23
|
+
# using a supported firewall, but you want to configure the redirection rule
|
24
|
+
# outside of TLSPretense. In this case, you need to name an actual firewall
|
25
|
+
# implementation so that the socket that receives the intercepted connection
|
26
|
+
# can acquire the original destination (redirected connections provide their
|
27
|
+
# original destination through various standard socket APIs).
|
28
|
+
#
|
29
|
+
# It the implementation is left commented out, then TLSPretense will guess
|
30
|
+
# which implementation to use.
|
31
|
+
#
|
32
|
+
# Options:
|
33
|
+
#
|
34
|
+
# - netfilter Linux netfilter
|
35
|
+
#
|
36
|
+
# - ipfw MacOSX10.6/BSD ipfw
|
37
|
+
#
|
38
|
+
# - pfrdr MacOSX10.7(and 10.8)'s version of PF
|
39
|
+
#
|
40
|
+
# - manual(destination) If you choose manual, you must also choose a
|
41
|
+
# default destination address or hostname.
|
42
|
+
#
|
43
|
+
# - external(implementation) Use firewall rules that are not managed by the
|
44
|
+
# test harness, but that might provide us with
|
45
|
+
# the original destination.
|
46
|
+
#implementation: manual(www.isecpartners.com)
|
47
|
+
|
48
|
+
# The remaining options are used to construct the firewall rule:
|
49
|
+
protocol: tcp
|
50
|
+
dest_port: 443
|
51
|
+
# Linux-like interface:
|
52
|
+
in_interface: eth1
|
53
|
+
# Mac OS X-like interface:
|
54
|
+
#in_interface: en1
|
55
|
+
|
56
|
+
# The port that PacketThief should redirect traffic to, and the port that the
|
57
|
+
# SSL interceptor will run on during each test.
|
58
|
+
listener_port: 54321
|
59
|
+
|
60
|
+
# The testing_method is used to determine whether the client has accepted or
|
61
|
+
# rejected a certificate. If you find any of these to be unreliable, then you
|
62
|
+
# will need to determine pass/fail yourself.
|
63
|
+
#
|
64
|
+
# - tlshandshake We say that the client accepts a test if it completes the
|
65
|
+
# TLS handshake, and it rejects a request if it does not
|
66
|
+
# complete the handshake.
|
67
|
+
# - senddata We say that the client accepts a test if it sends data,
|
68
|
+
# instead of whether it completes the TLS handshake. This may
|
69
|
+
# be necessary for Android and probably other Java-based SSL
|
70
|
+
# using code.
|
71
|
+
testing_method: senddata
|
72
|
+
|
73
|
+
# Meta-configuration for certificate generation. These values affect the
|
74
|
+
# default settings for certificate generation.
|
75
|
+
certmaker:
|
76
|
+
# The default subject string used by the generated certificates. Note that
|
77
|
+
# the substring %HOSTNAME% will be replaced with the value of hostname.
|
78
|
+
defaultsubject: &defaultsubject "C=US, CN=%HOSTNAME%"
|
79
|
+
|
80
|
+
# The default subject string for the null in subject certificate test.
|
81
|
+
# Intended to be almost identical to the defaultsubject.
|
82
|
+
defaultsubjectwithnull: &defaultsubjectwithnull "C=US, CN=%HOSTNAME%\0.foo.com"
|
83
|
+
|
84
|
+
# a subject string, but with the the hostname's parent domain instead of its
|
85
|
+
# domain. A test that should fail.
|
86
|
+
defaultparentsubject: &defaultparentsubject "C=US, CN=%PARENTHOSTNAME%"
|
87
|
+
|
88
|
+
# The directory where pregenerated certificates should be stored.
|
89
|
+
outdir: certs
|
90
|
+
|
91
|
+
# If a serial number is not explicitly set on a certificate definition, then
|
92
|
+
# this value helps decide how the certificate factory generates the
|
93
|
+
# certificate. Possible values:
|
94
|
+
#
|
95
|
+
# * <a number> Use this predefined value as the serial number. Note that
|
96
|
+
# some SSL clients (eg, Firefox) will detect duplicate serial
|
97
|
+
# numbers during a single run of the application.
|
98
|
+
#
|
99
|
+
# * random randomly generate a serial number
|
100
|
+
missing_serial_generation: random
|
101
|
+
|
102
|
+
# customgoodca allows you to load a CA certificate and key from a file. If it
|
103
|
+
# is commented out, then CertMaker will generate a new CA every time it is
|
104
|
+
# run. If this entry exists, but the files do not exist, then the first time
|
105
|
+
# goodca is generated, it will also be copied to these file locations in
|
106
|
+
# order to reuse it in the future.
|
107
|
+
customgoodca:
|
108
|
+
# The path to the PEM encoded certificate:
|
109
|
+
certfile: ca/goodcacert.pem
|
110
|
+
# The path to the PEM encoded key:
|
111
|
+
keyfile: ca/goodcakey.pem
|
112
|
+
# Uncomment keypass and set the password only if your key needs a password.
|
113
|
+
# If there is no password, leave it commented out. Note that the copy of
|
114
|
+
# the CA that will be created in the certs directory will not have any
|
115
|
+
# password protection.
|
116
|
+
#keypass: changeme
|
117
|
+
|
118
|
+
logger:
|
119
|
+
level: INFO
|
120
|
+
file: '-'
|
121
|
+
|
122
|
+
certs:
|
123
|
+
goodca: &goodca
|
124
|
+
subject: "C=US, CN=Trusted CA"
|
125
|
+
issuer: self
|
126
|
+
not_before: now
|
127
|
+
not_after: +365
|
128
|
+
extensions:
|
129
|
+
- "keyUsage = critical, keyCertSign" # can sign certificates
|
130
|
+
- "basicConstraints = critical,CA:true"
|
131
|
+
- "subjectKeyIdentifier=hash"
|
132
|
+
- "authorityKeyIdentifier=keyid:always"
|
133
|
+
key_type: RSA
|
134
|
+
key_size: 1024
|
135
|
+
signing_alg: SHA1
|
136
|
+
|
137
|
+
unknownca: &unknownca
|
138
|
+
<<: *goodca
|
139
|
+
subject: "C=US, CN=Unknown CA"
|
140
|
+
|
141
|
+
goodintermediate: &goodintermediate
|
142
|
+
<<: *goodca
|
143
|
+
subject: "C=US, CN=Intermediate Cert"
|
144
|
+
issuer: goodca
|
145
|
+
|
146
|
+
baseline: &baseline
|
147
|
+
subject: *defaultsubject
|
148
|
+
issuer: goodca
|
149
|
+
not_before: now
|
150
|
+
not_after: +365
|
151
|
+
extensions:
|
152
|
+
- "keyUsage=digitalSignature, keyEncipherment" # can sign data and can encrypt symmetric keys
|
153
|
+
- "extendedKeyUsage=serverAuth, clientAuth" # can be used as both a www server cert and www client cert
|
154
|
+
- "authorityKeyIdentifier=keyid:always"
|
155
|
+
- "subjectKeyIdentifier=hash"
|
156
|
+
- "basicConstraints = critical,CA:FALSE"
|
157
|
+
key_type: RSA
|
158
|
+
key_size: 1024
|
159
|
+
signing_alg: SHA1
|
160
|
+
|
161
|
+
wrongcname: &wrongcname
|
162
|
+
<<: *baseline
|
163
|
+
subject: "C=US, CN=www.foo.com"
|
164
|
+
|
165
|
+
parentcname: &parentcname
|
166
|
+
<<: *baseline
|
167
|
+
subject: *defaultparentsubject
|
168
|
+
|
169
|
+
nullincname: &nullincname
|
170
|
+
<<: *baseline
|
171
|
+
subject: *defaultsubjectwithnull
|
172
|
+
|
173
|
+
baselinesubjectaltname: &baselinesubjectaltname
|
174
|
+
<<: *baseline
|
175
|
+
addextensions:
|
176
|
+
- "subjectAltName=DNS:%HOSTNAME%"
|
177
|
+
|
178
|
+
subjectaltnameonly: &subjectaltnameonly
|
179
|
+
<<: *baseline
|
180
|
+
subject: "C=US, O=My Awesome Organization"
|
181
|
+
addextensions:
|
182
|
+
- "subjectAltName=DNS:%HOSTNAME%"
|
183
|
+
|
184
|
+
wrongsubjectaltnamerightsubject: &wrongsubjectaltnamerightsubject
|
185
|
+
<<: *baseline
|
186
|
+
addextensions:
|
187
|
+
- "subjectAltName=DNS:www.foo.com"
|
188
|
+
|
189
|
+
wrongsubjectaltnamewrongsubject: &wrongsubjectaltnamewrongsubject
|
190
|
+
<<: *baseline
|
191
|
+
subject: "C=US, CN=www.foo.com"
|
192
|
+
addextensions:
|
193
|
+
- "subjectAltName=DNS:www.foo.com"
|
194
|
+
|
195
|
+
# This fails to generate as desired. the null byte truncates the
|
196
|
+
# subjectAltName somewhere within OpenSSL. We need to manually construct the
|
197
|
+
# ASN1 encoding ourselves.
|
198
|
+
# nullinsubjectaltname: &nullinsubjectaltname
|
199
|
+
# <<: *subjectaltnameonly
|
200
|
+
# addextensions:
|
201
|
+
# - "subjectAltName=DNS:%HOSTNAME%\x00.foo.com, DNS:another.com"
|
202
|
+
|
203
|
+
parentinsubjectaltname: &parentinsubjectaltname
|
204
|
+
<<: *subjectaltnameonly
|
205
|
+
addextensions:
|
206
|
+
- "subjectAltName=DNS:%PARENTHOSTNAME%"
|
207
|
+
|
208
|
+
# extended key usage specifies code signing instead of serverAuth
|
209
|
+
wrongextendedkeyusage: &wrongextendedkeyusage
|
210
|
+
<<: *baseline
|
211
|
+
blockextensions:
|
212
|
+
- extendedKeyUsage
|
213
|
+
addextensions:
|
214
|
+
- "extendedKeyUsage = codeSigning"
|
215
|
+
|
216
|
+
rightextendedkeyusagecrit: &rightextendedkeyusagecrit
|
217
|
+
<<: *baseline
|
218
|
+
blockextensions:
|
219
|
+
- extendedKeyUsage
|
220
|
+
addextensions:
|
221
|
+
- "extendedKeyUsage = critical,serverAuth"
|
222
|
+
wrongextendedkeyusagecrit: &wrongextendedkeyusagecrit
|
223
|
+
<<: *baseline
|
224
|
+
blockextensions:
|
225
|
+
- extendedKeyUsage
|
226
|
+
addextensions:
|
227
|
+
- "extendedKeyUsage = critical,codeSigning"
|
228
|
+
|
229
|
+
selfsigned: &selfsigned
|
230
|
+
<<: *baseline
|
231
|
+
issuer: self
|
232
|
+
blockextensions:
|
233
|
+
- authorityKeyIdentifier
|
234
|
+
|
235
|
+
unknowncacert: &unknowncacert
|
236
|
+
<<: *baseline
|
237
|
+
issuer: unknownca
|
238
|
+
|
239
|
+
badsignature: &badsignature
|
240
|
+
<<: *baseline
|
241
|
+
signing_key: unknownca # signing_key defaults to the issuer unless added.
|
242
|
+
|
243
|
+
# we should probably also check for bad keyUsage, since keyUsage=keyCertSign also grants CA abilities
|
244
|
+
cafalseintermediate: &cafalseintermediate
|
245
|
+
<<: *baseline
|
246
|
+
subject: "C=US, CN=Intermediate with BasicConstraints CA:FALSE"
|
247
|
+
|
248
|
+
signedbycafalseint: &signedbycafalseint
|
249
|
+
<<: *baseline
|
250
|
+
issuer: cafalseintermediate
|
251
|
+
|
252
|
+
# we should probably also check for bad keyUsage, since keyUsage=keyCertSign also grants CA abilities
|
253
|
+
nobcintermediate: &nobcintermediate
|
254
|
+
<<: *baseline
|
255
|
+
subject: "C=US, CN=Intermediate with no basicConstraints"
|
256
|
+
blockextensions:
|
257
|
+
- basicconstraints
|
258
|
+
|
259
|
+
signedbynobcint:
|
260
|
+
<<: *baseline
|
261
|
+
issuer: nobcintermediate
|
262
|
+
|
263
|
+
badsigintermediate:
|
264
|
+
<<: *goodintermediate
|
265
|
+
subject: "C=US, CN=Intermediate with bad signature"
|
266
|
+
signing_key: unknownca # signing_key defaults to the issuer unless added
|
267
|
+
|
268
|
+
signedbybadsigintermediate:
|
269
|
+
<<: *baseline
|
270
|
+
issuer: badsigintermediate
|
271
|
+
|
272
|
+
# identical to goodca, but with its own key
|
273
|
+
cawithdifferentkey:
|
274
|
+
<<: *goodca
|
275
|
+
|
276
|
+
signedbydifferentkey:
|
277
|
+
<<: *baseline
|
278
|
+
issuer: cawithdifferentkey
|
279
|
+
|
280
|
+
expiredcert:
|
281
|
+
<<: *baseline
|
282
|
+
not_before: -365
|
283
|
+
not_after: -30
|
284
|
+
|
285
|
+
notyetvalidcert:
|
286
|
+
<<: *baseline
|
287
|
+
not_before: 365
|
288
|
+
not_after: 730
|
289
|
+
|
290
|
+
expiredintermediate:
|
291
|
+
<<: *goodintermediate
|
292
|
+
subject: "C=US, CN=Expired Intermediate"
|
293
|
+
not_before: -365
|
294
|
+
not_after: -30
|
295
|
+
|
296
|
+
signedbyexpiredint:
|
297
|
+
<<: *baseline
|
298
|
+
issuer: expiredintermediate
|
299
|
+
|
300
|
+
signedwithmd5:
|
301
|
+
<<: *baseline
|
302
|
+
signing_alg: MD5
|
303
|
+
|
304
|
+
signedwithmd4:
|
305
|
+
<<: *baseline
|
306
|
+
signing_alg: MD4
|
307
|
+
|
308
|
+
expiredca: &expiredca
|
309
|
+
<<: *goodca
|
310
|
+
subject: "C=US, CN=Expired CA"
|
311
|
+
not_before: -365
|
312
|
+
not_after: -30
|
313
|
+
|
314
|
+
signedbyexpiredca:
|
315
|
+
<<: *baseline
|
316
|
+
issuer: expiredca
|
317
|
+
|
318
|
+
|
319
|
+
tests:
|
320
|
+
# baseline
|
321
|
+
- alias: baseline
|
322
|
+
name: Baseline Happy Test
|
323
|
+
certchain:
|
324
|
+
- baseline
|
325
|
+
- goodca
|
326
|
+
expected_result: connected
|
327
|
+
|
328
|
+
# cname tests
|
329
|
+
- alias: wrongcname
|
330
|
+
name: Wrong CNAME
|
331
|
+
certchain:
|
332
|
+
- wrongcname
|
333
|
+
- goodca
|
334
|
+
expected_result: rejected
|
335
|
+
|
336
|
+
# cname tests
|
337
|
+
- alias: parentcname
|
338
|
+
name: "Parent domain's CNAME"
|
339
|
+
certchain:
|
340
|
+
- parentcname
|
341
|
+
- goodca
|
342
|
+
expected_result: rejected
|
343
|
+
|
344
|
+
- alias: nullincname
|
345
|
+
name: Null character in CNAME
|
346
|
+
certchain:
|
347
|
+
- nullincname
|
348
|
+
- goodca
|
349
|
+
expected_result: rejected
|
350
|
+
|
351
|
+
# subjectAltName tests
|
352
|
+
- alias: happysubjectaltname
|
353
|
+
name: Hostname is a dnsName in subjectAltName and in subject
|
354
|
+
certchain:
|
355
|
+
- baselinesubjectaltname
|
356
|
+
- goodca
|
357
|
+
expected_result: connected
|
358
|
+
|
359
|
+
- alias: happysubjectaltnameonly
|
360
|
+
name: hostname only a dnsName subjectAltName
|
361
|
+
certchain:
|
362
|
+
- subjectaltnameonly
|
363
|
+
- goodca
|
364
|
+
expected_result: connected
|
365
|
+
|
366
|
+
- alias: wrongsubjectaltnamewrongsubject
|
367
|
+
name: hostname in neither subjectAltName nor subject
|
368
|
+
certchain:
|
369
|
+
- wrongsubjectaltnamewrongsubject
|
370
|
+
- goodca
|
371
|
+
expected_result: rejected
|
372
|
+
|
373
|
+
- alias: wrongsubjectaltnamerightsubject
|
374
|
+
name: hostname in subject but not in subjectAltName
|
375
|
+
certchain:
|
376
|
+
- wrongsubjectaltnamerightsubject
|
377
|
+
- goodca
|
378
|
+
expected_result: rejected
|
379
|
+
|
380
|
+
#- alias: nullinsubjectaltname
|
381
|
+
# name: "null byte in subjectAltName"
|
382
|
+
# certchain:
|
383
|
+
# - nullinsubjectaltname
|
384
|
+
# - goodca
|
385
|
+
# expected_result: rejected
|
386
|
+
#
|
387
|
+
- alias: parentinsubjectaltname
|
388
|
+
name: "parent domain in subjectAltName"
|
389
|
+
certchain:
|
390
|
+
- parentinsubjectaltname
|
391
|
+
- goodca
|
392
|
+
expected_result: rejected
|
393
|
+
|
394
|
+
# key usage
|
395
|
+
- alias: wrongextendedkeyusage
|
396
|
+
name: extendedKeyUsage lacks serverAuth
|
397
|
+
certchain:
|
398
|
+
- wrongextendedkeyusage
|
399
|
+
- goodca
|
400
|
+
expected_result: rejected
|
401
|
+
|
402
|
+
- alias: rightextendedkeyusagecrit
|
403
|
+
name: extendedKeyUsage lacks serverAuth
|
404
|
+
certchain:
|
405
|
+
- rightextendedkeyusagecrit
|
406
|
+
- goodca
|
407
|
+
expected_result: connected
|
408
|
+
|
409
|
+
#####################
|
410
|
+
# This one fails against Java/Android's standard SSL client code.
|
411
|
+
- alias: wrongextendedkeyusagecrit
|
412
|
+
name: extendedKeyUsage lacks serverAuth
|
413
|
+
certchain:
|
414
|
+
- wrongextendedkeyusagecrit
|
415
|
+
- goodca
|
416
|
+
expected_result: rejected
|
417
|
+
#####################
|
418
|
+
|
419
|
+
# cert chain issues
|
420
|
+
- alias: selfsigned
|
421
|
+
name: Selfsigned certificate
|
422
|
+
certchain:
|
423
|
+
- selfsigned
|
424
|
+
expected_result: rejected
|
425
|
+
|
426
|
+
- alias: unknownca
|
427
|
+
name: Signed by an untrusted CA
|
428
|
+
certchain:
|
429
|
+
- unknowncacert
|
430
|
+
- unknownca
|
431
|
+
expected_result: rejected
|
432
|
+
|
433
|
+
- alias: differentkeyca
|
434
|
+
name: Signed by an untrusted CA (provided in the chain) with the same name but a different key
|
435
|
+
certchain:
|
436
|
+
- signedbydifferentkey
|
437
|
+
- cawithdifferentkey
|
438
|
+
expected_result: rejected
|
439
|
+
|
440
|
+
- alias: badsignature
|
441
|
+
name: Bad signature
|
442
|
+
certchain:
|
443
|
+
- badsignature
|
444
|
+
- goodca
|
445
|
+
expected_result: rejected
|
446
|
+
|
447
|
+
- alias: cafalseintermediate
|
448
|
+
name: "Intermediate certificate where BasicConstraints sets CA:FALSE"
|
449
|
+
certchain:
|
450
|
+
- signedbycafalseint
|
451
|
+
- cafalseintermediate
|
452
|
+
- goodca
|
453
|
+
expected_result: rejected
|
454
|
+
|
455
|
+
- alias: nobcintermediate
|
456
|
+
name: Intermediate certificate lacks BasicConstraints
|
457
|
+
certchain:
|
458
|
+
- signedbynobcint
|
459
|
+
- nobcintermediate
|
460
|
+
- goodca
|
461
|
+
expected_result: rejected
|
462
|
+
|
463
|
+
- alias: badsigonintermediate
|
464
|
+
name: Intermediate certificate has bad signature from CA
|
465
|
+
certchain:
|
466
|
+
- signedbybadsigintermediate
|
467
|
+
- badsigintermediate
|
468
|
+
- goodca
|
469
|
+
expected_result: rejected
|
470
|
+
|
471
|
+
- alias: signedwithmd5
|
472
|
+
name: Certificate signed with MD5
|
473
|
+
certchain:
|
474
|
+
- signedwithmd5
|
475
|
+
- goodca
|
476
|
+
expected_result: rejected
|
477
|
+
|
478
|
+
- alias: signedwithmd4
|
479
|
+
name: Certificate signed with MD4
|
480
|
+
certchain:
|
481
|
+
- signedwithmd4
|
482
|
+
- goodca
|
483
|
+
expected_result: rejected
|
484
|
+
|
485
|
+
## Need OpenSSL built with MD2 support
|
486
|
+
#- alias: signedwithmd2
|
487
|
+
# name: Certificate signed with MD2
|
488
|
+
# certchain:
|
489
|
+
# - signedwithmd2
|
490
|
+
# - goodca
|
491
|
+
# expected_result: rejected
|
492
|
+
|
493
|
+
- alias: expiredcert
|
494
|
+
name: Certificate that has expired
|
495
|
+
certchain:
|
496
|
+
- expiredcert
|
497
|
+
- goodca
|
498
|
+
expected_result: rejected
|
499
|
+
|
500
|
+
- alias: notyetvalidcert
|
501
|
+
name: Certificate that is valid in the future
|
502
|
+
certchain:
|
503
|
+
- notyetvalidcert
|
504
|
+
- goodca
|
505
|
+
expected_result: rejected
|
506
|
+
|
507
|
+
- alias: expiredintermediate
|
508
|
+
name: Certificate signed by an intermediate that has expired
|
509
|
+
certchain:
|
510
|
+
- signedbyexpiredint
|
511
|
+
- expiredintermediate
|
512
|
+
- goodca
|
513
|
+
expected_result: rejected
|
514
|
+
|
515
|
+
# This requires installing the expired CA that is also installed into the
|
516
|
+
# client's trusted root store.
|
517
|
+
#- alias: expiredca
|
518
|
+
# name: "Certificate signed by a trusted, but expired CA"
|
519
|
+
# certchain:
|
520
|
+
# - signedbyexpiredca
|
521
|
+
# - expiredca
|
522
|
+
# expected_result: rejected
|
523
|
+
|