tlspretense 0.6.2 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -0
  3. data/.travis.yml +5 -0
  4. data/README.rdoc +25 -16
  5. data/Rakefile +1 -4
  6. data/doc/general_setup.rdoc +22 -1
  7. data/doc/macosx_setup.rdoc +86 -0
  8. data/lib/packetthief.rb +8 -1
  9. data/lib/packetthief/handlers/abstract_ssl_handler.rb +1 -2
  10. data/lib/packetthief/handlers/ssl_server.rb +3 -4
  11. data/lib/packetthief/handlers/ssl_smart_proxy.rb +3 -3
  12. data/lib/packetthief/handlers/ssl_transparent_proxy.rb +1 -1
  13. data/lib/packetthief/handlers/transparent_proxy.rb +1 -2
  14. data/lib/packetthief/logging.rb +32 -24
  15. data/lib/tlspretense/app.rb +5 -2
  16. data/lib/tlspretense/cert_maker.rb +5 -0
  17. data/lib/tlspretense/cert_maker/certificate_factory.rb +11 -1
  18. data/lib/tlspretense/cert_maker/certificate_suite_generator.rb +21 -3
  19. data/lib/tlspretense/cert_maker/subject_alt_name_factory.rb +115 -0
  20. data/lib/tlspretense/ext_compat/openssl_pkey_read.rb +38 -0
  21. data/lib/tlspretense/skel/config.yml +194 -17
  22. data/lib/tlspretense/test_harness/input_handler.rb +6 -2
  23. data/lib/tlspretense/test_harness/runner.rb +9 -3
  24. data/lib/tlspretense/test_harness/ssl_test_case.rb +2 -9
  25. data/lib/tlspretense/test_harness/ssl_test_report.rb +3 -0
  26. data/lib/tlspretense/test_harness/test_listener.rb +2 -2
  27. data/lib/tlspretense/test_harness/test_manager.rb +1 -2
  28. data/lib/tlspretense/version.rb +1 -1
  29. data/packetthief_examples/ssl_client_simple.rb +7 -0
  30. data/spec/packetthief/impl/ipfw_spec.rb +4 -2
  31. data/spec/packetthief/impl/netfilter_spec.rb +4 -2
  32. data/spec/packetthief/impl/pf_divert_spec.rb +4 -2
  33. data/spec/packetthief/logging_spec.rb +24 -26
  34. data/spec/spec_helper.rb +7 -8
  35. data/spec/tlspretense/cert_maker/subject_alt_name_factory_spec.rb +75 -0
  36. data/spec/tlspretense/ext_compat/openssl_pkey_read_spec.rb +126 -0
  37. data/spec/tlspretense/test_harness/runner_spec.rb +3 -5
  38. data/tlspretense.gemspec +2 -2
  39. metadata +41 -48
  40. data/Gemfile.lock +0 -41
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4ed245d56d277c418ad64f001cfd058c143558fd
4
+ data.tar.gz: d32fe446d812f2a499df03ee9c955696486a88c2
5
+ SHA512:
6
+ metadata.gz: 282430a23df7618eac0eb73b1078e03738268cec66a9b5031d42ce7bed18f0b814edfc3426a6bfd1f7527347b6e4fcc35aabcf0b9040644d75ac7a93f531fae8
7
+ data.tar.gz: 709560af229dcc7f6c122321af8d51053a10e31a78a100bb850f2a23758459f6c32dec94ed4bbbdc8a9f41f2b8c3eeab88c2c4c910b8ed9eeab3a7ab76c3710f
data/.gitignore CHANGED
@@ -5,3 +5,4 @@ rdoc
5
5
  .bundle
6
6
  pkg
7
7
  tags
8
+ Gemfile.lock
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 2.2
4
+ - 2.3
5
+ - 2.4
@@ -126,11 +126,12 @@ Or just certain tests (in the order specified):
126
126
  though.
127
127
 
