tlspretense 0.6.2 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +1 -0
- data/.travis.yml +5 -0
- data/README.rdoc +25 -16
- data/Rakefile +1 -4
- data/doc/general_setup.rdoc +22 -1
- data/doc/macosx_setup.rdoc +86 -0
- data/lib/packetthief.rb +8 -1
- data/lib/packetthief/handlers/abstract_ssl_handler.rb +1 -2
- data/lib/packetthief/handlers/ssl_server.rb +3 -4
- data/lib/packetthief/handlers/ssl_smart_proxy.rb +3 -3
- data/lib/packetthief/handlers/ssl_transparent_proxy.rb +1 -1
- data/lib/packetthief/handlers/transparent_proxy.rb +1 -2
- data/lib/packetthief/logging.rb +32 -24
- data/lib/tlspretense/app.rb +5 -2
- data/lib/tlspretense/cert_maker.rb +5 -0
- data/lib/tlspretense/cert_maker/certificate_factory.rb +11 -1
- data/lib/tlspretense/cert_maker/certificate_suite_generator.rb +21 -3
- data/lib/tlspretense/cert_maker/subject_alt_name_factory.rb +115 -0
- data/lib/tlspretense/ext_compat/openssl_pkey_read.rb +38 -0
- data/lib/tlspretense/skel/config.yml +194 -17
- data/lib/tlspretense/test_harness/input_handler.rb +6 -2
- data/lib/tlspretense/test_harness/runner.rb +9 -3
- data/lib/tlspretense/test_harness/ssl_test_case.rb +2 -9
- data/lib/tlspretense/test_harness/ssl_test_report.rb +3 -0
- data/lib/tlspretense/test_harness/test_listener.rb +2 -2
- data/lib/tlspretense/test_harness/test_manager.rb +1 -2
- data/lib/tlspretense/version.rb +1 -1
- data/packetthief_examples/ssl_client_simple.rb +7 -0
- data/spec/packetthief/impl/ipfw_spec.rb +4 -2
- data/spec/packetthief/impl/netfilter_spec.rb +4 -2
- data/spec/packetthief/impl/pf_divert_spec.rb +4 -2
- data/spec/packetthief/logging_spec.rb +24 -26
- data/spec/spec_helper.rb +7 -8
- data/spec/tlspretense/cert_maker/subject_alt_name_factory_spec.rb +75 -0
- data/spec/tlspretense/ext_compat/openssl_pkey_read_spec.rb +126 -0
- data/spec/tlspretense/test_harness/runner_spec.rb +3 -5
- data/tlspretense.gemspec +2 -2
- metadata +41 -48
- data/Gemfile.lock +0 -41
checksums.yaml
ADDED
@@ -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
data/README.rdoc
CHANGED
@@ -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
|
132
|
-
|
133
|
-
|
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
|
-
*
|
144
|
-
|
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
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
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']
|
data/doc/general_setup.rdoc
CHANGED
@@ -49,10 +49,28 @@ This setup has the following network topography:
|
|
49
49
|
|
50
50
|
== Installing TLSPretense
|
51
51
|
|
52
|
-
|
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].
|
data/lib/packetthief.rb
CHANGED
@@ -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
|
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
|
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
|
149
|
-
super(tcpsocket
|
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
|
19
|
-
super(tcpsocket
|
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 "
|
56
|
+
logdebug "preflight for: #{hostname}"
|
57
57
|
begin
|
58
58
|
pfctx = OpenSSL::SSL::SSLContext.new
|
59
59
|
pfctx.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
data/lib/packetthief/logging.rb
CHANGED
@@ -1,48 +1,56 @@
|
|
1
1
|
module PacketThief
|
2
2
|
# Mix-in that provides some private convenience logging functions. Uses the
|
3
|
-
#
|
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
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
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
|
data/lib/tlspretense/app.rb
CHANGED
@@ -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
|
-
|
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+.
|