class TestMainSSL(unittest.TestCase): ''' Unittests for SSL. ''' logger = logging.getLogger('TestMainSSL') def test_bad_client1(self): ''' Plain TCP client causes unexpected UNEXPECTED_EOF instead of UNKNOWN_CA ''' self._main_test( [ '--user-cn', TEST_USER_CN, '--user-ca-cert', TEST_USER_CA_CERT_FILE, '--user-ca-key', TEST_USER_CA_KEY_FILE ], TCPHammer(), [ ExpectedSSLClientConnectionAuditResult((DEFAULT_CN, SELFSIGNED), '127.0.0.1', UNEXPECTED_EOF), ExpectedSSLClientConnectionAuditResult((TEST_USER_CN, SELFSIGNED), '127.0.0.1', UNEXPECTED_EOF), ExpectedSSLClientConnectionAuditResult((DEFAULT_CN, TEST_USER_CA_CN), '127.0.0.1', UNEXPECTED_EOF), ExpectedSSLClientConnectionAuditResult((TEST_USER_CN, TEST_USER_CA_CN), '127.0.0.1', UNEXPECTED_EOF) ]) # def test_bad_client2(self): # ''' Plain TCP client causes unexpected UNEXPECTED_EOF instead of UNKNOWN_CA ''' # self._main_test( # [ # '--user-cert', TEST_USER_CERT_FILE, # '--user-key', TEST_USER_KEY_FILE, # '--no-user-cert-sign' # ], # TCPHammer(), # [ # ExpectedSSLClientConnectionAuditResult((TEST_USER_CERT_CN, None), '127.0.0.1', UNEXPECTED_EOF), # ExpectedSSLClientConnectionAuditResult((DEFAULT_CN, SELFSIGNED), '127.0.0.1', UNEXPECTED_EOF), # ]) def test_notverifying_client(self): ''' A client which fails to verify the chain of trust reports no error ''' self._main_test( [ '--user-cn', TEST_USER_CN, '--server', TEST_SERVER ], NotVerifyingSSLHammer(), [ ExpectedSSLClientConnectionAuditResult((DEFAULT_CN, SELFSIGNED), '127.0.0.1', CONNECTED), ExpectedSSLClientConnectionAuditResult((TEST_USER_CN, SELFSIGNED), '127.0.0.1', CONNECTED), ExpectedSSLClientConnectionAuditResult((TEST_SERVER_CN, SELFSIGNED), '127.0.0.1', CONNECTED) ]) def test_verifying_client(self): ''' A client which properly verifies the certificate reports UNKNOWN_CA ''' self._main_test( [ '--user-cn', TEST_USER_CN, '--server', TEST_SERVER ], VerifyingSSLHammer(TEST_USER_CN), [ ExpectedSSLClientConnectionAuditResult((DEFAULT_CN, SELFSIGNED), '127.0.0.1', UNKNOWN_CA), ExpectedSSLClientConnectionAuditResult((TEST_USER_CN, SELFSIGNED), '127.0.0.1', UNKNOWN_CA), ExpectedSSLClientConnectionAuditResult((TEST_SERVER_CN, SELFSIGNED), '127.0.0.1', UNKNOWN_CA) ]) # ------------------------------------------------------------------------------------ def setUp(self): self.main = None def tearDown(self): if self.main != None: self.main.stop() def _main_test(self, 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(args, hammer) self._main_test_do(expected_results) def _main_test_init(self, args, hammer): # allocate port port = TestConfig.get_next_listener_port() # create main, the target of the test test_name = "%s %s" % (hammer, args) main_args = ['-l', TestConfig.TEST_LISTENER_ADDR, '-N', test_name, '-p', port] if isinstance(args, basestring): main_args.extend(['-m', args]) # for backward compatibility else: main_args.extend(args) self.main = Main(main_args) # collect classes of observed audit results self.actual_results = [] self.orig_main__handle_result = self.main.handle_result def main__handle_result(res): self.orig_main__handle_result(res) if isinstance(res, ClientConnectionAuditResult): self.actual_results.append(res) else: pass # ignore events print res self.main.handle_result = main__handle_result # create a client hammering the listener self.hammer = hammer if self.hammer != None: self.hammer.init_tcp((TestConfig.TEST_LISTENER_ADDR, port), self.main.auditor_set.len()) def _main_test_do(self, expected_results): # run the server self.main.start() # start the hammer if any if self.hammer != None: self.hammer.start() # wait for main to finish its job try: self.main.join(timeout=TestConfig.TEST_MAIN_JOIN_TIMEOUT) # on timeout throws exception, which we let propagate after we shut the hammer and the main thread finally: # stop the hammer if any if self.hammer != None: self.hammer.stop() # stop the server self.main.stop() # check if the actual results match expected ones if len(expected_results) != len(self.actual_results): mismatch = True print "! length mismatch len(er)=%d, len(ar)=%d" % (len(expected_results), len(self.actual_results)) for er in expected_results: print "er=%s" % er for ar in self.actual_results: print "ar=%s" % ar else: mismatch = False for i in range(len(expected_results)): er = expected_results[i] ar = self.actual_results[i] if not er.matches(ar): print "! mismatch\n\ter=%s\n\tar=%s" % (er, ar) mismatch = True self.assertFalse(mismatch)
class TestMainDummy(unittest.TestCase): ''' Test dummy client / auditor, no SSL whatsoever ''' logger = logging.getLogger('TestMainDummy') MAIN_JOIN_TIMEOUT = 5 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_start = 0 self.got_result = 0 self.got_result_end = 0 self.got_bulk_result = 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, ClientAuditStartEvent): self.got_result_start = self.got_result_start + 1 elif isinstance(res, ClientAuditEndEvent): self.got_result_end = self.got_result_end + 1 elif isinstance(res, ClientConnectionAuditResult): self.got_result = self.got_result + 1 elif isinstance(res, ClientAuditResult): self.got_bulk_result = self.got_bulk_result + 1 else: self.nstray = self.nstray + 1 # allocate port port = get_next_listener_port() # create a client hammering our test listener self.hammer = TCPHammer() # create main, the target of the test self.main = Main(['-m', 'dummy', '-l', TEST_LISTENER_ADDR, '-p', port]) self.main.handle_result = main__handle_result # tell the hammer how many attempts to make exactly self.hammer.init_tcp((TEST_LISTENER_ADDR, port), self.main.auditor_set.len()) # start server and client self.main.start() self.hammer.start() self.main.join(timeout=5) self.hammer.stop() self.main.stop() # make sure we have received expected number of results self.assertEquals(self.got_result_start, 1) self.assertEquals(self.got_result, self.main.auditor_set.len()) self.assertEquals(self.got_result_end, 1) self.assertEquals(self.got_bulk_result, 1) self.assertEquals(self.nstray, 0)