sslkeylog 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://travis-ci.org/Sharpie/sslkeylog.svg?branch=master)](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:
|