Exemple #1
0
 def test_is_valid_ip_address(self):
     valid_ips = ['127.0.0.1', '10.0.0.1', '200.100.0.1', 'fe80::1', '::1']
     invalid_ips = ['localhost', 'www.google.com', '']
     for address in valid_ips:
         self.assertTrue(utilities.is_valid_ip_address(address))
     for address in invalid_ips:
         self.assertFalse(utilities.is_valid_ip_address(address))
	def test_is_valid_ip_address(self):
		valid_ips = [
			'127.0.0.1',
			'10.0.0.1',
			'200.100.0.1',
			'fe80::1',
			'::1'
		]
		invalid_ips = [
			'localhost',
			'www.google.com',
			''
		]
		for address in valid_ips:
			self.assertTrue(utilities.is_valid_ip_address(address))
		for address in invalid_ips:
			self.assertFalse(utilities.is_valid_ip_address(address))
Exemple #3
0
def main():
    parser = argparse.ArgumentParser(
        description='King Phisher SPF Check Utility',
        conflict_handler='resolve')
    utilities.argp_add_args(parser)
    parser.add_argument('smtp_server_ip',
                        help='the ip address of the sending smtp server')
    parser.add_argument('target_email',
                        help='the email address that messages are from')
    arguments = parser.parse_args()

    utilities.configure_stream_logger(arguments.loglvl, arguments.logger)

    server_ip = arguments.smtp_server_ip
    target_email = arguments.target_email

    if not utilities.is_valid_ip_address(server_ip):
        color.print_error('the smtp server ip address specified is invalid')
        return

    if not '@' in target_email:
        target_email = utilities.random_string_lower_numeric(
            8) + '@' + target_email
        color.print_status(
            'target email appears to be just a domain, changed to: ' +
            target_email)

    if not utilities.is_valid_email_address(target_email):
        color.print_error('the email address specified is invalid')
        return

    spf_sender, spf_domain = target_email.split('@')
    spf_test = spf.SenderPolicyFramework(server_ip, spf_domain, spf_sender)
    try:
        result = spf_test.check_host()
    except spf.SPFPermError as error:
        color.print_error('check_host failed with error: permerror')
        color.print_error('error reason: ' + error.message)
        return
    except spf.SPFTempError as error:
        color.print_error('check_host failed with error: temperror')
        color.print_error('error reason: ' + error.message)
        return
    if not result:
        color.print_status('no spf policy was found for the specified domain')
        return

    color.print_good("spf policy result: {0}".format(result))
    color.print_status('top level spf records found:')
    for rid in range(len(spf_test.spf_records)):
        record = spf.record_unparse(spf_test.spf_records[rid])
        color.print_status("  #{0} {1: <10} {2}".format(
            rid + 1, ('(matched)' if rid == spf_test.spf_record_id else ''),
            record))
def main():
	parser = argparse.ArgumentParser(description='King Phisher SPF Check Utility', conflict_handler='resolve')
	utilities.argp_add_args(parser)
	parser.add_argument('smtp_server_ip', help='the ip address of the sending smtp server')
	parser.add_argument('target_email', help='the email address that messages are from')
	arguments = parser.parse_args()

	utilities.configure_stream_logger(arguments.loglvl, arguments.logger)

	server_ip = arguments.smtp_server_ip
	target_email = arguments.target_email

	if not utilities.is_valid_ip_address(server_ip):
		color.print_error('the smtp server ip address specified is invalid')
		return

	if not '@' in target_email:
		target_email = utilities.random_string_lower_numeric(8) + '@' + target_email
		color.print_status('target email appears to be just a domain, changed to: ' + target_email)

	if not utilities.is_valid_email_address(target_email):
		color.print_error('the email address specified is invalid')
		return

	spf_sender, spf_domain = target_email.split('@')
	spf_test = spf.SenderPolicyFramework(server_ip, spf_domain, spf_sender)
	try:
		result = spf_test.check_host()
	except spf.SPFPermError as error:
		color.print_error('check_host failed with error: permerror')
		color.print_error('error reason: ' + error.message)
		return
	except spf.SPFTempError as error:
		color.print_error('check_host failed with error: temperror')
		color.print_error('error reason: ' + error.message)
		return
	if not result:
		color.print_status('no spf policy was found for the specified domain')
		return

	color.print_good("spf policy result: {0}".format(result))
	color.print_status('top level spf records found:')
	for rid in range(len(spf_test.spf_records)):
		record = spf.record_unparse(spf_test.spf_records[rid])
		color.print_status("  #{0} {1: <10} {2}".format(rid + 1, ('(matched)' if rid == spf_test.spf_record_id else ''), record))