128
128
  * It currently uses the goodca to re-sign certificates from hostnames that do
129
- not match the configured test hostname.
129
+ not match the configured test hostname, instead of silently forwarding the
130
+ connection.
130
131
 
131
- * The existing PFDivert rule implementation does not work on Mac OS X 10.7 (and
132
- probably not on 10.8 either). OpenBSD 5.0(?) and FreeBSD 9 can make use of
133
- this functionality though.
132
+ * The existing PFDivert rule implementation does not work on Mac OS X 10.7 or
133
+ 10.8 (use PFRdr instead). OpenBSD newer than 4.3 and FreeBSD 9 can make use
134
+ of the newer PF syntax and functionality though.
134
135
 
135
136
  == TODO
136
137
 
@@ -140,25 +141,33 @@ Or just certain tests (in the order specified):
140
141
  until the pre-flight finishes. (the SSLClient within SSLTransparentProxy
141
142
  probably also should do this until the client connects)
142
143
 
143
- * Fix the subjectAltName null byte test. It requires manual construction of the
144
- ASN1 encoding due to the null byte causing a truncation somewhere in OpenSSL
145
- or Ruby's OpenSSL.
146
-
147
- * Add wildcard tests
144
+ * Add wildcard tests (need a hostname that has
145
+ domain.domain.domain.publicsuffix for all tests)
148
146
  * cert hostname: \*.%PARENTHOSTNAME%
149
- * bad hostname: \*.other.com
147
+ * bad hostname: \*.other.com (reject)
150
148
  * tld hostname: \*.%TLDHOSTNAME% (reject)
151
149
  * do we want to test more complicated wildcards?
150
+ * http://www.ietf.org/rfc/rfc2818.txt requires wildcards to only match a
151
+ single subdomain component, not all subdomain components. Eg, *.a.com matches
152
+ foo.a.com but not bar.foo.a.com
152
153
 
153
154
  * Decide how to deal with a wildcard cert at the original destination. If we
154
155
  are testing foo.somehost.com, and the client connects to other hostnames like
155
156
  bar.somehost.com, and they all use a *.somehost.com certificate, then
156
157
  TLSPretense gets confused.
157
-
158
- * Add extension criticality tests (need an extension oid that nobody knows how to verify)
159
- * If an extension is marked critical and the verifier doesn't know how to
160
- verify, then it should fail. If it is not marked critical, then it is
161
- allowed to skip the extension.
158
+ * If I allow *.somehost.com from the original server to match a test hostname
159
+ of foo.somehost.com, and the client then requests bar.somehost.com,
160
+ TLSPretense would present foo.somehost.com, making a well behaved client
161
+ reject the hostname mismatch.
162
+ * If I don't allow *.somehost.com from the original server match a test
163
+ hostname of foo.somehost.com, then TLSPretense will never successfully run
164
+ its tests.
165
+ * If I set the test hostname to *.somehost.com, then tests for wildcards and
166
+ subdomains wouldn't be valid, but the rest of the tests would work.
167
+ * Perhaps a better option would be to present a warning if the original
168
+ host has a wildcard in it, unless the target hostname also has a wildcard
169
+ in it. (which should present a warning about the sort of tests that won't
170
+ produce meaningful results)
162
171
 
163
172
  * Advanced: Add name constraints tests.
164
173
  * success: dnsName of leaf matches exactly the dnsName permitted constraint
@@ -226,6 +235,6 @@ Or just certain tests (in the order specified):
226
235
 
227
236
  == Copyright
228
237
 
229
- Copyright (c) 2012 iSEC Partners
238
+ Copyright (c) 2012-2013 iSEC Partners
230
239
 
231
240
  See LICENSE.txt for further details.
data/Rakefile CHANGED
@@ -18,6 +18,7 @@ task :default => :spec
18
18
 
19
19
  require 'rdoc/task'
20
20
  Rake::RDocTask.new do |rdoc|
21
+ $: << 'lib'
21
22
  require 'tlspretense/version'
