sslsmart 1.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.
- data/LICENSE.txt +45 -0
- data/README +5 -0
- data/bin/fs_icon_32.ico +0 -0
- data/bin/resultcontainer.rb +11 -0
- data/bin/rootcerts.pem +3509 -0
- data/bin/sslsmartconfig.rb +177 -0
- data/bin/sslsmartcontroller.rb +351 -0
- data/bin/sslsmartdb.rb +151 -0
- data/bin/sslsmartgui.rb +888 -0
- data/bin/sslsmartlib.rb +287 -0
- data/bin/sslsmartlog.rb +35 -0
- data/bin/sslsmartmisc.rb +50 -0
- data/sample.rb +19 -0
- data/sslsmart.gemspec +20 -0
- metadata +110 -0
data/bin/sslsmartlib.rb
ADDED
@@ -0,0 +1,287 @@
|
|
1
|
+
# Gursev Singh Kalra @ Foundstone(McAfee)
|
2
|
+
# Please see LICENSE.txt for licensing information
|
3
|
+
|
4
|
+
require 'net/https'
|
5
|
+
require 'singleton'
|
6
|
+
require 'uri'
|
7
|
+
require 'resultcontainer'
|
8
|
+
require 'sslsmartlog'
|
9
|
+
|
10
|
+
$log = SSLSmartLog.instance
|
11
|
+
|
12
|
+
module OpenSSL
|
13
|
+
module SSL
|
14
|
+
if(RUBY_VERSION =~ /^1\.8\.6/)
|
15
|
+
class SSLContext
|
16
|
+
RAW = 0
|
17
|
+
SPLIT = 1
|
18
|
+
DEFAULT_PARAMS = {
|
19
|
+
:verify_mode => OpenSSL::SSL::VERIFY_PEER,
|
20
|
+
:ciphers => "ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW",
|
21
|
+
:options => OpenSSL::SSL::OP_ALL,
|
22
|
+
}
|
23
|
+
|
24
|
+
|
25
|
+
def set_params(params={})
|
26
|
+
begin
|
27
|
+
$log.debug("Setting parameters #{params.inspect}") if(params!= {})
|
28
|
+
params = DEFAULT_PARAMS.merge(params)
|
29
|
+
params.each do|name, value|
|
30
|
+
next if(name == :ssl_version) #1.8.6 does not have ssl_version method
|
31
|
+
self.__send__("#{name}=", value)
|
32
|
+
end
|
33
|
+
rescue => ex
|
34
|
+
$log.error("#{ex.class}\t#{ex.message}")
|
35
|
+
raise
|
36
|
+
end
|
37
|
+
return params
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end #End of if(RUBY_VERSION =~ /^1\.8/)
|
43
|
+
|
44
|
+
|
45
|
+
def SSL.get_cipher_suites(filter)
|
46
|
+
$log.debug("requesting cipher suites with filter")
|
47
|
+
# Making the filters case insensitive
|
48
|
+
filter = filter.gsub(/tlsv1/i, "TLSv1").gsub(/sslv3/i, "SSLv3").gsub(/sslv2/i, "SSLv2")
|
49
|
+
version = :SSLv23
|
50
|
+
begin
|
51
|
+
# RUBY 1.8.6 OpenSSL api is not compatible with 1.9 for purpose required here
|
52
|
+
# Using the existing implementation to get ciphers suites
|
53
|
+
ncontext = OpenSSL::SSL::SSLContext.new
|
54
|
+
ohash = {:ciphers => filter, :ssl_version => version}
|
55
|
+
ncontext.set_params(ohash)
|
56
|
+
return ncontext.ciphers
|
57
|
+
rescue => ex
|
58
|
+
$log.error(ex.message)
|
59
|
+
raise ex
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
|
64
|
+
def SSL.get_mod_cipher_suites(filter)
|
65
|
+
$log.debug("requesting modified cipher suites with filter")
|
66
|
+
begin
|
67
|
+
suites = OpenSSL::SSL.get_cipher_suites(filter)
|
68
|
+
rescue => ex
|
69
|
+
$log.error(ex.message)
|
70
|
+
raise ex
|
71
|
+
end
|
72
|
+
|
73
|
+
sslv2 = []
|
74
|
+
sslv3 = []
|
75
|
+
tlsv1 = []
|
76
|
+
suites.each do |x|
|
77
|
+
case x[1]
|
78
|
+
when "SSLv2"
|
79
|
+
sslv2 << x
|
80
|
+
when "TLSv1/SSLv3"
|
81
|
+
#Suite Name -- Version -- Key Length -- Cipher Supported Key Length
|
82
|
+
sslv3 << [x[0], "SSLv3", x[2],x[3]]
|
83
|
+
tlsv1 << [x[0], "TLSv1", x[2],x[3]]
|
84
|
+
end
|
85
|
+
end
|
86
|
+
sslv2 + sslv3 + tlsv1
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
|
93
|
+
module Net
|
94
|
+
class HTTP
|
95
|
+
# Required for Ruby 1.9 support.
|
96
|
+
attr_accessor :enable_post_connection_check
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
module Net
|
101
|
+
class HTTP
|
102
|
+
|
103
|
+
CONNECT = 0
|
104
|
+
CONTENT = 1
|
105
|
+
CA_ROOT_BUNDLE = "rootcerts.pem"
|
106
|
+
|
107
|
+
|
108
|
+
# Verifies a given SSL configuration. It performs
|
109
|
+
# Few valid function calls
|
110
|
+
# rq.verify_ssl_config(:SSLv2, nil, Net::HTTP::CONTENT, "/")
|
111
|
+
# rq.verify_ssl_config(:SSLv3, ["AES256-SHA", "DES-CBC3-SHA","EXP-RC2-CBC-MD5"], Net::HTTP::CONTENT, "/")
|
112
|
+
# rq.verify_ssl_config(:SSLv3, "AES256-SHA", Net::HTTP::CONTENT, "/")
|
113
|
+
def verify_ssl_config(version, cipher_suite, scan_type, *args)
|
114
|
+
$log.debug("Verifying ssl configuration #{version}\t#{cipher_suite}\t#{scan_type}")
|
115
|
+
set_ssl_config(version, cipher_suite)
|
116
|
+
disable_validations
|
117
|
+
|
118
|
+
case scan_type
|
119
|
+
when CONNECT
|
120
|
+
return self.ssl_connect
|
121
|
+
when CONTENT
|
122
|
+
begin
|
123
|
+
response = self.get(*args)
|
124
|
+
return ResultContainer.new(true, response)
|
125
|
+
rescue OpenSSL::SSL::SSLError => ex
|
126
|
+
return ResultContainer.new(false, ex)
|
127
|
+
rescue => ex1
|
128
|
+
return ResultContainer.new(false, ex1)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
end
|
133
|
+
|
134
|
+
# Set SSL configuration for an HTTP Request.
|
135
|
+
# version provides the SSL version to be used for request. The value can be :SSLv2, :SSLv3, TLSv1 or SSLv23
|
136
|
+
# cipher_suite accepts the value of cipher suite to be used for a given request.
|
137
|
+
# The cipher suite values supported for a give version can be obtained by Net::HTTP::get_ssl_ciphers or Net::HTTP::get_ssl_ciphers_and_keylen class methods
|
138
|
+
def set_ssl_config(version, cipher_suite = nil)
|
139
|
+
$log.debug("Setting ssl configuration #{version}, #{cipher_suite}")
|
140
|
+
self.use_ssl = true
|
141
|
+
|
142
|
+
self.set_context = version
|
143
|
+
if(self.respond_to?(:ssl_version)) # For Ruby 1.9
|
144
|
+
self.ssl_version = version
|
145
|
+
end
|
146
|
+
self.ciphers = cipher_suite if(cipher_suite)
|
147
|
+
disable_validations
|
148
|
+
end
|
149
|
+
|
150
|
+
|
151
|
+
# Returns SSL Certificate details
|
152
|
+
def get_cert_details()
|
153
|
+
$log.debug("Returning certificate details")
|
154
|
+
self.use_ssl = true
|
155
|
+
disable_validations
|
156
|
+
begin
|
157
|
+
self.start do |x|
|
158
|
+
return ResultContainer.new(true, x.peer_cert)
|
159
|
+
end
|
160
|
+
rescue => ex
|
161
|
+
return ResultContainer.new(false, ex)
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
|
166
|
+
# PATH to Bundle of CA Root Certificates has to be prvided as a ca_root_bundle parameter.
|
167
|
+
# Mozilla Firefox Bundle of CA Root Certificates can be downloade from http://curl.haxx.se/ca/cacert.pem for your own use.
|
168
|
+
def verify_cert(ca_root_bundle = CA_ROOT_BUNDLE)
|
169
|
+
$log.debug("Verifying certificate")
|
170
|
+
ca_root_bundle = CA_ROOT_BUNDLE unless(ca_root_bundle)
|
171
|
+
unless (File.exist?(ca_root_bundle) && File.file?(ca_root_bundle))
|
172
|
+
return ResultContainer.new(false, "Invalid certificate file #{ca_root_bundle}")
|
173
|
+
end
|
174
|
+
|
175
|
+
self.use_ssl = true
|
176
|
+
enable_validations
|
177
|
+
self.ca_file = ca_root_bundle
|
178
|
+
begin
|
179
|
+
self.start do |x|
|
180
|
+
x.peer_cert
|
181
|
+
return ResultContainer.new(true, x.peer_cert)
|
182
|
+
end
|
183
|
+
rescue => ex
|
184
|
+
return ResultContainer.new(false, ex)
|
185
|
+
end
|
186
|
+
end
|
187
|
+
|
188
|
+
|
189
|
+
# This block supports connect scans only
|
190
|
+
def ssl_connect()
|
191
|
+
$log.debug("Initiating SSL Connect Test")
|
192
|
+
disable_validations
|
193
|
+
s = timeout(@open_timeout) { TCPSocket.open(conn_address(), conn_port()) }
|
194
|
+
s = OpenSSL::SSL::SSLSocket.new(s, @ssl_context)
|
195
|
+
s.sync_close = true
|
196
|
+
|
197
|
+
@socket = BufferedIO.new(s)
|
198
|
+
@socket.read_timeout = @read_timeout
|
199
|
+
@socket.debug_output = @debug_output
|
200
|
+
|
201
|
+
if proxy?
|
202
|
+
@socket.writeline sprintf('CONNECT %s:%s HTTP/%s', @address, @port, HTTPVersion)
|
203
|
+
@socket.writeline "Host: #{@address}:#{@port}"
|
204
|
+
@socket.writeline ''
|
205
|
+
HTTPResponse.read_new(@socket).value
|
206
|
+
end
|
207
|
+
|
208
|
+
begin
|
209
|
+
s.connect
|
210
|
+
return ResultContainer.new(true, nil)
|
211
|
+
rescue OpenSSL::SSL::SSLError => ex
|
212
|
+
return ResultContainer.new(false, ex)
|
213
|
+
rescue => ex2
|
214
|
+
return ResultContainer.new(false, ex2)
|
215
|
+
end
|
216
|
+
end
|
217
|
+
|
218
|
+
|
219
|
+
def enable_validations
|
220
|
+
#$log.debug("Enabling all validations")
|
221
|
+
self.enable_post_connection_check = true
|
222
|
+
verify_peer
|
223
|
+
end
|
224
|
+
|
225
|
+
|
226
|
+
def disable_validations
|
227
|
+
#$log.debug("Disabling all validations")
|
228
|
+
self.enable_post_connection_check = false
|
229
|
+
verify_none
|
230
|
+
end
|
231
|
+
|
232
|
+
|
233
|
+
# Turns on certificate validation for given HTTP request. If not used, a warning will be seen during the enumeration.
|
234
|
+
def verify_peer
|
235
|
+
#$log.debug("Enabling peer verification")
|
236
|
+
self.verify_mode = OpenSSL::SSL::VERIFY_PEER
|
237
|
+
end
|
238
|
+
|
239
|
+
|
240
|
+
# Turns off certificate validation for given HTTP request. If not used, a warning will be seen during the enumeration.
|
241
|
+
def verify_none
|
242
|
+
#$log.debug("Disabling peer validation")
|
243
|
+
self.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
244
|
+
end
|
245
|
+
|
246
|
+
|
247
|
+
# Sets context for a given HTTP request. The values accepted are any of valid SSL versions
|
248
|
+
def set_context=(value)
|
249
|
+
$log.debug("Setting context to #{value}")
|
250
|
+
@ssl_context ||= OpenSSL::SSL::SSLContext.new #Create a new context
|
251
|
+
@ssl_context &&= OpenSSL::SSL::SSLContext.new(value)
|
252
|
+
end
|
253
|
+
|
254
|
+
|
255
|
+
# Creating a private which allows ciphers to be set for a given HTTP request.
|
256
|
+
if RUBY_VERSION =~ /^1\.8/
|
257
|
+
ssl_context_accessor :ciphers
|
258
|
+
end
|
259
|
+
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
# Single unified interface to generate ciphers for OpenSSL filters
|
264
|
+
def get_cipher_suites(filter)
|
265
|
+
|
266
|
+
$log.debug("Requesting for get_cipher_suites standalone method of SSLSmartLib")
|
267
|
+
version = :SSLv23
|
268
|
+
begin
|
269
|
+
# RUBY 1.8.6 OpenSSL api is not compatible with 1.9 for purpose required here
|
270
|
+
# Using the existing implementation to get ciphers suites
|
271
|
+
if(RUBY_VERSION =~ /^1\.8/)
|
272
|
+
rq = Net::HTTP.new('dummy')
|
273
|
+
rq.set_ssl_config(version, filter) # Either this line of the three commented lines do the JOB
|
274
|
+
return rq.ciphers
|
275
|
+
elsif(RUBY_VERSION =~ /^1\.9/)
|
276
|
+
# RUBY 1.9 library call does not return cipher array when ciphers function is called on an HTTP object.
|
277
|
+
# The code below talks directly to OpenSSL Library and extracts the information.
|
278
|
+
ncontext = OpenSSL::SSL::SSLContext.new
|
279
|
+
ohash = {:ciphers => filter, :ssl_version => version}
|
280
|
+
ncontext.set_params(ohash)
|
281
|
+
return ncontext.ciphers
|
282
|
+
end
|
283
|
+
rescue => ex
|
284
|
+
$log.error(ex.message)
|
285
|
+
raise ex
|
286
|
+
end
|
287
|
+
end
|
data/bin/sslsmartlog.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# Gursev Singh Kalra @ Foundstone(McAfee)
|
2
|
+
# Please see LICENSE.txt for licensing information
|
3
|
+
|
4
|
+
require 'logger'
|
5
|
+
require 'singleton'
|
6
|
+
|
7
|
+
class SSLSmartLog
|
8
|
+
include Singleton
|
9
|
+
def initialize
|
10
|
+
@logfile = Logger.new('SSLSmart.log', 'daily')
|
11
|
+
@logfile.level = Logger::INFO
|
12
|
+
#@logfile.level = Logger::DEBUG
|
13
|
+
end
|
14
|
+
|
15
|
+
def fatal(message)
|
16
|
+
@logfile.fatal(message)
|
17
|
+
end
|
18
|
+
|
19
|
+
def error(message)
|
20
|
+
@logfile.error(message)
|
21
|
+
end
|
22
|
+
|
23
|
+
def warn(message)
|
24
|
+
@logfile.warn(message)
|
25
|
+
end
|
26
|
+
|
27
|
+
def info(message)
|
28
|
+
@logfile.info(message)
|
29
|
+
end
|
30
|
+
|
31
|
+
def debug(message)
|
32
|
+
@logfile.debug(message)
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
data/bin/sslsmartmisc.rb
ADDED
@@ -0,0 +1,50 @@
|
|
1
|
+
# Gursev Singh Kalra @ Foundstone(McAfee)
|
2
|
+
# Please see LICENSE.txt for licensing information
|
3
|
+
|
4
|
+
require 'uri'
|
5
|
+
require 'sslsmartlog'
|
6
|
+
|
7
|
+
$log = SSLSmartLog.instance
|
8
|
+
|
9
|
+
module SSLSmartMisc
|
10
|
+
|
11
|
+
def convert_to_url(line)
|
12
|
+
line.strip!
|
13
|
+
if(line == "")
|
14
|
+
$log.warn("No hostname provided")
|
15
|
+
return nil
|
16
|
+
end
|
17
|
+
|
18
|
+
line.sub!(/^https?:\/\//,"") if(line =~ /^https?:\/\//)
|
19
|
+
line[0,0] = 'https://'
|
20
|
+
begin
|
21
|
+
uri = URI.parse(line)
|
22
|
+
rescue URI::Error => e
|
23
|
+
$log.warn(e.message)
|
24
|
+
return nil
|
25
|
+
end
|
26
|
+
|
27
|
+
uri.path = "/" if(uri.path == "")
|
28
|
+
uri.to_s
|
29
|
+
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
def get_urls_from_file(filename)
|
34
|
+
|
35
|
+
unless(File.file?(filename))
|
36
|
+
$log.error("Invalid Filename #{filename}")
|
37
|
+
return nil
|
38
|
+
end
|
39
|
+
|
40
|
+
urls = []
|
41
|
+
File.open(filename) do |f|
|
42
|
+
f.each do |line|
|
43
|
+
url = convert_to_url(line) if(line.strip != "")
|
44
|
+
urls << url if(url)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
urls
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
data/sample.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
# Gursev Singh Kalra @ Foundstone
|
2
|
+
require 'bin/sslsmartlib'
|
3
|
+
|
4
|
+
host = ARGV[0]
|
5
|
+
port = ARGV[1]
|
6
|
+
|
7
|
+
suites = OpenSSL::SSL.get_mod_cipher_suites("SSLv3:!NULL:!aNULL")
|
8
|
+
q = Net::HTTP.new(host,port)
|
9
|
+
|
10
|
+
suites.each do |suite, version, bits, klen|
|
11
|
+
a = q.verify_ssl_config(version, suite, Net::HTTP::CONTENT, "/")
|
12
|
+
case a.status
|
13
|
+
when true
|
14
|
+
print "\n[+] Accepted%7s %-25s%5s bits %-s" % [version, suite, bits, a.data.body]
|
15
|
+
when false
|
16
|
+
print "\n[-] Rejected%7s %-25s%5s bits %-s" % [version, suite, bits, a.data]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
data/sslsmart.gemspec
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
# Gursev Singh Kalra @ Foundstone(McAfee)
|
2
|
+
# Please see LICENSE.txt for licensing information
|
3
|
+
|
4
|
+
require 'rubygems'
|
5
|
+
SPEC = Gem::Specification.new do |s|
|
6
|
+
s.name = 'sslsmart'
|
7
|
+
s.version = '1.0'
|
8
|
+
s.authors = ['Gursev Singh Kalra']
|
9
|
+
s.email = %q{gursev.kalra@foundstone.com}
|
10
|
+
s.files = ['bin/fs_icon_32.ico', 'bin/resultcontainer.rb', 'bin/rootcerts.pem', 'bin/sslsmartconfig.rb', 'bin/sslsmartcontroller.rb', 'bin/sslsmartdb.rb', 'bin/sslsmartgui.rb', 'bin/sslsmartlib.rb', 'bin/sslsmartlog.rb', 'bin/sslsmartmisc.rb', 'sslsmart.gemspec', 'README', 'sample.rb', 'LICENSE.txt']
|
11
|
+
s.homepage = 'http://www.foundstone.com'
|
12
|
+
s.platform = Gem::Platform::RUBY
|
13
|
+
s.require_paths = ["bin"]
|
14
|
+
s.summary = 'SSLSmart is a smart SSL cipher enumeration tool'
|
15
|
+
s.description = 'SSLSmart is an advanced and highly flexible Ruby based smart SSL cipher enumeration tool'
|
16
|
+
s.rubyforge_project = 'none'
|
17
|
+
s.add_dependency("wxruby", ">=2.0.0")
|
18
|
+
s.add_dependency("builder", ">=2.1.2")
|
19
|
+
|
20
|
+
end
|
metadata
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: sslsmart
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 15
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: "1.0"
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Gursev Singh Kalra
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-01-16 00:00:00 -05:00
|
18
|
+
default_executable:
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: wxruby
|
22
|
+
prerelease: false
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 15
|
29
|
+
segments:
|
30
|
+
- 2
|
31
|
+
- 0
|
32
|
+
- 0
|
33
|
+
version: 2.0.0
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: builder
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 15
|
45
|
+
segments:
|
46
|
+
- 2
|
47
|
+
- 1
|
48
|
+
- 2
|
49
|
+
version: 2.1.2
|
50
|
+
type: :runtime
|
51
|
+
version_requirements: *id002
|
52
|
+
description: SSLSmart is an advanced and highly flexible Ruby based smart SSL cipher enumeration tool
|
53
|
+
email: gursev.kalra@foundstone.com
|
54
|
+
executables: []
|
55
|
+
|
56
|
+
extensions: []
|
57
|
+
|
58
|
+
extra_rdoc_files: []
|
59
|
+
|
60
|
+
files:
|
61
|
+
- bin/fs_icon_32.ico
|
62
|
+
- bin/resultcontainer.rb
|
63
|
+
- bin/rootcerts.pem
|
64
|
+
- bin/sslsmartconfig.rb
|
65
|
+
- bin/sslsmartcontroller.rb
|
66
|
+
- bin/sslsmartdb.rb
|
67
|
+
- bin/sslsmartgui.rb
|
68
|
+
- bin/sslsmartlib.rb
|
69
|
+
- bin/sslsmartlog.rb
|
70
|
+
- bin/sslsmartmisc.rb
|
71
|
+
- sslsmart.gemspec
|
72
|
+
- README
|
73
|
+
- sample.rb
|
74
|
+
- LICENSE.txt
|
75
|
+
has_rdoc: true
|
76
|
+
homepage: http://www.foundstone.com
|
77
|
+
licenses: []
|
78
|
+
|
79
|
+
post_install_message:
|
80
|
+
rdoc_options: []
|
81
|
+
|
82
|
+
require_paths:
|
83
|
+
- bin
|
84
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
hash: 3
|
90
|
+
segments:
|
91
|
+
- 0
|
92
|
+
version: "0"
|
93
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
94
|
+
none: false
|
95
|
+
requirements:
|
96
|
+
- - ">="
|
97
|
+
- !ruby/object:Gem::Version
|
98
|
+
hash: 3
|
99
|
+
segments:
|
100
|
+
- 0
|
101
|
+
version: "0"
|
102
|
+
requirements: []
|
103
|
+
|
104
|
+
rubyforge_project: none
|
105
|
+
rubygems_version: 1.3.7
|
106
|
+
signing_key:
|
107
|
+
specification_version: 3
|
108
|
+
summary: SSLSmart is a smart SSL cipher enumeration tool
|
109
|
+
test_files: []
|
110
|
+
|