sslkeylog 0.2.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 +11 -0
- data/.rspec +2 -0
- data/.travis.yml +9 -0
- data/.yardopts +2 -0
- data/CHANGELOG.md +33 -0
- data/Gemfile +10 -0
- data/LICENSE +21 -0
- data/README.md +71 -0
- data/Rakefile +5 -0
- data/ext/openssl/extconf.rb +17 -0
- data/ext/openssl/openssl.c +133 -0
- data/lib/sslkeylog.rb +6 -0
- data/lib/sslkeylog/autotrace.rb +2 -0
- data/lib/sslkeylog/logging.rb +52 -0
- data/lib/sslkeylog/trace.rb +39 -0
- data/lib/sslkeylog/version.rb +3 -0
- data/spec/integration/client_spec.rb +61 -0
- data/spec/shared/ssl_server_context.rb +26 -0
- data/spec/spec_helper.rb +3 -0
- data/spec/unit/sslkeylog_openssl_spec.rb +18 -0
- data/sslkeylog.gemspec +25 -0
- data/tasks/compile.rake +5 -0
- data/tasks/spec.rake +4 -0
- data/tasks/yard.rake +9 -0
- metadata +112 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 5d2371c16ef153fca7e769b86512b6c115ff202b
|
4
|
+
data.tar.gz: 3d01e3e2c858beee98fc55caf029b2ca4cb45fa7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: aa39a32b4d64b14b99ae0f417a891ca7ced5706586c1bd20ac276ea291e75b09c7d8b1036c5f3ac7d87763a071185e82b616b4334595cd12da6e35625c647094
|
7
|
+
data.tar.gz: 996fa56a14a4076894eafd64e5d03dd0a4ca4d8861c32866ae15b4cec00911e5362de11ba693513724d2c2724c94ea8d4cae2ffea51dd92db572f3577f0c8ad2
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/.yardopts
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
SSLkeylog
|
2
|
+
=========
|
3
|
+
|
4
|
+
0.2.0
|
5
|
+
-----
|
6
|
+
|
7
|
+
2015-04-14
|
8
|
+
|
9
|
+
Backwards incompatible feature release.
|
10
|
+
|
11
|
+
- +Break
|
12
|
+
Library renamed from `OpenSSL::Keylog` to `SSLkeylog`.
|
13
|
+
|
14
|
+
- +Break
|
15
|
+
The library no longer extends (monkeypatches) the `OpenSSL::SSL::SSLSocket`
|
16
|
+
class. This functionality is now provided by module functions on
|
17
|
+
`SSLkeylog::OpenSSL`.
|
18
|
+
|
19
|
+
- +New
|
20
|
+
A simple tracing and logging system built on top of the standard `Logging`
|
21
|
+
library and the Ruby 2.0 `TracePoint` API that allows SSL client
|
22
|
+
connections to be logged.
|
23
|
+
|
24
|
+
|
25
|
+
0.1.0
|
26
|
+
-----
|
27
|
+
|
28
|
+
2015-04-12
|
29
|
+
|
30
|
+
(unreleased) First tagged prototype.
|
31
|
+
|
32
|
+
- +New
|
33
|
+
Added the `to_keylog` method for `OpenSSL:SSL::SSLSocket` objects which extracts and formats NSS Key Log data.
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2015 Charlie Sharpsteen
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
SSLkeylog
|
2
|
+
=========
|
3
|
+
|
4
|
+
An Ruby library that logs SSL session keys from client connections in [NSS Key Log Format][nss-format]. This log can be used by tools such as [Wireshark][wireshark] to decrypt data when analyzing network traffic.
|
5
|
+
|
6
|
+
**NOTE:** This version of the library is a functional prototype. The implementation may change in the future.
|
7
|
+
|
8
|
+
[](https://travis-ci.org/Sharpie/sslkeylog)
|
9
|
+
|
10
|
+
[nss-format]: https://developer.mozilla.org/en-US/docs/Mozilla/Projects/NSS/Key_Log_Format
|
11
|
+
|
12
|
+
[wireshark]:https://wiki.wireshark.org/SSL#Using_the_.28Pre.29-Master-Secret
|
13
|
+
|
14
|
+
|
15
|
+
## Installation
|
16
|
+
|
17
|
+
This gem uses a C extension to extract data from Ruby `OpenSSL::SSL::SSLSocket` objects. This means that the Gem will have to be built using the same OpenSSL headers that Ruby used during compilation.
|
18
|
+
|
19
|
+
The logic for locating the `include` directory is not particularly sophisticated, so the proper location may need to be specified during installation:
|
20
|
+
|
21
|
+
gem install openssl-keylog -- --with-openssl-include=...
|
22
|
+
|
23
|
+
Use of the wrong header file can result in segmentation faults and other unpleasantness.
|
24
|
+
|
25
|
+
|
26
|
+
## Usage
|
27
|
+
|
28
|
+
The simplest way to use this library is to set an output file using the `SSLKEYLOG` environment variable and then require the `sslkeylog/autotrace` module:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
# In bash: export SSLKEYLOG=$HOME/sslkeylog.log
|
32
|
+
require 'sslkeylog/autotrace'
|
33
|
+
```
|
34
|
+
|
35
|
+
If the `SSLKEYLOG` variable is unset, output will be sent to `$stderr`.
|
36
|
+
|
37
|
+
|
38
|
+
Tracing can be enabled for specific portions of a Ruby program and output can be routed to any object which behaves like a standard Ruby `Logger`:
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
require 'sslkeylog'
|
42
|
+
require 'stringio'
|
43
|
+
|
44
|
+
output = StringIO.new
|
45
|
+
SSLkeylog::Logging.logger = Logger.new(output)
|
46
|
+
|
47
|
+
socket = TCPSocket.new('github.com', '443')
|
48
|
+
ssl_socket = OpenSSL::SSL::SSLSocket.new(socket)
|
49
|
+
|
50
|
+
SSLkeylog::Trace.enable
|
51
|
+
ssl_socket.connect
|
52
|
+
SSLkeylog::Trace.disable
|
53
|
+
|
54
|
+
ssl_socket.close
|
55
|
+
puts output.string
|
56
|
+
# => I, [2015-04-14T12:51:33.016410 #90145] INFO -- : CLIENT_RANDOM 20A97D56EAE0850DE6CECB63D4D587D863E62750AF3AF032453608DA5F8787C0 58260274A5BD57E1158AD2CAFEE1D8F671F900419F37B6A2DDB20FA0AC8B96AC0940398B33D42F366E2937151C751CED
|
57
|
+
```
|
58
|
+
|
59
|
+
Data can be extracted directly from `OpenSSL::SSL:SSLSocket` objects using the `to_keylog` method of the `SSLkeylog::OpenSSL` module:
|
60
|
+
|
61
|
+
```ruby
|
62
|
+
require 'sslkeylog/openssl'
|
63
|
+
|
64
|
+
socket = TCPSocket.new('github.com', '443')
|
65
|
+
ssl_socket = OpenSSL::SSL::SSLSocket.new(socket)
|
66
|
+
ssl_socket.connect
|
67
|
+
|
68
|
+
puts SSLkeylog::OpenSSL.to_keylog(ssl_socket)
|
69
|
+
ssl_socket.close
|
70
|
+
# => "CLIENT_RANDOM 7374BF6508668783736B211242A4BC2CF075FC508E49B9797B038D6357370A10 C5BB2BDFEF788E7BB6ED0A37962BEEB140AC7F33DEF0E344F576D18305AF5A6C0121E069F1FF4CE4424530A83D443EFD\n"
|
71
|
+
```
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'mkmf'
|
2
|
+
require 'shellwords'
|
3
|
+
|
4
|
+
openssl_include = []
|
5
|
+
openssl_lib = []
|
6
|
+
|
7
|
+
# Check to see if Ruby was compiled with a custom OpenSSL
|
8
|
+
openssl_config = CONFIG['configure_args'].shellsplit.find {|e| e.start_with? '--with-openssl-dir='}
|
9
|
+
unless openssl_config.nil?
|
10
|
+
_, _, openssl_dir = openssl_config.partition('=')
|
11
|
+
|
12
|
+
openssl_include << File.join(openssl_dir, 'include')
|
13
|
+
openssl_lib << File.join(openssl_dir, 'lib')
|
14
|
+
end
|
15
|
+
|
16
|
+
dir_config('openssl', openssl_include, openssl_lib)
|
17
|
+
create_makefile('sslkeylog/openssl')
|
@@ -0,0 +1,133 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <openssl/ssl.h>
|
3
|
+
|
4
|
+
// Global variables pointing to Ruby namespaces of interest.
|
5
|
+
VALUE mOpenSSL, mSSL, cSSLSocket;
|
6
|
+
|
7
|
+
// Copies and hex encodes a char array, using two bytes in buffer for each byte
|
8
|
+
// in str.
|
9
|
+
static void
|
10
|
+
hex_encode(char *buffer, size_t size, const unsigned char *str)
|
11
|
+
{
|
12
|
+
static const char hex[] = "0123456789ABCDEF";
|
13
|
+
unsigned int i;
|
14
|
+
|
15
|
+
for (i = 0; i < size; i++) {
|
16
|
+
*(buffer++) = hex[str[i] >> 4];
|
17
|
+
*(buffer++) = hex[str[i] & 15];
|
18
|
+
}
|
19
|
+
}
|
20
|
+
|
21
|
+
/* Capture SSL session keys in NSS Key Log Format
|
22
|
+
*
|
23
|
+
* @param socket [OpenSSL::SSL::SSLSocket] A SSL socket instance to capture
|
24
|
+
* data from.
|
25
|
+
* @return [String] A string containing SSL session data.
|
26
|
+
* @return [nil] If `socket` has negotiated a SSLv2 connection.
|
27
|
+
* @return [nil] If `socket` has not been connected.
|
28
|
+
*
|
29
|
+
* @raise [TypeError] If `socket` is not an instance of
|
30
|
+
* `OpenSSL::SSL::SSLSocket`.
|
31
|
+
*/
|
32
|
+
static VALUE
|
33
|
+
to_keylog(VALUE mod, VALUE socket)
|
34
|
+
{
|
35
|
+
SSL *ssl;
|
36
|
+
// 14 byte header string
|
37
|
+
// + 64 byte hex encoded client random
|
38
|
+
// + 1 space
|
39
|
+
// + 96 byte hex encoded master secret
|
40
|
+
// + newline.
|
41
|
+
size_t buf_len = 14 + 64 + 1 + 96 + 1;
|
42
|
+
char buf[buf_len];
|
43
|
+
unsigned int i;
|
44
|
+
|
45
|
+
// PRIsVALUE is a special format string that causes functions like rb_raise
|
46
|
+
// to format data of type VALUE by calling `.to_s` on the Ruby object.
|
47
|
+
if (!rb_obj_is_instance_of(socket, cSSLSocket)) {
|
48
|
+
rb_raise(rb_eTypeError, "wrong argument (%"PRIsVALUE")! (Expected instance of %"PRIsVALUE")",
|
49
|
+
rb_obj_class(socket), cSSLSocket);
|
50
|
+
}
|
51
|
+
|
52
|
+
// NOTE: Should be able to use Data_Get_Struct here, but for some reason the
|
53
|
+
// SSLSocket instance passed to this function as `socket` fails the
|
54
|
+
// type check.
|
55
|
+
//
|
56
|
+
// So, we live dangerously and go directly for the data pointer.
|
57
|
+
ssl = (SSL*)DATA_PTR(socket);
|
58
|
+
|
59
|
+
// Check to see if the SSL data structure has been populated.
|
60
|
+
//
|
61
|
+
// NOTE: If the `s3` component is missing then SSLv2 is in use and we bail
|
62
|
+
// out. Such a thing is a bit crazy these days, but we could handle it in a
|
63
|
+
// more meaningful way by falling back to the old NSS Key Log format:
|
64
|
+
//
|
65
|
+
// RSA Session-ID:<16 byte session id> Master-Key:<48 byte master key>
|
66
|
+
if ( !(ssl) || !(ssl->session) || !(ssl->s3) ){
|
67
|
+
return Qnil;
|
68
|
+
}
|
69
|
+
|
70
|
+
memcpy(buf, "CLIENT_RANDOM ", 14);
|
71
|
+
i = 14;
|
72
|
+
hex_encode(buf + i, 32, ssl->s3->client_random);
|
73
|
+
i += 64;
|
74
|
+
buf[i++] = ' ';
|
75
|
+
hex_encode(buf + i, 48, ssl->session->master_key);
|
76
|
+
i += 96;
|
77
|
+
buf[i++] = '\n';
|
78
|
+
|
79
|
+
return rb_str_new(buf, buf_len);
|
80
|
+
}
|
81
|
+
|
82
|
+
/* Document-module: SSLkeylog::OpenSSL
|
83
|
+
*
|
84
|
+
* Generate NSS Key Log entries from Ruby OpenSSL objects
|
85
|
+
*
|
86
|
+
* The NSS Key Log format contains two pieces of information that can be used
|
87
|
+
* to decrypt SSL session data:
|
88
|
+
*
|
89
|
+
* 1. A string of 32 random bytes sent by the client during the
|
90
|
+
* "Client Hello" phase of the SSL handshake.
|
91
|
+
*
|
92
|
+
* 2. A string of 48 bytes generated during the handshake that is the
|
93
|
+
* "pre-master key" required to decrypt the data.
|
94
|
+
*
|
95
|
+
* The Ruby OpenSSL library exposes the pre-master key through the `to_text`
|
96
|
+
* method of `OpenSSL::SSL::Session` objects. Unfortunately, there is no way
|
97
|
+
* to access the client random data at the Ruby level. However, many Ruby
|
98
|
+
* objects are simple wrappers for C data structures and the OpenSSL `SSL`
|
99
|
+
* struct does contains all the data we need --- including the client random
|
100
|
+
* data. The Ruby object which wraps `struct SSL` is
|
101
|
+
* `OpenSSL::SSL::SSLSocket`. This `to_keylog` method provided is a simple C
|
102
|
+
* extension which un-wraps `SSLSocket` objects at the C level and reads the
|
103
|
+
* data required form a NSS Key Log entry.
|
104
|
+
*/
|
105
|
+
void
|
106
|
+
Init_openssl()
|
107
|
+
{
|
108
|
+
rb_require("openssl");
|
109
|
+
|
110
|
+
// Retrieve OpenSSL namespaces.
|
111
|
+
mOpenSSL = rb_const_get(rb_cObject, rb_intern("OpenSSL"));
|
112
|
+
mSSL = rb_const_get(mOpenSSL, rb_intern("SSL"));
|
113
|
+
cSSLSocket = rb_const_get(mSSL, rb_intern("SSLSocket"));
|
114
|
+
|
115
|
+
VALUE mSSLkeylog = rb_const_get(rb_cObject, rb_intern("SSLkeylog"));
|
116
|
+
|
117
|
+
VALUE mSSLkeylogOpenSSL = rb_define_module_under(mSSLkeylog, "OpenSSL");
|
118
|
+
rb_define_singleton_method(mSSLkeylogOpenSSL, "to_keylog", to_keylog, 1);
|
119
|
+
|
120
|
+
/* The version string of the OpenSSL headers used to build this library.
|
121
|
+
*
|
122
|
+
* @return [String] The OPENSSL_VERSION_TEXT definition from the OpenSSL
|
123
|
+
* header this library was built against.
|
124
|
+
*/
|
125
|
+
rb_define_const(mSSLkeylogOpenSSL, "OPENSSL_VERSION", rb_str_new2(OPENSSL_VERSION_TEXT));
|
126
|
+
|
127
|
+
/* The numeric version of the OpenSSL headers used to build this library.
|
128
|
+
*
|
129
|
+
* @return [Integer] The OPENSSL_VERSION_NUMBER definition from the OpenSSL
|
130
|
+
* header this library was built against.
|
131
|
+
*/
|
132
|
+
rb_define_const(mSSLkeylogOpenSSL, "OPENSSL_VERSION_NUMBER", INT2NUM(OPENSSL_VERSION_NUMBER));
|
133
|
+
}
|
data/lib/sslkeylog.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'logger'
|
2
|
+
|
3
|
+
module SSLkeylog
|
4
|
+
# This module configures logging used by SSL tracing
|
5
|
+
module Logging
|
6
|
+
class << self
|
7
|
+
# The global logger used by SSL tracers
|
8
|
+
#
|
9
|
+
# Must be set to an object that implements the interface provided by the
|
10
|
+
# standard Ruby `Logger` library.
|
11
|
+
#
|
12
|
+
# @return [Logger]
|
13
|
+
attr_accessor :logger
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns a default Logger formatter for NSS Key Log messages
|
17
|
+
#
|
18
|
+
# This formatter simply echoes any message without adding additional data
|
19
|
+
# such as timestamp, severity, etc.
|
20
|
+
#
|
21
|
+
# @return [Proc]
|
22
|
+
def self.default_formatter
|
23
|
+
Proc.new do |severity, datetime, progname, msg|
|
24
|
+
msg
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns a default Logger for NSS Key Log messages
|
29
|
+
#
|
30
|
+
# @return [Logger] A logger that appends to a file specified by the
|
31
|
+
# `SSLKEYLOG` environment variable.
|
32
|
+
# @return [Logger] A logger that writes to `$stderr` if the `SSLKEYLOG`
|
33
|
+
# environment variable is not set.
|
34
|
+
def self.default_logger
|
35
|
+
if ENV['SSLKEYLOG']
|
36
|
+
output = File.open(ENV['SSLKEYLOG'], 'a')
|
37
|
+
# Flush output after every write as an external process, such as
|
38
|
+
# Wireshark, may be watching this file.
|
39
|
+
output.sync = true
|
40
|
+
else
|
41
|
+
output = $stderr
|
42
|
+
end
|
43
|
+
|
44
|
+
logger = Logger.new(output)
|
45
|
+
logger.formatter = default_formatter
|
46
|
+
|
47
|
+
logger
|
48
|
+
end
|
49
|
+
|
50
|
+
self.logger = self.default_logger
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'sslkeylog/logging'
|
2
|
+
|
3
|
+
module SSLkeylog
|
4
|
+
|
5
|
+
# This module provides methods for tracing SSL connections
|
6
|
+
#
|
7
|
+
# Currently, tracing is only implemented for client connections. Tracing of
|
8
|
+
# connections accepted by servers is not implemented. Tracing is implemented
|
9
|
+
# using the Ruby 2.x `TracePoint` API.
|
10
|
+
module Trace
|
11
|
+
# A TracePoint that watches SSL client connections
|
12
|
+
#
|
13
|
+
# This tracepoint watches for returns from `OpenSSL::SSL::SSLSocket#connect`
|
14
|
+
# and logs the pre master secret to the logger returned by
|
15
|
+
# {SSLkeylog::Logging.logger}. Messages are logged at `info` level.
|
16
|
+
#
|
17
|
+
# @return [TracePoint]
|
18
|
+
CLIENT_TRACER = TracePoint.new(:c_return) do |tp|
|
19
|
+
if tp.method_id == :connect && tp.defined_class == ::OpenSSL::SSL::SSLSocket
|
20
|
+
ssl_info = ::SSLkeylog::OpenSSL.to_keylog(tp.self)
|
21
|
+
::SSLkeylog::Logging.logger.info(ssl_info) unless ssl_info.nil?
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
# Enable tracing of SSL connections
|
26
|
+
#
|
27
|
+
# @return [void]
|
28
|
+
def self.enable
|
29
|
+
CLIENT_TRACER.enable
|
30
|
+
end
|
31
|
+
|
32
|
+
# Disable tracing of SSL connections
|
33
|
+
#
|
34
|
+
# @return [void]
|
35
|
+
def self.disable
|
36
|
+
CLIENT_TRACER.disable
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'stringio'
|
3
|
+
|
4
|
+
describe 'OpenSSL client connections' do
|
5
|
+
let(:ssl_server_address) { '127.0.0.1' }
|
6
|
+
let(:ssl_server_port) { 9045 }
|
7
|
+
include_context 'ssl_server'
|
8
|
+
|
9
|
+
before(:each) do
|
10
|
+
@tcp_socket = TCPSocket.new(ssl_server_address, ssl_server_port)
|
11
|
+
@ssl_socket = OpenSSL::SSL::SSLSocket.new(@tcp_socket)
|
12
|
+
end
|
13
|
+
|
14
|
+
context 'before a connection is established' do
|
15
|
+
after(:each) { @tcp_socket.close }
|
16
|
+
|
17
|
+
it 'returns nil' do
|
18
|
+
expect(SSLkeylog::OpenSSL.to_keylog(@ssl_socket)).to be_nil
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'after a connection is established' do
|
23
|
+
before(:each) { @ssl_socket.connect }
|
24
|
+
after(:each) { @ssl_socket.close }
|
25
|
+
|
26
|
+
it 'returns a string starting with CLIENT_RANDOM' do
|
27
|
+
expect(SSLkeylog::OpenSSL.to_keylog(@ssl_socket)).to start_with('CLIENT_RANDOM')
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'contains the session master key' do
|
31
|
+
logged_key = SSLkeylog::OpenSSL.to_keylog(@ssl_socket).split.last.strip
|
32
|
+
master_key = @ssl_socket.session.to_text.lines.find {|l| l.match /^\s*Master-Key:/}.partition(': ').last.strip
|
33
|
+
|
34
|
+
expect(logged_key).to match(master_key)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'when tracing is enabled' do
|
39
|
+
subject { StringIO.new }
|
40
|
+
|
41
|
+
before(:each) do
|
42
|
+
logger = Logger.new(subject)
|
43
|
+
logger.formatter = SSLkeylog::Logging.default_formatter
|
44
|
+
SSLkeylog::Logging.logger = logger # TODO: Replace with a mock.
|
45
|
+
|
46
|
+
SSLkeylog::Trace.enable
|
47
|
+
@ssl_socket.connect
|
48
|
+
end
|
49
|
+
after(:each) do
|
50
|
+
@ssl_socket.close
|
51
|
+
SSLkeylog::Trace.disable
|
52
|
+
end
|
53
|
+
|
54
|
+
it 'logs the session master key' do
|
55
|
+
logged_key = subject.string.split.last.strip
|
56
|
+
master_key = @ssl_socket.session.to_text.lines.find {|l| l.match /^\s*Master-Key:/}.partition(': ').last.strip
|
57
|
+
|
58
|
+
expect(logged_key).to match(master_key)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'webrick/https'
|
2
|
+
|
3
|
+
# This context runs an OpenSSL::SSL:SSLServer that is accessible to tests. The
|
4
|
+
# `ssl_server_port` and `ssl_server_address` will need to be specified before
|
5
|
+
# this context is included:
|
6
|
+
#
|
7
|
+
# let(:ssl_server_address) { ... }
|
8
|
+
# let(:ssl_server_port) { ... }
|
9
|
+
# include 'ssl_server'
|
10
|
+
shared_context 'ssl_server' do
|
11
|
+
before(:each) do
|
12
|
+
@server = WEBrick::HTTPServer.new(
|
13
|
+
:BindAddress => ssl_server_address,
|
14
|
+
:Port => ssl_server_port,
|
15
|
+
:SSLEnable => true,
|
16
|
+
:SSLCertName => [%w[CN localhost]],
|
17
|
+
:Logger => WEBrick::Log.new(nil, WEBrick::BasicLog::WARN),
|
18
|
+
)
|
19
|
+
@thread = Thread.new { @server.start }
|
20
|
+
end
|
21
|
+
|
22
|
+
after(:each) do
|
23
|
+
@server.shutdown rescue nil
|
24
|
+
@thread.join rescue nil
|
25
|
+
end
|
26
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe SSLkeylog::OpenSSL do
|
4
|
+
it 'reports the OPENSSL_VERSION it was built against' do
|
5
|
+
expect(SSLkeylog::OpenSSL::OPENSSL_VERSION).to match(/^OpenSSL/)
|
6
|
+
end
|
7
|
+
|
8
|
+
it 'reports the OPENSSL_VERSION_NUMBER it was built against' do
|
9
|
+
expect(SSLkeylog::OpenSSL::OPENSSL_VERSION_NUMBER).to be_a(Integer)
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '.to_keylog' do
|
13
|
+
it 'rejects arguments that are not SSLSocket objects' do
|
14
|
+
expect { described_class.to_keylog('foo') }.to raise_error(TypeError,
|
15
|
+
/Expected instance of OpenSSL::SSL::SSLSocket\)$/)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
data/sslkeylog.gemspec
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'sslkeylog/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'sslkeylog'
|
8
|
+
spec.version = SSLkeylog::VERSION
|
9
|
+
spec.authors = ['Charlie Sharpsteen']
|
10
|
+
spec.email = ['source@sharpsteen.net']
|
11
|
+
spec.license = 'MIT'
|
12
|
+
|
13
|
+
spec.summary = 'A Ruby library that logs SSL session keys in NSS Key Log Format.'
|
14
|
+
spec.homepage = 'https://github.com/Sharpie/sslkeylog'
|
15
|
+
|
16
|
+
spec.files = %x[git ls-files].split($/)
|
17
|
+
spec.require_paths = ['lib']
|
18
|
+
spec.extensions = Dir['ext/**/extconf.rb']
|
19
|
+
|
20
|
+
spec.required_ruby_version = '>= 2.0.0'
|
21
|
+
|
22
|
+
spec.add_development_dependency 'rake'
|
23
|
+
spec.add_development_dependency 'rake-compiler'
|
24
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
25
|
+
end
|
data/tasks/compile.rake
ADDED
data/tasks/spec.rake
ADDED
data/tasks/yard.rake
ADDED
metadata
ADDED
@@ -0,0 +1,112 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sslkeylog
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.2.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Charlie Sharpsteen
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-04-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :development
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: rake-compiler
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '3.0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '3.0'
|
55
|
+
description:
|
56
|
+
email:
|
57
|
+
- source@sharpsteen.net
|
58
|
+
executables: []
|
59
|
+
extensions:
|
60
|
+
- ext/openssl/extconf.rb
|
61
|
+
extra_rdoc_files: []
|
62
|
+
files:
|
63
|
+
- ".gitignore"
|
64
|
+
- ".rspec"
|
65
|
+
- ".travis.yml"
|
66
|
+
- ".yardopts"
|
67
|
+
- CHANGELOG.md
|
68
|
+
- Gemfile
|
69
|
+
- LICENSE
|
70
|
+
- README.md
|
71
|
+
- Rakefile
|
72
|
+
- ext/openssl/extconf.rb
|
73
|
+
- ext/openssl/openssl.c
|
74
|
+
- lib/sslkeylog.rb
|
75
|
+
- lib/sslkeylog/autotrace.rb
|
76
|
+
- lib/sslkeylog/logging.rb
|
77
|
+
- lib/sslkeylog/trace.rb
|
78
|
+
- lib/sslkeylog/version.rb
|
79
|
+
- spec/integration/client_spec.rb
|
80
|
+
- spec/shared/ssl_server_context.rb
|
81
|
+
- spec/spec_helper.rb
|
82
|
+
- spec/unit/sslkeylog_openssl_spec.rb
|
83
|
+
- sslkeylog.gemspec
|
84
|
+
- tasks/compile.rake
|
85
|
+
- tasks/spec.rake
|
86
|
+
- tasks/yard.rake
|
87
|
+
homepage: https://github.com/Sharpie/sslkeylog
|
88
|
+
licenses:
|
89
|
+
- MIT
|
90
|
+
metadata: {}
|
91
|
+
post_install_message:
|
92
|
+
rdoc_options: []
|
93
|
+
require_paths:
|
94
|
+
- lib
|
95
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
96
|
+
requirements:
|
97
|
+
- - ">="
|
98
|
+
- !ruby/object:Gem::Version
|
99
|
+
version: 2.0.0
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
requirements:
|
102
|
+
- - ">="
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
requirements: []
|
106
|
+
rubyforge_project:
|
107
|
+
rubygems_version: 2.2.2
|
108
|
+
signing_key:
|
109
|
+
specification_version: 4
|
110
|
+
summary: A Ruby library that logs SSL session keys in NSS Key Log Format.
|
111
|
+
test_files: []
|
112
|
+
has_rdoc:
|