22
23
  version = TLSPretense::VERSION
23
24
 
@@ -38,7 +39,3 @@ Rake::RDocTask.new do |rdoc|
38
39
  end
39
40
  end
40
41
 
41
- require 'certmaker/tasks'
42
-
43
- desc "Runs certs:clean"
44
- task :clean => ['certs:clean']
@@ -49,10 +49,28 @@ This setup has the following network topography:
49
49
 
50
50
  == Installing TLSPretense
51
51
 
52
- Install with rubygems:
52
+ === General Case
53
+
54
+ The following assumes that the +gem+ command refers to the Ruby 1.9.3 version
55
+ of gem. If the Ruby 1.9.3 version on your system has a suffix, use that version
56
+ of +gem+ instead. Install with rubygems:
53
57
 
54
58
  umask 0022 ; sudo gem install tlspretense
55
59
 
60
+ === Ubuntu 12.04 and Later
61
+
62
+ If you are using Ubuntu, The ruby1.9.1 package on Ubuntu 12.04 is actually Ruby
63
+ 1.9.3 (1.9.1 in this case is the ABI version, not the software version).
64
+ Assuming you haven't already installed Ruby 1.9.3:
65
+
66
+ sudo apt-get install ruby1.9.1-full
67
+
68
+ then install with rubygems:
69
+
70
+ umask 0022 ; sudo gem1.9.1 install tlspretense
71
+
72
+ === Create a TLSPretense Project
73
+
56
74
  Create a new project:
57
75
 
58
76
  tlspretense init myproject
@@ -258,6 +276,9 @@ the firewall rule that redirects network traffic itself.
258
276
  For a sample Linux-specific configuration, see: {Linux
259
277
  Setup}[rdoc-ref:linux_setup].
260
278
 
279
+ For information on configuring TLSPretense on a Mac OS X system, see: {Mac OS X
280
+ Setup}[rdoc-ref:macosx_setup]
281
+
261
282
 
262
283
  == Running the tests
263
284
 
