def test_generate_with_export_cipher(self): cmk = ClientMasterKeyGenerator( cipher=constants.CipherSuite.SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5) state = ConnectionState() state.msg_sock = mock.MagicMock() state.get_server_public_key = mock.MagicMock() ret = cmk.generate(state) self.assertEqual(len(ret.clear_key), 11)
def test_generate_with_des_cipher(self): cmk = ClientMasterKeyGenerator( cipher=constants.CipherSuite.SSL_CK_DES_64_CBC_WITH_MD5) state = ConnectionState() state.msg_sock = mock.MagicMock() state.get_server_public_key = mock.MagicMock() ret = cmk.generate(state) self.assertEqual(ret.encrypted_key, state.get_server_public_key().encrypt())
def test_generate(self): cmk = ClientMasterKeyGenerator( cipher=constants.CipherSuite.SSL_CK_DES_192_EDE3_CBC_WITH_MD5) state = ConnectionState() state.msg_sock = mock.MagicMock() state.get_server_public_key = mock.MagicMock() ret = cmk.generate(state) self.assertEqual(ret.cipher, constants.CipherSuite.SSL_CK_DES_192_EDE3_CBC_WITH_MD5) self.assertEqual(ret.clear_key, bytearray(0)) self.assertEqual(ret.encrypted_key, state.get_server_public_key().encrypt()) self.assertEqual(ret.key_argument, state.msg_sock.calcSSL2PendingStates())
def test_generate_with_session_key(self): cmk = ClientMasterKeyGenerator( cipher=constants.CipherSuite.SSL_CK_DES_192_EDE3_CBC_WITH_MD5) state = ConnectionState() state.msg_sock = mock.MagicMock() state.get_server_public_key = mock.MagicMock() state.master_secret = bytearray(range(32)) ret = cmk.generate(state) state.msg_sock.calcSSL2PendingStates.assert_called_once_with( constants.CipherSuite.SSL_CK_DES_192_EDE3_CBC_WITH_MD5, bytearray(range(32)), bytearray(0), bytearray(0), None)
def main(): """Test if the server supports some of the SSLv2 ciphers""" conversations = {} host = "localhost" port = 4433 run_exclude = set() expected_failures = {} last_exp_tmp = None argv = sys.argv[1:] opts, argv = getopt.getopt(argv, "h:p:e:x:X:", ["help"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '-x': expected_failures[arg] = None last_exp_tmp = str(arg) elif opt == '-X': if not last_exp_tmp: raise ValueError("-x has to be specified before -X") expected_failures[last_exp_tmp] = str(arg) elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if argv: help_msg() raise ValueError("Unknown options: {0}".format(argv)) for cipher_id, cipher_name in { CipherSuite.SSL_CK_DES_192_EDE3_CBC_WITH_MD5: "DES-CBC3-MD5", CipherSuite.SSL_CK_RC4_128_WITH_MD5: "RC4-MD5", CipherSuite.SSL_CK_RC4_128_EXPORT40_WITH_MD5: "EXP-RC4-MD5" }.items(): # instruct RecordLayer to use SSLv2 record layer protocol (0, 2) conversation = Connect(host, port, version=(0, 2)) node = conversation ciphers = [ CipherSuite.SSL_CK_DES_192_EDE3_CBC_WITH_MD5, CipherSuite.SSL_CK_RC4_128_WITH_MD5, CipherSuite.SSL_CK_RC4_128_EXPORT40_WITH_MD5 ] node = node.add_child( ClientHelloGenerator(ciphers, version=(0, 2), ssl2=True)) node = node.add_child(ExpectServerHello2()) node = node.add_child(ClientMasterKeyGenerator(cipher=cipher_id)) node = node.add_child(FinishedGenerator()) # serves as a CCS # ExpectVerify could be be before FinishedGenerator, if the latter # didn't serve double duty as a CCS node = node.add_child(ExpectVerify()) node = node.add_child(ExpectFinished(version=(0, 2))) node = node.add_child( ApplicationDataGenerator(bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node.add_child(Close()) conversations["Connect with SSLv2 {0}".format( cipher_name)] = conversation good = 0 bad = 0 xfail = 0 xpass = 0 failed = [] xpassed = [] shuffled_tests = set(conversations.items()) for c_name, conversation in shuffled_tests: if c_name in run_exclude: continue print("{0} ...".format(c_name)) runner = Runner(conversation) res = True exception = None try: runner.run() except Exception as exp: exception = exp print("Error while processing") print(traceback.format_exc()) print("") res = False if c_name in expected_failures: if res: xpass += 1 xpassed.append(c_name) print("XPASS: expected failure but test passed\n") else: if expected_failures[c_name] is not None and \ expected_failures[c_name] not in str(exception): bad += 1 failed.append(c_name) print("Expected error message: {0}\n".format( expected_failures[c_name])) else: xfail += 1 print("OK-expected failure\n") else: if res: good += 1 print("OK\n") else: xfail += 1 print("Note: This test verifies that an implementation implements and") print(" will negotiate SSLv2 protocol. This is a BAD configuration.") print(" SSLv2 was officially deprecated (MUST NOT use) in 2011, see") print(" RFC 6176.") print(" It is left here only to verify that the tlslite-ng") print(" implementation is correct, so tests for disablement of SSLv2") print(" are sane.") print( " For same reason, if any of the connections succeeds, the exit") print(" code from this script will be 1 (i.e. 'failure')") print("") print("Test end") print(20 * '=') print("TOTAL: {0}".format(len(shuffled_tests))) print("SKIP: {0}".format( len(run_exclude.intersection(conversations.keys())))) print("PASS: {0}".format(good)) print("XFAIL: {0}".format(xfail)) print("FAIL: {0}".format(bad)) print("XPASS: {0}".format(xpass)) print(20 * '=') sort = sorted(xpassed, key=natural_sort_keys) if len(sort): print("XPASSED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) sort = sorted(failed, key=natural_sort_keys) if len(sort): print("FAILED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) if good > 0: sys.exit(1)
def main(): """Test if the server supports export grade SSLv2 ciphers""" conversations = {} host = "localhost" port = 4433 num_limit = None run_exclude = set() expected_failures = {} last_exp_tmp = None argv = sys.argv[1:] opts, argv = getopt.getopt(argv, "h:p:e:n:x:X:", ["help"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '-e': run_exclude.add(arg) elif opt == '-n': num_limit = int(arg) elif opt == '-x': expected_failures[arg] = None last_exp_tmp = str(arg) elif opt == '-X': if not last_exp_tmp: raise ValueError("-x has to be specified before -X") expected_failures[last_exp_tmp] = str(arg) elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if argv: help_msg() raise ValueError("Unknown options: {0}".format(argv)) for prot_vers, proto_name in { (0, 2): "SSLv2", (3, 0): "SSLv3", (3, 1): "TLSv1.0" }.items(): for cipher_id, cipher_name in { CipherSuite.SSL_CK_RC4_128_EXPORT40_WITH_MD5: "EXP-RC4-MD5", CipherSuite.SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5: "EXP-RC2-CBC-MD5" }.items(): # instruct RecordLayer to use SSLv2 record layer protocol (0, 2) conversation = Connect(host, port, version=(0, 2)) node = conversation ciphers = [ CipherSuite.SSL_CK_DES_192_EDE3_CBC_WITH_MD5, CipherSuite.SSL_CK_RC4_128_WITH_MD5, CipherSuite.SSL_CK_RC4_128_EXPORT40_WITH_MD5, CipherSuite.SSL_CK_RC2_128_CBC_WITH_MD5, CipherSuite.SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5, CipherSuite.SSL_CK_IDEA_128_CBC_WITH_MD5, CipherSuite.SSL_CK_DES_64_CBC_WITH_MD5 ] node = node.add_child( ClientHelloGenerator(ciphers, version=prot_vers, ssl2=True)) # we can get a ServerHello with no ciphers: node = node.add_child(ExpectServerHello2()) # or we can get an error stright away, and connection closure node.next_sibling = ExpectSSL2Alert(SSL2ErrorDescription.no_cipher) node.next_sibling.add_child(ExpectClose()) alternative = node.next_sibling # or the server may close the connection right away (likely in # case SSLv2 is completely disabled) alternative.next_sibling = ExpectClose() alternative = alternative.next_sibling # or finally, we can get a TLS Alert message alternative.next_sibling = ExpectAlert() alternative.next_sibling.add_child(ExpectClose()) # in case we got ServerHello, try to force one of the ciphers node = node.add_child(ClientMasterKeyGenerator(cipher=cipher_id)) # it should result in error node = node.add_child(ExpectSSL2Alert()) # or connection close node.next_sibling = ExpectClose() # in case of error, we expect the server to close connection node.add_child(ExpectClose()) conversations["Connect with {1} {0}".format( cipher_name, proto_name)] = conversation good = 0 bad = 0 xfail = 0 xpass = 0 failed = [] xpassed = [] if not num_limit: num_limit = len(conversations) sampled_tests = sample(list(conversations.items()), len(conversations)) for c_name, conversation in sampled_tests: if c_name in run_exclude: continue print("{0} ...".format(c_name)) runner = Runner(conversation) res = True exception = None try: runner.run() except Exception as exp: exception = exp print("Error while processing") print(traceback.format_exc()) print("") res = False if c_name in expected_failures: if res: xpass += 1 xpassed.append(c_name) print("XPASS-expected failure but test passed\n") else: if expected_failures[c_name] is not None and \ expected_failures[c_name] not in str(exception): bad += 1 failed.append(c_name) print("Expected error message: {0}\n".format( expected_failures[c_name])) else: xfail += 1 print("OK-expected failure\n") else: if res: good += 1 print("OK\n") else: bad += 1 print("Note: SSLv2 was officially deprecated (MUST NOT use) in 2011, see") print(" RFC 6176.") print( " If one or more of the tests fails because of error in form of") print("") print(" Unexpected message from peer: Handshake()") print("") print(" With any number inside parethensis, and the server is") print(" configured to not support SSLv2, it means it most") print(" likely is vulnerable to CVE-2015-3197 and CVE-2016-0800.") print(" In case it's a RC4 or 3DES cipher, you may verify that it") print(" really supports it using:") print(" test-sslv2-connection.py") print("") print("Test end") print(20 * '=') print("version: {0}".format(version)) print(20 * '=') print("TOTAL: {0}".format(len(sampled_tests))) print("SKIP: {0}".format( len(run_exclude.intersection(conversations.keys())))) print("PASS: {0}".format(good)) print("XFAIL: {0}".format(xfail)) print("FAIL: {0}".format(bad)) print("XPASS: {0}".format(xpass)) print(20 * '=') sort = sorted(xpassed, key=natural_sort_keys) if len(sort): print("XPASSED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) sort = sorted(failed, key=natural_sort_keys) if len(sort): print("FAILED:\n\t{0}".format('\n\t'.join(repr(i) for i in sort))) if bad > 0: sys.exit(1)
def main(): """ Test if the server will not accept cipher forcing from client client forces 3DES """ conversations = {} host = "localhost" port = 4433 argv = sys.argv[1:] opts, argv = getopt.getopt(argv, "h:p:", ["help"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if argv: help_msg() raise ValueError("Unknown options: {0}".format(argv)) for prot_vers, proto_name in { (0, 2): "SSLv2", (3, 0): "SSLv3", (3, 1): "TLSv1.0" }.items(): for cipher_id, cipher_name in { CipherSuite.SSL_CK_DES_192_EDE3_CBC_WITH_MD5: "DES-CBC3-MD5" }.items(): # instruct RecordLayer to use SSLv2 record layer protocol (0, 2) conversation = Connect(host, port, version=(0, 2)) node = conversation ciphers = [ CipherSuite.SSL_CK_DES_192_EDE3_CBC_WITH_MD5, CipherSuite.SSL_CK_RC4_128_WITH_MD5, CipherSuite.SSL_CK_RC4_128_EXPORT40_WITH_MD5, CipherSuite.SSL_CK_RC2_128_CBC_WITH_MD5, CipherSuite.SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5, CipherSuite.SSL_CK_IDEA_128_CBC_WITH_MD5, CipherSuite.SSL_CK_DES_64_CBC_WITH_MD5 ] node = node.add_child( ClientHelloGenerator(ciphers, version=prot_vers, ssl2=True)) # we can get a ServerHello with no ciphers: node = node.add_child(ExpectServerHello2()) # or we can get an error stright away, and connection closure node.next_sibling = ExpectSSL2Alert(SSL2ErrorDescription.no_cipher) node.next_sibling.add_child(ExpectClose()) alternative = node.next_sibling # or the server may close the connection right away (likely in # case SSLv2 is completely disabled) alternative.next_sibling = ExpectClose() alternative = alternative.next_sibling # or finally, we can get a TLS Alert message alternative.next_sibling = ExpectAlert() alternative.next_sibling.add_child(ExpectClose()) # in case we got ServerHello, try to force one of the ciphers node = node.add_child(ClientMasterKeyGenerator(cipher=cipher_id)) # it should result in error node = node.add_child(ExpectSSL2Alert()) # or connection close node.next_sibling = ExpectClose() # in case of error, we expect the server to close connection node.add_child(ExpectClose()) conversations["Connect with {1} {0}".format( cipher_name, proto_name)] = conversation good = 0 bad = 0 for conversation_name, conversation in conversations.items(): print("{0} ...".format(conversation_name)) runner = Runner(conversation) res = True try: runner.run() except: print("Error while processing") print(traceback.format_exc()) print("") res = False if res: good += 1 print("OK\n") else: bad += 1 print("Note: SSLv2 was officially deprecated (MUST NOT use) in 2011, see") print(" RFC 6176.") print( " If one or more of the tests fails because of error in form of") print("") print(" Unexpected message from peer: Handshake()") print("") print(" With any number inside parethensis, and the server is") print(" configured to not support SSLv2, it means it most") print(" likely is vulnerable to CVE-2015-3197.") print(" In case it's a RC4 or 3DES cipher, you may verify that it") print(" really supports it using:") print(" test-sslv2-connection.py") print("") print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) if bad > 0: sys.exit(1)
def main(): """Test if the server supports some of the SSLv2 ciphers""" conversations = {} host = "localhost" port = 4433 argv = sys.argv[1:] opts, argv = getopt.getopt(argv, "h:p:", ["help"]) for opt, arg in opts: if opt == '-h': host = arg elif opt == '-p': port = int(arg) elif opt == '--help': help_msg() sys.exit(0) else: raise ValueError("Unknown option: {0}".format(opt)) if argv: help_msg() raise ValueError("Unknown options: {0}".format(argv)) for cipher_id, cipher_name in { CipherSuite.SSL_CK_DES_192_EDE3_CBC_WITH_MD5:"DES-CBC3-MD5", CipherSuite.SSL_CK_RC4_128_WITH_MD5:"RC4-MD5", CipherSuite.SSL_CK_RC4_128_EXPORT40_WITH_MD5:"EXP-RC4-MD5" }.items(): # instruct RecordLayer to use SSLv2 record layer protocol (0, 2) conversation = Connect(host, port, version=(0, 2)) node = conversation ciphers = [CipherSuite.SSL_CK_DES_192_EDE3_CBC_WITH_MD5, CipherSuite.SSL_CK_RC4_128_WITH_MD5, CipherSuite.SSL_CK_RC4_128_EXPORT40_WITH_MD5] node = node.add_child(ClientHelloGenerator(ciphers, version=(0, 2), ssl2=True)) node = node.add_child(ExpectServerHello2()) node = node.add_child(ClientMasterKeyGenerator(cipher=cipher_id)) node = node.add_child(FinishedGenerator()) # serves as a CCS # ExpectVerify could be be before FinishedGenerator, if the latter # didn't serve double duty as a CCS node = node.add_child(ExpectVerify()) node = node.add_child(ExpectFinished(version=(0, 2))) node = node.add_child(ApplicationDataGenerator( bytearray(b"GET / HTTP/1.0\n\n"))) node = node.add_child(ExpectApplicationData()) node.add_child(Close()) conversations["Connect with SSLv2 {0}" .format(cipher_name)] = conversation good = 0 bad = 0 shuffled_tests = sample(list(conversations.items()), len(conversations)) for conversation_name, conversation in shuffled_tests: print("{0} ...".format(conversation_name)) runner = Runner(conversation) res = True try: runner.run() except: print("Error while processing") print(traceback.format_exc()) print("") res = False if res: good+=1 print("OK\n") else: bad+=1 print("Note: This test verifies that an implementation implements and") print(" will negotiate SSLv2 protocol. This is a BAD configuration.") print(" SSLv2 was officially deprecated (MUST NOT use) in 2011, see") print(" RFC 6176.") print(" It is left here only to verify that the tlslite-ng") print(" implementation is correct, so tests for disablement of SSLv2") print(" are sane.") print(" For same reason, if any of the connections succeeds, the exit") print(" code from this script will be 1 (i.e. 'failure')") print("") print("Test end") print("successful: {0}".format(good)) print("failed: {0}".format(bad)) if good > 0: sys.exit(1)
def main(host): """Test if the server supports some of the SSLv2 ciphers""" conversations = {} host = host port = 443 for prot_vers, proto_name in { (0, 2):"SSLv2", (3, 0):"SSLv3", (3, 1):"TLSv1.0" }.items(): for cipher_id, cipher_name in { CipherSuite.SSL_CK_DES_192_EDE3_CBC_WITH_MD5:"DES-CBC3-MD5", CipherSuite.SSL_CK_RC2_128_CBC_WITH_MD5: "RC2-CBC-MD5", CipherSuite.SSL_CK_RC4_128_WITH_MD5:"RC4-MD5", CipherSuite.SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5:"EXP-RC2-CBC-MD5", CipherSuite.SSL_CK_IDEA_128_CBC_WITH_MD5:"IDEA-CBC-MD5", CipherSuite.SSL_CK_RC4_128_EXPORT40_WITH_MD5: "EXP-RC4-MD5", CipherSuite.SSL_CK_DES_64_CBC_WITH_MD5:"DES-CBC-MD5" }.items(): conversation = Connect(host, port, version=(0, 2)) node = conversation ciphers = [CipherSuite.SSL_CK_DES_192_EDE3_CBC_WITH_MD5, CipherSuite.SSL_CK_RC4_128_WITH_MD5, CipherSuite.SSL_CK_RC4_128_EXPORT40_WITH_MD5, CipherSuite.SSL_CK_RC2_128_CBC_WITH_MD5, CipherSuite.SSL_CK_RC2_128_CBC_EXPORT40_WITH_MD5, CipherSuite.SSL_CK_IDEA_128_CBC_WITH_MD5, CipherSuite.SSL_CK_DES_64_CBC_WITH_MD5] node = node.add_child(ClientHelloGenerator(ciphers, version=prot_vers, ssl2=True)) # we can get a ServerHello with no ciphers: node = node.add_child(ExpectServerHello2()) # or we can get an error stright away, and connection closure node.next_sibling = ExpectSSL2Alert(SSL2ErrorDescription.no_cipher) node.next_sibling.add_child(ExpectClose()) alternative = node.next_sibling # or the server may close the connection right away (likely in # case SSLv2 is completely disabled) alternative.next_sibling = ExpectClose() alternative = alternative.next_sibling # or finally, we can get a TLS Alert message alternative.next_sibling = ExpectAlert() alternative.next_sibling.add_child(ExpectClose()) # in case we got ServerHello, try to force one of the ciphers node = node.add_child(ClientMasterKeyGenerator(cipher=cipher_id)) # it should result in error node = node.add_child(ExpectSSL2Alert()) # or connection close node.next_sibling = ExpectClose() # in case of error, we expect the server to close connection node = node.add_child(ExpectClose()) conversations["Connect with {1} {0}" .format(cipher_name, proto_name)] = conversation good = 0 bad = 0 for conversation_name, conversation in conversations.items(): print("{0} ...".format(conversation_name)) runner = Runner(conversation) res = True try: runner.run() except: print("Error while processing") print(traceback.format_exc()) print("") res = False if res: good+=1 print("OK\n") else: bad+=1 print("End of the Test") print("Successful: {0}".format(good)) print("Failed: {0}".format(bad)) if bad > 0: sys.exit(1)
def test_generate_with_unknown_cipher(self): cmk = ClientMasterKeyGenerator(cipher=0xffffff) state = ConnectionState() with self.assertRaises(AssertionError): cmk.generate(state)
def test_generate_with_no_cipher(self): cmk = ClientMasterKeyGenerator() with self.assertRaises(NotImplementedError): cmk.generate(None)