def server_ssh_connect(self): """ Connect to the remote SMTP server over SSH and configure port forwarding with :py:class:`.SSHTCPForwarder` for tunneling SMTP traffic. :return: The connection status as one of the :py:class:`.ConnectionErrorReason` constants. """ server = parse_server(self.config['ssh_server'], 22) username = self.config['ssh_username'] password = self.config['ssh_password'] remote_server = parse_server(self.config['smtp_server'], 25) try: self._ssh_forwarder = SSHTCPForwarder( server, username, password, remote_server, private_key=self.config.get('ssh_preferred_key'), missing_host_key_policy=ssh_host_key.MissingHostKeyPolicy(self.application) ) self._ssh_forwarder.start() except errors.KingPhisherAbortError as error: self.logger.info("ssh connection aborted ({0})".format(error.message)) except paramiko.AuthenticationException: self.logger.warning('failed to authenticate to the remote ssh server') return ConnectionErrorReason.ERROR_AUTHENTICATION_FAILED except paramiko.SSHException as error: self.logger.warning("failed with ssh exception '{0}'".format(error.message)) except Exception: self.logger.warning('failed to connect to the remote ssh server', exc_info=True) else: self.smtp_server = self._ssh_forwarder.local_server return ConnectionErrorReason.SUCCESS return ConnectionErrorReason.ERROR_UNKNOWN
def server_ssh_connect(self): """ Connect to the remote SMTP server over SSH and configure port forwarding with :py:class:`.SSHTCPForwarder` for tunneling SMTP traffic. :return: The connection status as one of the :py:class:`.ConnectionErrorReason` constants. """ server = parse_server(self.config['ssh_server'], 22) username = self.config['ssh_username'] password = self.config['ssh_password'] remote_server = parse_server(self.config['smtp_server'], 25) try: self._ssh_forwarder = SSHTCPForwarder( server, username, password, remote_server, preferred_private_key=self.config.get('ssh_preferred_key')) self._ssh_forwarder.start() except paramiko.AuthenticationException: self.logger.warning( 'failed to authenticate to the remote ssh server') return ConnectionErrorReason.ERROR_AUTHENTICATION_FAILED except Exception: self.logger.warning('failed to connect to the remote ssh server', exc_info=True) return ConnectionErrorReason.ERROR_UNKNOWN self.logger.info( "started ssh port forwarding to the remote smtp server ({0})". format(str(self._ssh_forwarder))) self.smtp_server = self._ssh_forwarder.local_server return ConnectionErrorReason.SUCCESS
def __init__(self, application, target_file, rpc, tab=None): """ :param application: The GTK application that the thread is associated with. :type application: :py:class:`.KingPhisherClientApplication` :param str target_file: The CSV formatted file to read message targets from. :param tab: The GUI tab to report information to. :type tab: :py:class:`.MailSenderSendTab` :param rpc: The client's connected RPC instance. :type rpc: :py:class:`.KingPhisherRPCClient` """ super(MailSenderThread, self).__init__() self.daemon = True self.logger = logging.getLogger('KingPhisher.Client.' + self.__class__.__name__) self.application = application self.config = self.application.config self.target_file = target_file """The name of the target file in CSV format.""" self.tab = tab """The optional :py:class:`.MailSenderSendTab` instance for reporting status messages to the GUI.""" self.rpc = rpc self._ssh_forwarder = None self.smtp_connection = None """The :py:class:`smtplib.SMTP` connection instance.""" self.smtp_server = parse_server(self.config['smtp_server'], 25) self.running = threading.Event() """A :py:class:`threading.Event` object indicating if emails are being sent.""" self.paused = threading.Event() """A :py:class:`threading.Event` object indicating if the email sending operation is or should be paused.""" self.should_stop = threading.Event() self.max_messages_per_minute = float(self.config.get('smtp_max_send_rate', 0.0))
def test_parse_server(self): parsed = utilities.parse_server('127.0.0.1', 80) self.assertIsInstance(parsed, tuple) self.assertEqual(len(parsed), 2) self.assertEqual(parsed[0], '127.0.0.1') self.assertEqual(parsed[1], 80) parsed = utilities.parse_server('127.0.0.1:8080', 80) self.assertIsInstance(parsed, tuple) self.assertEqual(len(parsed), 2) self.assertEqual(parsed[0], '127.0.0.1') self.assertEqual(parsed[1], 8080) parsed = utilities.parse_server('[::1]:8080', 80) self.assertIsInstance(parsed, tuple) self.assertEqual(len(parsed), 2) self.assertEqual(parsed[0], '::1') self.assertEqual(parsed[1], 8080)
def __init__(self, application, target_file, rpc, tab=None): """ :param application: The GTK application that the thread is associated with. :type application: :py:class:`.KingPhisherClientApplication` :param str target_file: The CSV formatted file to read message targets from. :param tab: The GUI tab to report information to. :type tab: :py:class:`.MailSenderSendTab` :param rpc: The client's connected RPC instance. :type rpc: :py:class:`.KingPhisherRPCClient` """ super(MailSenderThread, self).__init__() self.daemon = True self.logger = logging.getLogger('KingPhisher.Client.' + self.__class__.__name__) self.application = application self.config = self.application.config self.target_file = target_file """The name of the target file in CSV format.""" self.tab = tab """The optional :py:class:`.MailSenderSendTab` instance for reporting status messages to the GUI.""" self.rpc = rpc self._ssh_forwarder = None self.smtp_connection = None """The :py:class:`smtplib.SMTP` connection instance.""" self.smtp_server = parse_server(self.config['smtp_server'], 25) self.running = threading.Event() """A :py:class:`threading.Event` object indicating if emails are being sent.""" self.paused = threading.Event() """A :py:class:`threading.Event` object indicating if the email sending operation is or should be paused.""" self.should_stop = threading.Event() self.max_messages_per_minute = float( self.config.get('smtp_max_send_rate', 0.0)) self._mime_attachments = None
def on_server_initialized(self, server): self.bot = NotificationBot( self.config['jid'], self.config['password'], self.config['room'], self.config['verify_cert'] ) self.bot.connect(utilities.parse_server(self.config['server'], 5222)) self.bot.process(block=False)
def server_ssh_connect(self): """ Connect to the remote SMTP server over SSH and configure port forwarding with :py:class:`.SSHTCPForwarder` for tunneling SMTP traffic. :return: The connection status. :rtype: bool """ server = parse_server(self.config['ssh_server'], 22) username = self.config['ssh_username'] password = self.config['ssh_password'] remote_server = parse_server(self.config['smtp_server'], 25) local_port = random.randint(2000, 6000) try: self._ssh_forwarder = SSHTCPForwarder(server, username, password, local_port, remote_server, preferred_private_key=self.config.get('ssh_preferred_key')) self._ssh_forwarder.start() time.sleep(0.5) except Exception: self.logger.warning('failed to connect to remote ssh server', exc_info=True) return False self.smtp_server = ('localhost', local_port) return True
def build(self): self.root = RootWidget() if self.xmpp_config_ok: self.xmpp_client = OperatorXMPPClient( sz_utils.parse_server(self.configuration.get('xmpp', 'server'), 5222), self.configuration.get('xmpp', 'username'), self.configuration.get('xmpp', 'password'), self.configuration.get('xmpp', 'room'), self.configuration.getboolean('xmpp', 'filter')) self.xmpp_client.bind( on_user_location_update=self.on_user_location_update) self.xmpp_client.bind(on_message_receive=self.on_message_receive) self.xmpp_client.bind(on_muc_receive=self.on_muc_receive) else: self.logger.warning( "XMMP config invalid, disabling XMPP operations") self.map = self.root.ids.map_panel_widget.ids.map_widget self.messaging = self.root.ids.message_menu gps.configure(on_location=self.on_gps_location) gps.start() return self.root
def server_connect(self, username, password, otp=None): # pylint: disable=too-many-locals server_version_info = None title_rpc_error = 'Failed To Connect To The King Phisher RPC Service' active_window = self.get_active_window() server = parse_server(self.config['server'], 22) if ipaddress.is_loopback(server[0]): local_server = ('localhost', self.config['server_remote_port']) self.logger.info("connecting to local king phisher instance") else: local_server = self._create_ssh_forwarder(server, username, password) if not local_server: return False, ConnectionErrorReason.ERROR_PORT_FORWARD rpc = client_rpc.KingPhisherRPCClient(local_server, use_ssl=self.config.get('server_use_ssl')) if self.config.get('rpc.serializer'): try: rpc.set_serializer(self.config['rpc.serializer']) except ValueError as error: self.logger.error("failed to set the rpc serializer, error: '{0}'".format(error.message)) generic_message = 'Can not contact the RPC HTTP service, ensure that the ' generic_message += "King Phisher Server is currently running on port {0}.".format(int(self.config['server_remote_port'])) connection_failed = True try: server_version_info = rpc('version') assert server_version_info is not None except AdvancedHTTPServerRPCError as error: self.logger.warning('failed to connect to the remote rpc service due to http status: ' + str(error.status)) gui_utilities.show_dialog_error(title_rpc_error, active_window, "The server responded with HTTP status: {0}.".format(str(error.status))) except BadStatusLine as error: self.logger.warning('failed to connect to the remote rpc service due to http bad status line: ' + error.line) gui_utilities.show_dialog_error(title_rpc_error, active_window, generic_message) except socket.error as error: gui_utilities.show_dialog_exc_socket_error(error, active_window) except ssl.CertificateError as error: self.logger.warning('failed to connect to the remote rpc service with a https certificate error: ' + error.message) gui_utilities.show_dialog_error(title_rpc_error, active_window, 'The server presented an invalid SSL certificate.') except Exception: self.logger.warning('failed to connect to the remote rpc service', exc_info=True) gui_utilities.show_dialog_error(title_rpc_error, active_window, generic_message) else: connection_failed = False if connection_failed: self.emit('server-disconnected') return False, ConnectionErrorReason.ERROR_CONNECTION server_rpc_api_version = server_version_info.get('rpc_api_version', -1) if isinstance(server_rpc_api_version, int): # compatibility with pre-0.2.0 version server_rpc_api_version = (server_rpc_api_version, 0) self.logger.info( "successfully connected to the king phisher server (version: {0} rpc api version: {1}.{2})".format( server_version_info['version'], server_rpc_api_version[0], server_rpc_api_version[1] ) ) error_text = None if server_rpc_api_version[0] < version.rpc_api_version.major or (server_rpc_api_version[0] == version.rpc_api_version.major and server_rpc_api_version[1] < version.rpc_api_version.minor): error_text = 'The server is running an old and incompatible version.' error_text += '\nPlease update the remote server installation.' elif server_rpc_api_version[0] > version.rpc_api_version.major: error_text = 'The client is running an old and incompatible version.' error_text += '\nPlease update the local client installation.' if error_text: gui_utilities.show_dialog_error('The RPC API Versions Are Incompatible', active_window, error_text) self.emit('server-disconnected') return False, ConnectionErrorReason.ERROR_INCOMPATIBLE_VERSIONS login_result, login_reason = rpc.login(username, password, otp) if not login_result: self.logger.warning('failed to authenticate to the remote king phisher service, reason: ' + login_reason) self.emit('server-disconnected') return False, login_reason rpc.username = username self.logger.debug('successfully authenticated to the remote king phisher service') self.rpc = rpc self.emit('server-connected') return True, ConnectionErrorReason.SUCCESS
def server_connect(self): server_version_info = None title_rpc_error = 'Failed To Connect To The King Phisher RPC Service' active_window = self.get_active_window() server = parse_server(self.config['server'], 22) username = self.config['server_username'] password = self.config['server_password'] if server[0] == 'localhost' or (utilities.is_valid_ip_address(server[0]) and ipaddress.ip_address(server[0]).is_loopback): local_port = self.config['server_remote_port'] self.logger.info("connecting to local king-phisher instance") else: local_port = self._create_ssh_forwarder(server, username, password) if not local_port: return self.rpc = client_rpc.KingPhisherRPCClient(('localhost', local_port), username=username, password=password, use_ssl=self.config.get('server_use_ssl')) if self.config.get('rpc.serializer'): try: self.rpc.set_serializer(self.config['rpc.serializer']) except ValueError as error: self.logger.error("failed to set the rpc serializer, error: '{0}'".format(error.message)) connection_failed = True try: assert self.rpc('client/initialize') server_version_info = self.rpc('version') assert server_version_info != None except AdvancedHTTPServerRPCError as err: if err.status == 401: self.logger.warning('failed to authenticate to the remote king phisher service') gui_utilities.show_dialog_error(title_rpc_error, active_window, 'The server responded that the credentials are invalid.') else: self.logger.warning('failed to connect to the remote rpc server with http status: ' + str(err.status)) gui_utilities.show_dialog_error(title_rpc_error, active_window, 'The server responded with HTTP status: ' + str(err.status)) except socket.error as error: gui_utilities.show_dialog_exc_socket_error(error, active_window) except Exception as error: self.logger.warning('failed to connect to the remote rpc service', exc_info=True) gui_utilities.show_dialog_error(title_rpc_error, active_window, 'Ensure that the King Phisher Server is currently running.') else: connection_failed = False finally: if connection_failed: self.rpc = None self.server_disconnect() return server_rpc_api_version = server_version_info.get('rpc_api_version', -1) if isinstance(server_rpc_api_version, int): # compatibility with pre-0.2.0 version server_rpc_api_version = (server_rpc_api_version, 0) self.logger.info("successfully connected to the king phisher server (version: {0} rpc api version: {1}.{2})".format(server_version_info['version'], server_rpc_api_version[0], server_rpc_api_version[1])) error_text = None if server_rpc_api_version[0] < version.rpc_api_version.major or (server_rpc_api_version[0] == version.rpc_api_version.major and server_rpc_api_version[1] < version.rpc_api_version.minor): error_text = 'The server is running an old and incompatible version.' error_text += '\nPlease update the remote server installation.' elif server_rpc_api_version[0] > version.rpc_api_version.major: error_text = 'The client is running an old and incompatible version.' error_text += '\nPlease update the local client installation.' if error_text: gui_utilities.show_dialog_error('The RPC API Versions Are Incompatible', active_window, error_text) self.server_disconnect() return self.emit('server-connected') return
def server_connect(self, username, password, otp=None, window=None): """ Initialize the connection to the King Phisher server. :param str username: The username to authenticate with. :param str password: The password to authenticate with. :param str otp: The optional one-time password to authenticate with. :param window: The GTK window to use as the parent for error dialogs. :type window: :py:class:`Gtk.Window` :rtype: tuple """ # pylint: disable=too-many-locals server_version_info = None title_rpc_error = 'Failed To Connect To The King Phisher RPC Service' window = window or self.get_active_window() server = parse_server(self.config['server'], 22) if ipaddress.is_loopback(server[0]): local_server = ('localhost', self.config['server_remote_port']) self.logger.info("connecting to local king phisher instance") else: local_server = self._create_ssh_forwarder(server, username, password, window=window) if not local_server: return False, ConnectionErrorReason.ERROR_PORT_FORWARD rpc = client_rpc.KingPhisherRPCClient( local_server, use_ssl=self.config.get('server_use_ssl')) if self.config.get('rpc.serializer'): try: rpc.set_serializer(self.config['rpc.serializer']) except ValueError as error: self.logger.error( "failed to set the rpc serializer, error: '{0}'".format( error.message)) generic_message = 'Can not contact the RPC HTTP service, ensure that the ' generic_message += "King Phisher Server is currently running on port {0}.".format( int(self.config['server_remote_port'])) connection_failed = True try: server_version_info = rpc('version') if server_version_info is None: rpc.shutdown() raise RuntimeError( 'no version information was retrieved from the server') except advancedhttpserver.RPCError as error: self.logger.warning( 'failed to connect to the remote rpc service due to http status: ' + str(error.status)) gui_utilities.show_dialog_error( title_rpc_error, window, "The server responded with HTTP status: {0}.".format( str(error.status))) except http.client.BadStatusLine as error: self.logger.warning( 'failed to connect to the remote rpc service due to http bad status line: ' + error.line) gui_utilities.show_dialog_error(title_rpc_error, window, generic_message) except socket.error as error: self.logger.debug( 'failed to connect to the remote rpc service due to a socket error', exc_info=True) gui_utilities.show_dialog_exc_socket_error(error, window) except ssl.CertificateError as error: self.logger.warning( 'failed to connect to the remote rpc service with a https certificate error: ' + error.message) gui_utilities.show_dialog_error( title_rpc_error, window, 'The server presented an invalid SSL certificate.') except Exception: self.logger.warning('failed to connect to the remote rpc service', exc_info=True) gui_utilities.show_dialog_error(title_rpc_error, window, generic_message) else: connection_failed = False if connection_failed: rpc.shutdown() self.emit('server-disconnected') return False, ConnectionErrorReason.ERROR_CONNECTION server_rpc_api_version = server_version_info.get('rpc_api_version', -1) if isinstance(server_rpc_api_version, int): # compatibility with pre-0.2.0 version server_rpc_api_version = (server_rpc_api_version, 0) self.logger.info( "successfully connected to the king phisher server (version: {0} rpc api version: {1}.{2})" .format(server_version_info['version'], server_rpc_api_version[0], server_rpc_api_version[1])) error_text = None if server_rpc_api_version[0] < version.rpc_api_version.major or ( server_rpc_api_version[0] == version.rpc_api_version.major and server_rpc_api_version[1] < version.rpc_api_version.minor): error_text = 'The server is running an old and incompatible version.' error_text += '\nPlease update the remote server installation.' elif server_rpc_api_version[0] > version.rpc_api_version.major: error_text = 'The client is running an old and incompatible version.' error_text += '\nPlease update the local client installation.' if error_text: gui_utilities.show_dialog_error( 'The RPC API Versions Are Incompatible', window, error_text) rpc.shutdown() self.emit('server-disconnected') return False, ConnectionErrorReason.ERROR_INCOMPATIBLE_VERSIONS login_result, login_reason = rpc.login(username, password, otp) if not login_result: self.logger.warning( 'failed to authenticate to the remote king phisher service, reason: ' + login_reason) rpc.shutdown() self.emit('server-disconnected') return False, login_reason rpc.username = username self.logger.debug( 'successfully authenticated to the remote king phisher service') server_str = self.config['server'] history = self.config['server.history'] if server_str in history: history.remove(server_str) history.insert(0, server_str) self.config['server.history'] = history event_subscriber = server_events.ServerEventSubscriber(rpc) if not event_subscriber.is_connected: event_subscriber.reconnect = False event_subscriber.shutdown() rpc.shutdown() self.emit('server-disconnected') return False, ConnectionErrorReason.ERROR_UNKNOWN self.rpc = rpc self.server_events = event_subscriber self._rpc_ping_event = GLib.timeout_add_seconds( parse_timespan('5m'), functools.partial(_rpc_ping, rpc)) user = self.rpc.graphql( """\ query getUser($name: String!) { db { user(name: $name) { id name } } }""", {'name': self.config['server_username']})['db']['user'] self.server_user = ServerUser(id=user['id'], name=user['name']) self.emit('server-connected') return True, ConnectionErrorReason.SUCCESS
def server_connect(self, username, password, otp=None): # pylint: disable=too-many-locals server_version_info = None title_rpc_error = 'Failed To Connect To The King Phisher RPC Service' active_window = self.get_active_window() server = parse_server(self.config['server'], 22) if server[0] == 'localhost' or (utilities.is_valid_ip_address( server[0]) and ipaddress.ip_address(server[0]).is_loopback): local_server = ('localhost', self.config['server_remote_port']) self.logger.info("connecting to local king phisher instance") else: local_server = self._create_ssh_forwarder(server, username, password) if not local_server: return False, ConnectionErrorReason.ERROR_PORT_FORWARD rpc = client_rpc.KingPhisherRPCClient( local_server, use_ssl=self.config.get('server_use_ssl')) if self.config.get('rpc.serializer'): try: rpc.set_serializer(self.config['rpc.serializer']) except ValueError as error: self.logger.error( "failed to set the rpc serializer, error: '{0}'".format( error.message)) connection_failed = True try: server_version_info = rpc('version') assert server_version_info is not None except AdvancedHTTPServerRPCError as error: self.logger.warning( 'failed to connect to the remote rpc service with http status: ' + str(error.status)) gui_utilities.show_dialog_error( title_rpc_error, active_window, "The server responded with HTTP status: {0}.".format( str(error.status))) except socket.error as error: gui_utilities.show_dialog_exc_socket_error(error, active_window) except ssl.CertificateError as error: self.logger.warning( 'failed to connect to the remote rpc service with a https certificate error: ' + error.message) gui_utilities.show_dialog_error( title_rpc_error, active_window, 'The server presented an invalid SSL certificate.') except Exception: self.logger.warning('failed to connect to the remote rpc service', exc_info=True) gui_utilities.show_dialog_error( title_rpc_error, active_window, 'Ensure that the King Phisher Server is currently running.') else: connection_failed = False if connection_failed: self.server_disconnect() return False, ConnectionErrorReason.ERROR_CONNECTION server_rpc_api_version = server_version_info.get('rpc_api_version', -1) if isinstance(server_rpc_api_version, int): # compatibility with pre-0.2.0 version server_rpc_api_version = (server_rpc_api_version, 0) self.logger.info( "successfully connected to the king phisher server (version: {0} rpc api version: {1}.{2})" .format(server_version_info['version'], server_rpc_api_version[0], server_rpc_api_version[1])) error_text = None if server_rpc_api_version[0] < version.rpc_api_version.major or ( server_rpc_api_version[0] == version.rpc_api_version.major and server_rpc_api_version[1] < version.rpc_api_version.minor): error_text = 'The server is running an old and incompatible version.' error_text += '\nPlease update the remote server installation.' elif server_rpc_api_version[0] > version.rpc_api_version.major: error_text = 'The client is running an old and incompatible version.' error_text += '\nPlease update the local client installation.' if error_text: gui_utilities.show_dialog_error( 'The RPC API Versions Are Incompatible', active_window, error_text) self.server_disconnect() return False, ConnectionErrorReason.ERROR_INCOMPATIBLE_VERSIONS login_result, login_reason = rpc.login(username, password, otp) if not login_result: self.logger.warning( 'failed to authenticate to the remote king phisher service, reason: ' + login_reason) self.server_disconnect() return False, login_reason rpc.username = username self.logger.debug( 'successfully authenticated to the remote king phisher service') self.rpc = rpc self.emit('server-connected') return True, ConnectionErrorReason.SUCCESS
def server_connect(self, username, password, otp=None): # pylint: disable=too-many-locals server_version_info = None title_rpc_error = 'Failed To Connect To The King Phisher RPC Service' active_window = self.get_active_window() server = parse_server(self.config['server'], 22) if ipaddress.is_loopback(server[0]): local_server = ('localhost', self.config['server_remote_port']) self.logger.info("connecting to local king phisher instance") else: local_server = self._create_ssh_forwarder(server, username, password) if not local_server: return False, ConnectionErrorReason.ERROR_PORT_FORWARD rpc = client_rpc.KingPhisherRPCClient( local_server, use_ssl=self.config.get('server_use_ssl')) if self.config.get('rpc.serializer'): try: rpc.set_serializer(self.config['rpc.serializer']) except ValueError as error: self.logger.error( "failed to set the rpc serializer, error: '{0}'".format( error.message)) generic_message = 'Can not contact the RPC HTTP service, ensure that the ' generic_message += "King Phisher Server is currently running on port {0}.".format( int(self.config['server_remote_port'])) connection_failed = True try: server_version_info = rpc('version') if server_version_info is None: raise RuntimeError( 'no version information was retrieved from the server') except advancedhttpserver.RPCError as error: self.logger.warning( 'failed to connect to the remote rpc service due to http status: ' + str(error.status)) gui_utilities.show_dialog_error( title_rpc_error, active_window, "The server responded with HTTP status: {0}.".format( str(error.status))) except BadStatusLine as error: self.logger.warning( 'failed to connect to the remote rpc service due to http bad status line: ' + error.line) gui_utilities.show_dialog_error(title_rpc_error, active_window, generic_message) except socket.error as error: self.logger.debug( 'failed to connect to the remote rpc service due to a socket error', exc_info=True) gui_utilities.show_dialog_exc_socket_error(error, active_window) except ssl.CertificateError as error: self.logger.warning( 'failed to connect to the remote rpc service with a https certificate error: ' + error.message) gui_utilities.show_dialog_error( title_rpc_error, active_window, 'The server presented an invalid SSL certificate.') except Exception: self.logger.warning('failed to connect to the remote rpc service', exc_info=True) gui_utilities.show_dialog_error(title_rpc_error, active_window, generic_message) else: connection_failed = False if connection_failed: self.emit('server-disconnected') return False, ConnectionErrorReason.ERROR_CONNECTION server_rpc_api_version = server_version_info.get('rpc_api_version', -1) if isinstance(server_rpc_api_version, int): # compatibility with pre-0.2.0 version server_rpc_api_version = (server_rpc_api_version, 0) self.logger.info( "successfully connected to the king phisher server (version: {0} rpc api version: {1}.{2})" .format(server_version_info['version'], server_rpc_api_version[0], server_rpc_api_version[1])) error_text = None if server_rpc_api_version[0] < version.rpc_api_version.major or ( server_rpc_api_version[0] == version.rpc_api_version.major and server_rpc_api_version[1] < version.rpc_api_version.minor): error_text = 'The server is running an old and incompatible version.' error_text += '\nPlease update the remote server installation.' elif server_rpc_api_version[0] > version.rpc_api_version.major: error_text = 'The client is running an old and incompatible version.' error_text += '\nPlease update the local client installation.' if error_text: gui_utilities.show_dialog_error( 'The RPC API Versions Are Incompatible', active_window, error_text) self.emit('server-disconnected') return False, ConnectionErrorReason.ERROR_INCOMPATIBLE_VERSIONS login_result, login_reason = rpc.login(username, password, otp) if not login_result: self.logger.warning( 'failed to authenticate to the remote king phisher service, reason: ' + login_reason) self.emit('server-disconnected') return False, login_reason rpc.username = username self.logger.debug( 'successfully authenticated to the remote king phisher service') self._rpc_ping_event = GLib.timeout_add_seconds( parse_timespan('5m'), rpc.ping) self.rpc = rpc event_subscriber = server_events.ServerEventSubscriber(rpc) if not event_subscriber.is_connected: self.logger.error('failed to connect the server event socket') event_subscriber.reconnect = False event_subscriber.shutdown() return False, ConnectionErrorReason.ERROR_UNKNOWN self.server_events = event_subscriber self.emit('server-connected') return True, ConnectionErrorReason.SUCCESS
def server_connect(self, username, password, otp=None, window=None): """ Initialize the connection to the King Phisher server. :param str username: The username to authenticate with. :param str password: The password to authenticate with. :param str otp: The optional one-time password to authenticate with. :param window: The GTK window to use as the parent for error dialogs. :type window: :py:class:`Gtk.Window` :rtype: tuple """ # pylint: disable=too-many-locals server_version_info = None title_rpc_error = 'Failed To Connect To The King Phisher RPC Service' window = window or self.get_active_window() server = parse_server(self.config['server'], 22) if ipaddress.is_loopback(server[0]): local_server = ('localhost', self.config['server_remote_port']) self.logger.info("connecting to local king phisher instance") else: local_server = self._create_ssh_forwarder(server, username, password, window=window) if not local_server: return False, ConnectionErrorReason.ERROR_PORT_FORWARD rpc = client_rpc.KingPhisherRPCClient(local_server, use_ssl=self.config.get('server_use_ssl')) if self.config.get('rpc.serializer'): try: rpc.set_serializer(self.config['rpc.serializer']) except ValueError as error: self.logger.error("failed to set the rpc serializer, error: '{0}'".format(error.message)) generic_message = 'Can not contact the RPC HTTP service, ensure that the ' generic_message += "King Phisher Server is currently running on port {0}.".format(int(self.config['server_remote_port'])) connection_failed = True try: server_version_info = rpc('version') if server_version_info is None: raise RuntimeError('no version information was retrieved from the server') except advancedhttpserver.RPCError as error: self.logger.warning('failed to connect to the remote rpc service due to http status: ' + str(error.status)) gui_utilities.show_dialog_error(title_rpc_error, window, "The server responded with HTTP status: {0}.".format(str(error.status))) except http.client.BadStatusLine as error: self.logger.warning('failed to connect to the remote rpc service due to http bad status line: ' + error.line) gui_utilities.show_dialog_error(title_rpc_error, window, generic_message) except socket.error as error: self.logger.debug('failed to connect to the remote rpc service due to a socket error', exc_info=True) gui_utilities.show_dialog_exc_socket_error(error, window) except ssl.CertificateError as error: self.logger.warning('failed to connect to the remote rpc service with a https certificate error: ' + error.message) gui_utilities.show_dialog_error(title_rpc_error, window, 'The server presented an invalid SSL certificate.') except Exception: self.logger.warning('failed to connect to the remote rpc service', exc_info=True) gui_utilities.show_dialog_error(title_rpc_error, window, generic_message) else: connection_failed = False if connection_failed: self.emit('server-disconnected') return False, ConnectionErrorReason.ERROR_CONNECTION server_rpc_api_version = server_version_info.get('rpc_api_version', -1) if isinstance(server_rpc_api_version, int): # compatibility with pre-0.2.0 version server_rpc_api_version = (server_rpc_api_version, 0) self.logger.info( "successfully connected to the king phisher server (version: {0} rpc api version: {1}.{2})".format( server_version_info['version'], server_rpc_api_version[0], server_rpc_api_version[1] ) ) error_text = None if server_rpc_api_version[0] < version.rpc_api_version.major or (server_rpc_api_version[0] == version.rpc_api_version.major and server_rpc_api_version[1] < version.rpc_api_version.minor): error_text = 'The server is running an old and incompatible version.' error_text += '\nPlease update the remote server installation.' elif server_rpc_api_version[0] > version.rpc_api_version.major: error_text = 'The client is running an old and incompatible version.' error_text += '\nPlease update the local client installation.' if error_text: gui_utilities.show_dialog_error('The RPC API Versions Are Incompatible', window, error_text) self.emit('server-disconnected') return False, ConnectionErrorReason.ERROR_INCOMPATIBLE_VERSIONS login_result, login_reason = rpc.login(username, password, otp) if not login_result: self.logger.warning('failed to authenticate to the remote king phisher service, reason: ' + login_reason) self.emit('server-disconnected') return False, login_reason rpc.username = username self.logger.debug('successfully authenticated to the remote king phisher service') event_subscriber = server_events.ServerEventSubscriber(rpc) if not event_subscriber.is_connected: event_subscriber.reconnect = False event_subscriber.shutdown() return False, ConnectionErrorReason.ERROR_UNKNOWN self.rpc = rpc self.server_events = event_subscriber self._rpc_ping_event = GLib.timeout_add_seconds(parse_timespan('5m'), rpc.ping) user = self.rpc.graphql("""\ query getUser($name: String!) { db { user(name: $name) { id name } } }""", {'name': self.config['server_username']})['db']['user'] self.server_user = ServerUser(id=user['id'], name=user['name']) self.emit('server-connected') return True, ConnectionErrorReason.SUCCESS