ssl_scan 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 50673d3e4606c2493184377cd66f2db894497d6f
4
+ data.tar.gz: ad1ba5de18c080d1c3a242eee07547be7480a784
5
+ SHA512:
6
+ metadata.gz: 61212e9922e16b59635a12da8794fb25899a5be0a92b17d70aba9e98be1d535091a06ed47857d19000ef5a95168bc0f3d584612ac0cb59013efb80ba42ce9f3b
7
+ data.tar.gz: 4392e0d06c46fe83fe2b2f119c830399c746b0f3cc6875f741f882e3ce8b24a2c6f95b1fb035acaeefd98a5ad401cca95819c8e2da3dd558dbd1882f74b38e3b
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in sslscan.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 John Faucett
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # SSLScan
2
+
3
+ SSLScan is an extraction of the the sslscan module from the [metasploit-framework](https://github.com/rapid7/metasploit-framework). It provides lower level tools for testing sslv2/3 and tls connections with servers.
4
+
5
+ However, the sslscan module in metasploit is mainly used for finding weakpoints in SSL armor. What this gem does is adapt some of that functionality to provide ways for the user to debug ssl connections and conversely make ssl connections work - not discover weakpoints. For instance, maybe in your client you are attempting to use SSLv3 to connect to a server and throwing exceptions, you could use this gem to find out that SSLv3 is not supported by the peer and use TLSv1 with the servers preferred cipher instead to allow your client application to still work.
6
+
7
+ In addition to the goals stated above, this library also provides a pure ruby implementation for [sslscan](http://sourceforge.net/projects/sslscan/), with some added nicities.
8
+
9
+
10
+ ## Installation
11
+
12
+ Add this line to your application's Gemfile:
13
+
14
+ gem 'sslscan'
15
+
16
+ And then execute:
17
+
18
+ $ bundle
19
+
20
+ Or install it yourself as:
21
+
22
+ $ gem install sslscan
23
+
24
+ ## Usage
25
+
26
+ ```ruby
27
+
28
+ require 'ssl_scan'
29
+ scanner = SSLScan::Scanner.new('example.com')
30
+
31
+ # returns an SSLScan::Result object containing a list of accepted/rejected ciphers, peer_supported ssl versions, etc.
32
+ scanner.scan
33
+
34
+ # show the ciphers which the server prefers
35
+ scanner.get_preferred_ciphers
36
+
37
+ # You can also pass a block to the scan function to be able to do things
38
+ # like write to a socket stream and get some feedback to your users
39
+ # - status can be either accepted or rejected for a particular cipher
40
+ scanner.scan do |ssl_version, cipher, key_length, status, cert|
41
+ # ...
42
+ end
43
+ ```
44
+
45
+ ## Contributing
46
+
47
+ 1. Fork it ( http://github.com/<my-github-username>/sslscan/fork )
48
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
49
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
50
+ 4. Push to the branch (`git push origin my-new-feature`)
51
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
data/bin/ssl_scan ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.expand_path("../../lib", __FILE__)
4
+ require 'ssl_scan/client'
File without changes
@@ -0,0 +1,388 @@
1
+ # -*- coding: binary -*-
2
+ module SSLScan
3
+
4
+ ###
5
+ #
6
+ # This class provides os-specific functionality
7
+ #
8
+ ###
9
+ module Compat
10
+
11
+ STD_INPUT_HANDLE = -10
12
+ STD_OUTPUT_HANDLE = -11
13
+ STD_ERROR_HANDLE = -12
14
+
15
+ GENERIC_READ = 0x80000000
16
+ GENERIC_WRITE = 0x40000000
17
+ GENERIC_EXECUTE = 0x20000000
18
+
19
+ FILE_SHARE_READ = 0x00000001
20
+ FILE_SHARE_WRITE = 0x00000002
21
+ OPEN_EXISTING = 0x00000003
22
+
23
+ ENABLE_LINE_INPUT = 2
24
+ ENABLE_ECHO_INPUT = 4
25
+ ENABLE_PROCESSED_INPUT = 1
26
+
27
+
28
+
29
+ #
30
+ # Platform detection
31
+ #
32
+
33
+ @@is_windows = @@is_cygwin = @@is_macosx = @@is_linux = @@is_bsdi = @@is_freebsd = @@is_netbsd = @@is_openbsd = @@is_java = false
34
+ @@loaded_win32api = false
35
+ @@loaded_tempfile = false
36
+ @@loaded_fileutils = false
37
+
38
+
39
+ def self.is_windows
40
+ return @@is_windows if @@is_windows
41
+ @@is_windows = (RUBY_PLATFORM =~ /mswin(32|64)|mingw(32|64)/) ? true : false
42
+ end
43
+
44
+ def self.is_cygwin
45
+ return @@is_cygwin if @@is_cygwin
46
+ @@is_cygwin = (RUBY_PLATFORM =~ /cygwin/) ? true : false
47
+ end
48
+
49
+ def self.is_macosx
50
+ return @@is_macosx if @@is_macosx
51
+ @@is_macosx = (RUBY_PLATFORM =~ /darwin/) ? true : false
52
+ end
53
+
54
+ def self.is_linux
55
+ return @@is_linux if @@is_linux
56
+ @@is_linux = (RUBY_PLATFORM =~ /linux/) ? true : false
57
+ end
58
+
59
+ def self.is_bsdi
60
+ return @@is_bsdi if @@is_bsdi
61
+ @@is_bsdi = (RUBY_PLATFORM =~ /bsdi/i) ? true : false
62
+ end
63
+
64
+ def self.is_netbsd
65
+ return @@is_netbsd if @@is_netbsd
66
+ @@is_netbsd = (RUBY_PLATFORM =~ /netbsd/) ? true : false
67
+ end
68
+
69
+ def self.is_freebsd
70
+ return @@is_freebsd if @@is_freebsd
71
+ @@is_freebsd = (RUBY_PLATFORM =~ /freebsd/) ? true : false
72
+ end
73
+
74
+ def self.is_openbsd
75
+ return @@is_openbsd if @@is_openbsd
76
+ @@is_openbsd = (RUBY_PLATFORM =~ /openbsd/) ? true : false
77
+ end
78
+
79
+ def self.is_java
80
+ return @@is_java if @@is_java
81
+ @@is_java = (RUBY_PLATFORM =~ /java/) ? true : false
82
+ end
83
+
84
+ def self.is_wow64
85
+ return false if not is_windows
86
+ is64 = false
87
+ begin
88
+ buff = "\x00" * 4
89
+ Win32API.new("kernel32","IsWow64Process",['L','P'],'L').call(-1, buff)
90
+ is64 = (buff.unpack("V")[0]) == 1 ? true : false
91
+ rescue ::Exception
92
+ end
93
+ is64
94
+ end
95
+
96
+ def self.cygwin_to_win32(path)
97
+ if(path !~ /^\/cygdrive/)
98
+ return ::IO.popen("cygpath -w #{path}", "rb").read.strip
99
+ end
100
+ dir = path.split("/")
101
+ dir.shift
102
+ dir.shift
103
+ dir[0] = dir[0] + ":"
104
+ dir.join("\\")
105
+ end
106
+
107
+ def self.open_file(url='')
108
+ case RUBY_PLATFORM
109
+ when /cygwin/
110
+ path = self.cygwin_to_win32(url)
111
+ system(["cmd", "cmd"], "/c", "explorer", path)
112
+ else
113
+ self.open_browser(url)
114
+ end
115
+ end
116
+
117
+ def self.open_browser(url='http://google.com/')
118
+ case RUBY_PLATFORM
119
+ when /cygwin/
120
+ if(url[0,1] == "/")
121
+ self.open_file(url)
122
+ end
123
+ return if not @@loaded_win32api
124
+ Win32API.new("shell32.dll", "ShellExecute", ["PPPPPL"], "L").call(nil, "open", url, nil, nil, 0)
125
+ when /mswin32|mingw/
126
+ return if not @@loaded_win32api
127
+ Win32API.new("shell32.dll", "ShellExecute", ["PPPPPL"], "L").call(nil, "open", url, nil, nil, 0)
128
+ when /darwin/
129
+ system("open #{url}")
130
+ else
131
+ # Search through the PATH variable (if it exists) and chose a browser
132
+ # We are making an assumption about the nature of "PATH" so tread lightly
133
+ if defined? ENV['PATH']
134
+ # "xdg-open" is more general than "sensible-browser" and can be useful for lots of
135
+ # file types -- text files, pcaps, or URLs. It's nearly always
136
+ # going to use the application the user is expecting. If we're not
137
+ # on something Debian-based, fall back to likely browsers.
138
+ ['xdg-open', 'sensible-browser', 'firefox', 'firefox-bin', 'opera', 'konqueror', 'chromium-browser'].each do |browser|
139
+ ENV['PATH'].split(':').each do |path|
140
+ # Does the browser exists?
141
+ if File.exists?("#{path}/#{browser}")
142
+ system("#{browser} #{url} &")
143
+ return
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
150
+
151
+ def self.open_webrtc_browser(url='http://google.com/')
152
+ found_browser = false
153
+
154
+ case RUBY_PLATFORM
155
+ when /mswin2|mingw|cygwin/
156
+ paths = [
157
+ "Google\\Chrome\\Application\\chrome.exe",
158
+ "Mozilla Firefox\\firefox.exe",
159
+ "Opera\\launcher.exe"
160
+ ]
161
+
162
+ prog_files = ENV['ProgramFiles']
163
+ paths = paths.map { |p| "#{prog_files}\\#{p}" }
164
+
165
+ # Old chrome path
166
+ app_data = ENV['APPDATA']
167
+ paths << "#{app_data}\\Google\\Chrome\\Application\\chrome.exe"
168
+
169
+ paths.each do |p|
170
+ if File.exists?(p)
171
+ args = (p =~ /chrome\.exe/) ? "--allow-file-access-from-files" : ""
172
+ system("#{path} #{args} #{url}")
173
+ found_browser = true
174
+ break
175
+ end
176
+ end
177
+
178
+ when /darwin/
179
+ ['Google Chrome.app', 'Firefox.app'].each do |browser|
180
+ browser_path = "/Applications/#{browser}"
181
+ if File.directory?(browser_path)
182
+ args = (browser_path =~ /Chrome/) ? "--args --allow-file-access-from-files" : ""
183
+
184
+ system("open #{url} -a \"#{browser_path}\" #{args} &")
185
+ found_browser = true
186
+ break
187
+ end
188
+ end
189
+ else
190
+ if defined? ENV['PATH']
191
+ ['chrome', 'chromium', 'firefox', 'opera'].each do |browser|
192
+ ENV['PATH'].split(':').each do |path|
193
+ browser_path = "#{path}/#{browser}"
194
+ if File.exists?(browser_path)
195
+ args = (browser_path =~ /Chrome/) ? "--allow-file-access-from-files" : ""
196
+ system("#{browser_path} #{args} #{url} &")
197
+ found_browser = true
198
+ end
199
+ end
200
+ end
201
+ end
202
+ end
203
+
204
+ found_browser
205
+ end
206
+
207
+ def self.open_email(addr)
208
+ case RUBY_PLATFORM
209
+ when /mswin32|cygwin/
210
+ return if not @@loaded_win32api
211
+ Win32API.new("shell32.dll", "ShellExecute", ["PPPPPL"], "L").call(nil, "open", "mailto:"+addr, nil, nil, 0)
212
+ when /darwin/
213
+ system("open mailto:#{addr}")
214
+ else
215
+ # ?
216
+ end
217
+ end
218
+
219
+ def self.play_sound(path)
220
+ case RUBY_PLATFORM
221
+ when /cygwin/
222
+ path = self.cygwin_to_win32(path)
223
+ return if not @@loaded_win32api
224
+ Win32API.new("winmm.dll", "sndPlaySoundA", ["SI"], "I").call(path, 0x20000)
225
+ when /mswin32/
226
+ return if not @@loaded_win32api
227
+ Win32API.new("winmm.dll", "sndPlaySoundA", ["SI"], "I").call(path, 0x20000)
228
+ when /darwin/
229
+ system("afplay #{path} >/dev/null 2>&1")
230
+ else
231
+ system("aplay #{path} >/dev/null 2>&1")
232
+ end
233
+ end
234
+
235
+ def self.getenv(var)
236
+ if (is_windows and @@loaded_win32api)
237
+ f = Win32API.new("kernel32", "GetEnvironmentVariable", ["P", "P", "I"], "I")
238
+ buff = "\x00" * 16384
239
+ sz = f.call(var, buff, buff.length)
240
+ return nil if sz == 0
241
+ buff[0,sz]
242
+ else
243
+ ENV[var]
244
+ end
245
+ end
246
+
247
+ def self.setenv(var,val)
248
+ if (is_windows and @@loaded_win32api)
249
+ f = Win32API.new("kernel32", "SetEnvironmentVariable", ["P", "P"], "I")
250
+ f.call(var, val + "\x00")
251
+ else
252
+ ENV[var]= val
253
+ end
254
+ end
255
+
256
+
257
+ #
258
+ # Obtain the path to our interpreter
259
+ #
260
+ def self.win32_ruby_path
261
+ return nil if ! (is_windows and @@loaded_win32api)
262
+ gmh = Win32API.new("kernel32", "GetModuleHandle", ["P"], "L")
263
+ gmf = Win32API.new("kernel32", "GetModuleFileName", ["LPL"], "L")
264
+ mod = gmh.call(nil)
265
+ inf = "\x00" * 1024
266
+ gmf.call(mod, inf, 1024)
267
+ inf.unpack("Z*")[0]
268
+ end
269
+
270
+ #
271
+ # Call WinExec (equiv to system("cmd &"))
272
+ #
273
+ def self.win32_winexec(cmd)
274
+ return nil if ! (is_windows and @@loaded_win32api)
275
+ exe = Win32API.new("kernel32", "WinExec", ["PL"], "L")
276
+ exe.call(cmd, 0)
277
+ end
278
+
279
+ #
280
+ # Verify the Console2 environment
281
+ #
282
+ def self.win32_console2_verify
283
+ return nil if ! (is_windows and @@loaded_win32api)
284
+ buf = "\x00" * 512
285
+ out = Win32API.new("kernel32", "GetStdHandle", ["L"], "L").call(STD_OUTPUT_HANDLE)
286
+ res = Win32API.new("kernel32","GetConsoleTitle", ["PL"], "L").call(buf, buf.length-1) rescue 0
287
+ ( res > 0 and buf.index("Console2 command").nil? ) ? false : true
288
+ end
289
+
290
+ #
291
+ # Expand a 8.3 path to a full path
292
+ #
293
+ def self.win32_expand_path(path)
294
+ return nil if ! (is_windows and @@loaded_win32api)
295
+ glp = Win32API.new('kernel32', 'GetLongPathName', 'PPL', 'L')
296
+ buf = "\x00" * 260
297
+ len = glp.call(path, buf, buf.length)
298
+ buf[0, len]
299
+ end
300
+
301
+ #
302
+ # Platform independent socket pair
303
+ #
304
+ def self.pipe
305
+
306
+ if (! is_windows())
307
+ # Standard pipes should be fine
308
+ return ::IO.pipe
309
+ end
310
+
311
+ # Create a socket connection for Windows
312
+ serv = nil
313
+ port = 1024
314
+
315
+ while (! serv and port < 65535)
316
+ begin
317
+ serv = TCPServer.new('127.0.0.1', (port += 1))
318
+ rescue ::Exception
319
+ end
320
+ end
321
+
322
+ pipe1 = TCPSocket.new('127.0.0.1', port)
323
+
324
+ # Accept the forked child
325
+ pipe2 = serv.accept
326
+
327
+ # Shutdown the server
328
+ serv.close
329
+
330
+ return [pipe1, pipe2]
331
+ end
332
+
333
+ #
334
+ # Copy a file to a temporary path
335
+ #
336
+
337
+ def self.temp_copy(path)
338
+ raise RuntimeError,"missing Tempfile" if not @@loaded_tempfile
339
+ fd = File.open(path, "rb")
340
+ tp = Tempfile.new("msftemp")
341
+ tp.binmode
342
+ tp.write(fd.read(File.size(path)))
343
+ tp.close
344
+ fd.close
345
+ tp
346
+ end
347
+
348
+ #
349
+ # Delete an opened temporary file
350
+ #
351
+
352
+ def self.temp_delete(tp)
353
+ raise RuntimeError,"missing FileUtils" if not @@loaded_fileutils
354
+ begin
355
+ FileUtils.rm(tp.path)
356
+ rescue
357
+ end
358
+ end
359
+
360
+
361
+ #
362
+ # Initialization
363
+ #
364
+
365
+ if(is_windows or is_cygwin)
366
+ begin
367
+ require "Win32API"
368
+ @@loaded_win32api = true
369
+ rescue ::Exception
370
+ end
371
+ end
372
+
373
+ begin
374
+ require "tempfile"
375
+ @@loaded_tempfile = true
376
+ rescue ::Exception
377
+ end
378
+
379
+ begin
380
+ require "fileutils"
381
+ @@loaded_fileutils = true
382
+ rescue ::Exception
383
+ end
384
+
385
+
386
+
387
+ end
388
+ end