def create_connection( connection_type, socketpath=None, timeout=None, hostname=None, port=None, certfile=None, keyfile=None, cafile=None, ssh_username=None, ssh_password=None, **kwargs # pylint: disable=unused-argument ): if 'socket' in connection_type: return UnixSocketConnection(timeout=timeout, path=socketpath) if 'tls' in connection_type: return TLSConnection( timeout=timeout, hostname=hostname, port=port, certfile=certfile, keyfile=keyfile, cafile=cafile, ) return SSHConnection( timeout=timeout, hostname=hostname, port=port, username=ssh_username, password=ssh_password, )
def check_login(self): if (self.hostname_input.text() == "" or self.username_input.text() == "" or self.password_input.text() == ""): QMessageBox.about(QMainWindow(), "Error", "Please enter a all Information") else: try: connection = SSHConnection(hostname=self.hostname_input.text()) with Gmp(connection=connection, transform=ObjectTransform()) as gmp: try: response = gmp.authenticate( username=self.username_input.text(), password=self.password_input.text(), ) print(response) self.signal.login_event.emit(gmp, self.window) except GvmResponseError: QMessageBox.about(QMainWindow(), "Error", "Wrong username or password.") except (gaierror, NoValidConnectionsError, GvmError) as ex: QMessageBox.about(QMainWindow(), "Error", str(ex))
def test_init_with_none(self): ssh_connection = SSHConnection(timeout=None, hostname=None, port=None, username=None, password=None) self.check_ssh_connection_for_default_values(ssh_connection)
def test_connect_unknown_host(self): ssh_connection = SSHConnection(hostname="0.0.0.1", known_hosts_file=self.known_hosts_file) with self.assertRaises( GvmError, msg=("Could'nt establish a connection to fetch the remote " "server key: [Errno 65] No route to host"), ): ssh_connection.connect()
def test_connect(self): with patch("paramiko.SSHClient") as SSHClientMock: client_mock = SSHClientMock.return_value client_mock.exec_command.return_value = ["a", "b", "c"] ssh_connection = SSHConnection( known_hosts_file=self.known_hosts_file) ssh_connection.connect() self.assertEqual(ssh_connection._stdin, "a") self.assertEqual(ssh_connection._stdout, "b") self.assertEqual(ssh_connection._stderr, "c") ssh_connection.disconnect()
def test_trigger_paramiko_ssh_except_in_get_remote_key(self): with patch("paramiko.transport.Transport") as TransportMock: client_mock = TransportMock.return_value client_mock.start_client.side_effect = paramiko.SSHException("foo") ssh_connection = SSHConnection(hostname="0.0.0.0", ) with self.assertRaises( GvmError, msg="Couldn't fetch the remote server key: foo", ): ssh_connection._get_remote_host_key()
def test_connect_denied_known_hosts_file(self): if os.path.exists(self.known_hosts_file): os.chmod(self.known_hosts_file, 0000) ssh_connection = SSHConnection(hostname="0.0.0.1", known_hosts_file=self.known_hosts_file) with self.assertRaises( GvmError, msg=("Could'nt establish a connection to fetch the remote " "server key: [Errno 65] No route to host"), ): ssh_connection.connect()
def test_trigger_oserror_in_get_remote_key_disconnect(self): with patch("paramiko.transport.Transport") as TransportMock: client_mock = TransportMock.return_value client_mock.close.side_effect = paramiko.SSHException("foo") ssh_connection = SSHConnection(hostname="0.0.0.0", ) with self.assertRaises( GvmError, msg="Couldn't close the connection to the" "remote server key: foo", ): ssh_connection._get_remote_host_key()
def test_trigger_oserror_in_get_remote_key_connect(self): with patch("socket.socket") as SocketMock: client_mock = SocketMock.return_value client_mock.connect.side_effect = OSError("foo") ssh_connection = SSHConnection(hostname="0.0.0.0", ) with self.assertRaises( GvmError, msg="Couldn't establish a connection to fetch the" "remote server key: foo", ): ssh_connection._get_remote_host_key()
def test_send(self): with patch("paramiko.SSHClient") as SSHClientMock: client_mock = SSHClientMock.return_value stdin = Mock() stdin.channel.send.return_value = 4 client_mock.exec_command.return_value = [stdin, None, None] ssh_connection = SSHConnection( known_hosts_file=self.known_hosts_file) ssh_connection.connect() req = ssh_connection.send("blah") self.assertEqual(req, 4) ssh_connection.disconnect()
def test_read(self): with patch("paramiko.SSHClient") as SSHClientMock: client_mock = SSHClientMock.return_value stdout = Mock() stdout.channel.recv.return_value = b"foo bar baz" client_mock.exec_command.return_value = [None, stdout, None] ssh_connection = SSHConnection( known_hosts_file=self.known_hosts_file) ssh_connection.connect() recved = ssh_connection._read() self.assertEqual(recved, b"foo bar baz") ssh_connection.disconnect()
def test_send_error(self): with patch("paramiko.SSHClient") as SSHClientMock: client_mock = SSHClientMock.return_value stdin = Mock() stdin.channel.send.return_value = None client_mock.exec_command.return_value = [stdin, None, None] ssh_connection = SSHConnection( known_hosts_file=self.known_hosts_file) ssh_connection.connect() with self.assertRaises(GvmError, msg="Remote closed the connection"): ssh_connection.send("blah") ssh_connection.disconnect()
def test_disconnect_os_error(self): with patch("paramiko.SSHClient") as SSHClientMock: client_mock = SSHClientMock.return_value client_mock.exec_command.return_value = ["a", "b", "c"] client_mock.close.side_effect = OSError ssh_connection = SSHConnection( known_hosts_file=self.known_hosts_file) ssh_connection.connect() with self.assertRaises(OSError): with self.assertLogs("gvm.connections", level="INFO") as cm: ssh_connection.disconnect() self.assertEqual(cm.output, ["Connection closing error: "])
def test_send_and_slice(self): with patch("paramiko.SSHClient") as SSHClientMock: client_mock = SSHClientMock.return_value stdin = Mock() stdin.channel.send.side_effect = [2, 2] client_mock.exec_command.return_value = [stdin, None, None] ssh_connection = SSHConnection( known_hosts_file=self.known_hosts_file) ssh_connection.connect() req = ssh_connection.send("blah") self.assertEqual(req, 4) stdin.channel.send.assert_called() with self.assertRaises(AssertionError): stdin.channel.send.assert_called_once() ssh_connection.disconnect()
def test_connect_wrong_input(self, stdout_mock, input_mock): key_io = StringIO("""-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW QyNTUxOQAAACB69SvZKJh/9VgSL0G27b5xVYa8nethH3IERbi0YqJDXwAAAKhjwAdrY8AH awAAAAtzc2gtZWQyNTUxOQAAACB69SvZKJh/9VgSL0G27b5xVYa8nethH3IERbi0YqJDXw AAAEA9tGQi2IrprbOSbDCF+RmAHd6meNSXBUQ2ekKXm4/8xnr1K9komH/1WBIvQbbtvnFV hryd62EfcgRFuLRiokNfAAAAI2FsZXhfZ2F5bm9yQEFsZXhzLU1hY0Jvb2stQWlyLmxvY2 FsAQI= -----END OPENSSH PRIVATE KEY-----""") key = paramiko.Ed25519Key.from_private_key(key_io) hostname = "0.0.0.0" key_type = key.get_name().replace("ssh-", "").upper() inputs = ["asd", "yes", "yoo", "no"] input_mock.side_effect = inputs ssh_connection = SSHConnection(hostname=hostname, known_hosts_file=self.known_hosts_file) ssh_connection._socket = paramiko.SSHClient() with self.assertLogs("gvm.connections", level="INFO") as cm: hostkeys = paramiko.HostKeys(filename=self.known_hosts_file) ssh_connection._ssh_authentication_input_loop(hostkeys=hostkeys, key=key) ret = stdout_mock.getvalue() self.assertEqual( cm.output, [ "INFO:gvm.connections:Warning: " f"Host '{hostname}' ({key_type}) not added to " "the list of known hosts." ], ) self.assertEqual( ret, f"The authenticity of host '{hostname}' can't be established.\n" f"{key_type} key fingerprint is " "J6VESFdD3xSChn8y9PzWzeF+1tl892mOy2TqkMLO4ow.\n" "Are you sure you want to continue connecting (yes/no)? " "Please type 'yes' or 'no': " "Do you want to add 0.0.0.0 to known_hosts (yes/no)? " "Please type 'yes' or 'no': ", )
def test_connect_adding_and_dont_save_hostkey(self, input_mock): key_io = StringIO("""-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW QyNTUxOQAAACB69SvZKJh/9VgSL0G27b5xVYa8nethH3IERbi0YqJDXwAAAKhjwAdrY8AH awAAAAtzc2gtZWQyNTUxOQAAACB69SvZKJh/9VgSL0G27b5xVYa8nethH3IERbi0YqJDXw AAAEA9tGQi2IrprbOSbDCF+RmAHd6meNSXBUQ2ekKXm4/8xnr1K9komH/1WBIvQbbtvnFV hryd62EfcgRFuLRiokNfAAAAI2FsZXhfZ2F5bm9yQEFsZXhzLU1hY0Jvb2stQWlyLmxvY2 FsAQI= -----END OPENSSH PRIVATE KEY-----""") key = paramiko.Ed25519Key.from_private_key(key_io) key_type = key.get_name().replace("ssh-", "").upper() hostname = "0.0.0.0" input_mock.side_effect = ["yes", "no"] ssh_connection = SSHConnection(hostname=hostname, known_hosts_file=self.known_hosts_file) ssh_connection._socket = paramiko.SSHClient() keys = self.known_hosts_file.read_text(encoding="utf-8") self.assertEqual( keys, "127.0.0.1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBOZWi" "fs+DoMqIa5Nr0wiVrzQNpMbUwaLzuSTN6rNrYA\n", ) with self.assertLogs("gvm.connections", level="INFO") as cm: hostkeys = paramiko.HostKeys(filename=self.known_hosts_file) ssh_connection._ssh_authentication_input_loop(hostkeys=hostkeys, key=key) keys = self.known_hosts_file.read_text(encoding="utf-8") self.assertEqual( cm.output, [ "INFO:gvm.connections:Warning: " f"Host '{hostname}' ({key_type}) not added to " "the list of known hosts." ], ) self.assertEqual( keys, "127.0.0.1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBOZWi" "fs+DoMqIa5Nr0wiVrzQNpMbUwaLzuSTN6rNrYA\n", )
def test_user_denies_auth(self, input_mock): key_io = StringIO("""-----BEGIN OPENSSH PRIVATE KEY----- b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW QyNTUxOQAAACB69SvZKJh/9VgSL0G27b5xVYa8nethH3IERbi0YqJDXwAAAKhjwAdrY8AH awAAAAtzc2gtZWQyNTUxOQAAACB69SvZKJh/9VgSL0G27b5xVYa8nethH3IERbi0YqJDXw AAAEA9tGQi2IrprbOSbDCF+RmAHd6meNSXBUQ2ekKXm4/8xnr1K9komH/1WBIvQbbtvnFV hryd62EfcgRFuLRiokNfAAAAI2FsZXhfZ2F5bm9yQEFsZXhzLU1hY0Jvb2stQWlyLmxvY2 FsAQI= -----END OPENSSH PRIVATE KEY-----""") key = paramiko.Ed25519Key.from_private_key(key_io) hostname = "0.0.0.0" input_mock.return_value = "no" ssh_connection = SSHConnection(hostname=hostname, known_hosts_file=self.known_hosts_file) ssh_connection._socket = paramiko.SSHClient() with self.assertRaises( SystemExit, msg="User denied key. Host key verification failed."): hostkeys = paramiko.HostKeys(filename=self.known_hosts_file) ssh_connection._ssh_authentication_input_loop(hostkeys=hostkeys, key=key)
def test_disconnect(self): with patch("paramiko.SSHClient") as SSHClientMock: client_mock = SSHClientMock.return_value client_mock.exec_command.return_value = ["a", "b", "c"] ssh_connection = SSHConnection( known_hosts_file=self.known_hosts_file) ssh_connection.connect() self.assertEqual(ssh_connection._stdin, "a") self.assertEqual(ssh_connection._stdout, "b") self.assertEqual(ssh_connection._stderr, "c") ssh_connection.disconnect() # make sure the attributes have been deleted with self.assertRaises(AttributeError): type(ssh_connection._stdin) with self.assertRaises(AttributeError): type(ssh_connection._stdout) with self.assertRaises(AttributeError): type(ssh_connection._stderr) with self.assertRaises(AttributeError): type(ssh_connection._socket) with self.assertRaises(AttributeError): with self.assertLogs("gvm.connections", level="INFO") as cm: # disconnect twice should not work ... ssh_connection.disconnect() self.assertEqual( cm.output, [ "Connection might already be" " closed. No socket found.", ], ) ssh_connection._socket = None ssh_connection.disconnect()
def test_connect_error(self): print(self.known_hosts_file.read_text(encoding="utf-8")) ssh_connection = SSHConnection(known_hosts_file=self.known_hosts_file) with self.assertRaises(GvmError, msg="SSH Connection failed"): ssh_connection.connect()
def test_init_no_args(self): ssh_connection = SSHConnection() self.check_ssh_connection_for_default_values(ssh_connection)
def exportReports(filterID, filterString, optPagination, optDetails, optRewrite, taskName, genPDF): print('Loading previously completed reports data') ranReports = readRanReportsFile(taskName) #connect to our host as defined in the config file print("Trying to connect to: '", config['DEFAULT']['host'], "' on port: '", config['DEFAULT']['port'], "'") connection = SSHConnection(hostname=config['DEFAULT']['host'], timeout=18000) if config['DEFAULT']['port']: connection = SSHConnection(hostname=config['DEFAULT']['host'], port=config['DEFAULT']['port'], timeout=18000) print('Starting report processing') with Gmp(connection) as gmp: # Login print("Attempting to authenticate") gmp.authenticate(config['DEFAULT']['username'], config['DEFAULT']['password']) print('Connected to:', config['DEFAULT']['host']) #Get the CSV report format ID. We use CSV as the base format to transform into json reportFormatID = "c1645568-627a-11e3-a660-406186ea4fc5" #holds the format id for CSV report_format = gmp.get_report_formats() report_root = ET.fromstring(report_format) for report in report_root: report.tag == "report_format" for report_format in report: if report_format.text == 'CSV result list.': reportFormatID = report.attrib.get('id') getReports = [] #array of reportIDs print('Getting reports') allreports = gmp.get_reports( filter=taskName, details=0 ) #we only need the reportID so minimize the data returned print('Retreived reports') allreports_root = ET.fromstring(allreports) print("Fetched the following scans from %s" % (config['DEFAULT']['host'])) for report in allreports_root: if report.tag == 'report': for onereport in report: if onereport.tag == 'report': pretty_print(onereport) print(report.attrib) getReports.append(report.attrib.get('id')) #Step through the reportID list and grab them as csv files for reportID in getReports: print("Processing Report ID: {0}".format(reportID)) # we have a reportID. Check to see if it matches any existing reports already written to disk # if it does then we can skip this one. Note: we make sure filterID is null because we # only need to do the hashing once. if filterString and not filterID: # we need a consistent identify for this string so hashes to the rescue # we are going to reuse the filterID variable to hold it sha_1 = hashlib.sha1() #instantiate hash sha_1.update( filterString.encode('utf-8') ) #hash the string being sure to use proper encoding filterID = sha_1.hexdigest() #return the hash as a hex string # we use the filterID and the reportID to create a key for the ranReports dict. If it exists then skip # that report unless we are over writing (or regenerating) reports. ranReportsKey = filterID + reportID if ranReportsKey in ranReports and not optRewrite: print("This report was processed on %s" % (ranReports[ranReportsKey])) continue if filterString: #if they are using a custom filter string entered on the CLI reportscv = gmp.get_report(reportID, filter=filterString, report_format_id=reportFormatID, ignore_pagination=optPagination, details=optDetails) else: reportscv = gmp.get_report(reportID, filter_id=filterID, report_format_id=reportFormatID, ignore_pagination=optPagination, details=optDetails) obj = untangle.parse(reportscv) resultID = obj.get_reports_response.report['id'] base64CVSData = obj.get_reports_response.report.cdata data = str(base64.b64decode(base64CVSData), "utf-8") #Write the result to file writeResultToFile(resultID, data, filterID, filterString, taskName, genPDF, gmp, optPagination, optDetails)