def get_account_from_etree(node): """ Given a <account> node, this function returns a Exscript.Account instance. The following XML syntax is expected, whereby the children of <account> are all optional:: <account name="myaccount"> <password type="base64">Zm9v</password> <authorization-password type="cleartext">bar</authorization-password> <keyfile>/path/to/my/ssh/key</keyfile> </account> The <password> and <authorization-password> tags have an optional type attribute defaulting to 'cleartext'. Allowed values are 'cleartext' and 'base64'. @type node: lxml.etree.ElementNode @param node: A <account> element. @rtype: Exscript.Account @return: The resulting account. """ name = node.get('name', '').strip() password1_elem = node.find('password') password2_elem = node.find('authorization-password') keyfile = node.findtext('keyfile') if keyfile is None: key = None else: key = PrivateKey.from_file(keyfile) account = Exscript.Account(name, key = key) account.set_password(_get_password_from_node(password1_elem)) account.set_authorization_password(_get_password_from_node(password2_elem)) return account
def testAuthenticate(self): # Test can not work on the abstract base. if self.protocol.__class__ == Protocol: self.assertRaises(Exception, self.protocol.authenticate, self.account) return self.doConnect() # Password login. self.assertFalse(self.protocol.is_protocol_authenticated()) self.assertFalse(self.protocol.is_app_authenticated()) self.assertFalse(self.protocol.is_app_authorized()) self.protocol.authenticate(self.account, flush=False) self.assertTrue(self.protocol.response is not None) self.assertTrue(len(self.protocol.response) > 0) self.assertTrue(self.protocol.is_protocol_authenticated()) self.assertTrue(self.protocol.is_app_authenticated()) self.assertFalse(self.protocol.is_app_authorized()) # Key login. self.tearDown() self.setUp() key = PrivateKey.from_file('foo', keytype='rsa') account = Account(self.user, self.password, key=key) self.doConnect() self.assertFalse(self.protocol.is_protocol_authenticated()) self.assertFalse(self.protocol.is_app_authenticated()) self.assertFalse(self.protocol.is_app_authorized()) self.protocol.authenticate(account, flush=False) self.assertTrue(self.protocol.is_protocol_authenticated()) self.assertTrue(self.protocol.is_app_authenticated()) self.assertFalse(self.protocol.is_app_authorized())
def testAuthenticate(self): # Test can not work on the abstract base. if self.protocol.__class__ == Protocol: self.assertRaises(Exception, self.protocol.authenticate, self.account) return self.doConnect() # Password login. self.assertFalse(self.protocol.is_protocol_authenticated()) self.assertFalse(self.protocol.is_app_authenticated()) self.assertFalse(self.protocol.is_app_authorized()) self.protocol.authenticate(self.account, flush = False) self.assertTrue(self.protocol.response is not None) self.assertTrue(len(self.protocol.response) > 0) self.assertTrue(self.protocol.is_protocol_authenticated()) self.assertTrue(self.protocol.is_app_authenticated()) self.assertFalse(self.protocol.is_app_authorized()) # Key login. self.tearDown() self.setUp() key = PrivateKey.from_file('foo', keytype = 'rsa') account = Account(self.user, self.password, key = key) self.doConnect() self.assertFalse(self.protocol.is_protocol_authenticated()) self.assertFalse(self.protocol.is_app_authenticated()) self.assertFalse(self.protocol.is_app_authorized()) self.protocol.authenticate(account, flush = False) self.assertTrue(self.protocol.is_protocol_authenticated()) self.assertTrue(self.protocol.is_app_authenticated()) self.assertFalse(self.protocol.is_app_authorized())
def get_account_from_etree(node): """ Given a <account> node, this function returns a Exscript.Account instance. The following XML syntax is expected, whereby the children of <account> are all optional:: <account name="myaccount"> <password type="base64">Zm9v</password> <authorization-password type="cleartext">bar</authorization-password> <keyfile>/path/to/my/ssh/key</keyfile> </account> The <password> and <authorization-password> tags have an optional type attribute defaulting to 'cleartext'. Allowed values are 'cleartext' and 'base64'. @type node: lxml.etree.ElementNode @param node: A <account> element. @rtype: Exscript.Account @return: The resulting account. """ name = node.get('name', '').strip() password1_elem = node.find('password') password2_elem = node.find('authorization-password') keyfile = node.findtext('keyfile') if keyfile is None: key = None else: key = PrivateKey.from_file(keyfile) account = Exscript.Account(name, key=key) account.set_password(_get_password_from_node(password1_elem)) account.set_authorization_password(_get_password_from_node(password2_elem)) return account
def setUp(self): self.user = '******' self.password1 = 'test1' self.password2 = 'test2' self.key = PrivateKey() self.account = Account(self.user, self.password1, self.password2, self.key)
def testConstructor(self): key = PrivateKey() account = Account(self.user, self.password1, key = key) self.assertEqual(account.get_key(), key) self.assertEqual(account.get_password(), account.get_authorization_password()) account = Account(self.user, self.password1, self.password2) self.failIfEqual(account.get_password(), account.get_authorization_password())
def account_factory(username=getuser(), password=None, private_key="", keytype="rsa"): assert username != "" assert keytype in set(["rsa", "dsa", "ecdsa", "ed25519"]) if password is None: password = getpass("Login password for %s: " % username) private_key_obj = None if isinstance(private_key, str) and private_key != "": keypath = os.path.expanduser(private_key) assert os.path.isfile(keypath) private_key_obj = PrivateKey(keytype=keytype).from_file(keypath) account = Account(name=username, password=password, key=private_key_obj) return account
def testConstructor(self): self.key = PrivateKey() self.assertRaises(TypeError, PrivateKey, 'foo') PrivateKey('rsa') PrivateKey('dss')
# crash_id may not be set, if machine not present in initial vlist, if so then ignore log.info('Stopping running VM %s' % virtual_machine) conn.execute('vcrash %s' % crash_id) time.sleep(1) else: # conn.execute(start_command) lab_is_started = True first_match(conn, r'^The lab has been started') log.info('Lab started') # TODO: make this captured - need to debug capturing conn.send('exit') if key_filename: key = PrivateKey.from_file(key_filename) log.debug('Connecting to %s with username %s and key %s' % (host, username, key_filename)) accounts = [Account(username, key=key)] else: log.debug('Connecting to %s with username %s' % (host, username)) accounts = [Account(username)] hosts = ['ssh://%s' % host] verbosity = -1 start(accounts, hosts, start_lab, verbose=verbosity)
class PrivateKeyTest(unittest.TestCase): CORRELATE = PrivateKey def setUp(self): self.filename = 'my.key' self.password = '******' self.key = None def testConstructor(self): self.key = PrivateKey() self.assertRaises(TypeError, PrivateKey, 'foo') PrivateKey('rsa') PrivateKey('dss') def testFromFile(self): self.key = PrivateKey.from_file(self.filename, self.password, 'dss') self.assertEqual(self.key.get_type(), 'dss') self.assertEqual(self.filename, self.key.get_filename()) self.assertEqual(self.password, self.key.get_password()) def testGetType(self): self.testConstructor() self.assertEqual(self.key.get_type(), 'rsa') self.key = PrivateKey('dss') self.assertEqual(self.key.get_type(), 'dss') def testGetFilename(self): self.testConstructor() self.assertEqual(None, self.key.get_filename()) self.key.set_filename(self.filename) self.assertEqual(self.filename, self.key.get_filename()) def testSetFilename(self): self.testGetFilename() def testGetPassword(self): self.testConstructor() self.assertEqual(None, self.key.get_password()) self.key.set_password(self.password) self.assertEqual(self.password, self.key.get_password()) def testSetPassword(self): self.testGetPassword()
def testGetType(self): self.testConstructor() self.assertEqual(self.key.get_type(), 'rsa') self.key = PrivateKey('dss') self.assertEqual(self.key.get_type(), 'dss')
def main(): args = args_parser() print_banner() host = args.host port = args.port username = args.username password = args.password privatekey = args.privatekey passphrase = args.passphrase keytype = args.keytype ssh = args.ssh telnet = args.telnet category = args.category plugin = args.plugin if plugin and (category == None): sys.exit(RED + '\n[!] No category\n' + ENDC) # Set host if host == None: host = raw_input('set host' + BLUE + ' > ' + ENDC) # Set service if (ssh == False) and (telnet == False): service = raw_input('set service [ssh|telnet]' + BLUE + ' > ' + ENDC) if service.lower() == 'ssh': ssh = True elif service.lower() == 'telnet': telnet = True if ssh: conn = SSH2() elif telnet: conn = Telnet() else: sys.exit(RED + '\n[!] Bad service type. Options: [ssh|telnet]\n' + ENDC) # Set username if username == None: username = raw_input('set username' + BLUE + ' > ' + ENDC) # Set password if (password == None) and (privatekey == None): password = getpass.getpass('set password (leave blank to enter a private key)' + BLUE + ' > ' + ENDC) #set privatekey if (password == None): #set privatekey if (privatekey == None): privatekey = getpass.getpass('set private key path' + BLUE + ' > ' + ENDC) #set passphrase if (passphrase == None): passphrase = getpass.getpass('set private key passphrase (optional)' + BLUE + ' > ' + ENDC) #set keytype if (keytype == None): keytype = raw_input('set keytype (optional)' + BLUE + ' > ' + ENDC) if (keytype != "") and (passphrase != ""): key = PrivateKey.from_file(privatekey, password=passphrase, keytype=keytype) elif (keytype != ""): key = PrivateKey.from_file(privatekey, password=passphrase) else: key = PrivateKey.from_file(privatekey) else: key = None # Create account account = Account(username, password, key = key) # Connect and login conn.connect(host, port) conn.login(account) # Try to disable history for current shell session conn.execute('unset HISTFILE') # Print info about used Exscript driver driver = conn.get_driver() print BLUE + '\n[i] Using driver: ' + ENDC + driver.name # Set logs directory logs_path = LOGS_PATH + '/' + host + '-' + str(int(time.time())) if category: print BLUE + '\n[i] Plugins category: ' + ENDC + category + '\n' dict_categories = {} dict_plugins = {} # Run single plugin if plugin: try: eval_file(conn, INSTALL_PATH + '/plugins/' + category + '/' + plugin) dict_plugins[plugin] = conn.response print ' %-20s' % (plugin) + '[' + GREEN + 'ok' + ENDC + ']' except: print ' %-20s' % (plugin) + '[' + RED + 'ko' + ENDC + ']' pass dict_categories[category] = dict_plugins # Run plugins by single category else: for plugin in sorted(os.listdir(INSTALL_PATH + '/plugins/' + category)): try: eval_file(conn, INSTALL_PATH + '/plugins/' + category + '/' + plugin) dict_plugins[plugin] = conn.response print ' %-20s' % (plugin) + '[' + GREEN + 'ok' + ENDC + ']' except: print ' %-20s' % (plugin) + '[' + RED + 'ko' + ENDC + ']' pass dict_categories[category] = dict_plugins # Run all plugins by category if (category == None) and (plugin == None): dict_categories = {} for category in sorted(os.listdir(INSTALL_PATH + '/plugins')): print BLUE + '\n[i] Plugins category: ' + ENDC + category + '\n' dict_plugins = {} for plugin in sorted(os.listdir(INSTALL_PATH + '/plugins/' + category)): try: eval_file(conn, INSTALL_PATH + '/plugins/' + category + '/' + plugin) dict_plugins[plugin] = conn.response print ' %-20s' % (plugin) + '[' + GREEN + 'ok' + ENDC + ']' except: print ' %-20s' % (plugin) + '[' + RED + 'ko' + ENDC + ']' pass dict_categories[category] = dict_plugins # Exit and close remote connection conn.send('exit\r') conn.close() # Generate report html_report(dict_categories, logs_path) print BLUE + '\n[i] Report saved to: ' + ENDC + logs_path + '/index.html\n'
def do_ssh_login( self, connect_timeout=10, debug=0, ): assert isinstance(connect_timeout, int) assert isinstance(debug, int) assert len(self.account_list) > 0 # FIXME - clean up PrivateKey here... private_key = PrivateKey(keytype="rsa").from_file(self.private_key_path) self.downgrade_ssh_crypto = False if self.protocol == "ssh": for self.ssh_attempt_number in [1, 2, 3]: assert self.ssh_attempt_number <= self.MAX_SSH_ATTEMPT # You have to change allowed ciphers / key exchange options # **before** the connection # -> https://stackoverflow.com/a/31303321/667301 if self.downgrade_ssh_crypto is True: paramiko.Transport._preferred_ciphers = ( "aes128-cbc", "3des-cbc", ) paramiko.Transport._preferred_kex = ( "diffie-hellman-group-exchange-sha1", "diffie-hellman-group14-sha1", "diffie-hellman-group1-sha1", ) conn = SSH2(driver=self.driver) # Save default values... DEFAULT_CONNECT_TIMEOUT = conn.get_connect_timeout() DEFAULT_PROMPT_LIST = conn.get_prompt() DEFAULT_PROMPT_TIMEOUT = conn.get_timeout() # FIXME - Exscript should be handling this but the pypi pkg doesn't # conn.set_connect_timeout(connect_timeout) try: conn.connect(hostname=self.host, port=self.port) break except sock.timeout as ee: self.downgrade_ssh_crypto = True if self.ssh_attempt_number == self.MAX_SSH_ATTEMPT: error = "Timeout connecting to TCP port {1} on host:{0}".format( self.host, self.port ) logger.critical(error) raise OSError(error) else: assert self.ssh_attempt_number < self.MAX_SSH_ATTEMPT time.sleep(0.5) except SSHException as ee: self.downgrade_ssh_crypto = True if self.ssh_attempt_number == self.MAX_SSH_ATTEMPT: error = ( "Connection to host:{0} on TCP port {1} was reset".format( self.host, self.port ) ) logger.critical(error) raise OSError(error) else: assert self.ssh_attempt_number < self.MAX_SSH_ATTEMPT time.sleep(0.5) login_success = False for account in self.account_list: conn.login(account) try: assert isinstance(conn, SSH2) # This succeeds if logged in... login_success = True break except AssertionError as aa: # login with account failed... continue assert login_success is True if login_success is True: self.password = account.password else: raise ValueError("Login to host='%s' failed" % self.host) conn.set_connect_timeout(DEFAULT_CONNECT_TIMEOUT) return conn else: raise ValueError("FATAL: proto='%s' isn't a valid protocol" % proto)
def testFromFile(self): self.key = PrivateKey.from_file(self.filename, self.password, 'dss') self.assertEqual(self.key.get_type(), 'dss') self.assertEqual(self.filename, self.key.get_filename()) self.assertEqual(self.password, self.key.get_password())
from __future__ import absolute_import import sys import unittest import re import os.path sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..')) from .ProtocolTest import ProtocolTest from Exscript.servers import SSHd from Exscript.protocols import SSH2 from Exscript import PrivateKey keyfile = os.path.join(os.path.dirname(__file__), 'id_rsa') key = PrivateKey.from_file(keyfile) class SSH2Test(ProtocolTest): CORRELATE = SSH2 def createDaemon(self): self.daemon = SSHd(self.hostname, self.port, self.device, key=key) def createProtocol(self): self.protocol = SSH2(timeout=1) def testConstructor(self): self.assertIsInstance(self.protocol, SSH2) def testLogin(self): self.assertRaises(IOError, ProtocolTest.testLogin, self)
# crash_id may not be set, if machine not present in initial vlist, if so then ignore log.info('Stopping running VM %s' % virtual_machine) conn.execute('vcrash %s' % crash_id) time.sleep(1) else: # conn.execute(start_command) lab_is_started = True first_match(conn, r'^The lab has been started') log.info('Lab started' ) # TODO: make this captured - need to debug capturing conn.send('exit') if key_filename: key = PrivateKey.from_file(key_filename) log.debug('Connecting to %s with username %s and key %s' % (host, username, key_filename)) accounts = [Account(username, key=key)] else: log.debug('Connecting to %s with username %s' % (host, username)) accounts = [Account(username)] hosts = ['ssh://%s' % host] verbosity = -1 start(accounts, hosts, start_lab, verbose=verbosity)
import sys, unittest, re, os.path sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..', 'src')) from ProtocolTest import ProtocolTest from Exscript.servers import SSHd from Exscript.protocols import SSH2 from Exscript import PrivateKey keyfile = os.path.join(os.path.dirname(__file__), 'id_rsa') key = PrivateKey.from_file(keyfile) class SSH2Test(ProtocolTest): CORRELATE = SSH2 def createDaemon(self): self.daemon = SSHd(self.hostname, self.port, self.device, key = key) def createProtocol(self): self.protocol = SSH2() def testConstructor(self): self.assert_(isinstance(self.protocol, SSH2)) def testLogin(self): self.assertRaises(IOError, ProtocolTest.testLogin, self) def testAuthenticate(self): self.assertRaises(IOError, ProtocolTest.testAuthenticate, self) def suite(): return unittest.TestLoader().loadTestsFromTestCase(SSH2Test)