tlspretense 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. data/.document +6 -0
  2. data/.gitignore +7 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +2 -0
  5. data/Gemfile.lock +41 -0
  6. data/LICENSE.txt +20 -0
  7. data/README.rdoc +231 -0
  8. data/Rakefile +44 -0
  9. data/bin/makeder.sh +6 -0
  10. data/bin/tlspretense +7 -0
  11. data/bin/view.sh +3 -0
  12. data/doc/general_setup.rdoc +288 -0
  13. data/doc/linux_setup.rdoc +64 -0
  14. data/lib/certmaker.rb +61 -0
  15. data/lib/certmaker/certificate_factory.rb +106 -0
  16. data/lib/certmaker/certificate_suite_generator.rb +120 -0
  17. data/lib/certmaker/ext_core/hash_indifferent_fetch.rb +12 -0
  18. data/lib/certmaker/runner.rb +27 -0
  19. data/lib/certmaker/tasks.rb +20 -0
  20. data/lib/packetthief.rb +167 -0
  21. data/lib/packetthief/handlers.rb +14 -0
  22. data/lib/packetthief/handlers/abstract_ssl_handler.rb +249 -0
  23. data/lib/packetthief/handlers/proxy_redirector.rb +26 -0
  24. data/lib/packetthief/handlers/ssl_client.rb +87 -0
  25. data/lib/packetthief/handlers/ssl_server.rb +174 -0
  26. data/lib/packetthief/handlers/ssl_smart_proxy.rb +143 -0
  27. data/lib/packetthief/handlers/ssl_transparent_proxy.rb +225 -0
  28. data/lib/packetthief/handlers/transparent_proxy.rb +183 -0
  29. data/lib/packetthief/impl.rb +11 -0
  30. data/lib/packetthief/impl/ipfw.rb +140 -0
  31. data/lib/packetthief/impl/manual.rb +54 -0
  32. data/lib/packetthief/impl/netfilter.rb +109 -0
  33. data/lib/packetthief/impl/pf_divert.rb +168 -0
  34. data/lib/packetthief/impl/pf_rdr.rb +192 -0
  35. data/lib/packetthief/logging.rb +49 -0
  36. data/lib/packetthief/redirect_rule.rb +29 -0
  37. data/lib/packetthief/util.rb +36 -0
  38. data/lib/ssl_test.rb +21 -0
  39. data/lib/ssl_test/app_context.rb +17 -0
  40. data/lib/ssl_test/certificate_manager.rb +33 -0
  41. data/lib/ssl_test/config.rb +79 -0
  42. data/lib/ssl_test/ext_core/io_raw_input.rb +31 -0
  43. data/lib/ssl_test/input_handler.rb +35 -0
  44. data/lib/ssl_test/runner.rb +110 -0
  45. data/lib/ssl_test/runner_options.rb +68 -0
  46. data/lib/ssl_test/ssl_test_case.rb +46 -0
  47. data/lib/ssl_test/ssl_test_report.rb +24 -0
  48. data/lib/ssl_test/ssl_test_result.rb +30 -0
  49. data/lib/ssl_test/test_listener.rb +140 -0
  50. data/lib/ssl_test/test_manager.rb +116 -0
  51. data/lib/tlspretense.rb +13 -0
  52. data/lib/tlspretense/app.rb +52 -0
  53. data/lib/tlspretense/init_runner.rb +115 -0
  54. data/lib/tlspretense/skel/ca/goodcacert.pem +19 -0
  55. data/lib/tlspretense/skel/ca/goodcakey.pem +27 -0
  56. data/lib/tlspretense/skel/config.yml +523 -0
  57. data/lib/tlspretense/version.rb +3 -0
  58. data/packetthief_examples/em_ssl_test.rb +73 -0
  59. data/packetthief_examples/redirector.rb +29 -0
  60. data/packetthief_examples/setup_iptables.sh +24 -0
  61. data/packetthief_examples/ssl_client_simple.rb +27 -0
  62. data/packetthief_examples/ssl_server_simple.rb +44 -0
  63. data/packetthief_examples/ssl_smart_proxy.rb +115 -0
  64. data/packetthief_examples/ssl_transparent_proxy.rb +97 -0
  65. data/packetthief_examples/transparent_proxy.rb +56 -0
  66. data/spec/packetthief/impl/ipfw_spec.rb +98 -0
  67. data/spec/packetthief/impl/manual_spec.rb +65 -0
  68. data/spec/packetthief/impl/netfilter_spec.rb +66 -0
  69. data/spec/packetthief/impl/pf_divert_spec.rb +82 -0
  70. data/spec/packetthief/impl/pf_rdr_spec.rb +133 -0
  71. data/spec/packetthief/logging_spec.rb +78 -0
  72. data/spec/packetthief_spec.rb +47 -0
  73. data/spec/spec_helper.rb +53 -0
  74. data/spec/ssl_test/certificate_manager_spec.rb +222 -0
  75. data/spec/ssl_test/config_spec.rb +76 -0
  76. data/spec/ssl_test/runner_spec.rb +360 -0
  77. data/spec/ssl_test/ssl_test_case_spec.rb +113 -0
  78. data/spec/ssl_test/test_listener_spec.rb +199 -0
  79. data/spec/ssl_test/test_manager_spec.rb +324 -0
  80. data/tlspretense.gemspec +35 -0
  81. 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
@@ -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
+