def main():
	parser = argparse.ArgumentParser(description='King Phisher SPF Check Utility', conflict_handler='resolve')
	parser.add_argument('-v', '--version', action='version', version=parser.prog + ' Version: ' + version.version)
	parser.add_argument('-L', '--log', dest='loglvl', action='store', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], default='CRITICAL', help='set the logging level')
	parser.add_argument('smtp_server_ip', help='the ip address of the sending smtp server')
	parser.add_argument('target_email', help='the email address that messages are from')
	arguments = parser.parse_args()

	logging.getLogger('').setLevel(logging.DEBUG)
	console_log_handler = logging.StreamHandler()
	console_log_handler.setLevel(getattr(logging, arguments.loglvl))
	console_log_handler.setFormatter(logging.Formatter("%(levelname)-8s %(message)s"))
	logging.getLogger('').addHandler(console_log_handler)

	server_ip = arguments.smtp_server_ip
	target_email = arguments.target_email

	if not utilities.is_valid_ip_address(server_ip):
		color.print_error('the smtp server ip address specified is invalid')
		return

	if not utilities.is_valid_email_address(target_email):
		color.print_error('the email address specified is invalid')
		return

	spf_sender, spf_domain = target_email.split('@')
	spf_test = spf.SenderPolicyFramework(server_ip, spf_domain, spf_sender)
	try:
		result = spf_test.check_host()
	except spf.SPFPermError:
		color.print_error('check_host failed with error: permerror')
		return
	except spf.SPFTempError:
		color.print_error('check_host failed with error: temperror')
		return
	if not result:
		color.print_status('no spf policy was found for the specified domain')
		return

	color.print_good("spf policy result: {0}".format(result))
	color.print_status('top level spf records found:')
	for rid in range(len(spf_test.spf_records)):
		record = spf.record_unparse(spf_test.spf_records[rid])
		color.print_status("  #{0} {1: <10} {2}".format(rid + 1, ('(matched)' if rid == spf_test.spf_record_id else ''), record))
