def _main_test_init(self, args, hammer): # allocate port port = get_next_listener_port() # collect classes of observed audit results self.actual_results = [] def main__handle_result(res): #self.orig_main__handle_result(res) if isinstance(res, ConnectionAuditResult): self.actual_results.append(ACCAR(res)) else: pass # ignore other events # create options for the controller main_args = ['-l', '%s:%d' % (TEST_LISTENER_ADDR, port)] main_args.extend(args) options = SSLCAuditUI.parse_options(main_args) # create file_bag and controller file_bag = FileBag(basename='test-sslcaudit', use_tempdir=True) self.controller = BaseClientAuditController(options, file_bag, event_handler=main__handle_result) self.hammer = hammer if self.hammer is not None: self.hammer.set_peer((TEST_LISTENER_ADDR, port))
def run(self): ''' Print config info to the console before running the controller ''' if self.options.verbose > 0: print '# filebag location: %s' % str(self.file_bag.base_dir) BaseClientAuditController.run(self)
def test_dummy(self): ''' This test establishes a bunch of plain TCP connections against dummy auditor. The dummy auditor just acknowledges the fact of connection happening. ''' # these variables will be updated from a hook function invoked from main self.got_result_starts = 0 self.got_conn_results = 0 self.got_result_ends = 0 self.nstray = 0 # the hook function def main__handle_result(res): ''' This function overrides main.handle_result() and updates our counters ''' if isinstance(res, SessionStartEvent): self.got_result_starts = self.got_result_starts + 1 elif isinstance(res, SessionEndResult): self.got_result_ends = self.got_result_ends + 1 elif isinstance(res, ConnectionAuditResult): self.got_conn_results = self.got_conn_results + 1 else: self.nstray = self.nstray + 1 # allocate port port = get_next_listener_port() # create a client hammering our test listener self.hammer = TCPConnectionHammer(self.HAMMER_ATTEMPTS) # create main, the target of the test main_args = ['-m', 'dummy', '-l', ("%s:%d" % (TEST_LISTENER_ADDR, port))] options = SSLCAuditUI.parse_options(main_args) file_bag = FileBag(basename='test-sslcaudit', use_tempdir=True) controller = BaseClientAuditController(options, file_bag, event_handler=main__handle_result) # tell the hammer how many attempts to make exactly self.hammer.set_peer((TEST_LISTENER_ADDR, port)) # start server and client controller.start() self.hammer.start() controller.join(timeout=5) self.hammer.stop() # make sure we have received expected number of results self.assertEquals(self.got_result_starts, 1) self.assertEquals(self.got_conn_results, 2) self.assertEquals(self.got_result_ends, 1) self.assertEquals(self.nstray, 0)
class SSLCAuditQtBridge(logging.Handler, QThread): ''' This class is a bridge between PyQt GUI and the core of sslcaudit. The main window contains an instance of this class and uses it to communicate with the core. It invokes start(), stop(), isRunning() methods of the core to control it. It uses sendLog, sendError, sendConnection signals to receive events from the core. This class does not contain any control rules by itself. ''' sendLog = pyqtSignal(logging.LogRecord) sendControllerEvent = pyqtSignal(ControllerEvent) def __init__(self, file_bag): logging.Handler.__init__(self) self.setFormatter(logging.Formatter('%(asctime)s %(message)s', datefmt='%H:%M:%S')) QThread.__init__(self) self.file_bag = file_bag self.is_running = False def emit(self, record): ''' This method overrides logging.Handler.emit() ''' self.sendLog.emit(record) def init_controller(self, options): self.options = options self.controller = BaseClientAuditController(self.options, self.file_bag, event_handler=self.event_handler) def start(self): self.controller.start() self.is_running = True def run(self): raise NotImplemented('there is no use for this "thread" to run') def isRunning(self): return self.is_running def stop(self): self.controller.stop() self.is_running = False self.exit() def event_handler(self, event): ''' This method gets invoked asynchronously by BaseClientAuditController thread ''' self.sendControllerEvent.emit(event)
class SSLCAuditCLI(object): def __init__(self, options, file_bag): self.options = options self.controller = BaseClientAuditController( self.options, file_bag, event_handler=self.event_handler) def run(self): # print config info to the console before running the controller logger.info('filebag location: %s' % str(self.controller.file_bag.base_dir)) self.controller.start() # wait for the controller thread to finish, handle Ctrl-C if any interrupted_by_user = False while self.controller.isAlive(): try: self.controller.join(1) except KeyboardInterrupt: logger.info( 'Got KeyboardInterrupt exception, aborting the program ...' ) self.controller.stop() # graceful death interrupted_by_user = True # if the program is aborted by the user, return exitcode 1 if interrupted_by_user: return 1 else: return 0 def stop(self): self.controller.stop() def event_handler(self, res): if isinstance(res, ConnectionAuditResult): # dump: # * client address and port, # * server profile # * result # all in one line, in fixed width columns fields = [] client_address = '%s:%d' % (res.conn.client_address) fields.append('%-16s' % client_address) fields.append('%-80s' % (res.profile)) fields.append(str(res.result)) print OUTPUT_FIELD_SEPARATOR.join(fields)
class SSLCAuditCLI(object): def __init__(self, options, file_bag): self.options = options self.controller = BaseClientAuditController(self.options, file_bag, event_handler=self.event_handler) def run(self): # print config info to the console before running the controller logger.info('filebag location: %s' % str(self.controller.file_bag.base_dir)) self.controller.start() # wait for the controller thread to finish, handle Ctrl-C if any interrupted_by_user = False while self.controller.isAlive(): try: self.controller.join(1) except KeyboardInterrupt: logger.info('Got KeyboardInterrupt exception, aborting the program ...') self.controller.stop() # graceful death interrupted_by_user = True # if the program is aborted by the user, return exitcode 1 if interrupted_by_user: return 1 else: return 0 def stop(self): self.controller.stop() def event_handler(self, res): if isinstance(res, ConnectionAuditResult): # dump: # * client address and port, # * server profile # * result # all in one line, in fixed width columns fields = [] client_address = '%s:%d' % (res.conn.client_address) fields.append('%-16s' % client_address) fields.append('%-80s' % (res.profile)) fields.append(str(res.result)) print OUTPUT_FIELD_SEPARATOR.join(fields)
def test_dummy(self): ''' This test establishes a bunch of plain TCP connections against dummy auditor. The dummy auditor just acknowledges the fact of connection happening. ''' # these variables will be updated from a hook function invoked from main self.got_result_starts = 0 self.got_conn_results = 0 self.got_result_ends = 0 self.nstray = 0 # the hook function def main__handle_result(res): ''' This function overrides main.handle_result() and updates our counters ''' if isinstance(res, SessionStartEvent): self.got_result_starts = self.got_result_starts + 1 elif isinstance(res, SessionEndResult): self.got_result_ends = self.got_result_ends + 1 elif isinstance(res, ConnectionAuditResult): self.got_conn_results = self.got_conn_results + 1 else: self.nstray = self.nstray + 1 # allocate port port = get_next_listener_port() # create a client hammering our test listener self.hammer = TCPConnectionHammer(self.HAMMER_ATTEMPTS) # create main, the target of the test main_args = [ '-m', 'dummy', '-l', ("%s:%d" % (TEST_LISTENER_ADDR, port)) ] options = SSLCAuditUI.parse_options(main_args) file_bag = FileBag(basename='test-sslcaudit', use_tempdir=True) controller = BaseClientAuditController( options, file_bag, event_handler=main__handle_result) # tell the hammer how many attempts to make exactly self.hammer.set_peer((TEST_LISTENER_ADDR, port)) # start server and client controller.start() self.hammer.start() controller.join(timeout=5) self.hammer.stop() # make sure we have received expected number of results self.assertEquals(self.got_result_starts, 1) self.assertEquals(self.got_conn_results, 2) self.assertEquals(self.got_result_ends, 1) self.assertEquals(self.nstray, 0)
def init_controller(self, options): self.options = options self.controller = BaseClientAuditController(self.options, self.file_bag, event_handler=self.event_handler)
def __init__(self, argv): BaseClientAuditController.__init__(self, self.parse_options(argv))
def __init__(self, options, file_bag): self.options = options self.controller = BaseClientAuditController( self.options, file_bag, event_handler=self.event_handler)
class TestModule(unittest.TestCase): ''' This is a base class for testing modules of sslcaudit tool. ''' def setUp(self): self.controller = None def tearDown(self): if self.controller is not None: self.controller.stop() def _main_test(self, main_args, hammer, expected_results): ''' This is a main worker function. It allocates external resources and launches threads, to make sure they are freed this function was to be called exactly once per test method, to allow tearDown() method to cleanup properly. ''' self._main_test_init(main_args, hammer) self._main_test_do(expected_results) def _main_test_init(self, args, hammer): # allocate port port = get_next_listener_port() # collect classes of observed audit results self.actual_results = [] def main__handle_result(res): #self.orig_main__handle_result(res) if isinstance(res, ConnectionAuditResult): self.actual_results.append(ACCAR(res)) else: pass # ignore other events # create options for the controller main_args = ['-l', '%s:%d' % (TEST_LISTENER_ADDR, port)] main_args.extend(args) options = SSLCAuditUI.parse_options(main_args) # create file_bag and controller file_bag = FileBag(basename='test-sslcaudit', use_tempdir=True) self.controller = BaseClientAuditController(options, file_bag, event_handler=main__handle_result) self.hammer = hammer if self.hammer is not None: self.hammer.set_peer((TEST_LISTENER_ADDR, port)) def _main_test_do(self, expected_results): # run the server self.controller.start() # start the hammer, if any if self.hammer is not None: self.hammer.start() # wait for main to finish its job self.controller.join(timeout=TEST_MAIN_JOIN_TIMEOUT) # on timeout throws exception, which we let propagate after we shut the hammer and the main thread self.assertFalse(self.controller.is_alive(), 'main thread is still alive') # stop the hammer if any if self.hammer is not None: self.hammer.stop() # stop the server self.controller.stop() self.verify_results_ignore_order(expected_results, self.actual_results) def verify_results_ignore_order(self, expected_results, actual_results): expected_results_set = set(expected_results) actual_results_set = set(actual_results) unexpected = actual_results_set.difference(expected_results_set) missing = expected_results_set.difference(actual_results_set) if len(unexpected) != 0 or len(missing) != 0: print if len(unexpected) > 0: print '\tunexpected results' for r in unexpected: print '\t\t%s' % r if len(missing) > 0: print '\tmissing results' for r in missing: print '\t\t%s' % r self.assertTrue(len(unexpected) == 0 and len(missing) == 0, 'there are missing or unexpected results')
def __init__(self, options, file_bag): self.options = options self.controller = BaseClientAuditController(self.options, file_bag, event_handler=self.event_handler)