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.
@@ -0,0 +1,151 @@
1
+ # Gursev Singh Kalra @ Foundstone(McAfee)
2
+ # Please see LICENSE.txt for licensing information
3
+
4
+ # require 'sslsmartlib'
5
+ # require 'singleton'
6
+ # require 'uri'
7
+ require 'resultcontainer'
8
+ require 'sslsmartconfig'
9
+
10
+ $conf = SSLSmartConfig.instance
11
+
12
+ class UrlResults
13
+ def initialize()
14
+ @cert = nil
15
+ @cert_validity = nil
16
+ @progress = 0
17
+ @cipher_response_array = []
18
+ end
19
+
20
+
21
+ def add_cipher_response(index, response)
22
+ @cipher_response_array[index] = response
23
+ end
24
+
25
+
26
+ def update_progress
27
+ @progress = (@cipher_response_array.compact.length*100)/$conf.count_to_test if(@cipher_response_array)
28
+ end
29
+
30
+ attr_accessor :cert, :cert_validity, :cipher_response_array, :progress
31
+ end
32
+
33
+ class SSLSmartDB
34
+
35
+ def initialize()
36
+ @db = {}
37
+ end
38
+
39
+
40
+ def add_url(url)
41
+ return if(url == "" || url == nil)
42
+ @db[url.to_sym] = UrlResults.new
43
+ end
44
+
45
+
46
+ def add_cert(url, cert, cert_validity)
47
+ return if(url == "" || url == nil)
48
+ return unless(@db[url.to_sym])
49
+ @db[url.to_sym].cert = cert
50
+ @db[url.to_sym].cert_validity = cert_validity
51
+ @db[url.to_sym].progress = ($conf.count_to_test == 0)?100:1
52
+ end
53
+
54
+
55
+ def add_cipher_response(url, index, response)
56
+ return if(url == "" || url == nil)
57
+ @db[url.to_sym].add_cipher_response(index, response)
58
+ @db[url.to_sym].update_progress()
59
+ end
60
+
61
+
62
+ def cert_valid?(url)
63
+ return nil if(url == "" || url == nil)
64
+ return nil unless(@db[url.to_sym])
65
+ @db[url.to_sym].cert_validity
66
+ end
67
+
68
+
69
+ def get_cert(url)
70
+ return nil if(url == "" || url == nil)
71
+ return nil unless(@db[url.to_sym])
72
+ @db[url.to_sym].cert
73
+ end
74
+
75
+
76
+ def get_response(url, index)
77
+ return nil if(url == "" || url == nil)
78
+ return nil unless(@db[url.to_sym])
79
+ response = @db[url.to_sym].cipher_response_array[index]
80
+ return nil unless(response)
81
+ #return nil unless(response.data)
82
+ response
83
+ end
84
+
85
+
86
+ def get_html_response(url, index)
87
+ return nil if(url == "" || url == nil)
88
+ response = get_response(url, index)
89
+ return nil unless(response)
90
+ return nil unless(response.status)
91
+ if(response.data)
92
+ return response.data.body
93
+ else
94
+ return ""
95
+ end
96
+ end
97
+
98
+
99
+ def get_text_response(url, index)
100
+ return nil if(url == "" || url == nil)
101
+ response = get_response(url, index)
102
+ return nil unless(response)
103
+ return nil unless(response.status)
104
+
105
+ return "" unless(response.data)
106
+ response = response.data
107
+
108
+ text = ""
109
+ text = "HTTP\/#{response.http_version} #{response.code} #{response.msg}\n"
110
+ response.each do |header, body|
111
+ text << "#{header}: #{body}\n"
112
+ end
113
+ text << "\n\n"
114
+ text << response.body
115
+ text
116
+ end
117
+
118
+
119
+ def get_response_code(url, index)
120
+ return nil if(url == "" || url == nil)
121
+ response = get_response(url, index)
122
+ # REVIEW HERE
123
+ return nil unless(response)
124
+ return "" unless(response.data)
125
+
126
+ retval = response.data
127
+ case response.status
128
+ when true
129
+ return "HTTP\/#{retval.http_version} #{retval.code} #{retval.msg}"
130
+ when false
131
+ return retval.message
132
+ else
133
+ return nil
134
+ end
135
+ end
136
+
137
+
138
+ def get_all_cipher_results(url)
139
+ return nil if(url == "" || url == nil)
140
+ return nil unless(@db[url.to_sym])
141
+ @db[url.to_sym].cipher_response_array
142
+ end
143
+
144
+
145
+ def get_progress(url)
146
+ return 0 if(url == "" || url == nil)
147
+ return 0 unless(@db[url.to_sym])
148
+ @db[url.to_sym].progress
149
+ end
150
+
151
+ end
@@ -0,0 +1,888 @@
1
+ # Gursev Singh Kalra @ Foundstone(McAfee)
2
+ # Please see LICENSE.txt for licensing information
3
+
4
+ begin
5
+ require 'cgi'
6
+ require 'net/https'
7
+ require 'sslsmartlog'
8
+ require 'sslsmartlib'
9
+ require 'sslsmartconfig'
10
+ require 'sslsmartmisc'
11
+ require 'sslsmartcontroller'
12
+ rescue LoadError => ex
13
+ raise ex
14
+ end
15
+
16
+ begin
17
+ require 'rubygems'
18
+ rescue LoadError
19
+ end
20
+
21
+ $log = SSLSmartLog.instance
22
+ $conf = SSLSmartConfig.instance
23
+
24
+
25
+ require 'wx'
26
+
27
+ # IDentifiers for GUI controls
28
+ ID_SSLSMART_XML = 111
29
+ ID_SSLSMART_XML_VERBOSE = 112
30
+ ID_SSLSMART_HTML = 113
31
+ ID_SSLSMART_HTML_VERBOSE = 114
32
+ ID_SSLSMART_TEXT = 115
33
+ ID_SSLSMART_TEXT_VERBOSE = 116
34
+
35
+ ID_SSLSMART_EXIT = 117
36
+ ID_SSLSMART_CLOSE = 119
37
+ ID_SSLSMART_HELP = 121
38
+
39
+
40
+ HOST_BUTTON_SIZE = [100,25]
41
+ BUTTON_SIZE = [100,25]
42
+ HOST_CONTROL_SPACING = 5
43
+ HOST_BOX_HEIGHT = 100
44
+ HOST_BOX_WIDTH = 775
45
+ CIPHER_GRID_WIDTH = 775
46
+ CIPHER_GRID_HEIGHT = 200
47
+ HOSTS_PROPORTION = 1
48
+ CIPHER_PROPORTION = 3
49
+ HTML_PROPORTION = 4
50
+ CERT_PROPORTION = 2
51
+
52
+ SHOW_HTML = 0
53
+ SHOW_TEXT = 1
54
+
55
+ GRID_COLS = 6
56
+ TEST_COL = 0
57
+ VERSION_COL = 1
58
+ NAME_COL = 2
59
+ BITS_COL = 3
60
+ SUPPORTED_COL = 4
61
+ HTTP_COL = 5
62
+
63
+
64
+ class SSLSmartFrame < Wx::Frame
65
+
66
+ include SSLSmartMisc
67
+
68
+ ###########################################################
69
+ ##+ Start creation of Menu Bar and corresponding functions
70
+ ###########################################################
71
+
72
+ def create_menu_bar
73
+ menu_bar = Wx::MenuBar.new
74
+
75
+ # The "file" menu
76
+ menu_file = Wx::Menu.new
77
+ menu_file.append(ID_SSLSMART_HTML , "Export HTML Report\tCtrl-1" , "Export HTML Report")
78
+ menu_file.append(ID_SSLSMART_HTML_VERBOSE , "Export Verbose HTML Report\tCtrl-2" , "Export HTML Report")
79
+ menu_file.append(ID_SSLSMART_XML , "Export XML Report\tCtrl-3" , "Export XML Report")
80
+ menu_file.append(ID_SSLSMART_XML_VERBOSE , "Export Verbose XML Report\tCtrl-4" , "Export XML Report")
81
+ menu_file.append(ID_SSLSMART_TEXT , "Export TEXT Report\tCtrl-5" , "Export Text Report")
82
+ menu_file.append(ID_SSLSMART_TEXT_VERBOSE , "Export Verbose TEXT Report\tCtrl-6" , "Export Text Report")
83
+ menu_file.append_separator()
84
+ menu_file.append(Wx::ID_EXIT, "E&xit\tAlt-X", "Quit this program")
85
+ menu_bar.append(menu_file, "&File")
86
+
87
+ # The "help" menu
88
+ menu_help = Wx::Menu.new
89
+ menu_help.append(ID_SSLSMART_HELP, "SSLSmart Help\tF1", "")
90
+ menu_help.append(Wx::ID_ABOUT, "About........\tF2", "Show about dialog")
91
+ menu_bar.append(menu_help, "&Help")
92
+
93
+ self.menu_bar = menu_bar
94
+
95
+ # Set it up to handle menu events using the relevant methods.
96
+ evt_menu(Wx::ID_EXIT , :on_my_close)
97
+ evt_menu(Wx::ID_ABOUT , :on_about)
98
+ evt_menu(ID_SSLSMART_HTML) {|event| create_report(event, :html)}
99
+ evt_menu(ID_SSLSMART_HTML_VERBOSE) {|event| create_report(event, :htmlv)}# , :create_verbose_html_report)
100
+ evt_menu(ID_SSLSMART_XML) {|event| create_report(event, :xml)}
101
+ evt_menu(ID_SSLSMART_XML_VERBOSE) {|event| create_report(event, :xmlv)}
102
+ evt_menu(ID_SSLSMART_TEXT) {|event| create_report(event, :text)}
103
+ evt_menu(ID_SSLSMART_TEXT_VERBOSE) {|event| create_report(event, :textv)}
104
+ evt_menu(ID_SSLSMART_HELP, :show_help)
105
+
106
+ end
107
+
108
+
109
+ ###########################################################
110
+ ##- END Menu Bar and corresponding functions
111
+ ###########################################################
112
+
113
+
114
+ def write_results_to_file(content, filetype)
115
+ case filetype
116
+ when :html
117
+ append = ".html"
118
+ when :htmlv
119
+ filetype = :html
120
+ append = "_Verbose.html"
121
+ when :text
122
+ append = ".txt"
123
+ when :textv
124
+ filetype = :txt
125
+ append = "_Verbose.txt"
126
+ when :xml
127
+ append = ".xml"
128
+ when :xmlv
129
+ filetype = :xml
130
+ append = "_Verbose.xml"
131
+ end
132
+
133
+ file_dialog = Wx::FileDialog.new(self, "Export #{filetype.to_s.upcase} Results As", "", "SSLSmart#{append}", "*.*", Wx::FD_SAVE| Wx::FD_OVERWRITE_PROMPT)
134
+ file_dialog.show_modal
135
+ path = file_dialog.get_path
136
+ return if(path == nil || path == "")
137
+ begin
138
+ File.open(path, 'w') do |f|
139
+ f.puts content
140
+ end
141
+ rescue => ex
142
+ $log.error(ex.message)
143
+ Wx::MessageDialog.new(nil, "Error Occured!!\nPlease see log files for more details", "", Wx::OK ).show_modal()
144
+ end
145
+ end
146
+
147
+
148
+ def create_report(event, type)
149
+ return unless(@controller)
150
+ report_content = @controller.create_report(type)
151
+ write_results_to_file(report_content, type) if(report_content)
152
+ end
153
+
154
+
155
+ def show_help()
156
+ Wx::MessageDialog.new(nil, "Visit Foundstone website to download SSLSmart white paper", "SSLSmart Help", Wx::OK).show_modal
157
+ end
158
+
159
+
160
+ def on_my_close()
161
+ rval = Wx::MessageDialog.new(nil, "Are you sure you want to exit?","Exit Confirmation", Wx::ICON_QUESTION|Wx::YES_NO).show_modal
162
+ return if(rval == Wx::ID_NO)
163
+ $log.debug("Exiting SSLSmart")
164
+ destroy
165
+ exit
166
+ end
167
+
168
+
169
+ def on_about()
170
+ Wx::about_box(:name => self.title,
171
+ :version => "1.0",
172
+ :description => "For Smart SSL Cipher Enumeration",
173
+ :developers => ['Gursev Kalra @ Foundstone'] )
174
+ end
175
+
176
+
177
+ def on_changing_page(event)
178
+ event.veto if(@test_running)
179
+ end
180
+
181
+
182
+ ##+ Creating the two tabs to host all GUI elements
183
+ def create_workspace_and_options_tabs()
184
+ new_notebook = Wx::Notebook.new(self)
185
+
186
+ @ws_tab = Wx::Panel.new(new_notebook) # Add workspace tab
187
+ @ws_mvsizer = Wx::BoxSizer.new(Wx::VERTICAL)
188
+ @ws_tab.set_sizer(@ws_mvsizer)
189
+
190
+ @options_tab = Wx::Panel.new(new_notebook) # Add options tab
191
+ @options_mvsizer = Wx::BoxSizer.new(Wx::VERTICAL)
192
+ @options_tab.set_sizer(@options_mvsizer)
193
+
194
+
195
+ new_notebook.add_page(@ws_tab , "Workspace")
196
+ new_notebook.add_page(@options_tab , "Options")
197
+ evt_notebook_page_changing(new_notebook.get_id()) {|event| on_changing_page(event) }
198
+ end
199
+
200
+ ##- End of tab creation
201
+ def clear_gui_and_results()
202
+ $log.debug("Clearing GUI and Results")
203
+ return if(@test_running)
204
+ @controller = nil
205
+ ws_clear_results_from_grid()
206
+ $conf.urls.each_index do |i|
207
+ @hosts_listbox.check(i, false)
208
+ end
209
+ @pbar.set_value(0)
210
+ @response_html.set_page("")
211
+ @response_text.set_value("")
212
+ @cert_info.set_value("")
213
+ end
214
+
215
+
216
+ ###########################################################
217
+ ##+ Begin creating all GUI elements and related functionalities for WorkSheet Tab
218
+ ###########################################################
219
+
220
+ def ws_sync_from_conf()
221
+ $log.debug("Synchronizing configuration to GUI")
222
+ choices = {true => "1", false => ""}
223
+ rows = @ws_cipher_grid.get_number_rows
224
+ 0.upto(rows - 1) do |row|
225
+ @ws_cipher_grid.set_cell_value(row, TEST_COL, choices[$conf.cipher_suites[row].test])
226
+ end
227
+ end
228
+
229
+
230
+ def ws_sync_to_conf()
231
+ $log.debug("Synchronizing GUI to configuration")
232
+ choices = {"" => false, "1" => true}
233
+ rows = @ws_cipher_grid.get_number_rows
234
+ 0.upto(rows - 1) do |row|
235
+ cell_val = @ws_cipher_grid.get_cell_value(row, TEST_COL)
236
+ $conf.cipher_suites[row].test = choices[cell_val]
237
+ end
238
+ end
239
+
240
+
241
+ def ws_start_test(event)
242
+ return if(@test_running || $conf.urls == [])
243
+ $log.debug("Starting Test")
244
+ @stop_test = false
245
+ ws_sync_to_conf()
246
+ clear_gui_and_results()
247
+ @test_running = true
248
+
249
+ @controller = SSLSmartController.new
250
+ x = Thread.new do
251
+ $log.debug "Starting test thread"
252
+ begin
253
+ @controller.start_test do |url, url_index, suite_index|
254
+
255
+ progress = @controller.get_progress(url).to_i
256
+ if(@hosts_listbox.get_string_selection == url)
257
+ ws_populate_one_cipher_result(suite_index, @controller.get_response(url, suite_index)) if(suite_index)
258
+ ws_populate_cert_info(url)
259
+ @pbar.set_value(progress)
260
+ end
261
+ @hosts_listbox.check(url_index) if(progress == 100)
262
+ if(@stop_test)
263
+ @test_running = false
264
+ $log.warn("Forcibly killed thread")
265
+ Thread.kill(x)
266
+ end
267
+ end
268
+ @test_running = false
269
+ #@controller.show_results
270
+ rescue => ex
271
+ $log.fatal(ex.message)
272
+ $log.fatal(ex.backtrace)
273
+ ensure
274
+ @test_running = false
275
+ end
276
+ end
277
+
278
+ #event.skip
279
+ end
280
+
281
+
282
+ def ws_refresh_hosts_listbox(event)
283
+ @hosts_listbox.set($conf.urls)
284
+ event.skip
285
+ end
286
+
287
+
288
+ def ws_add_single_host(event)
289
+ $log.debug("Adding a single host")
290
+ host_entry_box = Wx::TextEntryDialog.new(@ws_mpanel,"", "Add URL/Host to Test")
291
+ retval = host_entry_box.show_modal
292
+ if(retval == Wx::ID_OK)
293
+ #url = SSLMisc.convert_to_url(host_entry_box.get_value)
294
+ url = convert_to_url(host_entry_box.get_value)
295
+ $conf.update_config({:urls => $conf.urls | [url]}) if(url)
296
+ ws_refresh_hosts_listbox(event)
297
+ end
298
+ event.skip
299
+ end
300
+
301
+
302
+ def ws_import_hosts(event)
303
+ $log.debug("Adding a multiple hosts")
304
+ file_control = Wx::FileDialog.new(@ws_mpanel, "Input File containing host entries (one per line)", "", "", "Text Files (*.txt)|*.txt", Wx::FD_MULTIPLE)
305
+ file_control.show_modal
306
+ file_names = file_control.get_paths
307
+ file_names.each do |x|
308
+ if(File.file?(x))
309
+ #urls = SSLMisc.get_urls_from_file(x)
310
+ urls = get_urls_from_file(x)
311
+ $conf.update_config({:urls => $conf.urls | urls})
312
+ ws_refresh_hosts_listbox(event)
313
+ end
314
+ end
315
+ event.skip
316
+ end
317
+
318
+
319
+ def ws_rem_hosts(event)
320
+ $log.debug("Removing hosts")
321
+
322
+ return if(@test_running)
323
+ arr = @hosts_listbox.get_selections
324
+ arr += @hosts_listbox.get_checked_items
325
+ keep = (0...$conf.urls.length).to_a - arr
326
+ $conf.update_config({:urls => $conf.urls.values_at(*keep)})
327
+ ws_refresh_hosts_listbox(event)
328
+ event.skip
329
+ end
330
+
331
+
332
+ def ws_rem_all_hosts(event)
333
+ $log.debug("Removing all hosts")
334
+ return if(@test_running)
335
+ clear_gui_and_results()
336
+ $conf.update_config({:urls => []})
337
+ ws_refresh_hosts_listbox(event)
338
+ event.skip
339
+ end
340
+
341
+ def ws_stop_test(event)
342
+ $log.info("Attempt to stop test")
343
+ @stop_test = true
344
+ end
345
+
346
+
347
+ def ws_clear_results(event)
348
+ $log.debug("Clearing all results")
349
+ clear_gui_and_results()
350
+ event.skip
351
+ end
352
+
353
+
354
+ def ws_create_buttons(parent_panel, sizer)
355
+ ws_hosts_button_hsizer = Wx::BoxSizer.new(Wx::HORIZONTAL) # sizer for hosts button controls
356
+
357
+ ws_start_test = Wx::Button.new(parent_panel, Wx::ID_ANY, "Start Test" , Wx::DEFAULT_POSITION, HOST_BUTTON_SIZE)
358
+ # Threads should come here
359
+ evt_button(ws_start_test.get_id()) { |event| ws_start_test(event) }
360
+
361
+ # Add URL/Host Button and Corresponding event handlers
362
+ ws_add_host = Wx::Button.new(parent_panel, Wx::ID_ANY, "Add URL/Host" , Wx::DEFAULT_POSITION, HOST_BUTTON_SIZE)
363
+ evt_button(ws_add_host.get_id()) { |event| ws_add_single_host(event)}
364
+
365
+ # Import URL's/Hosts
366
+ ws_import_hosts = Wx::Button.new(parent_panel, Wx::ID_ANY, "Import URLs/Hosts" , Wx::DEFAULT_POSITION, HOST_BUTTON_SIZE)
367
+ evt_button(ws_import_hosts.get_id()) { |event| ws_import_hosts(event)}
368
+
369
+ # Remove one host
370
+ ws_rem_host = Wx::Button.new(parent_panel, Wx::ID_ANY, "Remove" , Wx::DEFAULT_POSITION, HOST_BUTTON_SIZE)
371
+ evt_button(ws_rem_host.get_id()) { |event| ws_rem_hosts(event)}
372
+
373
+ # Remove one host
374
+ ws_rem_all_hosts = Wx::Button.new(parent_panel, Wx::ID_ANY, "Remove All" , Wx::DEFAULT_POSITION, HOST_BUTTON_SIZE)
375
+ evt_button(ws_rem_all_hosts.get_id()) { |event| ws_rem_all_hosts(event)}
376
+
377
+ ws_clear_results = Wx::Button.new(parent_panel, Wx::ID_ANY, "Clear Results" , Wx::DEFAULT_POSITION, HOST_BUTTON_SIZE)
378
+ evt_button(ws_clear_results.get_id()) { |event| ws_clear_results(event)}
379
+
380
+ ws_stop_test = Wx::Button.new(parent_panel, Wx::ID_ANY, "Stop Test" , Wx::DEFAULT_POSITION, HOST_BUTTON_SIZE)
381
+ evt_button(ws_stop_test.get_id()) { |event| ws_stop_test(event)}
382
+
383
+ ws_hosts_button_hsizer.add_item(ws_start_test , -1, 0, Wx::ALL, HOST_CONTROL_SPACING)
384
+ ws_hosts_button_hsizer.add_item(ws_add_host , -1, 0, Wx::ALL, HOST_CONTROL_SPACING)
385
+ ws_hosts_button_hsizer.add_item(ws_import_hosts , -1, 0, Wx::ALL, HOST_CONTROL_SPACING)
386
+ ws_hosts_button_hsizer.add_item(ws_rem_host , -1, 0, Wx::ALL, HOST_CONTROL_SPACING)
387
+ ws_hosts_button_hsizer.add_item(ws_rem_all_hosts , -1, 0, Wx::ALL, HOST_CONTROL_SPACING)
388
+ ws_hosts_button_hsizer.add_item(ws_clear_results , -1, 0, Wx::ALL, HOST_CONTROL_SPACING)
389
+ ws_hosts_button_hsizer.add_item(ws_stop_test , -1, 0, Wx::ALL, HOST_CONTROL_SPACING)
390
+
391
+ sizer.add_item(ws_hosts_button_hsizer , -1, 0, Wx::EXPAND|Wx::ALL)
392
+
393
+ end
394
+
395
+
396
+ def ws_populate_cipher_result(event)
397
+ @response_html.set_page("")
398
+ @response_text.set_value("")
399
+ return unless(@controller)
400
+
401
+ @selected_grid_row = event.get_row
402
+ url = @hosts_listbox.get_string_selection
403
+ if(url != "")
404
+ html_response = @controller.get_html_response(url, @selected_grid_row)
405
+ text_response = @controller.get_text_response(url, @selected_grid_row)
406
+
407
+ @response_html.set_page(html_response) if(html_response)
408
+ @response_text.set_value(text_response) if(text_response)
409
+ end
410
+ end
411
+
412
+
413
+ def ws_populate_cipher_result_for_url(url)
414
+ @response_html.set_page("")
415
+ @response_text.set_value("")
416
+ return unless(@controller)
417
+
418
+ if(url != "")
419
+ html_response = @controller.get_html_response(url, @selected_grid_row)
420
+ text_response = @controller.get_text_response(url, @selected_grid_row)
421
+
422
+ @response_html.set_page(html_response) if(html_response)
423
+ @response_text.set_value(text_response) if(text_response)
424
+ end
425
+ end
426
+
427
+
428
+ def ws_create_cipher_grid(parent_panel, sizer)
429
+ # TEST_COL = 0
430
+ # VERSION_COL = 1
431
+ # NAME_COL = 2
432
+ # BITS_COL = 3
433
+ # SUPPORTED_COL = 4
434
+ # HTTP_COL = 5
435
+
436
+ read_only = Wx::GridCellAttr.new
437
+ #read_only.set_read_only
438
+ # Starting the Cipher Grid GUI Code Here
439
+ cipher_hsizer = Wx::BoxSizer.new(Wx::HORIZONTAL) # sizer for ciphers grid
440
+
441
+ # @ws_cipher_grid is instance variable because it is going to be needed across functions and entire functionality
442
+ @ws_cipher_grid = Wx::Grid.new(parent_panel, -1, Wx::DEFAULT_POSITION, [CIPHER_GRID_WIDTH , CIPHER_GRID_HEIGHT])
443
+ #@ws_cipher_grid.auto_size
444
+
445
+ @ws_cipher_grid.create_grid($conf.cipher_suites.length, GRID_COLS)
446
+ #@ws_cipher_grid.enable_editing(false)
447
+ #@ws_cipher_grid.disable_cell_edit_control
448
+ @ws_cipher_grid.set_col_label_size(25)
449
+ @ws_cipher_grid.set_row_label_size(25)
450
+ @ws_cipher_grid.set_col_label_value( TEST_COL, "Test?" )
451
+ @ws_cipher_grid.set_col_size( TEST_COL, 35 )
452
+
453
+ @ws_cipher_grid.set_col_label_value( VERSION_COL, "SSL Version" )
454
+ @ws_cipher_grid.set_col_attr(VERSION_COL, read_only)
455
+
456
+ @ws_cipher_grid.set_col_label_value( NAME_COL, "Cipher Name" )
457
+ @ws_cipher_grid.set_col_size( NAME_COL, 200 )
458
+ @ws_cipher_grid.set_col_attr(NAME_COL, read_only)
459
+
460
+ @ws_cipher_grid.set_col_label_value( BITS_COL, "Key Length (bits)" )
461
+ @ws_cipher_grid.set_col_size( BITS_COL, 125 )
462
+ @ws_cipher_grid.set_col_attr(BITS_COL, read_only)
463
+
464
+ @ws_cipher_grid.set_col_label_value( SUPPORTED_COL, "Supported?" )
465
+ @ws_cipher_grid.set_col_attr(SUPPORTED_COL, read_only)
466
+
467
+ @ws_cipher_grid.set_col_label_value( HTTP_COL, "Response Code" )
468
+ @ws_cipher_grid.set_col_size( HTTP_COL, 180 )
469
+ @ws_cipher_grid.set_col_attr(HTTP_COL, read_only)
470
+ evt_grid_select_cell() {|event| ws_populate_cipher_result(event); event.skip}
471
+ #@ws_cipher_grid.set_selection_mode(Wx::Grid::GridSelectRows)
472
+ #@ws_cipher_grid.can_enable_cell_control
473
+ #populate_grid
474
+
475
+ # The below code was needs to be uncommented. ONLY ONE LINE
476
+ #evt_grid_select_cell() {|event| populate_cipher_result_in_html_box(event); event.skip}
477
+ #evt_grid_range_select() {|event| selected(event)}
478
+
479
+ cipher_hsizer.add_item(@ws_cipher_grid, -1, 0, Wx::EXPAND|Wx::ALL)
480
+
481
+ sizer.add_item(cipher_hsizer, -1, CIPHER_PROPORTION, Wx::EXPAND|Wx::ALL, HOST_CONTROL_SPACING)
482
+ # Ending the Cipher Grid GUI Code Here
483
+
484
+ end
485
+
486
+
487
+ def ws_create_progress_bar(parent_panel, sizer)
488
+ pbar_hsizer = Wx::BoxSizer.new(Wx::HORIZONTAL) # sizer for ciphers grid
489
+ @pbar = Wx::Gauge.new(parent_panel, -1, 100, Wx::DEFAULT_POSITION, [775,20])
490
+ pbar_hsizer.add_item(@pbar, -1, 0, Wx::EXPAND|Wx::ALL)
491
+ sizer.add_item(pbar_hsizer, -1, 0, Wx::EXPAND|Wx::ALL)
492
+ end
493
+
494
+ def ws_html_click(event)
495
+ return
496
+ end
497
+
498
+ def ws_create_response_display(parent_panel, sizer)
499
+ new_notebook = Wx::Notebook.new(parent_panel)
500
+
501
+ html_tab = Wx::Panel.new(new_notebook) # Add HTML display
502
+ html_sizer = Wx::BoxSizer.new(Wx::HORIZONTAL)
503
+ html_tab.set_sizer(html_sizer)
504
+ @response_html = Wx::HtmlWindow.new(html_tab, -1, Wx::DEFAULT_POSITION, [CIPHER_GRID_WIDTH - 15, CIPHER_GRID_HEIGHT], Wx::HW_DEFAULT_STYLE, "HtmlWindow")
505
+ html_sizer.add_item(@response_html, -1, 0, Wx::EXPAND|Wx::ALL, HOST_CONTROL_SPACING)
506
+ evt_html_link_clicked(@response_html.get_id()) { | event | ws_html_click(event) }
507
+ evt_html_cell_clicked(@response_html.get_id()) { | event | ws_html_click(event) }
508
+
509
+ text_tab = Wx::Panel.new(new_notebook) # Add HTML display
510
+ text_sizer = Wx::BoxSizer.new(Wx::HORIZONTAL)
511
+ text_tab.set_sizer(text_sizer)
512
+ @response_text = Wx::TextCtrl.new(text_tab, -1, "", Wx::DEFAULT_POSITION, [CIPHER_GRID_WIDTH - 15, CIPHER_GRID_HEIGHT], Wx::TE_READONLY|Wx::TE_MULTILINE, Wx::DEFAULT_VALIDATOR, "TextWindow")
513
+ text_sizer.add_item(@response_text, -1, 0, Wx::EXPAND|Wx::ALL, HOST_CONTROL_SPACING)
514
+
515
+ new_notebook.add_page(html_tab , "HTML")
516
+ new_notebook.add_page(text_tab , "Text")
517
+ sizer.add_item(new_notebook, -1, HTML_PROPORTION, Wx::EXPAND|Wx::ALL, HOST_CONTROL_SPACING)
518
+ end
519
+
520
+
521
+ def ws_create_cert_display(parent_panel, sizer)
522
+ #@cert_info = Wx::TextCtrl.new(parent_panel, -1, "", Wx::DEFAULT_POSITION, Wx::DEFAULT_SIZE, Wx::TE_READONLY|Wx::TE_MULTILINE|Wx::TE_RICH|Wx::TE_RICH2)
523
+ hsizer = Wx::BoxSizer.new(Wx::HORIZONTAL)
524
+ @cert_info = Wx::TextCtrl.new(parent_panel, -1, "", Wx::DEFAULT_POSITION, [CIPHER_GRID_WIDTH, CIPHER_GRID_HEIGHT], Wx::TE_READONLY|Wx::TE_MULTILINE|Wx::TE_RICH|Wx::TE_RICH2)
525
+ hsizer.add_item(@cert_info, -1, 0, Wx::EXPAND|Wx::ALL)
526
+ sizer.add_item(hsizer, -1, CERT_PROPORTION, Wx::EXPAND|Wx::ALL, HOST_CONTROL_SPACING)
527
+
528
+ end
529
+
530
+
531
+ def ws_populate_cert_info(url)
532
+ $log.debug("Populating certificate information")
533
+ @cert_info.set_value("")
534
+ return unless(@controller)
535
+ cert = @controller.get_cert(url)
536
+ return unless(cert)
537
+ txtattr = Wx::TextAttr.new(Wx::BLACK)
538
+ cert_validity = @controller.cert_valid?(url)
539
+
540
+ case cert_validity.status
541
+ when true
542
+ txtattr.set_background_colour(Wx::GREEN)
543
+ @cert_info.set_default_style(txtattr)
544
+ @cert_info.append_text("[+] Valid Digital Certificate\n")
545
+ when false
546
+ txtattr.set_background_colour(Wx::RED)
547
+ @cert_info.set_default_style(txtattr)
548
+ @cert_info.append_text("[-] Invalid Digital Certificate. #{cert_validity.data}\n")
549
+ end
550
+
551
+ if(cert.data.class == OpenSSL::X509::Certificate)
552
+ @cert_info.append_text(cert.data.to_text)
553
+ else
554
+ @cert_info.append_text(cert.data)
555
+ end
556
+ @cert_info.set_insertion_point(0)
557
+ end
558
+
559
+
560
+ def ws_clear_results_from_grid()
561
+ $log.debug("Clearing all results from cipher grid")
562
+ cipher_count = $conf.cipher_suites.length
563
+ 0.upto(cipher_count - 1) do |index|
564
+ @ws_cipher_grid.set_cell_value(index, SUPPORTED_COL, "")
565
+ @ws_cipher_grid.set_cell_value(index, HTTP_COL, "")
566
+ @ws_cipher_grid.set_cell_background_colour(index, SUPPORTED_COL, Wx::NULL_COLOUR)
567
+ end
568
+ end
569
+
570
+ # To be used inside SSLController.start_test
571
+ def ws_populate_one_cipher_result(suite_index, result)
572
+ return unless(result)
573
+ case result.status
574
+ when true
575
+ @ws_cipher_grid.set_cell_value(suite_index, SUPPORTED_COL, "Yes")
576
+ @ws_cipher_grid.set_cell_background_colour(suite_index, SUPPORTED_COL, Wx::GREEN)
577
+ @ws_cipher_grid.set_cell_value(suite_index, HTTP_COL, "HTTP\/#{result.data.http_version} #{result.data.code} #{result.data.msg}") if(result.data)
578
+ when false
579
+ @ws_cipher_grid.set_cell_value(suite_index, SUPPORTED_COL, "No")
580
+ @ws_cipher_grid.set_cell_background_colour(suite_index, SUPPORTED_COL, Wx::RED)
581
+ @ws_cipher_grid.set_cell_value(suite_index, HTTP_COL, "#{result.data}") if(result.data)
582
+ end # end of case
583
+ end
584
+
585
+
586
+ def ws_populate_host_results(url)
587
+ ws_clear_results_from_grid()
588
+ return unless(@controller)
589
+ cipher_results = @controller.get_all_cipher_results(url)
590
+ return if(cipher_results == nil || cipher_results == [])
591
+
592
+ cipher_results.each_with_index do |result, index|
593
+ ws_populate_one_cipher_result(index, result)
594
+ # case result.status
595
+ # when true
596
+ # @ws_cipher_grid.set_cell_value(index, SUPPORTED_COL, "Yes")
597
+ # @ws_cipher_grid.set_cell_background_colour(index, SUPPORTED_COL, Wx::GREEN)
598
+ # @ws_cipher_grid.set_cell_value(index, HTTP_COL, "HTTP\/#{result.data.http_version} #{result.data.code} #{result.data.msg}") if(result.data)
599
+ # when false
600
+ # @ws_cipher_grid.set_cell_value(index, SUPPORTED_COL, "No")
601
+ # @ws_cipher_grid.set_cell_background_colour(index, SUPPORTED_COL, Wx::RED)
602
+ # #@cipher_grid.set_cell_value(index, HTTP_COL, "#{result.data.message}") if(result.data)
603
+ # @ws_cipher_grid.set_cell_value(index, HTTP_COL, "#{result.data}") if(result.data)
604
+ # end # end of case
605
+ end
606
+ end
607
+
608
+
609
+ def ws_populate_progress(url)
610
+ return unless(@controller)
611
+ @pbar.set_value(@controller.get_progress(url).to_i)
612
+ end
613
+
614
+
615
+ def ws_populate_cert_info_and_test_results(url)
616
+ @response_html.set_page("")
617
+ @response_text.set_value("")
618
+ ws_populate_progress(url)
619
+ ws_populate_cipher_result_for_url(url)
620
+ ws_populate_cert_info(url)
621
+ ws_populate_host_results(url)
622
+ end
623
+
624
+
625
+ def ws_create_hosts_control(parent_panel, sizer)
626
+ hosts_hsizer = Wx::BoxSizer.new(Wx::HORIZONTAL) # sizer for hosts controls
627
+ @hosts_listbox = Wx::CheckListBox.new(parent_panel, -1, [10,10], [HOST_BOX_WIDTH,HOST_BOX_HEIGHT])#, ["1","3","4","5"], Wx::TE_READONLY)
628
+
629
+ #Uncomment the line below to make it working
630
+ evt_listbox(@hosts_listbox.get_id()) {|event| ws_populate_cert_info_and_test_results(@hosts_listbox.get_string_selection) }
631
+
632
+ hosts_hsizer.add_item(@hosts_listbox, -1, 0, Wx::EXPAND|Wx::ALL, HOST_CONTROL_SPACING)
633
+ sizer.add_item(hosts_hsizer , -1, HOSTS_PROPORTION, Wx::EXPAND|Wx::ALL)
634
+ end
635
+
636
+
637
+ def ws_create_gui(parent_panel, sizer)
638
+ $log.info("Creating WorkSpace GUI Tab")
639
+ ws_create_buttons(parent_panel, sizer)
640
+ ws_create_hosts_control(parent_panel, sizer)
641
+ ws_create_cipher_grid(parent_panel, sizer)
642
+ ws_create_progress_bar(parent_panel, sizer)
643
+ ws_create_response_display(parent_panel, sizer)
644
+ ws_create_cert_display(parent_panel, sizer)
645
+ end
646
+
647
+ ###########################################################
648
+ ##+ End of all GUI elements for WorkSheet Tab
649
+ ###########################################################
650
+
651
+ ###########################################################
652
+ ##+ Begin creating all GUI elements for Options Tab
653
+ ###########################################################
654
+
655
+ def options_update_config(event, hash)
656
+ return if(@test_running)
657
+ $conf.update_config(hash)
658
+ clear_gui_and_results() if(hash.has_key?(:scan_mode) || hash.has_key?(:scan_type) )
659
+ ws_sync_from_conf() if(hash.has_key?(:sslv2) || hash.has_key?(:tlsv1)|| hash.has_key?(:sslv3) )
660
+ event.skip
661
+ end
662
+
663
+
664
+ def options_create_cipher_checkbox(parent_panel, sizer)
665
+ sslv2 = "SSLv2"
666
+ sslv3 = "SSLv3"
667
+ tlsv1 = "TLSv1"
668
+ ssl_hsizer = Wx::BoxSizer.new(Wx::HORIZONTAL)
669
+ ssl_static_box = Wx::StaticBox.new(parent_panel, -1, "SSL Cipher Versions To Test")
670
+ ssl_vsizer = Wx::StaticBoxSizer.new(ssl_static_box, Wx::VERTICAL)
671
+
672
+
673
+ # IT IS NOT MANDATORY TO HAVE @sslv2, @sslv3 and @tlsv1 as instance variables.
674
+ # LOOK Into possibility of changing these to local variables
675
+
676
+ @sslv2 = Wx::CheckBox.new(parent_panel, -1, sslv2)
677
+ @sslv2.set_value($conf.sslv2)
678
+ evt_checkbox(@sslv2.get_id()) { |event| options_update_config(event, {:sslv2 => @sslv2.get_value}) }
679
+
680
+ @sslv3 = Wx::CheckBox.new(parent_panel, -1, sslv3)
681
+ @sslv3.set_value($conf.sslv3)
682
+ evt_checkbox(@sslv3.get_id()) { |event| options_update_config(event, {:sslv3 => @sslv3.get_value}) }
683
+
684
+ @tlsv1 = Wx::CheckBox.new(parent_panel, -1, tlsv1)
685
+ @tlsv1.set_value($conf.tlsv1)
686
+ evt_checkbox(@tlsv1.get_id()) { |event| options_update_config(event, {:tlsv1 => @tlsv1.get_value}) }
687
+
688
+ ssl_vsizer.add_item(@sslv2, -1, 0)
689
+ ssl_vsizer.add_item(@sslv3, -1, 0)
690
+ ssl_vsizer.add_item(@tlsv1, -1, 0)
691
+ #@ws_mvsizer.add_item(@hosts_button_hsizer , -1, 0, Wx::EXPAND|Wx::ALL)
692
+
693
+ ssl_hsizer.add_item(ssl_vsizer, -1, 1, Wx::EXPAND|Wx::ALL)
694
+ sizer.add_item(ssl_hsizer, -1, 0, Wx::EXPAND|Wx::ALL, 10)
695
+
696
+ end
697
+
698
+
699
+ def options_content_connect_radio(parent_panel, sizer)
700
+ choices = SSLSmartConfig::SCAN_TYPES
701
+ hsizer = Wx::BoxSizer.new(Wx::HORIZONTAL)
702
+ @content_connect = Wx::RadioBox.new(parent_panel, -1, "Perform Content or Connect Test", Wx::DEFAULT_POSITION, Wx::DEFAULT_SIZE, choices)
703
+ evt_radiobox(@content_connect.get_id()) {|event| options_update_config(event, {:scan_type => @content_connect.get_selection})}
704
+ @content_connect.set_string_selection("#{$conf.scan_type}")
705
+ hsizer.add_item(@content_connect, -1, 1, Wx::EXPAND|Wx::ALL)
706
+ sizer.add_item(hsizer, -1, 0, Wx::EXPAND|Wx::ALL, 10)
707
+ end
708
+
709
+
710
+ def options_suite_version_radio(parent_panel, sizer)
711
+ choices = SSLSmartConfig::SCAN_MODES
712
+ hsizer = Wx::BoxSizer.new(Wx::HORIZONTAL)
713
+ @scan_mode = Wx::RadioBox.new(parent_panel, -1, "Select Test Option", Wx::DEFAULT_POSITION, Wx::DEFAULT_SIZE, choices)
714
+ evt_radiobox(@scan_mode.get_id()) {|event| options_update_config(event, {:scan_mode => @scan_mode.get_selection}); options_apply_filter(@filter_combo.get_value())}
715
+ #evt_radiobox(@scan_mode.get_id()) {|event| options_update_config(event, {:scan_mode => @scan_mode.get_selection})}
716
+ @scan_mode.set_string_selection("#{$conf.scan_mode}")
717
+ hsizer.add_item(@scan_mode, -1, 1, Wx::EXPAND|Wx::ALL)
718
+ sizer.add_item(hsizer, -1, 0, Wx::EXPAND|Wx::ALL, 10)
719
+ end
720
+
721
+
722
+ def options_proxy_config(parent_panel, sizer)
723
+ proxy_input = Wx::StaticBox.new(parent_panel, -1, "Proxy Configuration (Must be a Transparent Proxy)")
724
+ proxy_vsizer = Wx::StaticBoxSizer.new(proxy_input, Wx::VERTICAL)
725
+
726
+ proxy_add_hsizer = Wx::BoxSizer.new(Wx::HORIZONTAL)
727
+ proxy_port_hsizer = Wx::BoxSizer.new(Wx::HORIZONTAL)
728
+
729
+ proxy_add_tag = Wx::StaticText.new(parent_panel, -1, "Proxy Address", Wx::DEFAULT_POSITION, [100,25])
730
+ @proxy_add = Wx::TextCtrl.new(parent_panel, -1, "", Wx::DEFAULT_POSITION, [150,25])
731
+ evt_text(@proxy_add.get_id()) {|event| options_update_config(event, {:proxy_add => @proxy_add.get_value})}
732
+ proxy_add_hsizer.add_item(proxy_add_tag)
733
+ proxy_add_hsizer.add_item(@proxy_add)
734
+
735
+ proxy_port_tag = Wx::StaticText.new(parent_panel, -1, "Proxy Port", Wx::DEFAULT_POSITION, [100,25])
736
+ @proxy_port = Wx::TextCtrl.new(parent_panel, -1, "", Wx::DEFAULT_POSITION, [150,25])
737
+ evt_text(@proxy_port.get_id()) {|event| options_update_config(event, {:proxy_port => @proxy_port.get_value})}
738
+ proxy_port_hsizer.add_item(proxy_port_tag)
739
+ proxy_port_hsizer.add_item(@proxy_port)
740
+
741
+ proxy_vsizer.add_item(proxy_add_hsizer)
742
+ proxy_vsizer.add_item(proxy_port_hsizer)
743
+
744
+ sizer.add_item(proxy_vsizer, -1, 0, Wx::EXPAND|Wx::ALL, 10)
745
+ end
746
+
747
+
748
+ def options_lookup_pem_file(parent_panel, event)
749
+ $log.debug("Looking up pem file")
750
+ return if(@test_running)
751
+ pem_file_control = Wx::FileDialog.new(parent_panel, "Choose Pem File with Root CA Certificates", "", "", "Pem Files (*.pem)|*.pem")
752
+ pem_file_control.show_modal
753
+ file_names = pem_file_control.get_paths
754
+ file_names.each do |x|
755
+ if(File.file?(x))
756
+ @pem_path.set_value(x)
757
+ $conf.update_config({:pem_path => x})
758
+ end
759
+ end
760
+ event.skip
761
+ end
762
+
763
+
764
+ def options_pem_config(parent_panel, sizer)
765
+ pem_input = Wx::StaticBox.new(parent_panel, -1, "PEM File Selector")
766
+ pem_hsizer = Wx::StaticBoxSizer.new(pem_input, Wx::HORIZONTAL)
767
+
768
+ choose_pem_button = Wx::Button.new(parent_panel, -1, "Choose Pem File", Wx::DEFAULT_POSITION, BUTTON_SIZE)
769
+ evt_button(choose_pem_button.get_id()) { |event| options_lookup_pem_file(parent_panel, event)}
770
+
771
+ @pem_path = Wx::TextCtrl.new(parent_panel, -1, $conf.rootcert_path, Wx::DEFAULT_POSITION, Wx::DEFAULT_SIZE, Wx::TE_READONLY)
772
+
773
+ pem_hsizer.add_item(choose_pem_button)
774
+ pem_hsizer.add_item(@pem_path, -1, 1, Wx::EXPAND|Wx::ALL)
775
+
776
+ sizer.add_item(pem_hsizer, -1, 0, Wx::EXPAND|Wx::ALL, 10)
777
+ end
778
+
779
+
780
+ def options_apply_filter(value)
781
+ return if(@test_running)
782
+ choices = {true => "1", false => ""}
783
+ clear_gui_and_results() #unless($conf.filter == value)
784
+
785
+ begin
786
+ $conf.update_config({:filter => value})
787
+ rescue => ex
788
+ Wx::MessageDialog.new(nil, "Error Occured!!\n#{ex.message}", "", Wx::OK ).show_modal()
789
+ $log.error "Error occured. #{ex.message}"
790
+ end
791
+
792
+ #Resize the grid if required
793
+ if ((diff = ($conf.cipher_suites.length - @ws_cipher_grid.get_number_rows)) >= 0 )
794
+ @ws_cipher_grid.append_rows(diff)
795
+ else
796
+ @ws_cipher_grid.delete_rows(0, diff.abs)
797
+ end
798
+
799
+ @ws_cipher_grid.clear_grid()
800
+ $conf.cipher_suites.each_with_index do |cipher_suite, row_number|
801
+ @ws_cipher_grid.set_cell_editor(row_number, TEST_COL , Wx::GridCellBoolEditor.new)
802
+ @ws_cipher_grid.set_cell_renderer(row_number, TEST_COL , Wx::GridCellBoolRenderer.new)
803
+ @ws_cipher_grid.set_cell_value(row_number, TEST_COL , choices[cipher_suite.test])
804
+ @ws_cipher_grid.set_cell_value(row_number, VERSION_COL , cipher_suite.version)
805
+ @ws_cipher_grid.set_cell_value(row_number, NAME_COL , cipher_suite.name.gsub(":",", "))
806
+ @ws_cipher_grid.set_cell_value(row_number, BITS_COL , cipher_suite.bits)
807
+ end
808
+
809
+ end
810
+
811
+
812
+ def options_cipher_filter(parent_panel, sizer)
813
+ filters = ["DEFAULT", "DEFAULT:!SSLv2", "DEFAULT:!SSLv3", "HIGH","MEDIUM", "LOW", "LOW:EXP", "LOW:EXP:SSLv2", "ALL:eNULL:aNULL", "NULL", "aNULL"]
814
+ filter_input = Wx::StaticBox.new(parent_panel, -1, "OpenSSL Filters for Cipher Suite Selection ")
815
+ hsizer = Wx::StaticBoxSizer.new(filter_input, Wx::HORIZONTAL)
816
+ @filter_combo = Wx::ComboBox.new(parent_panel, -1, "#{filters[0]}", Wx::DEFAULT_POSITION, Wx::DEFAULT_SIZE, filters)
817
+ apply_filter_button = Wx::Button.new(parent_panel, -1, "Apply Filter", Wx::DEFAULT_POSITION, BUTTON_SIZE)
818
+
819
+ evt_button(apply_filter_button.get_id()) {|event| options_apply_filter(@filter_combo.get_value())}
820
+ hsizer.add_item(apply_filter_button, -1, 0, Wx::EXPAND|Wx::ALL)
821
+ hsizer.add_item(@filter_combo, -1, 1, Wx::EXPAND|Wx::ALL)
822
+ sizer.add_item(hsizer, -1, 0, Wx::EXPAND|Wx::ALL, 10)
823
+
824
+ end
825
+
826
+
827
+ def options_create_gui(parent_panel, sizer)
828
+ $log.debug("Creating Options GUI Tab")
829
+ options_create_cipher_checkbox(parent_panel, sizer)
830
+ options_content_connect_radio(parent_panel, sizer)
831
+ options_suite_version_radio(parent_panel, sizer)
832
+ options_proxy_config(parent_panel, sizer)
833
+ options_pem_config(parent_panel, sizer)
834
+ options_cipher_filter(parent_panel, sizer)
835
+ end
836
+
837
+ ###########################################################
838
+ ##+ End of all GUI elements for Options Tab
839
+ ###########################################################
840
+
841
+
842
+ def init_config()
843
+ options_apply_filter("DEFAULT")
844
+ end
845
+
846
+
847
+ def initialize(title,x,y)
848
+ @controller = nil
849
+ @test_running = false
850
+ @stop_test = false
851
+ @selected_grid_row = 0
852
+ #@urls = []
853
+ #super(nil, -1, title, Wx::Point.new(x, y), Wx::Size.new(800, 800),Wx::DEFAULT_FRAME_STYLE & ~ (Wx::RESIZE_BORDER|Wx::RESIZE_BOX|Wx::MAXIMIZE_BOX))
854
+ super(nil, -1, title, Wx::Point.new(x, y), Wx::Size.new(800, 800))
855
+
856
+
857
+ fs_icon = Wx::Icon.new( File.join( File.expand_path("."), "fs_icon_32.ico"), Wx::BITMAP_TYPE_ICO )
858
+ set_icon(fs_icon)
859
+
860
+ create_menu_bar()
861
+ # Start GUI Control Creation
862
+ create_workspace_and_options_tabs()
863
+ ws_create_gui(@ws_tab, @ws_mvsizer)
864
+ evt_close {|event| on_my_close()}
865
+ options_create_gui(@options_tab, @options_mvsizer)
866
+ # End GUI Creation
867
+
868
+ init_config()
869
+
870
+ timer = Wx::Timer.new(self, Wx::ID_ANY)
871
+ evt_timer(timer.id) {Thread.pass}
872
+ timer.start(10)
873
+
874
+ end
875
+
876
+ end
877
+
878
+ class SSLSmartGUI < Wx::App
879
+ def on_init()
880
+ x = 50
881
+ y = 50
882
+ frame = SSLSmartFrame.new("SSLSmart", x, y)
883
+ frame.show(true)
884
+ end
885
+ end
886
+
887
+ sslsmart = SSLSmartGUI.new
888
+ sslsmart.main_loop