def __init__(self, host, port, proxy=None): """ :param proxy: (dict) Default: None; Set this one up if you wish to use a proxy to hit your target host. E.g.: { "server":"someproxy.com", "port":6000, "user":"******", "pass":"******" } """ self.host = host self.port = port self.policies = { "ssl2.0": { "allowed": False, "command": Sslv20ScanCommand() }, "ssl3.0": { "allowed": False, "command": Sslv30ScanCommand() }, "tls1.0": { "allowed": False, "command": Tlsv10ScanCommand() }, "tls1.1": { "allowed": False, "command": Tlsv11ScanCommand() }, "tls1.2": { "allowed": True, "command": Tlsv12ScanCommand() }, "tls1.3": { "allowed": True, "command": Tlsv13ScanCommand() }, } if not isinstance(host, str) or not isinstance(port, int): raise TypeError('EncryptionCheck class not properly initialized.') # Proxy setup if proxy is not None: if not ("server" in proxy and "port" in proxy): raise ValueError('Invalid proxy settings detected.') proxy_server = proxy['server'] proxy_port = proxy['port'] proxy_user = proxy.get('user', None) proxy_pass = proxy.get('pass', None) tunnel_settings = HttpConnectTunnelingSettings( proxy_server, proxy_port, basic_auth_user=proxy_user, basic_auth_password=proxy_pass) else: tunnel_settings = None self.tunnel = tunnel_settings self.proxy = proxy
def test_https_tunneling(self): # Start a local proxy proxy_port = 8000 p = multiprocessing.Process(target=proxy_worker, args=(proxy_port, )) p.start() try: # Run a scan through the proxy tunnel_settings = HttpConnectTunnelingSettings( 'localhost', proxy_port) server_info = ServerConnectivityInfo( hostname='www.google.com', http_tunneling_settings=tunnel_settings) # Try to connect to the proxy - retry if the proxy subprocess wasn't ready proxy_connection_attempts = 0 while True: try: server_info.test_connectivity_to_server() break except ServerConnectivityError: if proxy_connection_attempts > 3: raise proxy_connection_attempts += 1 plugin = CertificateInfoPlugin() plugin_result = plugin.process_task(server_info, 'certinfo_basic') self.assertTrue(plugin_result.certificate_chain) self.assertTrue(plugin_result.as_text()) self.assertTrue(plugin_result.as_xml()) finally: # Kill the local proxy - unclean p.terminate()
def test_https_tunneling_bad_arguments(self): # Ensure that an IP address cannot be specified when using an HTTP proxy for scans tunnel_settings = HttpConnectTunnelingSettings('fakedomain', 443) with self.assertRaisesRegexp( ValueError, 'Cannot specify both ip_address and http_tunneling_settings'): ServerConnectivityInfo(hostname='www.google.com', ip_address='1.2.3.4', http_tunneling_settings=tunnel_settings)
def test_https_tunneling_bad_arguments(self): # Ensure that an IP address cannot be specified when using an HTTP proxy for scans tunnel_settings = HttpConnectTunnelingSettings('fakedomain', 443) with pytest.raises(ValueError): ServerConnectivityTester( hostname='www.google.com', ip_address='1.2.3.4', http_tunneling_settings=tunnel_settings )
def test_https_tunneling(self): # Start a local proxy proxy_port = 8000 p = multiprocessing.Process(target=proxy_worker, args=(proxy_port, )) p.start() # On Travis CI, the server sometimes is still not ready to accept connections when we get here # Wait a bit more to make the test suite less flaky time.sleep(0.5) try: # Run a scan through the proxy tunnel_settings = HttpConnectTunnelingSettings( 'localhost', proxy_port, basic_auth_user='******', basic_auth_password='******') server_info = ServerConnectivityInfo( hostname='www.google.com', http_tunneling_settings=tunnel_settings) # Try to connect to the proxy - retry if the proxy subprocess wasn't ready proxy_connection_attempts = 0 while True: try: server_info.test_connectivity_to_server() break except ServerConnectivityError: if proxy_connection_attempts > 3: raise proxy_connection_attempts += 1 plugin = CertificateInfoPlugin() plugin_result = plugin.process_task(server_info, CertificateInfoScanCommand()) self.assertGreaterEqual(len(plugin_result.certificate_chain), 1) self.assertTrue(plugin_result.as_text()) self.assertTrue(plugin_result.as_xml()) finally: # Kill the local proxy - unclean p.terminate()
def test_with_http_tunneling(self): output_file = StringIO() generator = XmlOutputGenerator(output_file) # When scanning through a proxy, we do not know the final server's IP address # This makes sure the XML output properly handles that tunneling_settings = HttpConnectTunnelingSettings('prôxyé.com', 3128) server_info = MockServerConnectivityInfo(http_tunneling_settings=tunneling_settings) # noinspection PyTypeChecker server_scan = CompletedServerScan(server_info, []) generator.server_scan_completed(server_scan) generator.scans_completed(1.3) received_output = output_file.getvalue() output_file.close() # Ensure the output displayed the tunneling settings self.assertIn('httpsTunnelHostname="{}"'.format(tunneling_settings.hostname), received_output) self.assertIn('httpsTunnelPort="{}"'.format(tunneling_settings.port), received_output)
def test_server_connectivity_test_succeeded_with_http_tunneling(self): output_file = StringIO() generator = ConsoleOutputGenerator(output_file) # When scanning through a proxy, we do not know the final server's IP address # This makes sure the console output properly handles that tunneling_settings = HttpConnectTunnelingSettings('ûnicôdé.com', 3128) server_info = MockServerConnectivityInfo(http_tunneling_settings=tunneling_settings) generator.server_connectivity_test_succeeded(server_info) received_output = output_file.getvalue() output_file.close() # Ensure the console output properly listed the online domain and that it was going through a proxy assert server_info.hostname in received_output assert str(server_info.port) in received_output assert 'Proxy' in received_output assert tunneling_settings.hostname in received_output assert str(tunneling_settings.port) in received_output
def test_server_scan_completed_with_http_tunneling(self): output_file = StringIO() generator = ConsoleOutputGenerator(output_file) # When scanning through a proxy, we do not know the final server's IP address # This makes sure the console output properly handles that tunneling_settings = HttpConnectTunnelingSettings(u'ûnicôdé.com', 3128) server_info = MockServerConnectivityInfo( http_tunneling_settings=tunneling_settings) server_scan = CompletedServerScan(server_info, []) generator.server_scan_completed(server_scan) received_output = output_file.getvalue() output_file.close() # Ensure the console output properly listed the online domain and that it was going through a proxy self.assertIn(server_info.hostname, received_output.lower()) self.assertIn(str(server_info.port), received_output.lower()) self.assertIn('proxy', received_output.lower()) self.assertIn(tunneling_settings.hostname, received_output.lower()) self.assertIn(str(tunneling_settings.port), received_output.lower())
def parse_command_line(self): """Parses the command line used to launch SSLyze. """ (args_command_list, args_target_list) = self._parser.parse_args() # Handle the --targets_in command line and fill args_target_list if args_command_list.targets_in: if args_target_list: raise CommandLineParsingError("Cannot use --targets_list and specify targets within the command line.") try: # Read targets from a file with open(args_command_list.targets_in) as f: for target in f.readlines(): if target.strip(): # Ignore empty lines if not target.startswith('#'): # Ignore comment lines args_target_list.append(target.strip()) except IOError: raise CommandLineParsingError("Can't read targets from input file '{}.".format( args_command_list.targets_in)) if not args_target_list: raise CommandLineParsingError('No targets to scan.') # Handle the --regular command line parameter as a shortcut if self._parser.has_option('--regular'): if getattr(args_command_list, 'regular'): setattr(args_command_list, 'regular', False) for cmd in self.REGULAR_CMD: setattr(args_command_list, cmd, True) # Sanity checks on the command line options # Prevent --quiet and --xml_out - if args_command_list.xml_file and args_command_list.xml_file == '-' and args_command_list.quiet: raise CommandLineParsingError('Cannot use --quiet with --xml_out -.') # Prevent --quiet and --json_out - if args_command_list.json_file and args_command_list.json_file == '-' and args_command_list.quiet: raise CommandLineParsingError('Cannot use --quiet with --json_out -.') # Prevent --xml_out - and --json_out - if args_command_list.json_file and args_command_list.json_file == '-'\ and args_command_list.xml_file and args_command_list.xml_file == '-'.quiet: raise CommandLineParsingError('Cannot use --xml_out - with --json_out -.') # Sanity checks on the client cert options client_auth_creds = None if bool(args_command_list.cert) ^ bool(args_command_list.key): raise CommandLineParsingError('No private key or certificate file were given. See --cert and --key.') elif args_command_list.cert: # Private key formats if args_command_list.keyform == 'DER': key_type = SSL_FILETYPE_ASN1 elif args_command_list.keyform == 'PEM': key_type = SSL_FILETYPE_PEM else: raise CommandLineParsingError('--keyform should be DER or PEM.') # Let's try to open the cert and key files try: client_auth_creds = ClientAuthenticationCredentials(args_command_list.cert, args_command_list.key, key_type, args_command_list.keypass) except ValueError as e: raise CommandLineParsingError('Invalid client authentication settings: {}.'.format(e[0])) # HTTP CONNECT proxy http_tunneling_settings = None if args_command_list.https_tunnel: try: http_tunneling_settings = HttpConnectTunnelingSettings.from_url(args_command_list.https_tunnel) except ValueError as e: raise CommandLineParsingError('Invalid proxy URL for --https_tunnel: {}.'.format(e[0])) # STARTTLS tls_wrapped_protocol = TlsWrappedProtocolEnum.PLAIN_TLS if args_command_list.starttls: if args_command_list.starttls not in self.START_TLS_PROTOCOLS: raise CommandLineParsingError(self.START_TLS_USAGE) else: # StartTLS was specified if args_command_list.starttls in self.STARTTLS_PROTOCOL_DICT.keys(): # Protocol was given in the command line tls_wrapped_protocol = self.STARTTLS_PROTOCOL_DICT[args_command_list.starttls] # Number of connection retries if args_command_list.nb_retries < 1: raise CommandLineParsingError('Cannot have a number smaller than 1 for --nb_retries.') # Create the server connectivity info for each specifed servers # A limitation when using the command line is that only one client_auth_credentials and http_tunneling_settings # can be specified, for all the servers to scan good_server_list = [] bad_server_list = [] for server_string in args_target_list: try: good_server_list.append(ServerConnectivityInfo.from_command_line( server_string=server_string, tls_wrapped_protocol=tls_wrapped_protocol, tls_server_name_indication=args_command_list.sni, xmpp_to_hostname=args_command_list.xmpp_to, client_auth_credentials=client_auth_creds, http_tunneling_settings=http_tunneling_settings) ) except ServerConnectivityError as e: # Will happen for example if the DNS lookup failed or the server string is malformed bad_server_list.append((server_string, e)) except ValueError as e: # Will happen for example if xmpp_to is specified for a non-XMPP connection raise CommandLineParsingError(e[0]) # Command line hacks # Handle --starttls=auto now that we parsed the server strings if args_command_list.starttls == 'auto': for server_info in good_server_list: # We use the port number to deduce the protocol if server_info.port in self.STARTTLS_PROTOCOL_DICT.keys(): server_info.tls_wrapped_protocol = self.STARTTLS_PROTOCOL_DICT[server_info.port] # Handle --http_get now that we parsed the server strings # Doing it here is hacky as the option is defined within PluginOpenSSLCipherSuites if args_command_list.http_get: for server_info in good_server_list: if server_info.port == 443: server_info.tls_wrapped_protocol = TlsWrappedProtocolEnum.HTTPS return good_server_list, bad_server_list, args_command_list
def parse_command_line( self ) -> Tuple[List[ServerConnectivityTester], List[ServerStringParsingError], Any]: """Parses the command line used to launch SSLyze. """ (args_command_list, args_target_list) = self._parser.parse_args() if args_command_list.update_trust_stores: # Just update the trust stores and do nothing TrustStoresRepository.update_default() raise TrustStoresUpdateCompleted() # Handle the --targets_in command line and fill args_target_list if args_command_list.targets_in: if args_target_list: raise CommandLineParsingError( "Cannot use --targets_list and specify targets within the command line." ) try: # Read targets from a file with open(args_command_list.targets_in) as f: for target in f.readlines(): if target.strip(): # Ignore empty lines if not target.startswith( "#"): # Ignore comment lines args_target_list.append(target.strip()) except IOError: raise CommandLineParsingError( "Can't read targets from input file '{}.".format( args_command_list.targets_in)) if not args_target_list: raise CommandLineParsingError("No targets to scan.") # Handle the --regular command line parameter as a shortcut if self._parser.has_option("--regular"): if getattr(args_command_list, "regular"): setattr(args_command_list, "regular", False) for cmd in self.REGULAR_CMD: setattr(args_command_list, cmd, True) # Sanity checks on the command line options # Prevent --quiet and --xml_out - if args_command_list.xml_file and args_command_list.xml_file == "-" and args_command_list.quiet: raise CommandLineParsingError( "Cannot use --quiet with --xml_out -.") # Prevent --quiet and --json_out - if args_command_list.json_file and args_command_list.json_file == "-" and args_command_list.quiet: raise CommandLineParsingError( "Cannot use --quiet with --json_out -.") # Prevent --xml_out - and --json_out - if (args_command_list.json_file and args_command_list.json_file == "-" and args_command_list.xml_file and args_command_list.xml_file == "-"): raise CommandLineParsingError( "Cannot use --xml_out - with --json_out -.") # Sanity checks on the client cert options client_auth_creds = None if bool(args_command_list.cert) ^ bool(args_command_list.key): raise CommandLineParsingError( "No private key or certificate file were given. See --cert and --key." ) elif args_command_list.cert: # Private key formats if args_command_list.keyform == "DER": key_type = OpenSslFileTypeEnum.ASN1 elif args_command_list.keyform == "PEM": key_type = OpenSslFileTypeEnum.PEM else: raise CommandLineParsingError( "--keyform should be DER or PEM.") # Let's try to open the cert and key files try: client_auth_creds = ClientAuthenticationCredentials( args_command_list.cert, args_command_list.key, key_type, args_command_list.keypass) except ValueError as e: raise CommandLineParsingError( "Invalid client authentication settings: {}.".format( e.args[0])) # HTTP CONNECT proxy http_tunneling_settings = None if args_command_list.https_tunnel: try: http_tunneling_settings = HttpConnectTunnelingSettings.from_url( args_command_list.https_tunnel) except ValueError as e: raise CommandLineParsingError( "Invalid proxy URL for --https_tunnel: {}.".format( e.args[0])) # STARTTLS tls_wrapped_protocol = TlsWrappedProtocolEnum.PLAIN_TLS if args_command_list.starttls: if args_command_list.starttls not in self.START_TLS_PROTOCOLS: raise CommandLineParsingError(self.START_TLS_USAGE) else: # StartTLS was specified if args_command_list.starttls in self.STARTTLS_PROTOCOL_DICT.keys( ): # Protocol was given in the command line tls_wrapped_protocol = self.STARTTLS_PROTOCOL_DICT[ args_command_list.starttls] # Create the server connectivity tester for each specified servers # A limitation when using the command line is that only one client_auth_credentials and http_tunneling_settings # can be specified, for all the servers to scan good_server_list = [] bad_server_list = [] for server_string in args_target_list: try: hostname, ip_address, port = CommandLineServerStringParser.parse_server_string( server_string) except ServerStringParsingError as e: # Will happen if the server string is malformed bad_server_list.append(e) continue try: # TODO(AD): Unicode hostnames may fail on Python2 # hostname = hostname.decode('utf-8') server_info = ServerConnectivityTester( hostname=hostname, port=port, ip_address=ip_address, tls_wrapped_protocol=tls_wrapped_protocol, tls_server_name_indication=args_command_list.sni, xmpp_to_hostname=args_command_list.xmpp_to, client_auth_credentials=client_auth_creds, http_tunneling_settings=http_tunneling_settings, ) good_server_list.append(server_info) except ValueError as e: # Will happen for example if xmpp_to is specified for a non-XMPP connection raise CommandLineParsingError(e.args[0]) # Command line hacks # Handle --starttls=auto now that we parsed the server strings if args_command_list.starttls == "auto": for server_info in good_server_list: # We use the port number to deduce the protocol if server_info.port in self.STARTTLS_PROTOCOL_DICT.keys(): server_info.tls_wrapped_protocol = self.STARTTLS_PROTOCOL_DICT[ server_info.port] # Handle --http_get now that we parsed the server strings # Doing it here is hacky as the option is defined within PluginOpenSSLCipherSuites if args_command_list.http_get: for server_info in good_server_list: if server_info.port == 443: server_info.tls_wrapped_protocol = TlsWrappedProtocolEnum.HTTPS return good_server_list, bad_server_list, args_command_list
def parse_command_line(self): """Parses the command line used to launch SSLyze. """ (args_command_list, args_target_list) = self._parser.parse_args() # Handle the --targets_in command line and fill args_target_list if args_command_list.targets_in: if args_target_list: raise CommandLineParsingError( "Cannot use --targets_list and specify targets within the command line." ) try: # Read targets from a file with open(args_command_list.targets_in) as f: for target in f.readlines(): if target.strip(): # Ignore empty lines if not target.startswith( '#'): # Ignore comment lines args_target_list.append(target.strip()) except IOError: raise CommandLineParsingError( "Can't read targets from input file '{}.".format( args_command_list.targets_in)) if not args_target_list: raise CommandLineParsingError('No targets to scan.') # Handle the --regular command line parameter as a shortcut if self._parser.has_option('--regular'): if getattr(args_command_list, 'regular'): setattr(args_command_list, 'regular', False) for cmd in self.REGULAR_CMD: setattr(args_command_list, cmd, True) # Sanity checks on the command line options # Prevent --quiet and --xml_out - if args_command_list.xml_file and args_command_list.xml_file == '-' and args_command_list.quiet: raise CommandLineParsingError( 'Cannot use --quiet with --xml_out -.') # Prevent --quiet and --json_out - if args_command_list.json_file and args_command_list.json_file == '-' and args_command_list.quiet: raise CommandLineParsingError( 'Cannot use --quiet with --json_out -.') # Prevent --xml_out - and --json_out - if args_command_list.json_file and args_command_list.json_file == '-' \ and args_command_list.xml_file and args_command_list.xml_file == '-': raise CommandLineParsingError( 'Cannot use --xml_out - with --json_out -.') # Sanity checks on the client cert options client_auth_creds = None if bool(args_command_list.cert) ^ bool(args_command_list.key): raise CommandLineParsingError( 'No private key or certificate file were given. See --cert and --key.' ) elif args_command_list.cert: # Private key formats if args_command_list.keyform == 'DER': key_type = SSL_FILETYPE_ASN1 elif args_command_list.keyform == 'PEM': key_type = SSL_FILETYPE_PEM else: raise CommandLineParsingError( '--keyform should be DER or PEM.') # Let's try to open the cert and key files try: client_auth_creds = ClientAuthenticationCredentials( args_command_list.cert, args_command_list.key, key_type, args_command_list.keypass) except ValueError as e: raise CommandLineParsingError( 'Invalid client authentication settings: {}.'.format(e[0])) # HTTP CONNECT proxy http_tunneling_settings = None if args_command_list.https_tunnel: try: http_tunneling_settings = HttpConnectTunnelingSettings.from_url( args_command_list.https_tunnel) except ValueError as e: raise CommandLineParsingError( 'Invalid proxy URL for --https_tunnel: {}.'.format(e[0])) # STARTTLS tls_wrapped_protocol = TlsWrappedProtocolEnum.PLAIN_TLS if args_command_list.starttls: if args_command_list.starttls not in self.START_TLS_PROTOCOLS: raise CommandLineParsingError(self.START_TLS_USAGE) else: # StartTLS was specified if args_command_list.starttls in self.STARTTLS_PROTOCOL_DICT.keys( ): # Protocol was given in the command line tls_wrapped_protocol = self.STARTTLS_PROTOCOL_DICT[ args_command_list.starttls] # Number of connection retries if args_command_list.nb_retries < 1: raise CommandLineParsingError( 'Cannot have a number smaller than 1 for --nb_retries.') # Create the server connectivity info for each specifed servers # A limitation when using the command line is that only one client_auth_credentials and http_tunneling_settings # can be specified, for all the servers to scan good_server_list = [] bad_server_list = [] for server_string in args_target_list: # Support unicode domains server_string = unicode(server_string, 'utf-8') try: good_server_list.append( ServerConnectivityInfo.from_command_line( server_string=server_string, tls_wrapped_protocol=tls_wrapped_protocol, tls_server_name_indication=args_command_list.sni, xmpp_to_hostname=args_command_list.xmpp_to, client_auth_credentials=client_auth_creds, http_tunneling_settings=http_tunneling_settings)) except ServerConnectivityError as e: # Will happen for example if the DNS lookup failed or the server string is malformed bad_server_list.append((server_string, e)) except ValueError as e: # Will happen for example if xmpp_to is specified for a non-XMPP connection raise CommandLineParsingError(e[0]) # Command line hacks # Handle --starttls=auto now that we parsed the server strings if args_command_list.starttls == 'auto': for server_info in good_server_list: # We use the port number to deduce the protocol if server_info.port in self.STARTTLS_PROTOCOL_DICT.keys(): server_info.tls_wrapped_protocol = self.STARTTLS_PROTOCOL_DICT[ server_info.port] # Handle --http_get now that we parsed the server strings # Doing it here is hacky as the option is defined within PluginOpenSSLCipherSuites if args_command_list.http_get: for server_info in good_server_list: if server_info.port == 443: server_info.tls_wrapped_protocol = TlsWrappedProtocolEnum.HTTPS return good_server_list, bad_server_list, args_command_list
def parse_command_line(self) -> Tuple[List[ServerConnectivityTester], List[ServerStringParsingError], Any]: """Parses the command line used to launch SSLyze. """ (args_command_list, args_target_list) = self._parser.parse_args() if args_command_list.update_trust_stores: # Just update the trust stores and do nothing TrustStoresRepository.update_default() raise TrustStoresUpdateCompleted() # Handle the --targets_in command line and fill args_target_list if args_command_list.targets_in: if args_target_list: raise CommandLineParsingError('Cannot use --targets_list and specify targets within the command line.') try: # Read targets from a file with open(args_command_list.targets_in) as f: for target in f.readlines(): if target.strip(): # Ignore empty lines if not target.startswith('#'): # Ignore comment lines args_target_list.append(target.strip()) except IOError: raise CommandLineParsingError('Can\'t read targets from input file \'{}.'.format( args_command_list.targets_in)) if not args_target_list: raise CommandLineParsingError('No targets to scan.') # Handle the --regular command line parameter as a shortcut if self._parser.has_option('--regular'): if getattr(args_command_list, 'regular'): setattr(args_command_list, 'regular', False) for cmd in self.REGULAR_CMD: setattr(args_command_list, cmd, True) # Sanity checks on the command line options # Prevent --quiet and --xml_out - if args_command_list.xml_file and args_command_list.xml_file == '-' and args_command_list.quiet: raise CommandLineParsingError('Cannot use --quiet with --xml_out -.') # Prevent --quiet and --json_out - if args_command_list.json_file and args_command_list.json_file == '-' and args_command_list.quiet: raise CommandLineParsingError('Cannot use --quiet with --json_out -.') # Prevent --xml_out - and --json_out - if args_command_list.json_file and args_command_list.json_file == '-' \ and args_command_list.xml_file and args_command_list.xml_file == '-': raise CommandLineParsingError('Cannot use --xml_out - with --json_out -.') # Sanity checks on the client cert options client_auth_creds = None if bool(args_command_list.cert) ^ bool(args_command_list.key): raise CommandLineParsingError('No private key or certificate file were given. See --cert and --key.') elif args_command_list.cert: # Private key formats if args_command_list.keyform == 'DER': key_type = OpenSslFileTypeEnum.ASN1 elif args_command_list.keyform == 'PEM': key_type = OpenSslFileTypeEnum.PEM else: raise CommandLineParsingError('--keyform should be DER or PEM.') # Let's try to open the cert and key files try: client_auth_creds = ClientAuthenticationCredentials(args_command_list.cert, args_command_list.key, key_type, args_command_list.keypass) except ValueError as e: raise CommandLineParsingError('Invalid client authentication settings: {}.'.format(e.args[0])) # HTTP CONNECT proxy http_tunneling_settings = None if args_command_list.https_tunnel: try: http_tunneling_settings = HttpConnectTunnelingSettings.from_url(args_command_list.https_tunnel) except ValueError as e: raise CommandLineParsingError('Invalid proxy URL for --https_tunnel: {}.'.format(e.args[0])) # STARTTLS tls_wrapped_protocol = TlsWrappedProtocolEnum.PLAIN_TLS if args_command_list.starttls: if args_command_list.starttls not in self.START_TLS_PROTOCOLS: raise CommandLineParsingError(self.START_TLS_USAGE) else: # StartTLS was specified if args_command_list.starttls in self.STARTTLS_PROTOCOL_DICT.keys(): # Protocol was given in the command line tls_wrapped_protocol = self.STARTTLS_PROTOCOL_DICT[args_command_list.starttls] # Create the server connectivity tester for each specified servers # A limitation when using the command line is that only one client_auth_credentials and http_tunneling_settings # can be specified, for all the servers to scan good_server_list = [] bad_server_list = [] for server_string in args_target_list: try: hostname, ip_address, port = CommandLineServerStringParser.parse_server_string(server_string) except ServerStringParsingError as e: # Will happen if the server string is malformed bad_server_list.append(e) continue try: # TODO(AD): Unicode hostnames may fail on Python2 # hostname = hostname.decode('utf-8') server_info = ServerConnectivityTester( hostname=hostname, port=port, ip_address=ip_address, tls_wrapped_protocol=tls_wrapped_protocol, tls_server_name_indication=args_command_list.sni, xmpp_to_hostname=args_command_list.xmpp_to, client_auth_credentials=client_auth_creds, http_tunneling_settings=http_tunneling_settings ) good_server_list.append(server_info) except ValueError as e: # Will happen for example if xmpp_to is specified for a non-XMPP connection raise CommandLineParsingError(e.args[0]) # Command line hacks # Handle --starttls=auto now that we parsed the server strings if args_command_list.starttls == 'auto': for server_info in good_server_list: # We use the port number to deduce the protocol if server_info.port in self.STARTTLS_PROTOCOL_DICT.keys(): server_info.tls_wrapped_protocol = self.STARTTLS_PROTOCOL_DICT[server_info.port] # Handle --http_get now that we parsed the server strings # Doing it here is hacky as the option is defined within PluginOpenSSLCipherSuites if args_command_list.http_get: for server_info in good_server_list: if server_info.port == 443: server_info.tls_wrapped_protocol = TlsWrappedProtocolEnum.HTTPS return good_server_list, bad_server_list, args_command_list