@@ -0,0 +1,86 @@
1
+ = Setting Up Mac OS X for Use With TLSPretense
2
+
3
+ To run TLSPretense on Mac OS X, you need a Mac running Mac OS X 10.6 or later,
4
+ and you need to have at least two network interfaces. If you are using a Mac
5
+ laptop that only has wifi, you will need to use one or more ethernet adapters.
6
+
7
+ The following sections cover how to setup both Mac OS X 10.6 and 10.7.
8
+
9
+ == Configuring Internet Sharing
10
+
11
+ This example assumes that you want to test software running on a device
12
+ that uses wifi, such as an iOS or Android app. The sytem hosting TLSPretense
13
+ will be a Mac running Mac OS X 10.6, 10.7, or 10.8. We
14
+ will turn our wifi adapter into a wireless access point and then share our
15
+ Internet connection from a physical ethernet adapter with it.
16
+
17
+ First, open System Preferences and ensure that the ethernet connection has
18
+ Internet access. You may need to authenticate as an admin in order to make
19
+ changes.
20
+
21
+ Then, if your wifi adapter is currently connected to a network, tell it to
22
+ disconnect.
23
+
24
+ Next, go to the Sharing preference pane, and click on "Internet Sharing" to
25
+ configure it. Set "Share your connection from:" to your Ethernet connection
26
+ (usually en0), and share it to your airport connection (usually en1). Click on
27
+ "AirPort Options..." to configure the wireless access point it will create.
28
+ Finally, click the checkbox next to "Internet Sharing" enable it.
29
+
30
+ Internet Sharing will enable +natd+ in Mac OX X 10.6 (uses ipfw), ??? in
31
+ Mac OS X 10.7 and +natpmpd+ in 10.8 (10.7 and later use Apple's version of PF,
32
+ which is a much older version of PF than used by FreeBSD and OpenBSD). Both
33
+ versions of the NAT
34
+ will forward IPv4 traffic originating from devices connected to the Mac's
35
+ Airport card, and forward it on to the designated outgoing network device
36
+ (TODO: Does it handle IPv6 routing?).
37
+ Internet Sharing will also enable a DHCP server to automatically configure any
38
+ clients that connect to the internal side of the network.
39
+
40
+ TLSPretense uses its PacketThief library to capture the traffic it is
41
+ configured to intercept, and it will initiate new outgoing connections, usually
42
+ bypassing the NAT daemon for such traffic. We still want the NAT service because it will
43
+ forward traffic not intercepted by TLSPretense.
44
+
45
+ Once you have Internet Sharing enabled, you should test to make sure it works
46
+ with your test device.
47
+
48
+ == Configure the Test Device
49
+
50
+ Next, the system that will run the client code needs to be configured to use
51
+ the TLSPretense host as its gateway. This usually involves connecting the
52
+ client system to the new wireless access point or to the ethernet port that
53
+ represents the internal network. DHCP should automatically configure the
54
+ address, gateway, subnet mask, and DNS information for the client system, but
55
+ you may need to manually modify these values if something does not work
56
+ (wireshark on the system running TLSPretense can help you debug this).
57
+
58
+ == Configuring the PF Firewall
59
+
60
+ You need to add the following line to the bottom of your system's +/etc/pf.conf+:
61
+
62
+ rdr-anchor "packetthief"
63
+
64
+ It should be inserted after any NAT rules, but before any other redirect rules
65
+ (such as Apple's +rdr-anchor+ rule). Once you have added it, you should reload
66
+ the core ruleset:
67
+
68
+ sudo pfctl -f /etc/pf.conf
69
+
70
+
71
+ == Configure TLSPretense
72
+
73
+ Mac laptops use en0, en1, etc. for their Unix network interface names. Mac
74
+ laptops that have both ethernet and wifi built in usually have ethernet on en0
75
+ and their wifi interface on en1. However, on newer Mac laptops that only have
76
+ built-in wifi, the wifi is usually +en0+ and devices like Thunderbolt ethernet
77
+ adaptors will be assigned a higher-numbered interface name.
78
+
79
+ On Mac OS X 10.8, with Internet Sharing enabled, the internal LAN's gateway is
80
+ +bridge0+ rather than the +en*+ interface.
81
+
82
+ You should set +in_interface+ in the +packetthief+ section of your config.yml
83
+ to the network interface name of the correct internal network.
84
+
85
+ Aside from that, configure TLSPretense normally, as discussed in the {General
86
+ Setup}[rdoc-ref:general_setup].
@@ -117,6 +117,14 @@ module PacketThief
117
117
  include Logging
118
118
  end
119
119
 
120
+ def self.logger=(log)
121
+ PacketThief::Logging.logger = log
122
+ end
123
+
124
+ def self.logger
125
+ PacketThief::Logging.logger
126
+ end
127
+
120
128
  def self.implementation; @implementation ; end
121
129
 
122
130
  def self.implementation=(newimpl)
@@ -155,7 +163,6 @@ module PacketThief
155
163
  if self.implementation == nil
156
164
  self.implementation = guess_implementation
157
165
  end
158
- implementation.logger = @logger if implementation.respond_to? :logger=
159
166
  self.implementation.send(m, *args, &block)
160
167
  end
161
168
 
@@ -26,8 +26,7 @@ module PacketThief
26
26
  # is applied to the SSLSocket during #tls_begin.
27
27
  attr_accessor :sni_hostname
28
28
 
29
- def initialize(tcpsocket, logger=nil)
30
- @logger = logger
29
+ def initialize(tcpsocket)
31
30
  logdebug "initialize"
32
31
  # Set up initial values
33
32
  @tcpsocket = tcpsocket
@@ -103,11 +103,10 @@ module PacketThief
103
103
  logdebug "(#{@ssl_class}): Received a new connection, spawning a #{@ssl_class}"
104
104
  sock = @servsocket.accept_nonblock
105
105
 
106
- ::EM.watch sock, @ssl_class, sock, *@args, @logger do |h|
106
+ ::EM.watch sock, @ssl_class, sock, *@args do |h|
107
107
  logdebug "after initialize"
108
108
  h.server_handler = self
109
109
  h.notify_readable = true
110
- h.logger = @logger
111
110
  # Now call the caller's block.
112
111
  @block.call(h) if @block
113
112
  # And finally finish initialization by applying the context to an
@@ -145,8 +144,8 @@ module PacketThief
145
144
  ####
146
145
 
147
146
  public
148
- def initialize(tcpsocket,logger=nil)
149
- super(tcpsocket, logger)
147
+ def initialize(tcpsocket)
148
+ super(tcpsocket)
150
149
  @ctx.servername_cb = proc {|sslsocket, hostname| self.servername_cb(sslsocket, hostname) }
151
150
  end
152
151
 
@@ -15,8 +15,8 @@ module PacketThief
15
15
  # seconds.
16
16
  attr_accessor :preflight_timeout
17
17
 
18
- def initialize(tcpsocket, ca_chain, key, logger=nil)
19
- super(tcpsocket, logger)
18
+ def initialize(tcpsocket, ca_chain, key)
19
+ super(tcpsocket)
20
20
 
21
21
  @preflight_timeout = 5
22
22
  if ca_chain.kind_of? Array
@@ -53,7 +53,7 @@ module PacketThief
53
53
 
54
54
  # Requests a certificate from the original destination.
55
55
  def preflight_for_cert(hostname=nil)
56
- logdebug "prefilight for: #{hostname}"
56
+ logdebug "preflight for: #{hostname}"
57
57
  begin
58
58
  pfctx = OpenSSL::SSL::SSLContext.new
59
59
  pfctx.verify_mode = OpenSSL::SSL::VERIFY_NONE
@@ -83,7 +83,7 @@ module PacketThief
83
83
  # Initially, its verify_mode is set to OpenSSL::SSL::VERIFY_NONE.
84
84
  attr_accessor :dest_ctx
85
85
 
86
- def initialize(tcpsocket, logger=nil)
86
+ def initialize(tcpsocket)
87
87
  super
88
88
  @closed = false
89
89
 
@@ -68,8 +68,7 @@ module PacketThief
68
68
  # When the proxy should connect to a destination.
69
69
  attr_accessor :when_to_connect_to_dest
70
70
 
71
- def initialize(log=nil)
72
- @logger = log
71
+ def initialize
73
72
  end
74
73
 
75
74
  def post_init
@@ -1,48 +1,56 @@
1
1
  module PacketThief
2
2
  # Mix-in that provides some private convenience logging functions. Uses the
3
- # @logger instance variable.
3
+ # logger specified by this module. To set the current logger for all of
4
+ # PacketThief:
5
+ #
6
+ # PacketThief::Logging.logger = Logger.new
4
7
  module Logging
5
- # An optional Ruby Logger for debugging output. If it is unset, the log
6
- # methods will be silent.
7
- attr_accessor :logger
8
8
 
9
- private
10
-
11
- # Print a message at the specified log severity (prefixed with the component),
12
- # and display any additional arguments. For example:
13
- #
14
- # dlog(Logger::DEBUG, SomeClass, "hello", :somevalue => 'that value")
15
- #
16
- # Will print the message: "SomeClass: hello: somevalue=that value" at the
17
- # debug log level.
18
- def log(level, component, msg, args={})
19
- if @logger
20
- unless args.empty?
21
- kvstr = args.map { |pair| pair[0].to_s + ': ' + pair[1].inspect }.sort.join(', ')
22
- msg += ": " + kvstr
9
+ class << self
10
+
11
+ # An optional Ruby Logger for debugging output. If it is unset, the log
12
+ # methods will be silent.
13
+ attr_accessor :logger
14
+
15
+ # Print a message at the specified log severity (prefixed with the component),
16
+ # and display any additional arguments. For example:
17
+ #
18
+ # log(Logger::DEBUG, SomeClass, "hello", :somevalue => 'that value")
19
+ #
20
+ # Will print the message: "SomeClass: hello: somevalue=that value" at the
21
+ # debug log level.
22
+ def log(level, component, msg, args={})
23
+ if @logger
24
+ unless args.empty?
25
+ kvstr = args.map { |pair| pair[0].to_s + ': ' + pair[1].inspect }.sort.join(', ')
26
+ msg += ": " + kvstr
27
+ end
28
+ @logger.log(level, component.to_s + ': ' + msg)
23
29
  end
24
- @logger.log(level, component.to_s + ': ' + msg)
25
30
  end
31
+
26
32
  end
27
33
 
34
+ private
35
+
28
36
  def logdebug(msg, args={})
29
- log(Logger::DEBUG, (([Module, Class].include? self.class) ? self.name : self.class), msg, args)
37
+ Logging.log(Logger::DEBUG, (([Module, Class].include? self.class) ? self.name : self.class), msg, args)
30
38
  end
31
39
 
32
40
  def loginfo(msg, args={})
33
- log(Logger::INFO, self.class, msg, args)
41
+ Logging.log(Logger::INFO, self.class, msg, args)
34
42
  end
35
43
 
36
44
  def logwarn(msg, args={})
37
- log(Logger::WARN, self.class, msg, args)
45
+ Logging.log(Logger::WARN, self.class, msg, args)
38
46
  end
39
47
 
40
48
  def logerror(msg, args={})
41
- log(Logger::ERROR, self.class, msg, args)
49
+ Logging.log(Logger::ERROR, self.class, msg, args)
42
50
  end
43
51
 
44
52
  def logfatal(msg, args={})
45
- log(Logger::FATAL, self.class, msg, args)
53
+ Logging.log(Logger::FATAL, self.class, msg, args)
46
54
  end
47
55
 
48
56
  end
@@ -30,7 +30,9 @@ QUOTE
30
30
  when 'init'
31
31
  InitRunner.new(@action_args, @stdin, @stdout).run
32
32
  when 'run'
33
- TestHarness::Runner.new(@action_args, @stdin, @stdout).run
33
+ unless TestHarness::Runner.new(@action_args, @stdin, @stdout).run
34
+ return 1
35
+ end
34
36
  when 'list', 'ls'
35
37
  TestHarness::Runner.new(['--list'] + @action_args, @stdin, @stdout).run
36
38
  when 'ca'
@@ -45,8 +47,9 @@ QUOTE
45
47
  rescue CleanExitError => e
46
48
  @stdout.puts ""
47
49
  @stdout.puts "#{e.class}: #{e}"
48
- exit 1
50
+ return 1
49
51
  end
52
+ 0
50
53
  end
51
54
  end
52
55
  end
@@ -4,11 +4,16 @@ require 'yaml'
4
4
 
5
5
  require 'tlspretense/ext_core/hash_indifferent_fetch'
6
6
 
7
+ # Provide a limited version of OpenSSL::PKey.read for older Ruby versions.
8
+ require 'tlspretense/ext_compat/openssl_pkey_read'
9
+ TLSPretense::ExtCompat::OpenSSLPKeyRead.check_and_apply_patch
10
+
7
11
  module TLSPretense
8
12
  module CertMaker
9
13
 
10
14
  autoload :CertificateFactory, 'tlspretense/cert_maker/certificate_factory'
11
15
  autoload :CertificateSuiteGenerator, 'tlspretense/cert_maker/certificate_suite_generator'
16
+ autoload :SubjectAltNameFactory, 'tlspretense/cert_maker/subject_alt_name_factory'
12
17
 
13
18
 
14
19
  # Generate certificates and keys using +config+.