def test_works_when_client_auth_succeeded(self): # Given a server that requires client authentication with VulnerableOpenSslServer( client_auth_config=ClientAuthenticationServerConfigurationEnum. REQUIRED) as server: # And the client provides a client certificate client_creds = ClientAuthenticationCredentials( client_certificate_chain_path=server. get_client_certificate_path(), client_key_path=server.get_client_key_path(), ) server_test = ServerConnectivityTester( hostname=server.hostname, ip_address=server.ip_address, port=server.port, client_auth_credentials=client_creds, ) server_info = server_test.perform() # The plugin works fine plugin = SessionRenegotiationPlugin() plugin_result = plugin.process_task( server_info, SessionRenegotiationScanCommand()) self.assertTrue(plugin_result.accepts_client_renegotiation) self.assertTrue(plugin_result.supports_secure_renegotiation) self.assertTrue(plugin_result.as_text()) self.assertTrue(plugin_result.as_xml())
def test_works_when_client_auth_succeeded(self): # Given a server that requires client authentication with ModernOpenSslServer( client_auth_config=ClientAuthConfigEnum.REQUIRED) as server: # And the client provides a client certificate client_creds = ClientAuthenticationCredentials( client_certificate_chain_path=server. get_client_certificate_path(), client_key_path=server.get_client_key_path(), ) server_test = ServerConnectivityTester( hostname=server.hostname, ip_address=server.ip_address, port=server.port, client_auth_credentials=client_creds, ) server_info = server_test.perform() # The plugin works fine plugin = HttpHeadersPlugin() plugin_result = plugin.process_task(server_info, HttpHeadersScanCommand()) self.assertIsNone(plugin_result.expect_ct_header) self.assertTrue(plugin_result.as_text()) self.assertTrue(plugin_result.as_xml())
def test_works_when_client_auth_succeeded(self): # Given a server that requires client authentication try: with VulnerableOpenSslServer( client_auth_config= ClientAuthenticationServerConfigurationEnum.REQUIRED ) as server: # And the client provides a client certificate client_creds = ClientAuthenticationCredentials( client_certificate_chain_path=server. get_client_certificate_path(), client_key_path=server.get_client_key_path(), ) server_test = ServerConnectivityTester( hostname=server.hostname, ip_address=server.ip_address, port=server.port, client_auth_credentials=client_creds, ) server_info = server_test.perform() # The plugin works fine plugin = FallbackScsvPlugin() plugin_result = plugin.process_task(server_info, FallbackScsvScanCommand()) except NotOnLinux64Error: logging.warning('WARNING: Not on Linux - skipping test') return self.assertFalse(plugin_result.supports_fallback_scsv) self.assertTrue(plugin_result.as_text()) self.assertTrue(plugin_result.as_xml())
def test_works_when_client_auth_succeeded(self): # Given a server that requires client authentication with LegacyOpenSslServer(client_auth_config=ClientAuthConfigEnum.REQUIRED) as server: # And the client provides a client certificate client_creds = ClientAuthenticationCredentials( client_certificate_chain_path=server.get_client_certificate_path(), client_key_path=server.get_client_key_path(), ) server_test = ServerConnectivityTester( hostname=server.hostname, ip_address=server.ip_address, port=server.port, client_auth_credentials=client_creds, ) server_info = server_test.perform() # The plugin works fine plugin = FallbackScsvPlugin() plugin_result = plugin.process_task(server_info, FallbackScsvScanCommand()) assert not plugin_result.supports_fallback_scsv assert plugin_result.as_text() assert plugin_result.as_xml()
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