Exemple #6
0
def main():
	parser = argparse.ArgumentParser(description='King Phisher SPF Check Utility', conflict_handler='resolve')
	parser.add_argument('-v', '--version', action='version', version=parser.prog + ' Version: ' + version.version)
	parser.add_argument('-L', '--log', dest='loglvl', action='store', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'], default='CRITICAL', help='set the logging level')
	parser.add_argument('smtp_server_ip', help='the ip address of the sending smtp server')
	parser.add_argument('target_email', help='the email address that messages are from')
	arguments = parser.parse_args()

	logging.getLogger('').setLevel(logging.DEBUG)
	console_log_handler = logging.StreamHandler()
	console_log_handler.setLevel(getattr(logging, arguments.loglvl))
	console_log_handler.setFormatter(logging.Formatter("%(levelname)-8s %(message)s"))
	logging.getLogger('').addHandler(console_log_handler)

	server_ip = arguments.smtp_server_ip
	target_email = arguments.target_email

	if not utilities.is_valid_ip_address(server_ip):
		print('[-] the smtp server ip address specified is invalid')
		return

	if not utilities.is_valid_email_address(target_email):
		print('[-] the email address specified is invalid')
		return

	spf_sender, spf_domain = target_email.split('@')
	spf_test = spf.SenderPolicyFramework(server_ip, spf_domain, spf_sender)
	try:
		result = spf_test.check_host()
	except spf.SPFPermError:
		print('[-] check_host failed with error: permerror')
		return
	except spf.SPFTempError:
		print('[-] check_host failed with error: temperror')
		return
	if not result:
		print('[*] no spf policy was found for the specified domain')
		return

	print("[+] spf policy result: {0}".format(result))
	print('[*] top level spf records found:')
	for rid in range(len(spf_test.spf_records)):
		record = spf.record_unparse(spf_test.spf_records[rid])
		print("[*]   #{0} {1: <10} {2}".format(rid + 1, ('(matched)' if rid == spf_test.spf_record_id else ''), record))
Exemple #7
0
def guess_smtp_server_address(host, forward_host=None):
	"""
	Guess the IP address of the SMTP server that will be connected to given the
	SMTP host information and an optional SSH forwarding host. If a hostname is
	in use it will be resolved to an IP address, either IPv4 or IPv6 and in that
	order. If a hostname resolves to multiple IP addresses, None will be
	returned. This function is intended to guess the SMTP servers IP address
	given the client configuration so it can be used for SPF record checks.

	:param str host: The SMTP server that is being connected to.
	:param str forward_host: An optional host that is being used to tunnel the connection.
	:return: The IP address of the SMTP server.
	:rtype: None, :py:class:`ipaddress.IPv4Address`, :py:class:`ipaddress.IPv6Address`
	"""
	host = host.rsplit(':', 1)[0]
	if utilities.is_valid_ip_address(host):
		ip = ipaddress.ip_address(host)
		if not ip.is_loopback:
			return ip
	else:
		info = None
		for family in (socket.AF_INET, socket.AF_INET6):
			try:
				info = socket.getaddrinfo(host, 1, family)
			except socket.gaierror:
				continue
			info = set(list([r[4][0] for r in info]))
			if len(info) != 1:
				return
			break
		if info:
			ip = ipaddress.ip_address(info.pop())
			if not ip.is_loopback:
				return ip
	if forward_host:
		return guess_smtp_server_address(forward_host)
	return
Exemple #8
0
def guess_smtp_server_address(host, forward_host=None):
    """
	Guess the IP address of the SMTP server that will be connected to given the
	SMTP host information and an optional SSH forwarding host. If a hostname is
	in use it will be resolved to an IP address, either IPv4 or IPv6 and in that
	order. If a hostname resolves to multiple IP addresses, None will be
	returned. This function is intended to guess the SMTP servers IP address
	given the client configuration so it can be used for SPF record checks.

	:param str host: The SMTP server that is being connected to.
	:param str forward_host: An optional host that is being used to tunnel the connection.
	:return: The IP address of the SMTP server.
	:rtype: None, :py:class:`ipaddress.IPv4Address`, :py:class:`ipaddress.IPv6Address`
	"""
    host = host.rsplit(':', 1)[0]
    if utilities.is_valid_ip_address(host):
        ip = ipaddress.ip_address(host)
        if not ip.is_loopback:
            return ip
    else:
        info = None
        for family in (socket.AF_INET, socket.AF_INET6):
            try:
                info = socket.getaddrinfo(host, 1, family)
            except socket.gaierror:
                continue
            info = set(list([r[4][0] for r in info]))
            if len(info) != 1:
                return
            break
        if info:
            ip = ipaddress.ip_address(info.pop())
            if not ip.is_loopback:
                return ip
    if forward_host:
        return guess_smtp_server_address(forward_host)
    return
Exemple #9
0
	def get_client_ip(self):
		"""
		Intelligently get the IP address of the HTTP client, optionally
		accounting for proxies that may be in use.

		:return: The clients IP address
		:rtype: str
		"""
		address = self.client_address[0]
		cookie_name = self.config.get_if_exists('server.client_ip_cookie')
		if not cookie_name:
			return address
		cookie_value = self.headers.get(cookie_name, '')
		if not cookie_value:
			return address
		if cookie_value.startswith('['):
			# cookie_value looks like an IPv6 address
			cookie_value = cookie_value.split(']:', 1)[0]
		else:
			# treat cookie_value ad an IPv4 address
			cookie_value = cookie_value.split(':', 1)[0]
		if utilities.is_valid_ip_address(cookie_value):
			address = cookie_value
		return address
Exemple #10
0
    def get_client_ip(self):
        """
		Intelligently get the IP address of the HTTP client, optionally
		accounting for proxies that may be in use.

		:return: The clients IP address
		:rtype: str
		"""
        address = self.client_address[0]
        cookie_name = self.config.get_if_exists('server.client_ip_cookie')
        if not cookie_name:
            return address
        cookie_value = self.headers.get(cookie_name, '')
        if not cookie_value:
            return address
        if cookie_value.startswith('['):
            # cookie_value looks like an IPv6 address
            cookie_value = cookie_value.split(']:', 1)[0]
        else:
            # treat cookie_value ad an IPv4 address
            cookie_value = cookie_value.split(':', 1)[0]
        if utilities.is_valid_ip_address(cookie_value):
            address = cookie_value
        return address
	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
Exemple #12
0
    def signal_login_dialog_response(self, dialog, response, glade_dialog):
        server_version_info = None
        title_rpc_error = 'Failed To Connect To The King Phisher RPC Service'

        if response == Gtk.ResponseType.CANCEL or response == Gtk.ResponseType.DELETE_EVENT:
            dialog.destroy()
            self.emit('exit')
            return True
        glade_dialog.objects_save_to_config()
        server = utilities.server_parse(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 = 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, self,
                    '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, self,
                    'The server responded with HTTP status: ' +
                    str(err.status))
        except socket.error as error:
            gui_utilities.show_dialog_exc_socket_error(error, self)
        except Exception as error:
            self.logger.warning('failed to connect to the remote rpc service')
            gui_utilities.show_dialog_error(
                title_rpc_error, self,
                '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]))
        self.server_local_port = local_port

        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', self, error_text)
            self.server_disconnect()
            return
        dialog.destroy()
        self.emit('server-connected')
        return
Exemple #13
0
    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
Exemple #14
0
	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