Beispiel #1
0
class MyTSFTPRequestHandler(socketserver.BaseRequestHandler):
    timeout = 60
    auth_timeout = 60

    def setup(self):
        self.transport = Transport(self.request)
        self.transport.load_server_moduli()
        so = self.transport.get_security_options()
        so.digests = ('hmac-sha1', )
        so.compression = ('*****@*****.**', 'none')
        self.transport.add_server_key(self.server.host_key)
        self.transport.set_subsystem_handler('sftp', MyTSFTPServer,
                                             MyTSFTPServerInterface)

    def handle(self):
        try:
            self.transport.start_server(server=MyTServerInterface())
        except SSHException as e:
            logger.error("SSH error: %s" % str(e))
            self.transport.close()
        except EOFError as e:
            logger.error("Socket error: %s" % str(e))
        except Exception as e:
            logger.error("Error: %s" % str(e))

    def handle_timeout(self):
        self.transport.close()
 def __ensure_connection(self,
                         transport: paramiko.Transport,
                         force: bool = False) -> paramiko.Transport:
     if transport is None or not transport.is_active() or force:
         if transport is not None:
             transport.close()
         transport = paramiko.Transport((self.__host, self.__port))
         logger.info('Connecting to {} on port {}'.format(
             self.__host, self.__port))
         try:
             if isinstance(self.__credential, PasswordCredential):
                 logger.debug('Authenticating using a password')
                 transport.connect(username=self.__credential.username,
                                   password=self.__credential.password)
             elif isinstance(self.__credential, PubKeyCredential):
                 logger.debug('Authenticating using a public key')
                 key = self.__get_key_from_file(
                     self.__credential.public_key,
                     self.__credential.passphrase)
                 transport.connect(username=self.__credential.username,
                                   pkey=key)
             else:
                 raise RuntimeError('Unknown kind of credential')
             logger.info('Connection (re)established')
         except paramiko.SSHException:
             raise ConnectionError(
                 'Cerulean was disconnected and could not reconnect')
     return transport
Beispiel #3
0
    def run(self, ip, port=22, timeout=2):
        try:
            socket.setdefaulttimeout(timeout)
            s = socket.socket()
            s.connect((ip, port))
            banner = s.recv(50).strip(b"\r\n").split(b" ")
            try:
                self.data["version"] = banner[0].decode()
                self.data["os"] = banner[1].decode()
            except IndexError:
                pass

            s.send(banner[0] + b"\r\n")
            self._raw_recv = s.recv(2048)

            s.close()
            self._parse_raw_data()

            tran = Transport((ip, port))
            tran.start_client()
            pubkey = tran.get_remote_server_key()
            self.data["pubkey_name"] = pubkey.get_name()
            fp = pubkey.get_fingerprint()
            self.data["pubkey_fingerprint"] = fp.hex()
        except Exception as e:
            print(repr(e))
            return None
        finally:
            tran.close()
        return True
Beispiel #4
0
    def _on_open_port(args):
        host, port, socket = args
        try:
            ssh_conn = Transport(socket)

            if key_type is not None:
                new_preferred_keys = [key_type]
                new_preferred_keys.extend(ssh_conn._preferred_keys)
                ssh_conn._preferred_keys = tuple(new_preferred_keys)

            try:
                ssh_conn.start_client()

                key = ssh_conn.get_remote_server_key()
                key_md5 = md5(str(key)).hexdigest()
                fingerprint = ':'.join(
                    a + b for a, b in zip(key_md5[::2], key_md5[1::2]))

                data_cb(host, port, True,
                        (key.get_name(), fingerprint, b64encode(str(key))))

            finally:
                ssh_conn.close()

        except (socket_error, NoValidConnectionsError):
            data_cb(host, port, None, None)

        except Exception as e:
            data_cb(host, port, False,
                    'Exception: {}: {}'.format(type(e), str(e)))

        finally:
            socket.close()
Beispiel #5
0
def upload_file(host, port, usr, psw, local_path, remote_path):
    file_count = 0
    print('-' * 50 + '\n')
    print('Start uploading files')
    transport = Transport((host, port))
    transport.connect(username=usr, password=psw)
    sftp = SFTPClient.from_transport(transport)
    for file_name in listdir(local_path):
        local_file = local_path + '\\' + file_name
        remote_file = remote_path + '/' + file_name
        if file_name.split('.')[-1] == 'css':
            new_css = cssmini(open(local_file, 'r').read())
            with open('tmp.css', 'w') as tmp_css:
                tmp_css.write(new_css)
                tmp_css.close()
                sftp.put(cur_path + tmp_css.name, remote_file)
                remove(cur_path + tmp_css.name)
        elif file_name.split('.')[-1] == 'js':
            new_js = jsmini(open(local_file, 'r', encoding='utf-8').read())
            with open('tmp.js', 'w', encoding='utf-8') as tmp_js:
                tmp_js.write(new_js)
                tmp_js.close()
                sftp.put(cur_path + tmp_js.name, remote_file)
                remove(cur_path + tmp_js.name)
        else:
            sftp.put(local_file, remote_file)
        print(file_name + 'Upload completed')
        file_count += 1
    transport.close()
    print('All files have been uploaded, Connection has been closed, Number of files:{}'.format(file_count))
    print('-' * 50 + '\n')
Beispiel #6
0
class CSftpParamiko:
    def __init__(self):
        # set host, user, passwd
        self.hostname = '172.16.3.36'
        self.username = '******'
        self.password = '******'


# 		self.hostname = HOST_NAME
# 		self.username = USER_NAME
# 		self.password = PASSWORD

    def __exit__(self):
        pass

    def fileSave(self, local_file, remote_path):
        # connect to sftp server
        try:
            self.transport = Transport((self.hostname, 22))
            self.sftp = self.transport.connect(username=self.username,
                                               password=self.password)
            self.sftp_client = SFTPClient.from_transport(self.transport)
        except:
            print("[SFTP_P]: connect fail")

        try:
            self.sftp_client.put(local_file, remote_path)
        except:
            print("[SFTP_P]: put fail")

        try:
            self.sftp_client.close()
            self.transport.close()
        except:
            print("[SFTP_P]: close fail")
Beispiel #7
0
def sftpclient(sftpserver):
    transport = Transport((sftpserver.host, sftpserver.port))
    transport.connect(username="******", password="******")
    sftpclient = SFTPClient.from_transport(transport)
    yield sftpclient
    sftpclient.close()
    transport.close()
def _get_server_keys(hostname):

    server_keys = []

    # key_type_list = ["ssh-ed25519", "ssh-rsa", "ecdsa-sha2-nistp256"] # default key_type used by ssh-keysca
    # Supported key_type for OS
    # alinux     ssh-rsa,ssh-ed25519,ecdsa-sha2-nistp256
    # ubuntu1404 ssh-rsa,ssh-ed25519,ecdsa-sha2-nistp256
    # ubuntu1604 ssh-rsa,ssh-ed25519,ecdsa-sha2-nistp256
    # centos7    ssh-rsa,ssh-ed25519,ecdsa-sha2-nistp256
    # centos6    ssh-rsa
    key_type_list = ["ssh-rsa"]

    for key_type in key_type_list:
        transport = None
        try:
            sock = socket.socket()
            sock.settimeout(5)
            sock.connect((hostname, 22))
            transport = Transport(sock)
            transport._preferred_keys = [key_type]
            transport.start_client()
            server_keys.append(transport.get_remote_server_key())
        except Exception:
            pass
        finally:
            if transport:
                transport.close()

    if not server_keys:
        logging.error("Failed retrieving server key from host '%s'", hostname)

    return hostname, [(server_key.get_base64(), server_key.get_name())
                      for server_key in server_keys]
Beispiel #9
0
class SFTPUploader(object):
    """Uploads files to (s)ftp"""
    def __init__(self, sftp_settings):
        self.transport = Transport(
            (sftp_settings['HOST'], int(sftp_settings['PORT'])))
        self.transport.connect(username=sftp_settings['USER'],
                               password=sftp_settings['PASSWORD'])
        self.connection = SFTPClient.from_transport(self.transport)

        logger.debug(
            "SFTPUploader initiated. Sending files to {host}:{port}".format(
                host=sftp_settings['HOST'], port=sftp_settings['PORT']))

    def __del__(self):
        try:
            self.connection.close()
            self.transport.close()
        except AttributeError:
            pass

        logger.debug("SFTPUploader session completed. Connection closed.")

    def upload_file(self, local_filepath, filename):
        logger.debug("SFTPUploader: Uploading file {filepath}".format(
            filepath=local_filepath))
        try:
            self.connection.remove(path='./{filename}'.format(
                filename=filename))
        except IOError:
            pass
        self.connection.put(
            localpath=local_filepath,
            remotepath='./{filename}'.format(filename=filename))
def trans():
    """
    Create `LoopSocket`-based server/client `Transport`s, yielding the latter.

    Uses `NullServer` under the hood.
    """
    # NOTE: based on the setup/teardown/start_server/verify_finished methods
    # found in ye olde test_auth.py

    # "Network" setup
    socks = LoopSocket()
    sockc = LoopSocket()
    sockc.link(socks)
    tc = Transport(sockc)
    ts = Transport(socks)

    # Start up the in-memory server
    host_key = RSAKey.from_private_key_file(_support('test_rsa.key'))
    ts.add_server_key(host_key)
    event = threading.Event()
    server = NullServer()
    ts.start_server(event, server)

    # Tests frequently need to call Transport.connect on the client side, etc
    yield tc

    # Close things down
    tc.close()
    ts.close()
    socks.close()
    sockc.close()
Beispiel #11
0
    def run(self, ip, port=22, timeout=2):
        try:
            socket.setdefaulttimeout(timeout)
            s = socket.socket()
            s.connect((ip, port))
            banner = s.recv(50).strip('\r\n').split(' ')
            try:
                self.data["version"] = banner[0]
                self.data["os"] = banner[1]
            except IndexError:
                pass

            s.send('{}\r\n'.format(banner[0]))
            self._raw_recv = s.recv(2048)

            s.close()
            self._parse_raw_data()

            tran = Transport((ip, port))
            tran.start_client()
            pubkey = tran.get_remote_server_key()
            self.data["pubkey_name"] = pubkey.get_name()
            fp = pubkey.get_fingerprint()
            self.data["pubkey_fingerprint"] = ':'.join(map(lambda x:x.encode('hex'), fp))
        except Exception as e:
            cprint(str(e), 'error')
            return None
        finally:
            tran.close()
            self.clear()

        return True
def mx(src: str):
    spl = src.split(':')
    if len(spl) != 2:
        raise BaseException('Invalid url')
    map_id = spl[1]
    print('Downloading from MX: {}'.format(map_id))
    with urlopen('https://tm.mania-exchange.com/tracks/download/{}'.format(
            map_id)) as res:
        _, params = cgi.parse_header(res.headers.get('Content-Disposition',
                                                     ''))
        filename = params.get('filename', '{}.Map.Gbx'.format(map_id))
        data = res.read()
    t = Transport((settings['host'], settings['port']))
    print('Connecting')
    t.connect(username=settings['user'],
              pkey=paramiko.rsakey.RSAKey.from_private_key_file(
                  settings['pkey']))
    print('Connected')
    client = sftp.SFTPClient.from_transport(t)
    print('Uploading file')
    dst = settings['dest']
    with client.open('{}/{}'.format(dst, filename), 'wb') as file:
        file.write(data)
    print('Done')
    client.close()
    t.close()
Beispiel #13
0
def remote_scp(ftp_type, host_ip, remote_path, local_path, username, password):
    ssh_port = 22
    try:
        conn = Transport((host_ip, ssh_port))
        conn.connect(username=username, password=password)
        sftp = SFTPClient.from_transport(conn)
        if ftp_type == 'remoteRead':
            print('read')
            if not local_path:
                filename = os.path.split(remote_path)
                local_path = os.path.join('/tmp', filename[-1])
            print('开始从服务器下载文件......')
            sftp.get(remote_path, local_path)
            print(f'文件{filename[-1]}已经下载到本地')

        if ftp_type == "remoteWrite":
            print('write')
            sftp.put(local_path, remote_path)

        conn.close()
        return True
    except IOError as e:
        print('没有找到目录', e)
    except Exception as e:
        print('error!!!', e)
Beispiel #14
0
 def transport(self):
     transport = Transport((self.host, self.port))
     transport.connect(username=self.username, password=self.password)
     sftp = SFTPClient.from_transport(transport)
     sftp.put(f'{self.project_url}/web/caweb/html.zip',
              f'{self.nginx_url}/html.zip')
     sftp.put(f'{self.project_url}/server/caserver.zip',
              f'{self.nginx_url}/server/new_caserver.zip')
     print("transport finished!")
     transport.close()
Beispiel #15
0
def connect(username, hostname='lxplus.cern.ch', port=22):
    "Connect to a given host"
    print "Connecting to %s@%s" % (username, hostname)
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.connect((hostname, port))
    except Exception as err:
        print '*** Connect failed: ' + str(err)
        sys.exit(1)
    transport = Transport(sock)
    try:
        transport.start_client()
    except paramiko.SSHException as err:
        print "SSH negotiation failed\n%s" % str(err)

    try:
        keys = paramiko.util.load_host_keys(\
                os.path.expanduser('~/.ssh/known_hosts'))
    except IOError:
        try:
            keys = paramiko.util.load_host_keys(\
                os.path.expanduser('~/ssh/known_hosts'))
        except IOError:
            print '*** Unable to open host keys file'
            keys = {}

    # check server's host key -- this is important.
    key = transport.get_remote_server_key()
    if  not keys.has_key(hostname):
        print '*** WARNING: Unknown host key!'
    elif not keys[hostname].has_key(key.get_name()):
        print '*** WARNING: Unknown host key!'
    elif keys[hostname][key.get_name()] != key:
        print '*** WARNING: Host key has changed!!!'
        sys.exit(1)
    else:
        pass

    # get username
    if  username == '':
        default_username = getpass.getuser()
        username = raw_input('Username [%s]: ' % default_username)
        if  len(username) == 0:
            username = default_username

    agent_auth(transport, username)
    if not transport.is_authenticated():
        manual_auth(transport, username, hostname)
    if not transport.is_authenticated():
        print '*** Authentication failed. :('
        transport.close()
        sys.exit(1)
    return transport, sock
Beispiel #16
0
def connect(username, hostname='lxplus.cern.ch', port=22):
    "Connect to a given host"
    print "Connecting to %s@%s" % (username, hostname)
    try:
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.connect((hostname, port))
    except Exception as err:
        print '*** Connect failed: ' + str(err)
        sys.exit(1)
    transport = Transport(sock)
    try:
        transport.start_client()
    except paramiko.SSHException as err:
        print "SSH negotiation failed\n%s" % str(err)

    try:
        keys = paramiko.util.load_host_keys(\
                os.path.expanduser('~/.ssh/known_hosts'))
    except IOError:
        try:
            keys = paramiko.util.load_host_keys(\
                os.path.expanduser('~/ssh/known_hosts'))
        except IOError:
            print '*** Unable to open host keys file'
            keys = {}

    # check server's host key -- this is important.
    key = transport.get_remote_server_key()
    if not keys.has_key(hostname):
        print '*** WARNING: Unknown host key!'
    elif not keys[hostname].has_key(key.get_name()):
        print '*** WARNING: Unknown host key!'
    elif keys[hostname][key.get_name()] != key:
        print '*** WARNING: Host key has changed!!!'
        sys.exit(1)
    else:
        pass

    # get username
    if username == '':
        default_username = getpass.getuser()
        username = raw_input('Username [%s]: ' % default_username)
        if len(username) == 0:
            username = default_username

    agent_auth(transport, username)
    if not transport.is_authenticated():
        manual_auth(transport, username, hostname)
    if not transport.is_authenticated():
        print '*** Authentication failed. :('
        transport.close()
        sys.exit(1)
    return transport, sock
	def sshAuthentication(self, clientsock):
		# setup logging
		paramiko.util.log_to_file(C.SYSLOG_FILE)

		# Check that SSH server parameters have been set:
		if (self.sshData == None):
			return clientsock, False, None
		else:
			# Load private key of the server
			filekey = self.sshData["hostKeyFile"]
			if (not filekey.startswith("/")):
				filekey = C.YENCAP_CONF_HOME + "/" + filekey

			# Build a key object from the file path:
			if (self.sshData["hostKeyType"] == "dss"):
				priv_host_key = paramiko.DSSKey(filename=filekey)
			elif (self.sshData["hostKeyType"] == "rsa"):
				priv_host_key = paramiko.RSAKey(filename=filekey)

		try:
			event = threading.Event()
			# Create a new SSH session over an existing socket, or socket-like object.
			t = Transport(clientsock)
			# Add a host key to the list of keys used for server mode.
			t.add_server_key(priv_host_key)
			# paramiko.ServerInterface defines an interface for controlling the behavior of paramiko in server mode.
			server = SSHServerModule()
			# Negotiate a new SSH2 session as a server.
			t.start_server(event, server)
			while 1:
				event.wait(0.1)
				if not t.is_active():
					return clientsock, False, None
				if event.isSet():
					break
		
			# Return the next channel opened by the client over this transport, in server mode.
			channel = t.accept(20)
			
			if channel is None:
				return clientsock, False, None
		
		except Exception, e:
			LogManager.getInstance().logError("Caught exception: %s: %s" % (str(e.__class__), str(e)))
			traceback.print_exc()

			try:
				t.close()
			except:
				pass
			return clientsock, False, None
Beispiel #18
0
    def sshAuthentication(self, clientsock):
        # setup logging
        paramiko.util.log_to_file(C.SYSLOG_FILE)
        # Check that SSH server parameters have been set:
        if (self.sshData == None):
            return clientsock, False, None
        else:
            # Load private key of the server
            filekey = self.sshData["hostKeyFile"]
            if (not filekey.startswith("/")):
                filekey = C.YENCAP_CONF_KEYS + "/" + filekey

            # Build a key object from the file path:
            if (self.sshData["hostKeyType"] == "dss"):
                priv_host_key = paramiko.DSSKey(filename=filekey)
            elif (self.sshData["hostKeyType"] == "rsa"):
                priv_host_key = paramiko.RSAKey(filename=filekey)

        try:
            event = threading.Event()
            # Create a new SSH session over an existing socket, or socket-like object.
            t = Transport(clientsock)
            # Add a host key to the list of keys used for server mode.
            t.add_server_key(priv_host_key)
            # paramiko.ServerInterface defines an interface for controlling the behavior of paramiko in server mode.
            server = SSHServerModule()
            # Negotiate a new SSH2 session as a server.
            t.start_server(event, server)
            while 1:
                event.wait(0.1)
                if not t.is_active():
                    return clientsock, False, None
                if event.isSet():
                    break

            # Return the next channel opened by the client over this transport, in server mode.
            channel = t.accept(20)

            if channel is None:
                return clientsock, False, None

        except Exception, e:
            LogManager.getInstance().logError("Caught exception: %s: %s" %
                                              (str(e.__class__), str(e)))
            traceback.print_exc()

            try:
                t.close()
            except:
                pass
            return clientsock, False, None
Beispiel #19
0
def get_remote_file(ssh_config: SshClientConfig, local_path: Path, remote_path: Path):
    """Use SFTP to copy a file from a remote server to the local server.

    :param ssh_config: Configuration of the SSH session used for SFTP
    :param local_path: Destination path of the file being transferred
    :param remote_path: Source path of the file being transferred
    """
    ssh_transport = Transport((ssh_config.remote_server, int(ssh_config.ssh_port)))
    ssh_key = RSAKey.from_private_key_file("/home/mycroft/.ssh/id_rsa")
    ssh_transport.connect(hostkey=None, username=ssh_config.remote_user, pkey=ssh_key)
    sftp_client = SFTPClient.from_transport(ssh_transport)
    sftp_client.get(str(remote_path), str(local_path))
    sftp_client.close()
    ssh_transport.close()
Beispiel #20
0
class SftpAuth:
    def __init__(self, user, hostname, port, rsa_key, remote_dir):
        self.user = user
        self.hostname = hostname
        self.port = port
        self.rsa_key = rsa_key
        self.remote_dir = remote_dir
        logger.info(self.__repr__())

    def __repr__(self):
        return "The sftp instance was initialized. " \
               "user={}, hostname={}, port={}, rsa_key={}, remote_dir={}"\
            .format(self.user, self.hostname, self.port, self.rsa_key, self.remote_dir)

    def set_transport(self):
        logger.debug("Try to initialize transport.")
        try:
            self.transport = Transport(f"{self.hostname}:{self.port}")
            self.transport.start_client(event=None, timeout=15)
            self.transport.get_remote_server_key()
            rsa_key = RSAKey.from_private_key_file(self.rsa_key)
            self.transport.auth_publickey(self.user, rsa_key)
        except Exception as e:
            logger.debug(e)
            print(json.dumps({
                "error": {
                    "code": 00,
                    "message": e
                },
            }),
                  flush=True)
            raise

        logger.info("Transport was initialized.")

    def __enter__(self):
        self.set_transport()
        self.sftp = SFTPClient.from_transport(self.transport)
        try:
            logger.info("Try to make a directory")
            self.sftp.mkdir(self.remote_dir)
        except Exception as e:
            logger.info(e)
        logger.info(f"Change the current directory into {self.remote_dir}")
        self.sftp.chdir(self.remote_dir)
        return self.sftp

    def __exit__(self, exc_type, exc_val, exc_tb):
        self.transport.close()
        self.sftp.close()
def sftp_client(ip,uname,pw,r_path,l_path):
#	util.log_to_file('/root/download_config/paramiko.log')
	try:
		t=Transport((ip,22))
		t.connect(username=uname,password=pw)
		sftp=SFTPClient.from_transport(t)
		sftp.get(r_path,l_path)
		t.close()
#	ssh = SSHClient()
#	ssh.set_missing_host_key_policy(AutoAddPolicy())
#	ssh.connect(ip,22,uname,pw,look_for_keys=False,allow_agent=False)
#	t=ssh.get_transport()
#	sftp=SFTPClient.from_transport(t)
#	sftp.get(r_path,l_path)
#	t.close()
	except:
		print 'sftp %s failed' % (ip)
Beispiel #22
0
    def upload_report_to_sftp(self, client_id, report_date, absolute_filename):
        """
        Upload the given file, using SFTP, to the configured FTP server. The
        file should be uploaded to the appropriate directory for the specified
        client and the date of the report.
        """
        try:
            client = Clients.objects.get(id=client_id)
        except Clients.DoesNotExist:
            logger.exception(u'No configuration for client {0}.'.format(client_id))
            raise

        filename = basename(absolute_filename)
        base_folder, env_folder, year_folder, month_folder = self._get_sftp_dirs(client, report_date)

        try:
            logger.debug(u'SFTP logging on to {0} as {1}'.format(settings.SFTP_SERVER, settings.SFTP_USERNAME))
            transport = Transport((settings.SFTP_SERVER, settings.SFTP_PORT))
            transport.connect(username=settings.SFTP_USERNAME, password=settings.SFTP_PASSWORD)
            sftp = SFTPClient.from_transport(transport)

            logger.debug(u'SFTP dir {0}/{1}/{2}/{3}'.format(base_folder, env_folder, year_folder, month_folder))
            sftp.chdir(base_folder)
            self._make_or_change_sftp_dir(sftp, env_folder)
            self._make_or_change_sftp_dir(sftp, year_folder)
            self._make_or_change_sftp_dir(sftp, month_folder)

            logger.debug(u'SFTP uploading {0}'.format(filename))
            sftp.put(absolute_filename, filename)
        except Exception:
            logger.exception(u'Unrecoverable exception during SFTP upload process.')
            raise
        finally:
            logger.debug(u'SFTP logging off')

            try:
                sftp.close()
            except Exception:
                logger.exception(u'SFTP exception while closing SFTP session.')

            try:
                transport.close()
            except Exception:
                logger.exception(u'SFTP exception while closing SSH connection.')
Beispiel #23
0
class MyTSFTPRequestHandler(SocketServer.BaseRequestHandler):
    timeout = 60
    auth_timeout = 60

    def setup(self):
        self.transport = Transport(self.request)
        self.transport.load_server_moduli()
        so = self.transport.get_security_options()
        so.digests = ('hmac-sha1', )
        so.compression = ('*****@*****.**', 'none')
        self.transport.add_server_key(self.server.host_key)
        self.transport.set_subsystem_handler(
            'sftp', MyTSFTPServer, MyTSFTPServerInterface)

    def handle(self):
        self.transport.start_server(server=MyTServerInterface())

    def handle_timeout(self):
        self.transport.close()
    def __cacheIfRemote(self, importTitle, path):
        protocol = None
        for prefix in DataImportFactory.remoteProtocols:
            if path.startswith(prefix):
                protocol = prefix

        if not protocol:
            return path

        fileName = path.split("/").pop()
        outPath = os.path.join(self.__system.getConfig().getOutputPath(),
                               "imports",
                               "{0}_{1}".format(importTitle, fileName))

        if not os.path.exists(os.path.dirname(outPath)):
            os.makedirs(os.path.dirname(outPath))

        if not os.path.exists(outPath):
            self.__getLog().info("Downloading {0} to {1}".format(
                path, outPath))
            if protocol == "sftp://":
                loginInfo, hostPath = path.split("@")
                userName, password = loginInfo.rsplit(":", 1)
                userName = userName.split(protocol).pop()
                hostName, remotePath = hostPath.split("/", 1)
                transport = Transport((hostName, 22))
                transport.connect(username=userName, password=password)
                sftp = SFTPClient.from_transport(transport)
                sftp.get("/{0}".format(remotePath), outPath)
                transport.close()
            else:
                r = requests.get(path, stream=True)
                with open(outPath, "wb") as outFile:
                    for chunk in r.iter_content():
                        outFile.write(chunk)
        else:
            self.__getLog().info("Using existing {0} for {1}".format(
                outPath, path))

        return outPath
Beispiel #25
0
class MyTSFTPRequestHandler(SocketServer.BaseRequestHandler):
    timeout = 60
    auth_timeout = 60

    def setup(self):
        self.transport = Transport(self.request)
        self.transport.load_server_moduli()
        so = self.transport.get_security_options()
        so.digests = ('hmac-sha1', )
        so.compression = ('*****@*****.**', 'none')
        self.transport.add_server_key(self.server.host_key)
        self.transport.set_subsystem_handler(
            'sftp', MyTSFTPServer, MyTSFTPServerInterface)

    def handle(self):
        self.transport.start_server(server=MyTServerInterface())

    def handle_timeout(self):
        try:
            self.transport.close()
        finally:
            super(MyTSFTPRequestHandler, self).handle_timeout()
Beispiel #26
0
    def run(self, ip, port=22, timeout=2):

        try:
            socket.setdefaulttimeout(timeout)
            s = socket.socket()
            s.connect((ip, port))
            banner = s.recv(50).strip('\r\n').split(' ')

            try:
                self.data.version = banner[0]
                self.data.os = banner[1]
            except IndexError:
                pass

            s.send('{}\r\n'.format(banner[0]))
            self._raw_recv = s.recv(2048)

            s.close()
            self._parse_raw_data()

            # use paramiko to get hostkey because of lazyless...
            tran = Transport((ip, port))
            tran.start_client()
            pubkey = tran.get_remote_server_key()
            self.data.pubkey_name = pubkey.get_name()
            fp = pubkey.get_fingerprint()
            self.data.pubkey_fingerprint = ':'.join(
                map(lambda x: x.encode('hex'), fp))

            ServicesInfo.add(ip, port, 'ssh', self.data)

        except Exception as e:
            cprint(str(e), 'error')
            return None
        finally:
            tran.close()
            self.clear()

        return True
Beispiel #27
0
    def run(self, ip, port=22, timeout=2):

        try:
            socket.setdefaulttimeout(timeout)
            s = socket.socket()
            s.connect((ip, port))
            banner = s.recv(50).strip('\r\n').split(' ')

            try:
                self.data.version = banner[0]
                self.data.os = banner[1]
            except IndexError:
                pass

            s.send('{}\r\n'.format(banner[0]))
            self._raw_recv = s.recv(2048)

            s.close()
            self._parse_raw_data()

            # use paramiko to get hostkey because of lazyless...
            tran = Transport((ip, port))
            tran.start_client()
            pubkey = tran.get_remote_server_key()
            self.data.pubkey_name = pubkey.get_name()
            fp = pubkey.get_fingerprint()
            self.data.pubkey_fingerprint = ':'.join(map(lambda x:x.encode('hex'), fp))
            
            ServicesInfo.add(ip, port, 'ssh', self.data)

        except Exception as e:
            cprint(str(e), 'error')
            return None
        finally:
            tran.close()
            self.clear()

        return True
  def handle_connection(self, host_key):
    try:
      DoGSSAPIKeyExchange = False
      t = Transport(self.sock, gss_kex=DoGSSAPIKeyExchange)
      t.set_subsystem_handler('netconf', self.subsys)
      t.set_gss_host(socket.getfqdn(""))
      try:
        t.load_server_moduli()
      except:
        Logger.warning('Failed to load moduli -- gex will be unsupported.')
      t.add_server_key(host_key)
      server = Server()
      t.start_server(server=server)

      # wait for auth
      self.channel = t.accept(20)
      if self.channel is None:
        Logger.error('No SSH channel')
        return

      Logger.info('Waiting for message')
      server.event.wait(10)
      Logger.info('Closing')
      ##self.channel.close()
      Logger.info('Client connection closed')
    except ConnectionResetError as e:
      Logger.debug(5,'Connection reset by peer')
    except SSHException:
      Logger.error('SSH negotiation failed, client connection dropped')
    except Exception as e:
      Logger.error('Caught exception: ' + str(e.__class__) + ': ' + str(e))
      traceback.print_exc()
      try:
        t.close()
      except:
        pass
def main():
    if len(sys.argv) < 2:
        print('Usage: {} <map file>'.format(sys.argv[0]))
        raise BaseException('')
    src = sys.argv[1]
    if not os.path.isfile(src):
        if src.startswith('mxupload:'):
            mx(src)
            return
        print('File not found {}'.format(src))
        raise BaseException('')
    t = Transport((settings['host'], settings['port']))
    print('Connecting')
    t.connect(username=settings['user'],
              pkey=paramiko.rsakey.RSAKey.from_private_key_file(
                  settings['pkey']))
    print('Connected')
    client = sftp.SFTPClient.from_transport(t)
    print('Uploading file')
    dst = settings['dest']
    client.put(sys.argv[1], '{}/{}'.format(dst, os.path.basename(src)))
    print('Done')
    client.close()
    t.close()
Beispiel #30
0
class TransportTest(unittest.TestCase):
    def setUp(self):
        self.socks = LoopSocket()
        self.sockc = LoopSocket()
        self.sockc.link(self.socks)
        self.tc = Transport(self.sockc)
        self.ts = Transport(self.socks)

    def tearDown(self):
        self.tc.close()
        self.ts.close()
        self.socks.close()
        self.sockc.close()

    def setup_test_server(self, client_options=None, server_options=None):
        host_key = RSAKey.from_private_key_file(test_path('test_rsa.key'))
        public_host_key = RSAKey(data=host_key.asbytes())
        self.ts.add_server_key(host_key)

        if client_options is not None:
            client_options(self.tc.get_security_options())
        if server_options is not None:
            server_options(self.ts.get_security_options())

        event = threading.Event()
        self.server = NullServer()
        self.assertTrue(not event.is_set())
        self.ts.start_server(event, self.server)
        self.tc.connect(hostkey=public_host_key,
                        username='******',
                        password='******')
        event.wait(1.0)
        self.assertTrue(event.is_set())
        self.assertTrue(self.ts.is_active())

    def test_1_security_options(self):
        o = self.tc.get_security_options()
        self.assertEqual(type(o), SecurityOptions)
        self.assertTrue(('aes256-cbc', 'blowfish-cbc') != o.ciphers)
        o.ciphers = ('aes256-cbc', 'blowfish-cbc')
        self.assertEqual(('aes256-cbc', 'blowfish-cbc'), o.ciphers)
        try:
            o.ciphers = ('aes256-cbc', 'made-up-cipher')
            self.assertTrue(False)
        except ValueError:
            pass
        try:
            o.ciphers = 23
            self.assertTrue(False)
        except TypeError:
            pass

    def test_2_compute_key(self):
        self.tc.K = 123281095979686581523377256114209720774539068973101330872763622971399429481072519713536292772709507296759612401802191955568143056534122385270077606457721553469730659233569339356140085284052436697480759510519672848743794433460113118986816826624865291116513647975790797391795651716378444844877749505443714557929
        self.tc.H = b'\x0C\x83\x07\xCD\xE6\x85\x6F\xF3\x0B\xA9\x36\x84\xEB\x0F\x04\xC2\x52\x0E\x9E\xD3'
        self.tc.session_id = self.tc.H
        key = self.tc._compute_key('C', 32)
        self.assertEqual(
            b'207E66594CA87C44ECCBA3B3CD39FDDB378E6FDB0F97C54B2AA0CFBF900CD995',
            hexlify(key).upper())

    def test_3_simple(self):
        """
        verify that we can establish an ssh link with ourselves across the
        loopback sockets.  this is hardly "simple" but it's simpler than the
        later tests. :)
        """
        host_key = RSAKey.from_private_key_file(test_path('test_rsa.key'))
        public_host_key = RSAKey(data=host_key.asbytes())
        self.ts.add_server_key(host_key)
        event = threading.Event()
        server = NullServer()
        self.assertTrue(not event.is_set())
        self.assertEqual(None, self.tc.get_username())
        self.assertEqual(None, self.ts.get_username())
        self.assertEqual(False, self.tc.is_authenticated())
        self.assertEqual(False, self.ts.is_authenticated())
        self.ts.start_server(event, server)
        self.tc.connect(hostkey=public_host_key,
                        username='******',
                        password='******')
        event.wait(1.0)
        self.assertTrue(event.is_set())
        self.assertTrue(self.ts.is_active())
        self.assertEqual('slowdive', self.tc.get_username())
        self.assertEqual('slowdive', self.ts.get_username())
        self.assertEqual(True, self.tc.is_authenticated())
        self.assertEqual(True, self.ts.is_authenticated())

    def test_3a_long_banner(self):
        """
        verify that a long banner doesn't mess up the handshake.
        """
        host_key = RSAKey.from_private_key_file(test_path('test_rsa.key'))
        public_host_key = RSAKey(data=host_key.asbytes())
        self.ts.add_server_key(host_key)
        event = threading.Event()
        server = NullServer()
        self.assertTrue(not event.is_set())
        self.socks.send(LONG_BANNER)
        self.ts.start_server(event, server)
        self.tc.connect(hostkey=public_host_key,
                        username='******',
                        password='******')
        event.wait(1.0)
        self.assertTrue(event.is_set())
        self.assertTrue(self.ts.is_active())

    def test_4_special(self):
        """
        verify that the client can demand odd handshake settings, and can
        renegotiate keys in mid-stream.
        """
        def force_algorithms(options):
            options.ciphers = ('aes256-cbc', )
            options.digests = ('hmac-md5-96', )

        self.setup_test_server(client_options=force_algorithms)
        self.assertEqual('aes256-cbc', self.tc.local_cipher)
        self.assertEqual('aes256-cbc', self.tc.remote_cipher)
        self.assertEqual(12, self.tc.packetizer.get_mac_size_out())
        self.assertEqual(12, self.tc.packetizer.get_mac_size_in())

        self.tc.send_ignore(1024)
        self.tc.renegotiate_keys()
        self.ts.send_ignore(1024)

    def test_5_keepalive(self):
        """
        verify that the keepalive will be sent.
        """
        self.setup_test_server()
        self.assertEqual(None, getattr(self.server, '_global_request', None))
        self.tc.set_keepalive(1)
        time.sleep(2)
        self.assertEqual('*****@*****.**', self.server._global_request)

    def test_6_exec_command(self):
        """
        verify that exec_command() does something reasonable.
        """
        self.setup_test_server()

        chan = self.tc.open_session()
        schan = self.ts.accept(1.0)
        try:
            chan.exec_command('no')
            self.assertTrue(False)
        except SSHException:
            pass

        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)
        schan.send('Hello there.\n')
        schan.send_stderr('This is on stderr.\n')
        schan.close()

        f = chan.makefile()
        self.assertEqual('Hello there.\n', f.readline())
        self.assertEqual('', f.readline())
        f = chan.makefile_stderr()
        self.assertEqual('This is on stderr.\n', f.readline())
        self.assertEqual('', f.readline())

        # now try it with combined stdout/stderr
        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)
        schan.send('Hello there.\n')
        schan.send_stderr('This is on stderr.\n')
        schan.close()

        chan.set_combine_stderr(True)
        f = chan.makefile()
        self.assertEqual('Hello there.\n', f.readline())
        self.assertEqual('This is on stderr.\n', f.readline())
        self.assertEqual('', f.readline())

    def test_6a_channel_can_be_used_as_context_manager(self):
        """
        verify that exec_command() does something reasonable.
        """
        self.setup_test_server()

        with self.tc.open_session() as chan:
            with self.ts.accept(1.0) as schan:
                chan.exec_command('yes')
                schan.send('Hello there.\n')
                schan.close()

                f = chan.makefile()
                self.assertEqual('Hello there.\n', f.readline())
                self.assertEqual('', f.readline())

    def test_7_invoke_shell(self):
        """
        verify that invoke_shell() does something reasonable.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.invoke_shell()
        schan = self.ts.accept(1.0)
        chan.send('communist j. cat\n')
        f = schan.makefile()
        self.assertEqual('communist j. cat\n', f.readline())
        chan.close()
        self.assertEqual('', f.readline())

    def test_8_channel_exception(self):
        """
        verify that ChannelException is thrown for a bad open-channel request.
        """
        self.setup_test_server()
        try:
            chan = self.tc.open_channel('bogus')
            self.fail('expected exception')
        except ChannelException as e:
            self.assertTrue(e.code == OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED)

    def test_9_exit_status(self):
        """
        verify that get_exit_status() works.
        """
        self.setup_test_server()

        chan = self.tc.open_session()
        schan = self.ts.accept(1.0)
        chan.exec_command('yes')
        schan.send('Hello there.\n')
        self.assertTrue(not chan.exit_status_ready())
        # trigger an EOF
        schan.shutdown_read()
        schan.shutdown_write()
        schan.send_exit_status(23)
        schan.close()

        f = chan.makefile()
        self.assertEqual('Hello there.\n', f.readline())
        self.assertEqual('', f.readline())
        count = 0
        while not chan.exit_status_ready():
            time.sleep(0.1)
            count += 1
            if count > 50:
                raise Exception("timeout")
        self.assertEqual(23, chan.recv_exit_status())
        chan.close()

    def test_A_select(self):
        """
        verify that select() on a channel works.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.invoke_shell()
        schan = self.ts.accept(1.0)

        # nothing should be ready
        r, w, e = select.select([chan], [], [], 0.1)
        self.assertEqual([], r)
        self.assertEqual([], w)
        self.assertEqual([], e)

        schan.send('hello\n')

        # something should be ready now (give it 1 second to appear)
        for i in range(10):
            r, w, e = select.select([chan], [], [], 0.1)
            if chan in r:
                break
            time.sleep(0.1)
        self.assertEqual([chan], r)
        self.assertEqual([], w)
        self.assertEqual([], e)

        self.assertEqual(b'hello\n', chan.recv(6))

        # and, should be dead again now
        r, w, e = select.select([chan], [], [], 0.1)
        self.assertEqual([], r)
        self.assertEqual([], w)
        self.assertEqual([], e)

        schan.close()

        # detect eof?
        for i in range(10):
            r, w, e = select.select([chan], [], [], 0.1)
            if chan in r:
                break
            time.sleep(0.1)
        self.assertEqual([chan], r)
        self.assertEqual([], w)
        self.assertEqual([], e)
        self.assertEqual(bytes(), chan.recv(16))

        # make sure the pipe is still open for now...
        p = chan._pipe
        self.assertEqual(False, p._closed)
        chan.close()
        # ...and now is closed.
        self.assertEqual(True, p._closed)

    def test_B_renegotiate(self):
        """
        verify that a transport can correctly renegotiate mid-stream.
        """
        self.setup_test_server()
        self.tc.packetizer.REKEY_BYTES = 16384
        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)

        self.assertEqual(self.tc.H, self.tc.session_id)
        for i in range(20):
            chan.send('x' * 1024)
        chan.close()

        # allow a few seconds for the rekeying to complete
        for i in range(50):
            if self.tc.H != self.tc.session_id:
                break
            time.sleep(0.1)
        self.assertNotEqual(self.tc.H, self.tc.session_id)

        schan.close()

    def test_C_compression(self):
        """
        verify that zlib compression is basically working.
        """
        def force_compression(o):
            o.compression = ('zlib', )

        self.setup_test_server(force_compression, force_compression)
        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)

        bytes = self.tc.packetizer._Packetizer__sent_bytes
        chan.send('x' * 1024)
        bytes2 = self.tc.packetizer._Packetizer__sent_bytes
        # tests show this is actually compressed to *52 bytes*!  including packet overhead!  nice!! :)
        self.assertTrue(bytes2 - bytes < 1024)
        self.assertEqual(52, bytes2 - bytes)

        chan.close()
        schan.close()

    def test_D_x11(self):
        """
        verify that an x11 port can be requested and opened.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)

        requested = []

        def handler(c, addr_port):
            addr, port = addr_port
            requested.append((addr, port))
            self.tc._queue_incoming_channel(c)

        self.assertEqual(None, getattr(self.server, '_x11_screen_number',
                                       None))
        cookie = chan.request_x11(0, single_connection=True, handler=handler)
        self.assertEqual(0, self.server._x11_screen_number)
        self.assertEqual('MIT-MAGIC-COOKIE-1', self.server._x11_auth_protocol)
        self.assertEqual(cookie, self.server._x11_auth_cookie)
        self.assertEqual(True, self.server._x11_single_connection)

        x11_server = self.ts.open_x11_channel(('localhost', 6093))
        x11_client = self.tc.accept()
        self.assertEqual('localhost', requested[0][0])
        self.assertEqual(6093, requested[0][1])

        x11_server.send('hello')
        self.assertEqual(b'hello', x11_client.recv(5))

        x11_server.close()
        x11_client.close()
        chan.close()
        schan.close()

    def test_E_reverse_port_forwarding(self):
        """
        verify that a client can ask the server to open a reverse port for
        forwarding.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)

        requested = []

        def handler(c, origin_addr_port, server_addr_port):
            requested.append(origin_addr_port)
            requested.append(server_addr_port)
            self.tc._queue_incoming_channel(c)

        port = self.tc.request_port_forward('127.0.0.1', 0, handler)
        self.assertEqual(port, self.server._listen.getsockname()[1])

        cs = socket.socket()
        cs.connect(('127.0.0.1', port))
        ss, _ = self.server._listen.accept()
        sch = self.ts.open_forwarded_tcpip_channel(ss.getsockname(),
                                                   ss.getpeername())
        cch = self.tc.accept()

        sch.send('hello')
        self.assertEqual(b'hello', cch.recv(5))
        sch.close()
        cch.close()
        ss.close()
        cs.close()

        # now cancel it.
        self.tc.cancel_port_forward('127.0.0.1', port)
        self.assertTrue(self.server._listen is None)

    def test_F_port_forwarding(self):
        """
        verify that a client can forward new connections from a locally-
        forwarded port.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)

        # open a port on the "server" that the client will ask to forward to.
        greeting_server = socket.socket()
        greeting_server.bind(('127.0.0.1', 0))
        greeting_server.listen(1)
        greeting_port = greeting_server.getsockname()[1]

        cs = self.tc.open_channel('direct-tcpip', ('127.0.0.1', greeting_port),
                                  ('', 9000))
        sch = self.ts.accept(1.0)
        cch = socket.socket()
        cch.connect(self.server._tcpip_dest)

        ss, _ = greeting_server.accept()
        ss.send(b'Hello!\n')
        ss.close()
        sch.send(cch.recv(8192))
        sch.close()

        self.assertEqual(b'Hello!\n', cs.recv(7))
        cs.close()

    def test_G_stderr_select(self):
        """
        verify that select() on a channel works even if only stderr is
        receiving data.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.invoke_shell()
        schan = self.ts.accept(1.0)

        # nothing should be ready
        r, w, e = select.select([chan], [], [], 0.1)
        self.assertEqual([], r)
        self.assertEqual([], w)
        self.assertEqual([], e)

        schan.send_stderr('hello\n')

        # something should be ready now (give it 1 second to appear)
        for i in range(10):
            r, w, e = select.select([chan], [], [], 0.1)
            if chan in r:
                break
            time.sleep(0.1)
        self.assertEqual([chan], r)
        self.assertEqual([], w)
        self.assertEqual([], e)

        self.assertEqual(b'hello\n', chan.recv_stderr(6))

        # and, should be dead again now
        r, w, e = select.select([chan], [], [], 0.1)
        self.assertEqual([], r)
        self.assertEqual([], w)
        self.assertEqual([], e)

        schan.close()
        chan.close()

    def test_H_send_ready(self):
        """
        verify that send_ready() indicates when a send would not block.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.invoke_shell()
        schan = self.ts.accept(1.0)

        self.assertEqual(chan.send_ready(), True)
        total = 0
        K = '*' * 1024
        limit = 1 + (64 * 2**15)
        while total < limit:
            chan.send(K)
            total += len(K)
            if not chan.send_ready():
                break
        self.assertTrue(total < limit)

        schan.close()
        chan.close()
        self.assertEqual(chan.send_ready(), True)

    def test_I_rekey_deadlock(self):
        """
        Regression test for deadlock when in-transit messages are received after MSG_KEXINIT is sent

        Note: When this test fails, it may leak threads.
        """

        # Test for an obscure deadlocking bug that can occur if we receive
        # certain messages while initiating a key exchange.
        #
        # The deadlock occurs as follows:
        #
        # In the main thread:
        #   1. The user's program calls Channel.send(), which sends
        #      MSG_CHANNEL_DATA to the remote host.
        #   2. Packetizer discovers that REKEY_BYTES has been exceeded, and
        #      sets the __need_rekey flag.
        #
        # In the Transport thread:
        #   3. Packetizer notices that the __need_rekey flag is set, and raises
        #      NeedRekeyException.
        #   4. In response to NeedRekeyException, the transport thread sends
        #      MSG_KEXINIT to the remote host.
        #
        # On the remote host (using any SSH implementation):
        #   5. The MSG_CHANNEL_DATA is received, and MSG_CHANNEL_WINDOW_ADJUST is sent.
        #   6. The MSG_KEXINIT is received, and a corresponding MSG_KEXINIT is sent.
        #
        # In the main thread:
        #   7. The user's program calls Channel.send().
        #   8. Channel.send acquires Channel.lock, then calls Transport._send_user_message().
        #   9. Transport._send_user_message waits for Transport.clear_to_send
        #      to be set (i.e., it waits for re-keying to complete).
        #      Channel.lock is still held.
        #
        # In the Transport thread:
        #   10. MSG_CHANNEL_WINDOW_ADJUST is received; Channel._window_adjust
        #       is called to handle it.
        #   11. Channel._window_adjust tries to acquire Channel.lock, but it
        #       blocks because the lock is already held by the main thread.
        #
        # The result is that the Transport thread never processes the remote
        # host's MSG_KEXINIT packet, because it becomes deadlocked while
        # handling the preceding MSG_CHANNEL_WINDOW_ADJUST message.

        # We set up two separate threads for sending and receiving packets,
        # while the main thread acts as a watchdog timer.  If the timer
        # expires, a deadlock is assumed.

        class SendThread(threading.Thread):
            def __init__(self, chan, iterations, done_event):
                threading.Thread.__init__(self, None, None,
                                          self.__class__.__name__)
                self.setDaemon(True)
                self.chan = chan
                self.iterations = iterations
                self.done_event = done_event
                self.watchdog_event = threading.Event()
                self.last = None

            def run(self):
                try:
                    for i in range(1, 1 + self.iterations):
                        if self.done_event.is_set():
                            break
                        self.watchdog_event.set()
                        #print i, "SEND"
                        self.chan.send("x" * 2048)
                finally:
                    self.done_event.set()
                    self.watchdog_event.set()

        class ReceiveThread(threading.Thread):
            def __init__(self, chan, done_event):
                threading.Thread.__init__(self, None, None,
                                          self.__class__.__name__)
                self.setDaemon(True)
                self.chan = chan
                self.done_event = done_event
                self.watchdog_event = threading.Event()

            def run(self):
                try:
                    while not self.done_event.is_set():
                        if self.chan.recv_ready():
                            chan.recv(65536)
                            self.watchdog_event.set()
                        else:
                            if random.randint(0, 1):
                                time.sleep(random.randint(0, 500) / 1000.0)
                finally:
                    self.done_event.set()
                    self.watchdog_event.set()

        self.setup_test_server()
        self.ts.packetizer.REKEY_BYTES = 2048

        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)

        # Monkey patch the client's Transport._handler_table so that the client
        # sends MSG_CHANNEL_WINDOW_ADJUST whenever it receives an initial
        # MSG_KEXINIT.  This is used to simulate the effect of network latency
        # on a real MSG_CHANNEL_WINDOW_ADJUST message.
        self.tc._handler_table = self.tc._handler_table.copy(
        )  # copy per-class dictionary
        _negotiate_keys = self.tc._handler_table[MSG_KEXINIT]

        def _negotiate_keys_wrapper(self, m):
            if self.local_kex_init is None:  # Remote side sent KEXINIT
                # Simulate in-transit MSG_CHANNEL_WINDOW_ADJUST by sending it
                # before responding to the incoming MSG_KEXINIT.
                m2 = Message()
                m2.add_byte(cMSG_CHANNEL_WINDOW_ADJUST)
                m2.add_int(chan.remote_chanid)
                m2.add_int(1)  # bytes to add
                self._send_message(m2)
            return _negotiate_keys(self, m)

        self.tc._handler_table[MSG_KEXINIT] = _negotiate_keys_wrapper

        # Parameters for the test
        iterations = 500  # The deadlock does not happen every time, but it
        # should after many iterations.
        timeout = 5

        # This event is set when the test is completed
        done_event = threading.Event()

        # Start the sending thread
        st = SendThread(schan, iterations, done_event)
        st.start()

        # Start the receiving thread
        rt = ReceiveThread(chan, done_event)
        rt.start()

        # Act as a watchdog timer, checking
        deadlocked = False
        while not deadlocked and not done_event.is_set():
            for event in (st.watchdog_event, rt.watchdog_event):
                event.wait(timeout)
                if done_event.is_set():
                    break
                if not event.is_set():
                    deadlocked = True
                    break
                event.clear()

        # Tell the threads to stop (if they haven't already stopped).  Note
        # that if one or more threads are deadlocked, they might hang around
        # forever (until the process exits).
        done_event.set()

        # Assertion: We must not have detected a timeout.
        self.assertFalse(deadlocked)

        # Close the channels
        schan.close()
        chan.close()

    def test_J_sanitze_packet_size(self):
        """
        verify that we conform to the rfc of packet and window sizes.
        """
        for val, correct in [(4095, MIN_PACKET_SIZE),
                             (None, DEFAULT_MAX_PACKET_SIZE),
                             (2**32, MAX_WINDOW_SIZE)]:
            self.assertEqual(self.tc._sanitize_packet_size(val), correct)

    def test_K_sanitze_window_size(self):
        """
        verify that we conform to the rfc of packet and window sizes.
        """
        for val, correct in [(32767, MIN_WINDOW_SIZE),
                             (None, DEFAULT_WINDOW_SIZE),
                             (2**32, MAX_WINDOW_SIZE)]:
            self.assertEqual(self.tc._sanitize_window_size(val), correct)

    def test_L_handshake_timeout(self):
        """
        verify that we can get a hanshake timeout.
        """
        host_key = RSAKey.from_private_key_file(test_path('test_rsa.key'))
        public_host_key = RSAKey(data=host_key.asbytes())
        self.ts.add_server_key(host_key)
        event = threading.Event()
        server = NullServer()
        self.assertTrue(not event.is_set())
        self.tc.handshake_timeout = 0.000000000001
        self.ts.start_server(event, server)
        self.assertRaises(EOFError,
                          self.tc.connect,
                          hostkey=public_host_key,
                          username='******',
                          password='******')
Beispiel #31
0
class Transporter(object):
    def __init__(self, \
                 timeout, \
                 remoteMachine, \
                 port, \
                 username, \
                 password, \
                 loggerName, \
                 pk, \
                 bufsize = 8192):
                 

        import logging
        self.logger = logging.getLogger(loggerName)
        
        self.timeout = timeout
        self.remoteMachine = remoteMachine
        self.port = port
        self.username = username
        self.password = password
        self.bufsize = bufsize
        self.pk = DSSKey.from_private_key_file(expanduser(pk))
        self.logger.info('Object succesfully created')
        self.logger.debug ('timeout = %s, remoteMachine = %s, port = %s, username = %s'%(self.timeout, self.remoteMachine, self.port, self.username))
        #util.log_to_file('paramiko.log')
        

    def Link(self,\
            sftp=None,\
            ssh=True):
        self.sock = socket()
        self.sock.settimeout(self.timeout)
        self.Errors = []
        self.protocol = []
        self.logger.info('Trying to start link using parameters [SSH=%s,SFTP=%s]'%(ssh,sftp))
        try:
            self.sock.connect((self.remoteMachine, self.port))

        except:
            self.Unlink()
            self.logger.error('Link: Could not open a socket [remoteMachine = %s, port = %s]' % (self.remoteMachine, self.port))
            

        self.transport = Transport(self.sock)

        try:
            if not self.password:
                self.transport.connect(username = self.username, pkey = self.pk)
                self.logger.info('Trying to connect using private key..')
            else:
                self.transport.connect(username = self.username, password = self.password)
                self.logger.info('Trying to connect using password..')

        except:
            if not self.password:
                self.logger.error('Private Key not installed and no password specified!')
                
            self.Unlink()
            self.logger.error('Could not connect using SFTP [remoteMachine = %s, Username = %s, port = %s]' %(self.remoteMachine, self.username, self.port))
            
            sftp=None

            
        if ssh:
            try:
                self.protocol.append(mySSHClient())
                self.ssh = self.protocol[-1]
                self.ssh.set_missing_host_key_policy(AutoAddPolicy())
                self.ssh.connect(self.remoteMachine, port = self.port, username = self.username, password = self.password)
                self.logger.info ('ssh connection created..')
            except:
                self.logger.error('Could not connect using SSH [remoteMachine = %s, Username = %s, port = %s]'%(self.remoteMachine, self.username, self.port))

        if sftp:
            try:
                if ssh == None:
                    self.logger.error ('SSH must be enabled in order to connect with SFTP')
                    
                
                self.protocol.append(SFTPClient.from_transport(self.transport))
                self.sftp = self.protocol[-1]
                self.client = self.sftp
                self.logger.info('sftp connection created..')
            except:
                self.logger.error ('Could not bring up SFTP connection')
                
                self.sftp=None
    
        return ssh, sftp
    
    def RemoteCommand (self, command, check_exit=True, OSD=None):
        try:
            if not self.ssh:
                raise Exception, 'SSH must be enabled on remote machine in order to run commands.'
            remoteHost = self.ssh
            if not command is 'close_connection':
                self.command = command
                stdin, self.output, stderr = remoteHost.exec_command(self.command, timeout=40)
                output_lines = self.output.readlines()
                fprint=''.join(output_lines)
                if OSD:
                    print fprint #On Screen Display formatted output
                self.logger.debug('output of remote command `%s` on [%s]: %s' %(self.command,\
                        self.remoteMachine,\
                        fprint))
                if check_exit:
                    errorList = stderr.readlines()
                    if len(errorList) !=0:
                        self.logger.error(errorList)
                        raise Exception, 'Failed to execute command %s on [%s]' %(self.command, \
                                self.remoteMachine)
                    else:
                        self.logger.info('Command `%s` on [%s] completed successfuly'%(self.command,\
                                self.remoteMachine))

            else:
                try:
                    self.logger.info ('Trying to close connections..')
                    self.Unlink()
                    self.logger.info ('Connections closed succesfully..')
                except:
                    self.logger.error('Could not close connections! ' )
                    
            return output_lines

        except:
             raise Exception, 'Could not complete the command %s'%(self.command)
             #raise
        
            


    def CopyToRemote(self, \
            localFolder, \
            remoteFolder, \
            fileName, \
            copyProtocol='scp', \
            scpCommand='scp -o ConnectTimeout=30 -p -P', \
            response = True):
        '''
        Gets: localFolder, remoteFolder, fileName
        Returns: Response.
        '''
        localFilePath = pJoin(localFolder, fileName)
        remoteFilePath = pJoin(remoteFolder, fileName)
        if copyProtocol == 'sftp':
            try:
                self.sftp.put(localFilePath, remoteFilePath)
                self.logger.info ('Copied file %s to %s:%s'%(localFilePath, self.remoteMachine, remoteFilePath))
        
            except AttributeError:
                self.logger.error('SFTP connection is not open')
                
                response = False
            except:
                raise Exception, 'Could not connect using SFTP'
                
               
            return response
        
        elif copyProtocol == 'scp':
            try:
                scpCopy=getstatusoutput('%s %s %s %s@%s:%s '%(self.scpCommand, self.port, localFilePath, self.username, \
                        self.remoteMachine, remoteFilePath))
                if scpCopy[0] != 0:
                    self.logger.error (scpCopy[1])
                    self.logger.error('Error %s: %s'%(scpCopy[0],self.Errors))
                    response = False
                else:
                    self.logger.info('Copied file from "%s" to "%s:%s" successfuly' % (localFilePath, \
                            self.remoteMachine, remoteFilePath))
            except:
                self.logger.error('Could not transfer file %s to [%s] using SCP'%(remoteFilePath,self.remoteMachine))
                
                response = False

        else:
            raise Exception, 'Unknown copy protocol "%s", scp and sftp support only'%copyProtocol
            response = False
        return response
            
  
    def RenameLocalFile (self, localFolder, OrigFileName, NewFileName):
        
        self.logger.info ('Renaming %s to %s'%(OrigFileName, NewFileName))
        localFilePath = pJoin(localFolder, OrigFileName)
        renamedFilePath = pJoin(localFolder, NewFileName)
        try:
            rename (localFilePath, renamedFilePath) 
        except:
            raise Exception, 'Could not rename file %s to %s'%(localFilePath, renamedFilePath)
             


    def Unlink(self):
        try:
            self.ssh.close()
        except:
            self.logger.error('No SSH client to close...')
        try:
            self.sftp.close()
        except:
            self.logger.error('No SFTP client to close...')
        try:
            self.transport.close()
        except:
            self.logger.error('No transport to close...')
        try:
            self.sock.close()
        except:
            self.logger('No socket to close...')

    def dotTmp(self, \
               localFileFolder, \
               localFileName, \
               remoteFileFolder, \
               remoteFileName, \
               index, \
               runType = 'put'):
        '''
        Gets: localFileFolder, localFileName,
              remoteFileFolder, remoteFileName,
              index, runType.
 
        Returns: True
        '''

        self.Errors = []
        response = True
        localFilePath = pJoin(localFileFolder, localFileName)
        remoteTempFilePath = pJoin(remoteFileFolder, '%s.%s.tmp' % (remoteFileName, index))
        remoteFilePath = pJoin(remoteFileFolder, '%s.%s' % (remoteFileName, index))

        try:
            if runType == 'put':
                self.client.put(localFilePath, remoteTempFilePath)
            elif runType == 'open':
                self._WriteLocalDataToRemoteFile(localFilePath, remoteTempFilePath)
        except:
            self.logger.error('Failed creating "%s" on the remote server "%s"' % (remoteFilePath, self.remoteMachine))
            response = False

        try:
            self.client.remove(remoteFilePath)
        except:
            pass

        try:
            self.client.rename(remoteTempFilePath, remoteFilePath)
        except:
            self.logger.error('Failed moving "%s" to "%s" on the remote server "%s"' % (remoteTempFilePath, remoteFilePath, self.remoteMachine))
            response = False

        if len(self.Errors) != 0:
            self.logger.error(self.Errors)
        return response


    def MD5Compare (self,
                    MD5File,
                    localFolder,
                    DPIFileType,
                    DateTimeFormat='%Y%m%d%H%M%S',
                    Collect=True,
                    Rename=True,
                    PRX_MD5Command = 'list-files',
                    copyProtocol='scp'):
        
#         '''
#         Gets: a file name made from  pickle.
#               a local folder where to files should be saved.
#         Returns: a list of changed files.
#         '''
        CurrentTimeDate=datetime.now().strftime(DateTimeFormat)
        listedFiles = self.GetMD5FromPrx(rqstType = DPIFileType, md5cmd = PRX_MD5Command)
        CurrentMD5Dict = {self.remoteMachine : listedFiles}
        
        if not path.exists(MD5File): # MD5File does not exist
            LastSavedDict = {}
        else:
            LastSavedDict = self._readMD5fromFile(MD5File)
            
        if LastSavedDict.get(self.remoteMachine, 0) == 0: # Machine not found in MD5File (First time accessing)
            LocalSavedDict = {}
            for ftype in DPIFileType:
                LocalSavedDict[ftype] = {}
        else:
            LocalSavedDict = LastSavedDict[self.remoteMachine]
            
        DPIMD5Dict = CurrentMD5Dict[self.remoteMachine]
        self.logger.debug ('Local Saved Files before copy = %s'%LocalSavedDict)
        
        if LocalSavedDict == DPIMD5Dict: ## If there was not change in files. 
            self.logger.info('All files are up to date. No files copied')
        else:
            changedFiles = []
            for ftype in DPIFileType:
                for fileName, md5 in DPIMD5Dict.get(ftype, {}).iteritems():
                    if md5 != LocalSavedDict.get(ftype, {}).get(fileName, ''):
                    #if LocalSavedDict.get(ftype, {}).get(md5, None):
                        if Collect:
                            self.Collector(localFolder=localFolder, remoteFolder=ftype, copyProtocol=copyProtocol,collectedFileName=fileName,collectedSuffix='',\
                                                       getLatestOnly = False, removeRemoteFiles = False)
                        if Rename:
                            (name, ext) = path.splitext(fileName)
                            self.RenameLocalFile(OrigFileName = fileName, NewFileName = name+'.'+self.remoteMachine+'.'+CurrentTimeDate+ext+'.report', \
                                                localFolder=localFolder)
                        if ftype not in LocalSavedDict: LocalSavedDict[ftype] = {}
                        LocalSavedDict[ftype][fileName] = md5
                        changedFiles.append(fileName)
            
            LastSavedDict[self.remoteMachine] = LocalSavedDict
            self.logger.debug('Local Saved Files after copy = %s'%LocalSavedDict)
            self._writeMD5toFile(MD5File,LastSavedDict)
            
    def CreatePrxStat(self,
                      remoteMachine,
                      localFolder,
                      DPI_Statistics,
                      filename,
                      Prefix,
                      Suffix,
                      cmdTimeout,
                      DateTimeFormat='%Y%m%d%H%M%S'):
        
        
        ''' Create statistic file from command (list-protocols --statistics) '''
        CurrentTimeDate=datetime.now().strftime(DateTimeFormat)
        command = self.RemoteCommand(DPI_Statistics, cmdTimeout)
        timestamp = int(time.time())
        
        try:
            f = '%s-%s.%s.%s%s' % (Prefix, filename, remoteMachine, CurrentTimeDate, Suffix)
            statfile = open(localFolder + f, 'w')
            #statfile.write('timestamp: ' + str(timestamp) + os.linesep)
            #statfile.write('system-id: ' + remoteMachine + os.linesep)
            statfile.write('timestamp: ' + str(timestamp) + '\n')
            statfile.write('system-id: ' + remoteMachine + '\n')
            for linestat in command:
                statfile.write(linestat)
            statfile.close()
        except:
            self.logger.error('Failed to Create %s file' % f)
            raise


    def dotDone(self, \
                localFileFolder, \
                localFileName, \
                remoteFileFolder, \
                remoteFileName, \
                doneFileFolder, \
                doneFileName, \
                doneFileSuffix, \
                index, \
                runType = 'put'):
        '''
        Gets: localFileFolder, localFileName,
              remoteFileFolder, remoteFileName,
              doneFileFolder, doneFileName,
              doneFileSuffix, index,
              runType.

        Returns: True
        '''

        self.Errors = []
        response = True
        localFilePath = pJoin(localFileFolder, localFileName)
        doneFilePath = pJoin(doneFileFolder, '%s.%s.%s' % (doneFileName, doneFileSuffix, index))
        remoteFilePath = pJoin(remoteFileFolder, '%s.%s' % (remoteFileName, index))
        remoteDoneFilePath = pJoin(doneFileFolder, '%s.delta.%s' % (remoteFileName, index))

        try:
            if runType == 'put':
                self.client.put(localFilePath, remoteFilePath)
                self.client.put(localFilePath, remoteDoneFilePath)
            elif runType == 'open':
                self._WriteLocalDataToRemoteFile(localFilePath, remoteFilePath)
                self._WriteLocalDataToRemoteFile(localFilePath, remoteDoneFilePath)
        except:
            self.logger.error('Failed creating "%s" on the remote server "%s"' % (remoteFilePath, self.remoteMachine))
            response = False

        try:
            self.client.open(doneFilePath, 'w').close()
        except:
            self.logger.error('Failed creating done file "%s" on the remote server "%s"' % (doneFilePath, self.remoteMachine))
            response = False

        if len(self.Errors) != 0:
            self.logger.error(self.Errors)

        return response

    
    def Collector(self, \
                  localFolder, \
                  remoteFolder, \
                  copyProtocol = 'sftp', \
                  collectedFileName = '', \
                  collectedSuffix = '', \
                  getLatestOnly = True, \
                  removeRemoteFiles = True):
        '''
        Gets: localFolder, remoteFolder,
              collectedFileName, collectedSuffix,
              getLatestOnly, removeRemoteFiles.
        Returns: True
        '''

        self.Errors = []
        response = True
        CollectedFiles = []
        RemoteFilesDict = {}
        if copyProtocol == 'sftp':
            if collectedFileName != '' and collectedSuffix == '':
                CollectedFiles.append(collectedFileName)
                remoteFilePath = pJoin(remoteFolder, collectedFileName)
                try:
                    RemoteFilesDict[0] = self.client.stat(remoteFilePath)
                    self.logger.debug ('Collected file name: %s'%(collectedFileName))
                except:
                    self.logger.error ('Could not get file stat for %s'%(collectedFileName))
                    

            elif collectedSuffix != '' and collectedFileName == '':
                RemoteFiles = self.client.listdir(remoteFolder)
                self.logger.debug ('Files in remote dir: %s'%(RemoteFiles))
                try:
                    suffix = search('(.*)(\.)(.*)', collectedSuffix).group(3)
                    self.logger.debug ('Filtered Suffix: %s'%(suffix))
                except:
                    self.logger.error('Invalid files suffix given: %s' % collectedSuffix)
                    
                    response = False

                for remoteFile in RemoteFiles:
                    try:
                        search('\.%s$' % suffix, remoteFile).group()
                        CollectedFiles.append(remoteFile)
                        remoteFilePath = pJoin(remoteFolder, remoteFile)
                        RemoteFilesDict[remoteFile] = self.client.stat(remoteFilePath)
                    except:
                        pass
                    #if remoteFile.endswith(collectedSuffix):
                    #    CollectedFiles.append(remoteFile)
                    #    remoteFilePath = pJoin(remoteFolder, remoteFile)
                    #    RemoteFilesDict[remoteFile] = self.client.stat(remoteFilePath)
                self.logger.debug ('Remote Files Dic: %s'%RemoteFilesDict)
            else:
                raise Exception, 'No remote file name or suffix specified'
                response = False
        
            if getLatestOnly == True and len(RemoteFilesDict) != 0:
                latestRemoteFile = self._GetLatestFile(RemoteFilesDict)
                self._GetRemoteFile(localFolder, remoteFolder, latestRemoteFile, copyProtocol)
                if removeRemoteFiles == True:
                    self._RemoveRemoteFile(remoteFolder, latestRemoteFile)
            elif getLatestOnly == False and len(RemoteFilesDict) != 0:
                for collectedFile in CollectedFiles:
                    try:
                        self._GetRemoteFile(localFolder, remoteFolder, collectedFile, copyProtocol=copyProtocol)
                        
                    except:
                        self.logger.error('Failed getting "%s" from remote host "%s" to local folder "%s"' \
                                       % (pJoin(remoteFolder, collectedFile), self.remoteMachine, localFolder))
                        
                        response = False
                    if removeRemoteFiles == True:
                        self._RemoveRemoteFile(remoteFolder, collectedFile)
            else:
                response = False
                self.logger.debug ('%s'%(len(RemoteFilesDict)))
            return response

        elif copyProtocol == 'scp':
            if getLatestOnly == True:
                self.logger.error ('Get latest only is not supported when using scp')
                getLatestOnly == False
            if removeRemoteFiles == True:
                self.logger.error ('Remote file removal is not supported when using scp')
                removeRemoteFiles == False
            try:
                self._GetRemoteFile(localFolder, remoteFolder, collectedFileName, copyProtocol=copyProtocol)
            except:
                response = False
                raise Exception, ('Could not get file %s from %s to %s'%(collectedFileName, remoteFolder, localFolder))
                
            return response
                
    
    def _writeMD5toFile(self, MD5File, dictionary={}):
        ## Write MD5 dictionary to file
        try:
            MD5ToSave = open (MD5File, 'wb')
            pickle.dump(dictionary, MD5ToSave)
            MD5ToSave.close()
            return MD5ToSave
        except:
            self.logger.error ('could not write MD5 file:\n%s:%s'%(sys.exc_info()[0],sys.exc_info()[1]))
    
    def _readMD5fromFile (self, MD5File):
        ## Read last saved MD5 dictionary from file. 
        LastSavedFile = open (MD5File,'rb')
        SavedMD5Dict = pickle.load(LastSavedFile)
        LastSavedFile.close()
        return SavedMD5Dict
    
                    
    def _WriteLocalDataToRemoteFile(self, localFilePath, remoteFilePath):
        '''
        Gets: localFilePath, remoteFilePath.
        Returns: N/A
        '''

        fh = open(localFilePath, 'r')
        Lines = fh.readlines()
        fh.close()

        rfh = self.client.open(filename = remoteFilePath, mode = 'w', bufsize = self.bufsize)
        for line in Lines:
            rfh.write(line)
        rfh.close()

    def _GetRemoteFile(self, localFolder, remoteFolder, collectedFileName, copyProtocol):
        '''
        Gets: localFolder, remoteFolder, collectedFileName.
        Returns: N/A
        '''
        remoteFilePath = pJoin(remoteFolder, collectedFileName)
        localFilePath = pJoin(localFolder, collectedFileName)
        if copyProtocol == 'sftp':
            try:
                self.client.get(remoteFilePath, localFilePath)
                self.logger.info('Copied file from "%s:%s" to "%s" successfuly' % (self.remoteMachine, remoteFilePath,\
                        localFilePath))
            except:
                self.logger.error('Could not get file %s from [%s] using SFTP'%(remoteFilePath,self.remoteMachine))
                
        
        elif copyProtocol == 'scp':
            scpCopy=getstatusoutput('scp -o ConnectTimeout=5 -p -P %s %s@%s:%s %s'%(self.port, self.username, self.remoteMachine, \
                    remoteFilePath, localFilePath))
            if scpCopy[0] != 0:
                self.logger.error (scpCopy[1])
                self.logger.error('Could not get file %s from [%s] using SCP'%(remoteFilePath,self.remoteMachine))
                self.logger.error(self.Errors)
                print ('%s'%self.Errors[0])

            else:
                self.logger.info('Copied file from "%s:%s" to "%s" successfuly' % (self.remoteMachine, \
                        remoteFilePath, localFilePath))
        else:
            self.logger.error('Unknown copy protocol %s, scp and sftp support only'%copyProtocol)


    def GetMD5FromPrx (self, rqstType, md5cmd='list-files'):
        try:
            fileType = {}
            for r in rqstType:
                fileType[r] = {}
            command = self.RemoteCommand(md5cmd)              
            found = False
            ignoreFileType = True
            for line in command:
                lineList = line.split()
                for fType in fileType: #.keys():
                    if fType == line[1:].strip()[:-1]:
                        if fType not in rqstType:
                            ignoreFileType = True
                        else:
                            ignoreFileType = False
                        type = fType
                        found = True
                        break
                    else:
                        found = False
                if found: continue
                if lineList and not ignoreFileType:
                    try:
                        #fileType[type].update({lineList[-2] : lineList[-1]}) ## {md5:file}
                        fileType[type].update({lineList[-1] : lineList[-2]})  ## {file:md5}
                    except IndexError:
                        ignoreFileType = True
            self.logger.debug ('File Dictionary on PRX %s'%fileType) 
            return fileType
        except:
            self.logger.error ('Could not get md5cmd from PRX: %s:%s'%(sys.exc_info()[0],sys.exc_info()[1]))

        
    def _GetLatestFile(self, SftpClientFilesDict):
        '''
        Gets: SftpClientFilesDict.
        Returns: latestFileName.
        '''
        latest = 0
        for sftpClientFile in SftpClientFilesDict.iterkeys():
            if SftpClientFilesDict[sftpClientFile].st_mtime > latest:
                latestFileName = sftpClientFile
                latest = SftpClientFilesDict[sftpClientFile].st_mtime
        return latestFileName


    def _RemoveRemoteFile(self, remoteFileFolder, remoteFile):
        '''
        Gets: remoteFileFolder, remoteFile.
        Returns: N/A.
        '''
        remoteFilePath = pJoin(remoteFileFolder, remoteFile)
        try:
            self.client.remove(remoteFilePath)
            self.logger.info('Removing remote file "%s"' % remoteFilePath)
        except:
            raise Exception, 'Failed removing remote file "%s"...' % remoteFilePath
Beispiel #32
0
class TransportTest(unittest.TestCase):
    def setUp(self):
        self.socks = LoopSocket()
        self.sockc = LoopSocket()
        self.sockc.link(self.socks)
        self.tc = Transport(self.sockc)
        self.ts = Transport(self.socks)

    def tearDown(self):
        self.tc.close()
        self.ts.close()
        self.socks.close()
        self.sockc.close()

    def setup_test_server(
        self, client_options=None, server_options=None, connect_kwargs=None,
    ):
        host_key = RSAKey.from_private_key_file(_support('test_rsa.key'))
        public_host_key = RSAKey(data=host_key.asbytes())
        self.ts.add_server_key(host_key)

        if client_options is not None:
            client_options(self.tc.get_security_options())
        if server_options is not None:
            server_options(self.ts.get_security_options())

        event = threading.Event()
        self.server = NullServer()
        self.assertTrue(not event.is_set())
        self.ts.start_server(event, self.server)
        if connect_kwargs is None:
            connect_kwargs = dict(
                hostkey=public_host_key,
                username='******',
                password='******',
            )
        self.tc.connect(**connect_kwargs)
        event.wait(1.0)
        self.assertTrue(event.is_set())
        self.assertTrue(self.ts.is_active())

    def test_1_security_options(self):
        o = self.tc.get_security_options()
        self.assertEqual(type(o), SecurityOptions)
        self.assertTrue(('aes256-cbc', 'blowfish-cbc') != o.ciphers)
        o.ciphers = ('aes256-cbc', 'blowfish-cbc')
        self.assertEqual(('aes256-cbc', 'blowfish-cbc'), o.ciphers)
        try:
            o.ciphers = ('aes256-cbc', 'made-up-cipher')
            self.assertTrue(False)
        except ValueError:
            pass
        try:
            o.ciphers = 23
            self.assertTrue(False)
        except TypeError:
            pass

    def test_1b_security_options_reset(self):
        o = self.tc.get_security_options()
        # should not throw any exceptions
        o.ciphers = o.ciphers
        o.digests = o.digests
        o.key_types = o.key_types
        o.kex = o.kex
        o.compression = o.compression

    def test_2_compute_key(self):
        self.tc.K = 123281095979686581523377256114209720774539068973101330872763622971399429481072519713536292772709507296759612401802191955568143056534122385270077606457721553469730659233569339356140085284052436697480759510519672848743794433460113118986816826624865291116513647975790797391795651716378444844877749505443714557929
        self.tc.H = b'\x0C\x83\x07\xCD\xE6\x85\x6F\xF3\x0B\xA9\x36\x84\xEB\x0F\x04\xC2\x52\x0E\x9E\xD3'
        self.tc.session_id = self.tc.H
        key = self.tc._compute_key('C', 32)
        self.assertEqual(b'207E66594CA87C44ECCBA3B3CD39FDDB378E6FDB0F97C54B2AA0CFBF900CD995',
                          hexlify(key).upper())

    def test_3_simple(self):
        """
        verify that we can establish an ssh link with ourselves across the
        loopback sockets.  this is hardly "simple" but it's simpler than the
        later tests. :)
        """
        host_key = RSAKey.from_private_key_file(_support('test_rsa.key'))
        public_host_key = RSAKey(data=host_key.asbytes())
        self.ts.add_server_key(host_key)
        event = threading.Event()
        server = NullServer()
        self.assertTrue(not event.is_set())
        self.assertEqual(None, self.tc.get_username())
        self.assertEqual(None, self.ts.get_username())
        self.assertEqual(False, self.tc.is_authenticated())
        self.assertEqual(False, self.ts.is_authenticated())
        self.ts.start_server(event, server)
        self.tc.connect(hostkey=public_host_key,
                        username='******', password='******')
        event.wait(1.0)
        self.assertTrue(event.is_set())
        self.assertTrue(self.ts.is_active())
        self.assertEqual('slowdive', self.tc.get_username())
        self.assertEqual('slowdive', self.ts.get_username())
        self.assertEqual(True, self.tc.is_authenticated())
        self.assertEqual(True, self.ts.is_authenticated())

    def test_3a_long_banner(self):
        """
        verify that a long banner doesn't mess up the handshake.
        """
        host_key = RSAKey.from_private_key_file(_support('test_rsa.key'))
        public_host_key = RSAKey(data=host_key.asbytes())
        self.ts.add_server_key(host_key)
        event = threading.Event()
        server = NullServer()
        self.assertTrue(not event.is_set())
        self.socks.send(LONG_BANNER)
        self.ts.start_server(event, server)
        self.tc.connect(hostkey=public_host_key,
                        username='******', password='******')
        event.wait(1.0)
        self.assertTrue(event.is_set())
        self.assertTrue(self.ts.is_active())

    def test_4_special(self):
        """
        verify that the client can demand odd handshake settings, and can
        renegotiate keys in mid-stream.
        """
        def force_algorithms(options):
            options.ciphers = ('aes256-cbc',)
            options.digests = ('hmac-md5-96',)
        self.setup_test_server(client_options=force_algorithms)
        self.assertEqual('aes256-cbc', self.tc.local_cipher)
        self.assertEqual('aes256-cbc', self.tc.remote_cipher)
        self.assertEqual(12, self.tc.packetizer.get_mac_size_out())
        self.assertEqual(12, self.tc.packetizer.get_mac_size_in())

        self.tc.send_ignore(1024)
        self.tc.renegotiate_keys()
        self.ts.send_ignore(1024)

    @slow
    def test_5_keepalive(self):
        """
        verify that the keepalive will be sent.
        """
        self.setup_test_server()
        self.assertEqual(None, getattr(self.server, '_global_request', None))
        self.tc.set_keepalive(1)
        time.sleep(2)
        self.assertEqual('*****@*****.**', self.server._global_request)

    def test_6_exec_command(self):
        """
        verify that exec_command() does something reasonable.
        """
        self.setup_test_server()

        chan = self.tc.open_session()
        schan = self.ts.accept(1.0)
        try:
            chan.exec_command(b'command contains \xfc and is not a valid UTF-8 string')
            self.assertTrue(False)
        except SSHException:
            pass

        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)
        schan.send('Hello there.\n')
        schan.send_stderr('This is on stderr.\n')
        schan.close()

        f = chan.makefile()
        self.assertEqual('Hello there.\n', f.readline())
        self.assertEqual('', f.readline())
        f = chan.makefile_stderr()
        self.assertEqual('This is on stderr.\n', f.readline())
        self.assertEqual('', f.readline())

        # now try it with combined stdout/stderr
        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)
        schan.send('Hello there.\n')
        schan.send_stderr('This is on stderr.\n')
        schan.close()

        chan.set_combine_stderr(True)
        f = chan.makefile()
        self.assertEqual('Hello there.\n', f.readline())
        self.assertEqual('This is on stderr.\n', f.readline())
        self.assertEqual('', f.readline())
        
    def test_6a_channel_can_be_used_as_context_manager(self):
        """
        verify that exec_command() does something reasonable.
        """
        self.setup_test_server()

        with self.tc.open_session() as chan:
            with self.ts.accept(1.0) as schan:
                chan.exec_command('yes')
                schan.send('Hello there.\n')
                schan.close()

                f = chan.makefile()
                self.assertEqual('Hello there.\n', f.readline())
                self.assertEqual('', f.readline())

    def test_7_invoke_shell(self):
        """
        verify that invoke_shell() does something reasonable.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.invoke_shell()
        schan = self.ts.accept(1.0)
        chan.send('communist j. cat\n')
        f = schan.makefile()
        self.assertEqual('communist j. cat\n', f.readline())
        chan.close()
        self.assertEqual('', f.readline())

    def test_8_channel_exception(self):
        """
        verify that ChannelException is thrown for a bad open-channel request.
        """
        self.setup_test_server()
        try:
            chan = self.tc.open_channel('bogus')
            self.fail('expected exception')
        except ChannelException as e:
            self.assertTrue(e.code == OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED)

    def test_9_exit_status(self):
        """
        verify that get_exit_status() works.
        """
        self.setup_test_server()

        chan = self.tc.open_session()
        schan = self.ts.accept(1.0)
        chan.exec_command('yes')
        schan.send('Hello there.\n')
        self.assertTrue(not chan.exit_status_ready())
        # trigger an EOF
        schan.shutdown_read()
        schan.shutdown_write()
        schan.send_exit_status(23)
        schan.close()

        f = chan.makefile()
        self.assertEqual('Hello there.\n', f.readline())
        self.assertEqual('', f.readline())
        count = 0
        while not chan.exit_status_ready():
            time.sleep(0.1)
            count += 1
            if count > 50:
                raise Exception("timeout")
        self.assertEqual(23, chan.recv_exit_status())
        chan.close()

    def test_A_select(self):
        """
        verify that select() on a channel works.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.invoke_shell()
        schan = self.ts.accept(1.0)

        # nothing should be ready
        r, w, e = select.select([chan], [], [], 0.1)
        self.assertEqual([], r)
        self.assertEqual([], w)
        self.assertEqual([], e)

        schan.send('hello\n')

        # something should be ready now (give it 1 second to appear)
        for i in range(10):
            r, w, e = select.select([chan], [], [], 0.1)
            if chan in r:
                break
            time.sleep(0.1)
        self.assertEqual([chan], r)
        self.assertEqual([], w)
        self.assertEqual([], e)

        self.assertEqual(b'hello\n', chan.recv(6))

        # and, should be dead again now
        r, w, e = select.select([chan], [], [], 0.1)
        self.assertEqual([], r)
        self.assertEqual([], w)
        self.assertEqual([], e)

        schan.close()

        # detect eof?
        for i in range(10):
            r, w, e = select.select([chan], [], [], 0.1)
            if chan in r:
                break
            time.sleep(0.1)
        self.assertEqual([chan], r)
        self.assertEqual([], w)
        self.assertEqual([], e)
        self.assertEqual(bytes(), chan.recv(16))

        # make sure the pipe is still open for now...
        p = chan._pipe
        self.assertEqual(False, p._closed)
        chan.close()
        # ...and now is closed.
        self.assertEqual(True, p._closed)

    def test_B_renegotiate(self):
        """
        verify that a transport can correctly renegotiate mid-stream.
        """
        self.setup_test_server()
        self.tc.packetizer.REKEY_BYTES = 16384
        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)

        self.assertEqual(self.tc.H, self.tc.session_id)
        for i in range(20):
            chan.send('x' * 1024)
        chan.close()

        # allow a few seconds for the rekeying to complete
        for i in range(50):
            if self.tc.H != self.tc.session_id:
                break
            time.sleep(0.1)
        self.assertNotEqual(self.tc.H, self.tc.session_id)

        schan.close()

    def test_C_compression(self):
        """
        verify that zlib compression is basically working.
        """
        def force_compression(o):
            o.compression = ('zlib',)
        self.setup_test_server(force_compression, force_compression)
        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)

        bytes = self.tc.packetizer._Packetizer__sent_bytes
        chan.send('x' * 1024)
        bytes2 = self.tc.packetizer._Packetizer__sent_bytes
        block_size = self.tc._cipher_info[self.tc.local_cipher]['block-size']
        mac_size = self.tc._mac_info[self.tc.local_mac]['size']
        # tests show this is actually compressed to *52 bytes*!  including packet overhead!  nice!! :)
        self.assertTrue(bytes2 - bytes < 1024)
        self.assertEqual(16 + block_size + mac_size, bytes2 - bytes)

        chan.close()
        schan.close()

    def test_D_x11(self):
        """
        verify that an x11 port can be requested and opened.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)

        requested = []
        def handler(c, addr_port):
            addr, port = addr_port
            requested.append((addr, port))
            self.tc._queue_incoming_channel(c)

        self.assertEqual(None, getattr(self.server, '_x11_screen_number', None))
        cookie = chan.request_x11(0, single_connection=True, handler=handler)
        self.assertEqual(0, self.server._x11_screen_number)
        self.assertEqual('MIT-MAGIC-COOKIE-1', self.server._x11_auth_protocol)
        self.assertEqual(cookie, self.server._x11_auth_cookie)
        self.assertEqual(True, self.server._x11_single_connection)

        x11_server = self.ts.open_x11_channel(('localhost', 6093))
        x11_client = self.tc.accept()
        self.assertEqual('localhost', requested[0][0])
        self.assertEqual(6093, requested[0][1])

        x11_server.send('hello')
        self.assertEqual(b'hello', x11_client.recv(5))

        x11_server.close()
        x11_client.close()
        chan.close()
        schan.close()

    def test_E_reverse_port_forwarding(self):
        """
        verify that a client can ask the server to open a reverse port for
        forwarding.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)

        requested = []
        def handler(c, origin_addr_port, server_addr_port):
            requested.append(origin_addr_port)
            requested.append(server_addr_port)
            self.tc._queue_incoming_channel(c)

        port = self.tc.request_port_forward('127.0.0.1', 0, handler)
        self.assertEqual(port, self.server._listen.getsockname()[1])

        cs = socket.socket()
        cs.connect(('127.0.0.1', port))
        ss, _ = self.server._listen.accept()
        sch = self.ts.open_forwarded_tcpip_channel(ss.getsockname(), ss.getpeername())
        cch = self.tc.accept()

        sch.send('hello')
        self.assertEqual(b'hello', cch.recv(5))
        sch.close()
        cch.close()
        ss.close()
        cs.close()

        # now cancel it.
        self.tc.cancel_port_forward('127.0.0.1', port)
        self.assertTrue(self.server._listen is None)

    def test_F_port_forwarding(self):
        """
        verify that a client can forward new connections from a locally-
        forwarded port.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)

        # open a port on the "server" that the client will ask to forward to.
        greeting_server = socket.socket()
        greeting_server.bind(('127.0.0.1', 0))
        greeting_server.listen(1)
        greeting_port = greeting_server.getsockname()[1]

        cs = self.tc.open_channel('direct-tcpip', ('127.0.0.1', greeting_port), ('', 9000))
        sch = self.ts.accept(1.0)
        cch = socket.socket()
        cch.connect(self.server._tcpip_dest)

        ss, _ = greeting_server.accept()
        ss.send(b'Hello!\n')
        ss.close()
        sch.send(cch.recv(8192))
        sch.close()

        self.assertEqual(b'Hello!\n', cs.recv(7))
        cs.close()

    def test_G_stderr_select(self):
        """
        verify that select() on a channel works even if only stderr is
        receiving data.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.invoke_shell()
        schan = self.ts.accept(1.0)

        # nothing should be ready
        r, w, e = select.select([chan], [], [], 0.1)
        self.assertEqual([], r)
        self.assertEqual([], w)
        self.assertEqual([], e)

        schan.send_stderr('hello\n')

        # something should be ready now (give it 1 second to appear)
        for i in range(10):
            r, w, e = select.select([chan], [], [], 0.1)
            if chan in r:
                break
            time.sleep(0.1)
        self.assertEqual([chan], r)
        self.assertEqual([], w)
        self.assertEqual([], e)

        self.assertEqual(b'hello\n', chan.recv_stderr(6))

        # and, should be dead again now
        r, w, e = select.select([chan], [], [], 0.1)
        self.assertEqual([], r)
        self.assertEqual([], w)
        self.assertEqual([], e)

        schan.close()
        chan.close()

    def test_H_send_ready(self):
        """
        verify that send_ready() indicates when a send would not block.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.invoke_shell()
        schan = self.ts.accept(1.0)

        self.assertEqual(chan.send_ready(), True)
        total = 0
        K = '*' * 1024
        limit = 1+(64 * 2 ** 15)
        while total < limit:
            chan.send(K)
            total += len(K)
            if not chan.send_ready():
                break
        self.assertTrue(total < limit)

        schan.close()
        chan.close()
        self.assertEqual(chan.send_ready(), True)

    def test_I_rekey_deadlock(self):
        """
        Regression test for deadlock when in-transit messages are received after MSG_KEXINIT is sent

        Note: When this test fails, it may leak threads.
        """

        # Test for an obscure deadlocking bug that can occur if we receive
        # certain messages while initiating a key exchange.
        #
        # The deadlock occurs as follows:
        #
        # In the main thread:
        #   1. The user's program calls Channel.send(), which sends
        #      MSG_CHANNEL_DATA to the remote host.
        #   2. Packetizer discovers that REKEY_BYTES has been exceeded, and
        #      sets the __need_rekey flag.
        #
        # In the Transport thread:
        #   3. Packetizer notices that the __need_rekey flag is set, and raises
        #      NeedRekeyException.
        #   4. In response to NeedRekeyException, the transport thread sends
        #      MSG_KEXINIT to the remote host.
        #
        # On the remote host (using any SSH implementation):
        #   5. The MSG_CHANNEL_DATA is received, and MSG_CHANNEL_WINDOW_ADJUST is sent.
        #   6. The MSG_KEXINIT is received, and a corresponding MSG_KEXINIT is sent.
        #
        # In the main thread:
        #   7. The user's program calls Channel.send().
        #   8. Channel.send acquires Channel.lock, then calls Transport._send_user_message().
        #   9. Transport._send_user_message waits for Transport.clear_to_send
        #      to be set (i.e., it waits for re-keying to complete).
        #      Channel.lock is still held.
        #
        # In the Transport thread:
        #   10. MSG_CHANNEL_WINDOW_ADJUST is received; Channel._window_adjust
        #       is called to handle it.
        #   11. Channel._window_adjust tries to acquire Channel.lock, but it
        #       blocks because the lock is already held by the main thread.
        #
        # The result is that the Transport thread never processes the remote
        # host's MSG_KEXINIT packet, because it becomes deadlocked while
        # handling the preceding MSG_CHANNEL_WINDOW_ADJUST message.

        # We set up two separate threads for sending and receiving packets,
        # while the main thread acts as a watchdog timer.  If the timer
        # expires, a deadlock is assumed.

        class SendThread(threading.Thread):
            def __init__(self, chan, iterations, done_event):
                threading.Thread.__init__(self, None, None, self.__class__.__name__)
                self.setDaemon(True)
                self.chan = chan
                self.iterations = iterations
                self.done_event = done_event
                self.watchdog_event = threading.Event()
                self.last = None

            def run(self):
                try:
                    for i in range(1, 1+self.iterations):
                        if self.done_event.is_set():
                            break
                        self.watchdog_event.set()
                        #print i, "SEND"
                        self.chan.send("x" * 2048)
                finally:
                    self.done_event.set()
                    self.watchdog_event.set()

        class ReceiveThread(threading.Thread):
            def __init__(self, chan, done_event):
                threading.Thread.__init__(self, None, None, self.__class__.__name__)
                self.setDaemon(True)
                self.chan = chan
                self.done_event = done_event
                self.watchdog_event = threading.Event()

            def run(self):
                try:
                    while not self.done_event.is_set():
                        if self.chan.recv_ready():
                            chan.recv(65536)
                            self.watchdog_event.set()
                        else:
                            if random.randint(0, 1):
                                time.sleep(random.randint(0, 500) / 1000.0)
                finally:
                    self.done_event.set()
                    self.watchdog_event.set()

        self.setup_test_server()
        self.ts.packetizer.REKEY_BYTES = 2048

        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)

        # Monkey patch the client's Transport._handler_table so that the client
        # sends MSG_CHANNEL_WINDOW_ADJUST whenever it receives an initial
        # MSG_KEXINIT.  This is used to simulate the effect of network latency
        # on a real MSG_CHANNEL_WINDOW_ADJUST message.
        self.tc._handler_table = self.tc._handler_table.copy()  # copy per-class dictionary
        _negotiate_keys = self.tc._handler_table[MSG_KEXINIT]
        def _negotiate_keys_wrapper(self, m):
            if self.local_kex_init is None: # Remote side sent KEXINIT
                # Simulate in-transit MSG_CHANNEL_WINDOW_ADJUST by sending it
                # before responding to the incoming MSG_KEXINIT.
                m2 = Message()
                m2.add_byte(cMSG_CHANNEL_WINDOW_ADJUST)
                m2.add_int(chan.remote_chanid)
                m2.add_int(1)    # bytes to add
                self._send_message(m2)
            return _negotiate_keys(self, m)
        self.tc._handler_table[MSG_KEXINIT] = _negotiate_keys_wrapper

        # Parameters for the test
        iterations = 500    # The deadlock does not happen every time, but it
                            # should after many iterations.
        timeout = 5

        # This event is set when the test is completed
        done_event = threading.Event()

        # Start the sending thread
        st = SendThread(schan, iterations, done_event)
        st.start()

        # Start the receiving thread
        rt = ReceiveThread(chan, done_event)
        rt.start()

        # Act as a watchdog timer, checking
        deadlocked = False
        while not deadlocked and not done_event.is_set():
            for event in (st.watchdog_event, rt.watchdog_event):
                event.wait(timeout)
                if done_event.is_set():
                    break
                if not event.is_set():
                    deadlocked = True
                    break
                event.clear()

        # Tell the threads to stop (if they haven't already stopped).  Note
        # that if one or more threads are deadlocked, they might hang around
        # forever (until the process exits).
        done_event.set()

        # Assertion: We must not have detected a timeout.
        self.assertFalse(deadlocked)

        # Close the channels
        schan.close()
        chan.close()

    def test_J_sanitze_packet_size(self):
        """
        verify that we conform to the rfc of packet and window sizes.
        """
        for val, correct in [(4095, MIN_PACKET_SIZE),
                             (None, DEFAULT_MAX_PACKET_SIZE),
                             (2**32, MAX_WINDOW_SIZE)]:
            self.assertEqual(self.tc._sanitize_packet_size(val), correct)

    def test_K_sanitze_window_size(self):
        """
        verify that we conform to the rfc of packet and window sizes.
        """
        for val, correct in [(32767, MIN_WINDOW_SIZE),
                             (None, DEFAULT_WINDOW_SIZE),
                             (2**32, MAX_WINDOW_SIZE)]:
            self.assertEqual(self.tc._sanitize_window_size(val), correct)

    @slow
    def test_L_handshake_timeout(self):
        """
        verify that we can get a hanshake timeout.
        """
        # Tweak client Transport instance's Packetizer instance so
        # its read_message() sleeps a bit. This helps prevent race conditions
        # where the client Transport's timeout timer thread doesn't even have
        # time to get scheduled before the main client thread finishes
        # handshaking with the server.
        # (Doing this on the server's transport *sounds* more 'correct' but
        # actually doesn't work nearly as well for whatever reason.)
        class SlowPacketizer(Packetizer):
            def read_message(self):
                time.sleep(1)
                return super(SlowPacketizer, self).read_message()
        # NOTE: prettttty sure since the replaced .packetizer Packetizer is now
        # no longer doing anything with its copy of the socket...everything'll
        # be fine. Even tho it's a bit squicky.
        self.tc.packetizer = SlowPacketizer(self.tc.sock)
        # Continue with regular test red tape.
        host_key = RSAKey.from_private_key_file(_support('test_rsa.key'))
        public_host_key = RSAKey(data=host_key.asbytes())
        self.ts.add_server_key(host_key)
        event = threading.Event()
        server = NullServer()
        self.assertTrue(not event.is_set())
        self.tc.handshake_timeout = 0.000000000001
        self.ts.start_server(event, server)
        self.assertRaises(EOFError, self.tc.connect,
                          hostkey=public_host_key,
                          username='******',
                          password='******')

    def test_M_select_after_close(self):
        """
        verify that select works when a channel is already closed.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.invoke_shell()
        schan = self.ts.accept(1.0)
        schan.close()

        # give client a moment to receive close notification
        time.sleep(0.1)

        r, w, e = select.select([chan], [], [], 0.1)
        self.assertEqual([chan], r)
        self.assertEqual([], w)
        self.assertEqual([], e)

    def test_channel_send_misc(self):
        """
        verify behaviours sending various instances to a channel
        """
        self.setup_test_server()
        text = u"\xa7 slice me nicely"
        with self.tc.open_session() as chan:
            schan = self.ts.accept(1.0)
            if schan is None:
                self.fail("Test server transport failed to accept")
            sfile = schan.makefile()

            # TypeError raised on non string or buffer type
            self.assertRaises(TypeError, chan.send, object())
            self.assertRaises(TypeError, chan.sendall, object())

            # sendall() accepts a unicode instance
            chan.sendall(text)
            expected = text.encode("utf-8")
            self.assertEqual(sfile.read(len(expected)), expected)

    @needs_builtin('buffer')
    def test_channel_send_buffer(self):
        """
        verify sending buffer instances to a channel
        """
        self.setup_test_server()
        data = 3 * b'some test data\n whole'
        with self.tc.open_session() as chan:
            schan = self.ts.accept(1.0)
            if schan is None:
                self.fail("Test server transport failed to accept")
            sfile = schan.makefile()

            # send() accepts buffer instances
            sent = 0
            while sent < len(data):
                sent += chan.send(buffer(data, sent, 8))
            self.assertEqual(sfile.read(len(data)), data)

            # sendall() accepts a buffer instance
            chan.sendall(buffer(data))
            self.assertEqual(sfile.read(len(data)), data)

    @needs_builtin('memoryview')
    def test_channel_send_memoryview(self):
        """
        verify sending memoryview instances to a channel
        """
        self.setup_test_server()
        data = 3 * b'some test data\n whole'
        with self.tc.open_session() as chan:
            schan = self.ts.accept(1.0)
            if schan is None:
                self.fail("Test server transport failed to accept")
            sfile = schan.makefile()

            # send() accepts memoryview slices
            sent = 0
            view = memoryview(data)
            while sent < len(view):
                sent += chan.send(view[sent:sent+8])
            self.assertEqual(sfile.read(len(data)), data)

            # sendall() accepts a memoryview instance
            chan.sendall(memoryview(data))
            self.assertEqual(sfile.read(len(data)), data)

    def test_server_rejects_open_channel_without_auth(self):
        try:
            self.setup_test_server(connect_kwargs={})
            self.tc.open_session()
        except ChannelException as e:
            assert e.code == OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
        else:
            assert False, "Did not raise ChannelException!"

    def test_server_rejects_arbitrary_global_request_without_auth(self):
        self.setup_test_server(connect_kwargs={})
        # NOTE: this dummy global request kind would normally pass muster
        # from the test server.
        self.tc.global_request('acceptable')
        # Global requests never raise exceptions, even on failure (not sure why
        # this was the original design...ugh.) Best we can do to tell failure
        # happened is that the client transport's global_response was set back
        # to None; if it had succeeded, it would be the response Message.
        err = "Unauthed global response incorrectly succeeded!"
        assert self.tc.global_response is None, err

    def test_server_rejects_port_forward_without_auth(self):
        # NOTE: at protocol level port forward requests are treated same as a
        # regular global request, but Paramiko server implements a special-case
        # method for it, so it gets its own test. (plus, THAT actually raises
        # an exception on the client side, unlike the general case...)
        self.setup_test_server(connect_kwargs={})
        try:
            self.tc.request_port_forward('localhost', 1234)
        except SSHException as e:
            assert "forwarding request denied" in str(e)
        else:
            assert False, "Did not raise SSHException!"
Beispiel #33
0
class AuthTest (unittest.TestCase):

    def setUp(self):
        self.socks = LoopSocket()
        self.sockc = LoopSocket()
        self.sockc.link(self.socks)
        self.tc = Transport(self.sockc)
        self.ts = Transport(self.socks)

    def tearDown(self):
        self.tc.close()
        self.ts.close()
        self.socks.close()
        self.sockc.close()

    def start_server(self):
        host_key = RSAKey.from_private_key_file(test_path('test_rsa.key'))
        self.public_host_key = RSAKey(data=host_key.asbytes())
        self.ts.add_server_key(host_key)
        self.event = threading.Event()
        self.server = NullServer()
        self.assertTrue(not self.event.is_set())
        self.ts.start_server(self.event, self.server)

    def verify_finished(self):
        self.event.wait(1.0)
        self.assertTrue(self.event.is_set())
        self.assertTrue(self.ts.is_active())

    def test_1_bad_auth_type(self):
        """
        verify that we get the right exception when an unsupported auth
        type is requested.
        """
        self.start_server()
        try:
            self.tc.connect(hostkey=self.public_host_key,
                            username='******', password='******')
            self.assertTrue(False)
        except:
            etype, evalue, etb = sys.exc_info()
            self.assertEqual(BadAuthenticationType, etype)
            self.assertEqual(['publickey'], evalue.allowed_types)

    def test_2_bad_password(self):
        """
        verify that a bad password gets the right exception, and that a retry
        with the right password works.
        """
        self.start_server()
        self.tc.connect(hostkey=self.public_host_key)
        try:
            self.tc.auth_password(username='******', password='******')
            self.assertTrue(False)
        except:
            etype, evalue, etb = sys.exc_info()
            self.assertTrue(issubclass(etype, AuthenticationException))
        self.tc.auth_password(username='******', password='******')
        self.verify_finished()

    def test_3_multipart_auth(self):
        """
        verify that multipart auth works.
        """
        self.start_server()
        self.tc.connect(hostkey=self.public_host_key)
        remain = self.tc.auth_password(username='******', password='******')
        self.assertEqual(['publickey'], remain)
        key = DSSKey.from_private_key_file(test_path('test_dss.key'))
        remain = self.tc.auth_publickey(username='******', key=key)
        self.assertEqual([], remain)
        self.verify_finished()

    def test_4_interactive_auth(self):
        """
        verify keyboard-interactive auth works.
        """
        self.start_server()
        self.tc.connect(hostkey=self.public_host_key)

        def handler(title, instructions, prompts):
            self.got_title = title
            self.got_instructions = instructions
            self.got_prompts = prompts
            return ['cat']
        remain = self.tc.auth_interactive('commie', handler)
        self.assertEqual(self.got_title, 'password')
        self.assertEqual(self.got_prompts, [('Password', False)])
        self.assertEqual([], remain)
        self.verify_finished()

    def test_5_interactive_auth_fallback(self):
        """
        verify that a password auth attempt will fallback to "interactive"
        if password auth isn't supported but interactive is.
        """
        self.start_server()
        self.tc.connect(hostkey=self.public_host_key)
        remain = self.tc.auth_password('commie', 'cat')
        self.assertEqual([], remain)
        self.verify_finished()

    def test_6_auth_utf8(self):
        """
        verify that utf-8 encoding happens in authentication.
        """
        self.start_server()
        self.tc.connect(hostkey=self.public_host_key)
        remain = self.tc.auth_password('utf8', _pwd)
        self.assertEqual([], remain)
        self.verify_finished()

    def test_7_auth_non_utf8(self):
        """
        verify that non-utf-8 encoded passwords can be used for broken
        servers.
        """
        self.start_server()
        self.tc.connect(hostkey=self.public_host_key)
        remain = self.tc.auth_password('non-utf8', '\xff')
        self.assertEqual([], remain)
        self.verify_finished()

    def test_8_auth_gets_disconnected(self):
        """
        verify that we catch a server disconnecting during auth, and report
        it as an auth failure.
        """
        self.start_server()
        self.tc.connect(hostkey=self.public_host_key)
        try:
            remain = self.tc.auth_password('bad-server', 'hello')
        except:
            etype, evalue, etb = sys.exc_info()
            self.assertTrue(issubclass(etype, AuthenticationException))

    def test_9_auth_non_responsive(self):
        """
        verify that authentication times out if server takes to long to
        respond (or never responds).
        """
        self.tc.auth_timeout = 1  # 1 second, to speed up test
        self.start_server()
        self.tc.connect()
        try:
            remain = self.tc.auth_password('unresponsive-server', 'hello')
        except:
            etype, evalue, etb = sys.exc_info()
            self.assertTrue(issubclass(etype, AuthenticationException))
            self.assertTrue('Authentication timeout' in str(evalue))
Beispiel #34
0
class SSHHandler(ServerInterface, BaseRequestHandler):
    telnet_handler = None
    pty_handler = None
    host_key = None
    username = None

    def __init__(self, request, client_address, server):
        self.request = request
        self.client_address = client_address
        self.tcp_server = server

        # Keep track of channel information from the transport
        self.channels = {}

        try:
            self.client = request._sock
        except AttributeError as e:
            self.client = request
        # Transport turns the socket into an SSH transport
        self.transport = Transport(self.client)

        # Create the PTY handler class by mixing in
        TelnetHandlerClass = self.telnet_handler

        class MixedPtyHandler(TelnetToPtyHandler, TelnetHandlerClass):
            # BaseRequestHandler does not inherit from object, must call the __init__ directly
            def __init__(self, *args):
                super(MixedPtyHandler, self).__init__(*args)
                TelnetHandlerClass.__init__(self, *args)

        self.pty_handler = MixedPtyHandler

        # Call the base class to run the handler
        BaseRequestHandler.__init__(self, request, client_address, server)

    def setup(self):
        """Setup the connection."""
        log.debug('New request from address %s, port %d', self.client_address)

        try:
            self.transport.load_server_moduli()
        except:
            log.exception('(Failed to load moduli -- gex will be unsupported.)')
            raise
        try:
            self.transport.add_server_key(self.host_key)
        except:
            if self.host_key is None:
                log.critical('Host key not set!  SSHHandler MUST define the host_key parameter.')
                raise NotImplementedError('Host key not set!  SSHHandler instance must define '
                                          'the host_key parameter.  Try host_key = paramiko_ssh'
                                          '.getRsaKeyFile("server_rsa.key").')

        try:
            # Tell transport to use this object as a server
            log.debug('Starting SSH server-side negotiation')
            self.transport.start_server(server=self)
        except SSHException as e:
            log.warn('SSH negotiation failed. %s', e)
            raise

        # Accept any requested channels
        while True:
            channel = self.transport.accept(20)
            if channel is None:
                # check to see if any thread is running
                any_running = False
                for c, thread in self.channels.items():
                    if thread.is_alive():
                        any_running = True
                        break
                if not any_running:
                    break
            else:
                log.info('Accepted channel %s', channel)

    class dummy_request(object):
        def __init__(self):
            self._sock = None

    @classmethod
    def streamserver_handle(cls, socket, address):
        """Translate this class for use in a StreamServer"""
        request = cls.dummy_request()
        request._sock = socket
        server = None
        cls(request, address, server)

    def finish(self):
        """Called when the socket closes from the client."""
        self.transport.close()

    def check_channel_request(self, kind, chanid):
        if kind == 'session':
            return OPEN_SUCCEEDED
        return OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED

    def set_username(self, username):
        self.username = username
        log.info('User logged in: %s' % username)

    # Handle User Authentication ######

    # Override these with functions to use for callbacks
    authCallback = None
    authCallbackKey = None
    authCallbackUsername = None

    def get_allowed_auths(self, username):
        methods = []
        if self.authCallbackUsername is not None:
            methods.append('none')
        if self.authCallback is not None:
            methods.append('password')
        if self.authCallbackKey is not None:
            methods.append('publickey')

        if not methods:
            # If no methods were defined, use none
            methods.append('none')

        log.debug('Configured authentication methods: %r', methods)
        return ','.join(methods)

    def check_auth_password(self, username, password):
        # print 'check_auth_password(%s, %s)' % (username, password)
        try:
            self.authCallback(username, password)
        except:
            return AUTH_FAILED
        else:
            self.set_username(username)
            return AUTH_SUCCESSFUL

    def check_auth_publickey(self, username, key):
        # print 'Auth attempt with key: ' + hexlify(key.get_fingerprint())
        try:
            self.authCallbackKey(username, key)
        except:
            return AUTH_FAILED
        else:
            self.set_username(username)
            return AUTH_SUCCESSFUL
            # if (username == 'xx') and (key == self.good_pub_key):
            #    return AUTH_SUCCESSFUL

    def check_auth_none(self, username):
        if self.authCallbackUsername is None:
            self.set_username(username)
            return AUTH_SUCCESSFUL
        try:
            self.authCallbackUsername(username)
        except:
            return AUTH_FAILED
        else:
            self.set_username(username)
            return AUTH_SUCCESSFUL

    def check_channel_shell_request(self, channel):
        '''Request to start a shell on the given channel'''
        try:
            self.channels[channel].start()
        except KeyError:
            log.error('Requested to start a channel (%r) that was not previously set up.', channel)
            return False
        else:
            return True

    def check_channel_pty_request(self, channel, term, width, height, pixelwidth,
                                  pixelheight, modes):
        """Request to allocate a PTY terminal."""
        # self.sshterm = term
        # print "term: %r, modes: %r" % (term, modes)
        log.debug('PTY requested.  Setting up %r.', self.telnet_handler)
        pty_thread = Thread(target=self.start_pty_request, args=(channel, term, modes))
        self.channels[channel] = pty_thread

        return True

    def start_pty_request(self, channel, term, modes):
        """Start a PTY - intended to run it a (green)thread."""
        request = self.dummy_request()
        request._sock = channel
        request.modes = modes
        request.term = term
        request.username = self.username

        # modes = http://www.ietf.org/rfc/rfc4254.txt page 18
        # for i in xrange(50):
        #    print "%r: %r" % (int(m[i*5].encode('hex'), 16), int(''.join(m[i*5+1:i*5+5]).encode('hex'), 16))

        # This should block until the user quits the pty
        self.pty_handler(request, self.client_address, self.tcp_server)

        # Shutdown the entire session
        self.transport.close()
Beispiel #35
0
# -*- coding: utf-8 -*- 
__author__ = 'Administrator'


from paramiko import Transport,RSAKey,SFTPClient
import os

host="54.187.91.18"
port=22

private_key_file=os.path.expanduser("~/.ssh/id_rsa")
key=RSAKey.from_private_key_file(private_key_file)


t=Transport((host,port))
t.connect(username="******",pkey=key)

sftp=SFTPClient.from_transport(t)
try:
	sftp.put("/data/websites/test/a.php","/data/websites/")
except Exception,e:
	print(e)

sftp.close()
t.close()

Beispiel #36
0
def exec_async_task(app, server_id, user_id, login_name, password, secret_key):
    with app.app_context():
        tasks = ServerTask.query.filter_by(user_id=user_id).filter_by(server_id=server_id).\
                                 filter_by(status=Status.Wait).all()
        server = Server.query.get_or_404(int(server_id))
        t = Transport((server.ip,int(server.ssh_port)))
        try:
            t.connect(username=login_name, password=password + secret_key)
        except Exception:
            return False
        sftp = SFTPClient.from_transport(t)
        default_name_pawd = ServerLogin(user_id=user_id,server_id=server.id,login_name=login_name,password=password)
        db.session.add(default_name_pawd)
        for task in tasks:
            task.be_work()
            db.session.commit()
            if task.filename.rsplit('.', 1)[1] == 'gz':
                dir = task.filename.split('.')[0] + str(task.id)
                sh.cd(current_app.config['MAGIC_MIRROR_TMPFILE_PATH'])
                sh.tar.bake('xzf')(task.filename)
                sh.mv.bake(current_app.config['MAGIC_MIRROR_TMPFILE_PATH'] + task.filename.split('.')[0])(current_app.config['MAGIC_MIRROR_TMPFILE_PATH'] + dir)
                files = os.listdir(current_app.config['MAGIC_MIRROR_TMPFILE_PATH'] + dir)
                filenames = []
                for file in files:
                    if os.path.isfile(current_app.config['MAGIC_MIRROR_TMPFILE_PATH'] + dir + '/' + file):
                        filenames.append((current_app.config['MAGIC_MIRROR_TMPFILE_PATH'] + dir + '/' + file,task.filename.split('.')[0] + '/' + file))
            elif task.filename.rsplit('.', 1)[1] == 'rar':
                dir = task.filename.split('.')[0] + str(task.id)
                sh.cd(current_app.config['MAGIC_MIRROR_TMPFILE_PATH'])
                sh.rar.bake('x')(task.filename)
                sh.mv.bake(current_app.config['MAGIC_MIRROR_TMPFILE_PATH'] + task.filename.split('.')[0])(current_app.config['MAGIC_MIRROR_TMPFILE_PATH'] + dir)
                files = os.listdir(current_app.config['MAGIC_MIRROR_TMPFILE_PATH'] + dir)
                filenames = []
                for file in files:
                    if os.path.isfile(current_app.config['MAGIC_MIRROR_TMPFILE_PATH'] + dir + '/' + file):
                        filenames.append((current_app.config['MAGIC_MIRROR_TMPFILE_PATH'] + dir + '/' + file,task.filename.split('.')[0] + '/' + file))
            elif task.filename.rsplit('.', 1)[1] == 'beam':
                filenames = [(current_app.config['MAGIC_MIRROR_TMPFILE_PATH'] + task.filename,'ebin/' + task.filename)]
            else:
                filenames = [(current_app.config['MAGIC_MIRROR_TMPFILE_PATH'] + task.filename,'db_update/' + datetime.now().strftime("%Y%m%d") + '.sql')]
            log = 'lastupload.status'
            sh.touch(current_app.config['MAGIC_MIRROR_TMPFILE_PATH'] + log) 
            logfilename = (current_app.config['MAGIC_MIRROR_TMPFILE_PATH'] + log, log)
            if task.model == 'login':
                for source,target in filenames:
                    remotepath = current_app.config['MAGIC_MIRROR_LOGIN_PATH'] + target
                    if task.filename.rsplit('.', 1)[1] == 'sql':
                        oldfiles = sftp.listdir(current_app.config['MAGIC_MIRROR_LOGIN_PATH'] + 'db_update/')
                        for oldfile in oldfiles:
                            sftp.remove(current_app.config['MAGIC_MIRROR_LOGIN_PATH'] + 'db_update/' + oldfile)
                    localpath = source
                    sftp.put(localpath,remotepath)
                logsource = logfilename[0]
                logtarget = current_app.config['MAGIC_MIRROR_LOGIN_PATH'] + logfilename[1]        
                sftp.put(logsource,logtarget)
                time = 0
                while(sftp.stat(logtarget).st_mode == mode_664 and time < 60):
                    sleep(2)
                    time += 1
                if sftp.stat(logtarget).st_mode == mode_674:
                    task.be_wrong()
                    db.session.commit()
                    continue
            if task.model == 'android_qa':
                for source,target in filenames:
                    remotepath = current_app.config['MAGIC_MIRROR_ANDROID_QA_PATH'] + target
                    if task.filename.rsplit('.', 1)[1] == 'sql':
                        oldfiles = sftp.listdir(current_app.config['MAGIC_MIRROR_ANDROID_QA_PATH'] + 'db_update/')
                        for oldfile in oldfiles:
                            sftp.remove(current_app.config['MAGIC_MIRROR_ANDROID_QA_PATH'] + 'db_update/' + oldfile)
                    localpath = source
                    sftp.put(localpath,remotepath)
                logsource = logfilename[0]
                logtarget = current_app.config['MAGIC_MIRROR_ANDROID_QA_PATH'] + logfilename[1]        
                sftp.put(logsource,logtarget)
                time = 0
                while(sftp.stat(logtarget).st_mode == mode_664 and time < 60):
                    sleep(2)
                    time += 1
                if sftp.stat(logtarget).st_mode == mode_674:
                    task.be_wrong()
                    db.session.commit()
                    continue
            if task.model == 'android_review':
                for source,target in filenames:
                    remotepath = current_app.config['MAGIC_MIRROR_ANDROID_REVIEW_PATH'] + target
                    if task.filename.rsplit('.', 1)[1] == 'sql':
                        oldfiles = sftp.listdir(current_app.config['MAGIC_MIRROR_ANDROID_REVIEW_PATH'] + 'db_update/')
                        for oldfile in oldfiles:
                            sftp.remove(current_app.config['MAGIC_MIRROR_ANDROID_REVIEW_PATH'] + 'db_update/' + oldfile)
                    localpath = source
                    sftp.put(localpath,remotepath)
                logsource = logfilename[0]
                logtarget = current_app.config['MAGIC_MIRROR_ANDROID_REVIEW_PATH'] + logfilename[1]        
                sftp.put(logsource,logtarget)
                time = 0
                while(sftp.stat(logtarget).st_mode == mode_664 and time < 60):
                    sleep(2)
                    time += 1
                if sftp.stat(logtarget).st_mode == mode_674:
                    task.be_wrong()
                    db.session.commit()
                    continue
            if task.model == 'android_online':
                for source,target in filenames:
                    remotepath = current_app.config['MAGIC_MIRROR_ANDROID_ONLINE_PATH'] + target
                    if task.filename.rsplit('.', 1)[1] == 'sql':
                        oldfiles = sftp.listdir(current_app.config['MAGIC_MIRROR_ANDROID_ONLINE_PATH'] + 'db_update/')
                        for oldfile in oldfiles:
                            sftp.remove(current_app.config['MAGIC_MIRROR_ANDROID_ONLINE_PATH'] + 'db_update/' + oldfile)
                    localpath = source
                    sftp.put(localpath,remotepath)
                logsource = logfilename[0]
                logtarget = current_app.config['MAGIC_MIRROR_ANDROID_ONLINE_PATH'] + logfilename[1]        
                sftp.put(logsource,logtarget)
                time = 0
                while(sftp.stat(logtarget).st_mode == mode_664 and time < 60):
                    sleep(2)
                    time += 1
                if sftp.stat(logtarget).st_mode == mode_674:
                    task.be_wrong()
                    db.session.commit()
                    continue
            if task.model == 'ios_qa':
                for source,target in filenames:
                    remotepath = current_app.config['MAGIC_MIRROR_IOS_QA_PATH'] + target
                    if task.filename.rsplit('.', 1)[1] == 'sql':
                        oldfiles = sftp.listdir(current_app.config['MAGIC_MIRROR_IOS_QA_PATH'] + 'db_update/')
                        for oldfile in oldfiles:
                            sftp.remove(current_app.config['MAGIC_MIRROR_IOS_QA_PATH'] + 'db_update/' + oldfile)
                    localpath = source
                    sftp.put(localpath,remotepath)
                logsource = logfilename[0]
                logtarget = current_app.config['MAGIC_MIRROR_IOS_QA_PATH'] + logfilename[1]        
                sftp.put(logsource,logtarget)
                time = 0
                while(sftp.stat(logtarget).st_mode == mode_664 and time < 60):
                    sleep(2)
                    time += 1
                if sftp.stat(logtarget).st_mode == mode_674:
                    task.be_wrong()
                    db.session.commit()
                    continue
            if task.model == 'ios_review':
                for source,target in filenames:
                    remotepath = current_app.config['MAGIC_MIRROR_IOS_REVIEW_PATH'] + target
                    if task.filename.rsplit('.', 1)[1] == 'sql':
                        oldfiles = sftp.listdir(current_app.config['MAGIC_MIRROR_IOS_REVIEW_PATH'] + 'db_update/')
                        for oldfile in oldfiles:
                            sftp.remove(current_app.config['MAGIC_MIRROR_IOS_REVIEW_PATH'] + 'db_update/' + oldfile)
                    localpath = source
                    sftp.put(localpath,remotepath)
                logsource = logfilename[0]
                logtarget = current_app.config['MAGIC_MIRROR_IOS_REVIEW_PATH'] + logfilename[1]        
                sftp.put(logsource,logtarget)
                time = 0
                while(sftp.stat(logtarget).st_mode == mode_664 and time < 60):
                    sleep(2)
                    time += 1
                if sftp.stat(logtarget).st_mode == mode_674:
                    task.be_wrong()
                    db.session.commit()
                    continue
            if task.model == 'ios_online':
                for source,target in filenames:
                    remotepath = current_app.config['MAGIC_MIRROR_IOS_ONLINE_PATH'] + target
                    if task.filename.rsplit('.', 1)[1] == 'sql':
                        oldfiles = sftp.listdir(current_app.config['MAGIC_MIRROR_IOS_ONLINE_PATH'] + 'db_update/')
                        for oldfile in oldfiles:
                            sftp.remove(current_app.config['MAGIC_MIRROR_IOS_ONLINE_PATH'] + 'db_update/' + oldfile)
                    localpath = source
                    sftp.put(localpath,remotepath)
                logsource = logfilename[0]
                logtarget = current_app.config['MAGIC_MIRROR_IOS_ONLINE_PATH'] + logfilename[1]        
                sftp.put(logsource,logtarget)
                time = 0
                while(sftp.stat(logtarget).st_mode == mode_664 and time < 60):
                    sleep(2)
                    time += 1
                if sftp.stat(logtarget).st_mode == mode_674:
                    task.be_wrong()
                    db.session.commit()
                    continue
            task.be_done()
            if not ServerTask.query.filter_by(filename=task.filename).filter(ServerTask.id!=task.id).\
                        filter(ServerTask.status!=Status.Done).filter(ServerTask.status!=Status.Wrong).first():
                if task.filename.rsplit('.', 1)[1] in ('gz','rar'):
                    sh.rm.bake('-rf')(current_app.config['MAGIC_MIRROR_TMPFILE_PATH'] + task.filename.split('.')[0] + str(task.id))
                sh.rm.bake('-f')(current_app.config['MAGIC_MIRROR_TMPFILE_PATH'] + task.filename)
        t.close()
        sftp.close()
    return True
Beispiel #37
0
class SFTP(FileBackend):
    def __init__(self, config):
        FileBackend.__init__(self, config)
        self._init_config()
        self.session = None
        self._init_session()

    DEFAULT_CONFIG = {
        'sftp_host': 'localhost',
        'sftp_port': 22,
        'sftp_user': '******',
        'sftp_password': '',
        'output_path': ''}

    def _init_config(self):
        some_changes = False
        if 'type' in self.config:
            for option, value in SFTP.DEFAULT_CONFIG.items():
                if not option in self.config:
                    self.config[option] = value
                    some_changes = True
                    logging.info('set default sftp config.')
        else:
            self.config['type'] = 'sftp'
            self.config.update(SFTP.DEFAULT_CONFIG)
            some_changes = True
            logging.info('set default sftp config.')
        if some_changes:
            self.config.save()

        # cast config types
        self.config['sftp_port'] = int(self.config['sftp_port'])

    def _init_session(self):
        self.connect()

    def connect(self):
        self._authenticate()
        self.state = self.STATE_CONNECTED

    def _authenticate(self):
        self._transport = SFTPTransport((self.config['sftp_host'],
                                         self.config['sftp_port']))
        self._transport.connect(username=self.config['sftp_user'],
                                password=self.config['sftp_password'])
        self.session = SFTPClient.from_transport(self._transport)
        logging.info('SFTP Authorization succeed')

    def disconnect(self):
        self.session.close()
        self._transport.close()

    def file_create_folder(self, path):
        if self.state == self.STATE_CONNECTED:
            dirlist = path.split('/')
            current_dirlist = ['']
            missing_dirlist = []
            current_dirlist.extend(dirlist[:])
            while len(current_dirlist) > 0:
                current_path = '/'.join(current_dirlist)
                try:
                    self.session.chdir(current_path)
                    break
                except:
                    missing_dirlist.append(current_dirlist.pop())
            missing_dirlist.reverse()
            for dirname in missing_dirlist:
                dir_contents = self.session.listdir()
                if not dirname in dir_contents:
                    self.session.mkdir(dirname)
                    logging.info('Create remote directory %s' % self.session.getcwd() + '/' + dirname)
                self.session.chdir(dirname)
        elif self.state == self.STATE_DISCONNECTED:
            raise self.ConnectionException('SFTP is %s' % self.state)
        else:
            raise NotImplementedError()

    def put_file(self, path, file_handle):
        if self.state == self.STATE_CONNECTED:
            dirpath = '/'.join(path.split('/')[:-1])
            self.file_create_folder(dirpath)
            try:
                self.session.putfo(fl=file_handle, remotepath='/' + path)
                logging.info('Create remote file %s' % '/' + path)
            except Exception as ex:
                logging.error(ex)
        elif self.state == self.STATE_DISCONNECTED:
            raise self.ConnectionException('SFTP is %s' % self.state)
        else:
            raise NotImplementedError()
Beispiel #38
0
    def upload_report(self, filepath, file_name, report_date):
        """
        >>> a = CSVgenerator('123')
        >>> a.upload_report(None, 'upload.txt', '2014-05-06')
        """
        # appropriate changes required for doc test to run - dev only.
        # test_file_path = join(settings.REPORTS_ROOT, '16b6a354-ff32-4be4-b648-fe51fc5b1508.csv')
        # # trace.info('----- {}'.format(abspath(test_file_path)))
        # absolute_filename = abspath(test_file_path)
        # test_filename = '16b6a354-ff32-4be4-b648-fe51fc5b1508.csv'

        #TODO remove after QA testing.
        if not filepath:
            test_file_path = join(settings.REPORTS_ROOT, file_name)
            absolute_filename = abspath(test_file_path)
        else:
            absolute_filename = abspath(filepath)

        try:
            report_date = report_date if isinstance(report_date, str) else report_date.strftime(settings.DATE_FORMAT_YMD)
        except Exception:
            log.exception('')

        try:
            #TODO use sftp credentials, once available.
            #TODO get client upload location for per-client report.
            # ftp_client_dir = client.ftp_client_dir
            # if ftp_client_dir == '':
            #     ftp_client_dir = getattr(settings, 'DEFAULT_SFTP_LOCATION', 'default')
            #     logger.exception(u'No FTP configuration for client {} using default value.'.format(client.name))
            #

            year_folder, month_folder, _ = report_date.split('-')

            base_folder_path = self._sftp_settings.get('path', '')

            base_path = base_folder_path.split('/')
            base_folders = [i for i in base_path[1:-1]]
            base_folder = '/' + join(*base_folders)
            env_folder = str(base_path[-1:][0])

            from paramiko import Transport, SFTPClient
            try:
                log.info(u'SFTP logging on to {0} as {1}'.format(settings.SFTP_SERVER, settings.SFTP_USERNAME))
                transport = Transport((
                    self._sftp_settings.get('server', ''),
                    self._sftp_settings.get('port', 22))
                )
                transport.connect(
                    username=self._sftp_settings.get('username', ''),
                    password=self._sftp_settings.get('password', '')
                )
                sftp = SFTPClient.from_transport(transport)
                log.info(u'SFTP dir {0}/{1}/{2}/{3}'.format(base_folder, env_folder, year_folder, month_folder))
                try:
                    sftp.chdir(base_folder)
                except Exception:
                    log.debug('Unable to change to base folder on ftp server.')

                self._make_or_change_sftp_dir(sftp, env_folder)
                self._make_or_change_sftp_dir(sftp, year_folder)
                self._make_or_change_sftp_dir(sftp, month_folder)

                log.debug(u'SFTP uploading {0}'.format(filepath))
                sftp.put(absolute_filename, file_name)
            except Exception:
                log.exception(u'Unrecoverable exception during SFTP upload process.')

            finally:
                log.debug(u'SFTP logging off')

                try:
                    sftp.close()
                except Exception:
                    log.exception(u'SFTP exception while closing SFTP session.')

                try:
                    transport.close()
                except Exception:
                    log.exception(u'SFTP exception while closing SSH connection.')

        except Exception:
            log.debug('Error while uploading report.')
class TransportTest (unittest.TestCase):

    def setUp(self):
        self.socks = LoopSocket()
        self.sockc = LoopSocket()
        self.sockc.link(self.socks)
        self.tc = Transport(self.sockc)
        self.ts = Transport(self.socks)

    def tearDown(self):
        self.tc.close()
        self.ts.close()
        self.socks.close()
        self.sockc.close()

    def setup_test_server(self):
        host_key = RSAKey.from_private_key_file('tests/test_rsa.key')
        public_host_key = RSAKey(data=str(host_key))
        self.ts.add_server_key(host_key)
        event = threading.Event()
        self.server = NullServer()
        self.assert_(not event.isSet())
        self.ts.start_server(event, self.server)
        self.tc.connect(hostkey=public_host_key)
        self.tc.auth_password(username='******', password='******')
        event.wait(1.0)
        self.assert_(event.isSet())
        self.assert_(self.ts.is_active())

    def test_1_security_options(self):
        o = self.tc.get_security_options()
        self.assertEquals(type(o), SecurityOptions)
        self.assert_(('aes256-cbc', 'blowfish-cbc') != o.ciphers)
        o.ciphers = ('aes256-cbc', 'blowfish-cbc')
        self.assertEquals(('aes256-cbc', 'blowfish-cbc'), o.ciphers)
        try:
            o.ciphers = ('aes256-cbc', 'made-up-cipher')
            self.assert_(False)
        except ValueError:
            pass
        try:
            o.ciphers = 23
            self.assert_(False)
        except TypeError:
            pass
            
    def test_2_compute_key(self):
        self.tc.K = 123281095979686581523377256114209720774539068973101330872763622971399429481072519713536292772709507296759612401802191955568143056534122385270077606457721553469730659233569339356140085284052436697480759510519672848743794433460113118986816826624865291116513647975790797391795651716378444844877749505443714557929L
        self.tc.H = unhexlify('0C8307CDE6856FF30BA93684EB0F04C2520E9ED3')
        self.tc.session_id = self.tc.H
        key = self.tc._compute_key('C', 32)
        self.assertEquals('207E66594CA87C44ECCBA3B3CD39FDDB378E6FDB0F97C54B2AA0CFBF900CD995',
                          hexlify(key).upper())

    def test_3_simple(self):
        """
        verify that we can establish an ssh link with ourselves across the
        loopback sockets.  this is hardly "simple" but it's simpler than the
        later tests. :)
        """
        host_key = RSAKey.from_private_key_file('tests/test_rsa.key')
        public_host_key = RSAKey(data=str(host_key))
        self.ts.add_server_key(host_key)
        event = threading.Event()
        server = NullServer()
        self.assert_(not event.isSet())
        self.assertEquals(None, self.tc.get_username())
        self.assertEquals(None, self.ts.get_username())
        self.assertEquals(False, self.tc.is_authenticated())
        self.assertEquals(False, self.ts.is_authenticated())
        self.ts.start_server(event, server)
        self.tc.connect(hostkey=public_host_key,
                        username='******', password='******')
        event.wait(1.0)
        self.assert_(event.isSet())
        self.assert_(self.ts.is_active())
        self.assertEquals('slowdive', self.tc.get_username())
        self.assertEquals('slowdive', self.ts.get_username())
        self.assertEquals(True, self.tc.is_authenticated())
        self.assertEquals(True, self.ts.is_authenticated())

    def test_4_special(self):
        """
        verify that the client can demand odd handshake settings, and can
        renegotiate keys in mid-stream.
        """
        host_key = RSAKey.from_private_key_file('tests/test_rsa.key')
        public_host_key = RSAKey(data=str(host_key))
        self.ts.add_server_key(host_key)
        event = threading.Event()
        server = NullServer()
        self.assert_(not event.isSet())
        self.ts.start_server(event, server)
        options = self.tc.get_security_options()
        options.ciphers = ('aes256-cbc',)
        options.digests = ('hmac-md5-96',)
        self.tc.connect(hostkey=public_host_key,
                        username='******', password='******')
        event.wait(1.0)
        self.assert_(event.isSet())
        self.assert_(self.ts.is_active())
        self.assertEquals('aes256-cbc', self.tc.local_cipher)
        self.assertEquals('aes256-cbc', self.tc.remote_cipher)
        self.assertEquals(12, self.tc.packetizer.get_mac_size_out())
        self.assertEquals(12, self.tc.packetizer.get_mac_size_in())
        
        self.tc.send_ignore(1024)
        self.tc.renegotiate_keys()
        self.ts.send_ignore(1024)

    def test_5_keepalive(self):
        """
        verify that the keepalive will be sent.
        """
        self.tc.set_hexdump(True)
        
        host_key = RSAKey.from_private_key_file('tests/test_rsa.key')
        public_host_key = RSAKey(data=str(host_key))
        self.ts.add_server_key(host_key)
        event = threading.Event()
        server = NullServer()
        self.assert_(not event.isSet())
        self.ts.start_server(event, server)
        self.tc.connect(hostkey=public_host_key,
                        username='******', password='******')
        event.wait(1.0)
        self.assert_(event.isSet())
        self.assert_(self.ts.is_active())
        
        self.assertEquals(None, getattr(server, '_global_request', None))
        self.tc.set_keepalive(1)
        time.sleep(2)
        self.assertEquals('*****@*****.**', server._global_request)
        
    def test_6_bad_auth_type(self):
        """
        verify that we get the right exception when an unsupported auth
        type is requested.
        """
        host_key = RSAKey.from_private_key_file('tests/test_rsa.key')
        public_host_key = RSAKey(data=str(host_key))
        self.ts.add_server_key(host_key)
        event = threading.Event()
        server = NullServer()
        self.assert_(not event.isSet())
        self.ts.start_server(event, server)
        try:
            self.tc.connect(hostkey=public_host_key,
                            username='******', password='******')
            self.assert_(False)
        except:
            etype, evalue, etb = sys.exc_info()
            self.assertEquals(BadAuthenticationType, etype)
            self.assertEquals(['publickey'], evalue.allowed_types)

    def test_7_bad_password(self):
        """
        verify that a bad password gets the right exception, and that a retry
        with the right password works.
        """
        host_key = RSAKey.from_private_key_file('tests/test_rsa.key')
        public_host_key = RSAKey(data=str(host_key))
        self.ts.add_server_key(host_key)
        event = threading.Event()
        server = NullServer()
        self.assert_(not event.isSet())
        self.ts.start_server(event, server)
        self.tc.ultra_debug = True
        self.tc.connect(hostkey=public_host_key)
        try:
            self.tc.auth_password(username='******', password='******')
            self.assert_(False)
        except:
            etype, evalue, etb = sys.exc_info()
            self.assert_(issubclass(etype, SSHException))
        self.tc.auth_password(username='******', password='******')
        event.wait(1.0)
        self.assert_(event.isSet())
        self.assert_(self.ts.is_active())
    
    def test_8_multipart_auth(self):
        """
        verify that multipart auth works.
        """
        host_key = RSAKey.from_private_key_file('tests/test_rsa.key')
        public_host_key = RSAKey(data=str(host_key))
        self.ts.add_server_key(host_key)
        event = threading.Event()
        server = NullServer()
        self.assert_(not event.isSet())
        self.ts.start_server(event, server)
        self.tc.ultra_debug = True
        self.tc.connect(hostkey=public_host_key)
        remain = self.tc.auth_password(username='******', password='******')
        self.assertEquals(['publickey'], remain)
        key = DSSKey.from_private_key_file('tests/test_dss.key')
        remain = self.tc.auth_publickey(username='******', key=key)
        self.assertEquals([], remain)
        event.wait(1.0)
        self.assert_(event.isSet())
        self.assert_(self.ts.is_active())

    def test_9_interactive_auth(self):
        """
        verify keyboard-interactive auth works.
        """
        host_key = RSAKey.from_private_key_file('tests/test_rsa.key')
        public_host_key = RSAKey(data=str(host_key))
        self.ts.add_server_key(host_key)
        event = threading.Event()
        server = NullServer()
        self.assert_(not event.isSet())
        self.ts.start_server(event, server)
        self.tc.ultra_debug = True
        self.tc.connect(hostkey=public_host_key)

        def handler(title, instructions, prompts):
            self.got_title = title
            self.got_instructions = instructions
            self.got_prompts = prompts
            return ['cat']
        remain = self.tc.auth_interactive('commie', handler)
        self.assertEquals(self.got_title, 'password')
        self.assertEquals(self.got_prompts, [('Password', False)])
        self.assertEquals([], remain)
        event.wait(1.0)
        self.assert_(event.isSet())
        self.assert_(self.ts.is_active())
        
    def test_A_interactive_auth_fallback(self):
        """
        verify that a password auth attempt will fallback to "interactive"
        if password auth isn't supported but interactive is.
        """
        host_key = RSAKey.from_private_key_file('tests/test_rsa.key')
        public_host_key = RSAKey(data=str(host_key))
        self.ts.add_server_key(host_key)
        event = threading.Event()
        server = NullServer()
        self.assert_(not event.isSet())
        self.ts.start_server(event, server)
        self.tc.ultra_debug = True
        self.tc.connect(hostkey=public_host_key)
        remain = self.tc.auth_password('commie', 'cat')
        self.assertEquals([], remain)
        event.wait(1.0)
        self.assert_(event.isSet())
        self.assert_(self.ts.is_active())
            
    def test_B_exec_command(self):
        """
        verify that exec_command() does something reasonable.
        """
        self.setup_test_server()

        chan = self.tc.open_session()
        schan = self.ts.accept(1.0)
        try:
            chan.exec_command('no')
            self.assert_(False)
        except SSHException, x:
            pass
        
        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)
        schan.send('Hello there.\n')
        schan.send_stderr('This is on stderr.\n')
        schan.close()

        f = chan.makefile()
        self.assertEquals('Hello there.\n', f.readline())
        self.assertEquals('', f.readline())
        f = chan.makefile_stderr()
        self.assertEquals('This is on stderr.\n', f.readline())
        self.assertEquals('', f.readline())
        
        # now try it with combined stdout/stderr
        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)
        schan.send('Hello there.\n')
        schan.send_stderr('This is on stderr.\n')
        schan.close()

        chan.set_combine_stderr(True)        
        f = chan.makefile()
        self.assertEquals('Hello there.\n', f.readline())
        self.assertEquals('This is on stderr.\n', f.readline())
        self.assertEquals('', f.readline())
class TransportTest(ParamikoTest):
    def setUp(self):
        self.socks = LoopSocket()
        self.sockc = LoopSocket()
        self.sockc.link(self.socks)
        self.tc = Transport(self.sockc)
        self.ts = Transport(self.socks)

    def tearDown(self):
        self.tc.close()
        self.ts.close()
        self.socks.close()
        self.sockc.close()

    def setup_test_server(self, client_options=None, server_options=None):
        host_key = RSAKey.from_private_key_file('tests/test_rsa.key')
        public_host_key = RSAKey(data=str(host_key))
        self.ts.add_server_key(host_key)

        if client_options is not None:
            client_options(self.tc.get_security_options())
        if server_options is not None:
            server_options(self.ts.get_security_options())

        event = threading.Event()
        self.server = NullServer()
        self.assert_(not event.isSet())
        self.ts.start_server(event, self.server)
        self.tc.connect(hostkey=public_host_key,
                        username='******', password='******')
        event.wait(1.0)
        self.assert_(event.isSet())
        self.assert_(self.ts.is_active())

    def test_1_security_options(self):
        o = self.tc.get_security_options()
        self.assertEquals(type(o), SecurityOptions)
        self.assert_(('aes256-cbc', 'blowfish-cbc') != o.ciphers)
        o.ciphers = ('aes256-cbc', 'blowfish-cbc')
        self.assertEquals(('aes256-cbc', 'blowfish-cbc'), o.ciphers)
        try:
            o.ciphers = ('aes256-cbc', 'made-up-cipher')
            self.assert_(False)
        except ValueError:
            pass
        try:
            o.ciphers = 23
            self.assert_(False)
        except TypeError:
            pass

    def test_2_compute_key(self):
        self.tc.K = long(123281095979686581523377256114209720774539068973101330872763622971399429481072519713536292772709507296759612401802191955568143056534122385270077606457721553469730659233569339356140085284052436697480759510519672848743794433460113118986816826624865291116513647975790797391795651716378444844877749505443714557929)
        self.tc.H = unhexlify('0C8307CDE6856FF30BA93684EB0F04C2520E9ED3')
        self.tc.session_id = self.tc.H
        key = self.tc._compute_key('C', 32)
        self.assertEquals('207E66594CA87C44ECCBA3B3CD39FDDB378E6FDB0F97C54B2AA0CFBF900CD995',
                          hexlify(key).upper())

    def test_3_simple(self):
        """
        verify that we can establish an ssh link with ourselves across the
        loopback sockets.  this is hardly "simple" but it's simpler than the
        later tests. :)
        """
        host_key = RSAKey.from_private_key_file('tests/test_rsa.key')
        public_host_key = RSAKey(data=str(host_key))
        self.ts.add_server_key(host_key)
        event = threading.Event()
        server = NullServer()
        self.assert_(not event.isSet())
        self.assertEquals(None, self.tc.get_username())
        self.assertEquals(None, self.ts.get_username())
        self.assertEquals(False, self.tc.is_authenticated())
        self.assertEquals(False, self.ts.is_authenticated())
        self.ts.start_server(event, server)
        self.tc.connect(hostkey=public_host_key,
                        username='******', password='******')
        event.wait(1.0)
        self.assert_(event.isSet())
        self.assert_(self.ts.is_active())
        self.assertEquals('slowdive', self.tc.get_username())
        self.assertEquals('slowdive', self.ts.get_username())
        self.assertEquals(True, self.tc.is_authenticated())
        self.assertEquals(True, self.ts.is_authenticated())

    def test_3a_long_banner(self):
        """
        verify that a long banner doesn't mess up the handshake.
        """
        host_key = RSAKey.from_private_key_file('tests/test_rsa.key')
        public_host_key = RSAKey(data=str(host_key))
        self.ts.add_server_key(host_key)
        event = threading.Event()
        server = NullServer()
        self.assert_(not event.isSet())
        self.socks.send(LONG_BANNER)
        self.ts.start_server(event, server)
        self.tc.connect(hostkey=public_host_key,
                        username='******', password='******')
        event.wait(1.0)
        self.assert_(event.isSet())
        self.assert_(self.ts.is_active())

    def test_4_special(self):
        """
        verify that the client can demand odd handshake settings, and can
        renegotiate keys in mid-stream.
        """
        def force_algorithms(options):
            options.ciphers = ('aes256-cbc',)
            options.digests = ('hmac-md5-96',)
        self.setup_test_server(client_options=force_algorithms)
        self.assertEquals('aes256-cbc', self.tc.local_cipher)
        self.assertEquals('aes256-cbc', self.tc.remote_cipher)
        self.assertEquals(12, self.tc.packetizer.get_mac_size_out())
        self.assertEquals(12, self.tc.packetizer.get_mac_size_in())

        self.tc.send_ignore(1024)
        self.tc.renegotiate_keys()
        self.ts.send_ignore(1024)

    def test_5_keepalive(self):
        """
        verify that the keepalive will be sent.
        """
        self.setup_test_server()
        self.assertEquals(None, getattr(self.server, '_global_request', None))
        self.tc.set_keepalive(1)
        time.sleep(2)
        self.assertEquals('*****@*****.**', self.server._global_request)

    def test_6_exec_command(self):
        """
        verify that exec_command() does something reasonable.
        """
        self.setup_test_server()

        chan = self.tc.open_session()
        schan = self.ts.accept(1.0)
        try:
            chan.exec_command('no')
            self.assert_(False)
        except SSHException, x:
            pass

        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)
        schan.send('Hello there.\n')
        schan.send_stderr('This is on stderr.\n')
        schan.close()

        f = chan.makefile()
        self.assertEquals('Hello there.\n', f.readline())
        self.assertEquals('', f.readline())
        f = chan.makefile_stderr()
        self.assertEquals('This is on stderr.\n', f.readline())
        self.assertEquals('', f.readline())

        # now try it with combined stdout/stderr
        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)
        schan.send('Hello there.\n')
        schan.send_stderr('This is on stderr.\n')
        schan.close()

        chan.set_combine_stderr(True)
        f = chan.makefile()
        self.assertEquals('Hello there.\n', f.readline())
        self.assertEquals('This is on stderr.\n', f.readline())
        self.assertEquals('', f.readline())
class TransportTest(unittest.TestCase):
    def setUp(self):
        self.socks = LoopSocket()
        self.sockc = LoopSocket()
        self.sockc.link(self.socks)
        self.tc = Transport(self.sockc)
        self.ts = Transport(self.socks)

    def tearDown(self):
        self.tc.close()
        self.ts.close()
        self.socks.close()
        self.sockc.close()

    def setup_test_server(
        self, client_options=None, server_options=None, connect_kwargs=None
    ):
        host_key = RSAKey.from_private_key_file(_support("test_rsa.key"))
        public_host_key = RSAKey(data=host_key.asbytes())
        self.ts.add_server_key(host_key)

        if client_options is not None:
            client_options(self.tc.get_security_options())
        if server_options is not None:
            server_options(self.ts.get_security_options())

        event = threading.Event()
        self.server = NullServer()
        self.assertTrue(not event.is_set())
        self.ts.start_server(event, self.server)
        if connect_kwargs is None:
            connect_kwargs = dict(
                hostkey=public_host_key,
                username="******",
                password="******",
            )
        self.tc.connect(**connect_kwargs)
        event.wait(1.0)
        self.assertTrue(event.is_set())
        self.assertTrue(self.ts.is_active())

    def test_security_options(self):
        o = self.tc.get_security_options()
        self.assertEqual(type(o), SecurityOptions)
        self.assertTrue(("aes256-cbc", "blowfish-cbc") != o.ciphers)
        o.ciphers = ("aes256-cbc", "blowfish-cbc")
        self.assertEqual(("aes256-cbc", "blowfish-cbc"), o.ciphers)
        try:
            o.ciphers = ("aes256-cbc", "made-up-cipher")
            self.assertTrue(False)
        except ValueError:
            pass
        try:
            o.ciphers = 23
            self.assertTrue(False)
        except TypeError:
            pass

    def testb_security_options_reset(self):
        o = self.tc.get_security_options()
        # should not throw any exceptions
        o.ciphers = o.ciphers
        o.digests = o.digests
        o.key_types = o.key_types
        o.kex = o.kex
        o.compression = o.compression

    def test_compute_key(self):
        self.tc.K = 123281095979686581523377256114209720774539068973101330872763622971399429481072519713536292772709507296759612401802191955568143056534122385270077606457721553469730659233569339356140085284052436697480759510519672848743794433460113118986816826624865291116513647975790797391795651716378444844877749505443714557929  # noqa
        self.tc.H = b"\x0C\x83\x07\xCD\xE6\x85\x6F\xF3\x0B\xA9\x36\x84\xEB\x0F\x04\xC2\x52\x0E\x9E\xD3"  # noqa
        self.tc.session_id = self.tc.H
        key = self.tc._compute_key("C", 32)
        self.assertEqual(
            b"207E66594CA87C44ECCBA3B3CD39FDDB378E6FDB0F97C54B2AA0CFBF900CD995",  # noqa
            hexlify(key).upper(),
        )

    def test_simple(self):
        """
        verify that we can establish an ssh link with ourselves across the
        loopback sockets.  this is hardly "simple" but it's simpler than the
        later tests. :)
        """
        host_key = RSAKey.from_private_key_file(_support("test_rsa.key"))
        public_host_key = RSAKey(data=host_key.asbytes())
        self.ts.add_server_key(host_key)
        event = threading.Event()
        server = NullServer()
        self.assertTrue(not event.is_set())
        self.assertEqual(None, self.tc.get_username())
        self.assertEqual(None, self.ts.get_username())
        self.assertEqual(False, self.tc.is_authenticated())
        self.assertEqual(False, self.ts.is_authenticated())
        self.ts.start_server(event, server)
        self.tc.connect(
            hostkey=public_host_key, username="******", password="******"
        )
        event.wait(1.0)
        self.assertTrue(event.is_set())
        self.assertTrue(self.ts.is_active())
        self.assertEqual("slowdive", self.tc.get_username())
        self.assertEqual("slowdive", self.ts.get_username())
        self.assertEqual(True, self.tc.is_authenticated())
        self.assertEqual(True, self.ts.is_authenticated())

    def testa_long_banner(self):
        """
        verify that a long banner doesn't mess up the handshake.
        """
        host_key = RSAKey.from_private_key_file(_support("test_rsa.key"))
        public_host_key = RSAKey(data=host_key.asbytes())
        self.ts.add_server_key(host_key)
        event = threading.Event()
        server = NullServer()
        self.assertTrue(not event.is_set())
        self.socks.send(LONG_BANNER)
        self.ts.start_server(event, server)
        self.tc.connect(
            hostkey=public_host_key, username="******", password="******"
        )
        event.wait(1.0)
        self.assertTrue(event.is_set())
        self.assertTrue(self.ts.is_active())

    def test_special(self):
        """
        verify that the client can demand odd handshake settings, and can
        renegotiate keys in mid-stream.
        """

        def force_algorithms(options):
            options.ciphers = ("aes256-cbc",)
            options.digests = ("hmac-md5-96",)

        self.setup_test_server(client_options=force_algorithms)
        self.assertEqual("aes256-cbc", self.tc.local_cipher)
        self.assertEqual("aes256-cbc", self.tc.remote_cipher)
        self.assertEqual(12, self.tc.packetizer.get_mac_size_out())
        self.assertEqual(12, self.tc.packetizer.get_mac_size_in())

        self.tc.send_ignore(1024)
        self.tc.renegotiate_keys()
        self.ts.send_ignore(1024)

    @slow
    def test_keepalive(self):
        """
        verify that the keepalive will be sent.
        """
        self.setup_test_server()
        self.assertEqual(None, getattr(self.server, "_global_request", None))
        self.tc.set_keepalive(1)
        time.sleep(2)
        self.assertEqual("*****@*****.**", self.server._global_request)

    def test_exec_command(self):
        """
        verify that exec_command() does something reasonable.
        """
        self.setup_test_server()

        chan = self.tc.open_session()
        schan = self.ts.accept(1.0)
        try:
            chan.exec_command(
                b"command contains \xfc and is not a valid UTF-8 string"
            )
            self.assertTrue(False)
        except SSHException:
            pass

        chan = self.tc.open_session()
        chan.exec_command("yes")
        schan = self.ts.accept(1.0)
        schan.send("Hello there.\n")
        schan.send_stderr("This is on stderr.\n")
        schan.close()

        f = chan.makefile()
        self.assertEqual("Hello there.\n", f.readline())
        self.assertEqual("", f.readline())
        f = chan.makefile_stderr()
        self.assertEqual("This is on stderr.\n", f.readline())
        self.assertEqual("", f.readline())

        # now try it with combined stdout/stderr
        chan = self.tc.open_session()
        chan.exec_command("yes")
        schan = self.ts.accept(1.0)
        schan.send("Hello there.\n")
        schan.send_stderr("This is on stderr.\n")
        schan.close()

        chan.set_combine_stderr(True)
        f = chan.makefile()
        self.assertEqual("Hello there.\n", f.readline())
        self.assertEqual("This is on stderr.\n", f.readline())
        self.assertEqual("", f.readline())

    def testa_channel_can_be_used_as_context_manager(self):
        """
        verify that exec_command() does something reasonable.
        """
        self.setup_test_server()

        with self.tc.open_session() as chan:
            with self.ts.accept(1.0) as schan:
                chan.exec_command("yes")
                schan.send("Hello there.\n")
                schan.close()

                f = chan.makefile()
                self.assertEqual("Hello there.\n", f.readline())
                self.assertEqual("", f.readline())

    def test_invoke_shell(self):
        """
        verify that invoke_shell() does something reasonable.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.invoke_shell()
        schan = self.ts.accept(1.0)
        chan.send("communist j. cat\n")
        f = schan.makefile()
        self.assertEqual("communist j. cat\n", f.readline())
        chan.close()
        self.assertEqual("", f.readline())

    def test_channel_exception(self):
        """
        verify that ChannelException is thrown for a bad open-channel request.
        """
        self.setup_test_server()
        try:
            self.tc.open_channel("bogus")
            self.fail("expected exception")
        except ChannelException as e:
            self.assertTrue(e.code == OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED)

    def test_exit_status(self):
        """
        verify that get_exit_status() works.
        """
        self.setup_test_server()

        chan = self.tc.open_session()
        schan = self.ts.accept(1.0)
        chan.exec_command("yes")
        schan.send("Hello there.\n")
        self.assertTrue(not chan.exit_status_ready())
        # trigger an EOF
        schan.shutdown_read()
        schan.shutdown_write()
        schan.send_exit_status(23)
        schan.close()

        f = chan.makefile()
        self.assertEqual("Hello there.\n", f.readline())
        self.assertEqual("", f.readline())
        count = 0
        while not chan.exit_status_ready():
            time.sleep(0.1)
            count += 1
            if count > 50:
                raise Exception("timeout")
        self.assertEqual(23, chan.recv_exit_status())
        chan.close()

    def test_select(self):
        """
        verify that select() on a channel works.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.invoke_shell()
        schan = self.ts.accept(1.0)

        # nothing should be ready
        r, w, e = select.select([chan], [], [], 0.1)
        self.assertEqual([], r)
        self.assertEqual([], w)
        self.assertEqual([], e)

        schan.send("hello\n")

        # something should be ready now (give it 1 second to appear)
        for i in range(10):
            r, w, e = select.select([chan], [], [], 0.1)
            if chan in r:
                break
            time.sleep(0.1)
        self.assertEqual([chan], r)
        self.assertEqual([], w)
        self.assertEqual([], e)

        self.assertEqual(b"hello\n", chan.recv(6))

        # and, should be dead again now
        r, w, e = select.select([chan], [], [], 0.1)
        self.assertEqual([], r)
        self.assertEqual([], w)
        self.assertEqual([], e)

        schan.close()

        # detect eof?
        for i in range(10):
            r, w, e = select.select([chan], [], [], 0.1)
            if chan in r:
                break
            time.sleep(0.1)
        self.assertEqual([chan], r)
        self.assertEqual([], w)
        self.assertEqual([], e)
        self.assertEqual(bytes(), chan.recv(16))

        # make sure the pipe is still open for now...
        p = chan._pipe
        self.assertEqual(False, p._closed)
        chan.close()
        # ...and now is closed.
        self.assertEqual(True, p._closed)

    def test_renegotiate(self):
        """
        verify that a transport can correctly renegotiate mid-stream.
        """
        self.setup_test_server()
        self.tc.packetizer.REKEY_BYTES = 16384
        chan = self.tc.open_session()
        chan.exec_command("yes")
        schan = self.ts.accept(1.0)

        self.assertEqual(self.tc.H, self.tc.session_id)
        for i in range(20):
            chan.send("x" * 1024)
        chan.close()

        # allow a few seconds for the rekeying to complete
        for i in range(50):
            if self.tc.H != self.tc.session_id:
                break
            time.sleep(0.1)
        self.assertNotEqual(self.tc.H, self.tc.session_id)

        schan.close()

    def test_compression(self):
        """
        verify that zlib compression is basically working.
        """

        def force_compression(o):
            o.compression = ("zlib",)

        self.setup_test_server(force_compression, force_compression)
        chan = self.tc.open_session()
        chan.exec_command("yes")
        schan = self.ts.accept(1.0)

        bytes = self.tc.packetizer._Packetizer__sent_bytes
        chan.send("x" * 1024)
        bytes2 = self.tc.packetizer._Packetizer__sent_bytes
        block_size = self.tc._cipher_info[self.tc.local_cipher]["block-size"]
        mac_size = self.tc._mac_info[self.tc.local_mac]["size"]
        # tests show this is actually compressed to *52 bytes*!  including
        # packet overhead!  nice!! :)
        self.assertTrue(bytes2 - bytes < 1024)
        self.assertEqual(16 + block_size + mac_size, bytes2 - bytes)

        chan.close()
        schan.close()

    def test_x11(self):
        """
        verify that an x11 port can be requested and opened.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.exec_command("yes")
        schan = self.ts.accept(1.0)

        requested = []

        def handler(c, addr_port):
            addr, port = addr_port
            requested.append((addr, port))
            self.tc._queue_incoming_channel(c)

        self.assertEqual(
            None, getattr(self.server, "_x11_screen_number", None)
        )
        cookie = chan.request_x11(0, single_connection=True, handler=handler)
        self.assertEqual(0, self.server._x11_screen_number)
        self.assertEqual("MIT-MAGIC-COOKIE-1", self.server._x11_auth_protocol)
        self.assertEqual(cookie, self.server._x11_auth_cookie)
        self.assertEqual(True, self.server._x11_single_connection)

        x11_server = self.ts.open_x11_channel(("localhost", 6093))
        x11_client = self.tc.accept()
        self.assertEqual("localhost", requested[0][0])
        self.assertEqual(6093, requested[0][1])

        x11_server.send("hello")
        self.assertEqual(b"hello", x11_client.recv(5))

        x11_server.close()
        x11_client.close()
        chan.close()
        schan.close()

    def test_reverse_port_forwarding(self):
        """
        verify that a client can ask the server to open a reverse port for
        forwarding.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.exec_command("yes")
        self.ts.accept(1.0)

        requested = []

        def handler(c, origin_addr_port, server_addr_port):
            requested.append(origin_addr_port)
            requested.append(server_addr_port)
            self.tc._queue_incoming_channel(c)

        port = self.tc.request_port_forward("127.0.0.1", 0, handler)
        self.assertEqual(port, self.server._listen.getsockname()[1])

        cs = socket.socket()
        cs.connect(("127.0.0.1", port))
        ss, _ = self.server._listen.accept()
        sch = self.ts.open_forwarded_tcpip_channel(
            ss.getsockname(), ss.getpeername()
        )
        cch = self.tc.accept()

        sch.send("hello")
        self.assertEqual(b"hello", cch.recv(5))
        sch.close()
        cch.close()
        ss.close()
        cs.close()

        # now cancel it.
        self.tc.cancel_port_forward("127.0.0.1", port)
        self.assertTrue(self.server._listen is None)

    def test_port_forwarding(self):
        """
        verify that a client can forward new connections from a locally-
        forwarded port.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.exec_command("yes")
        self.ts.accept(1.0)

        # open a port on the "server" that the client will ask to forward to.
        greeting_server = socket.socket()
        greeting_server.bind(("127.0.0.1", 0))
        greeting_server.listen(1)
        greeting_port = greeting_server.getsockname()[1]

        cs = self.tc.open_channel(
            "direct-tcpip", ("127.0.0.1", greeting_port), ("", 9000)
        )
        sch = self.ts.accept(1.0)
        cch = socket.socket()
        cch.connect(self.server._tcpip_dest)

        ss, _ = greeting_server.accept()
        ss.send(b"Hello!\n")
        ss.close()
        sch.send(cch.recv(8192))
        sch.close()

        self.assertEqual(b"Hello!\n", cs.recv(7))
        cs.close()

    def test_stderr_select(self):
        """
        verify that select() on a channel works even if only stderr is
        receiving data.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.invoke_shell()
        schan = self.ts.accept(1.0)

        # nothing should be ready
        r, w, e = select.select([chan], [], [], 0.1)
        self.assertEqual([], r)
        self.assertEqual([], w)
        self.assertEqual([], e)

        schan.send_stderr("hello\n")

        # something should be ready now (give it 1 second to appear)
        for i in range(10):
            r, w, e = select.select([chan], [], [], 0.1)
            if chan in r:
                break
            time.sleep(0.1)
        self.assertEqual([chan], r)
        self.assertEqual([], w)
        self.assertEqual([], e)

        self.assertEqual(b"hello\n", chan.recv_stderr(6))

        # and, should be dead again now
        r, w, e = select.select([chan], [], [], 0.1)
        self.assertEqual([], r)
        self.assertEqual([], w)
        self.assertEqual([], e)

        schan.close()
        chan.close()

    def test_send_ready(self):
        """
        verify that send_ready() indicates when a send would not block.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.invoke_shell()
        schan = self.ts.accept(1.0)

        self.assertEqual(chan.send_ready(), True)
        total = 0
        K = "*" * 1024
        limit = 1 + (64 * 2 ** 15)
        while total < limit:
            chan.send(K)
            total += len(K)
            if not chan.send_ready():
                break
        self.assertTrue(total < limit)

        schan.close()
        chan.close()
        self.assertEqual(chan.send_ready(), True)

    def test_rekey_deadlock(self):
        """
        Regression test for deadlock when in-transit messages are received
        after MSG_KEXINIT is sent

        Note: When this test fails, it may leak threads.
        """

        # Test for an obscure deadlocking bug that can occur if we receive
        # certain messages while initiating a key exchange.
        #
        # The deadlock occurs as follows:
        #
        # In the main thread:
        #   1. The user's program calls Channel.send(), which sends
        #      MSG_CHANNEL_DATA to the remote host.
        #   2. Packetizer discovers that REKEY_BYTES has been exceeded, and
        #      sets the __need_rekey flag.
        #
        # In the Transport thread:
        #   3. Packetizer notices that the __need_rekey flag is set, and raises
        #      NeedRekeyException.
        #   4. In response to NeedRekeyException, the transport thread sends
        #      MSG_KEXINIT to the remote host.
        #
        # On the remote host (using any SSH implementation):
        #   5. The MSG_CHANNEL_DATA is received, and MSG_CHANNEL_WINDOW_ADJUST
        #      is sent.
        #   6. The MSG_KEXINIT is received, and a corresponding MSG_KEXINIT is
        #      sent.
        #
        # In the main thread:
        #   7. The user's program calls Channel.send().
        #   8. Channel.send acquires Channel.lock, then calls
        #      Transport._send_user_message().
        #   9. Transport._send_user_message waits for Transport.clear_to_send
        #      to be set (i.e., it waits for re-keying to complete).
        #      Channel.lock is still held.
        #
        # In the Transport thread:
        #   10. MSG_CHANNEL_WINDOW_ADJUST is received; Channel._window_adjust
        #       is called to handle it.
        #   11. Channel._window_adjust tries to acquire Channel.lock, but it
        #       blocks because the lock is already held by the main thread.
        #
        # The result is that the Transport thread never processes the remote
        # host's MSG_KEXINIT packet, because it becomes deadlocked while
        # handling the preceding MSG_CHANNEL_WINDOW_ADJUST message.

        # We set up two separate threads for sending and receiving packets,
        # while the main thread acts as a watchdog timer.  If the timer
        # expires, a deadlock is assumed.

        class SendThread(threading.Thread):
            def __init__(self, chan, iterations, done_event):
                threading.Thread.__init__(
                    self, None, None, self.__class__.__name__
                )
                self.setDaemon(True)
                self.chan = chan
                self.iterations = iterations
                self.done_event = done_event
                self.watchdog_event = threading.Event()
                self.last = None

            def run(self):
                try:
                    for i in range(1, 1 + self.iterations):
                        if self.done_event.is_set():
                            break
                        self.watchdog_event.set()
                        # print i, "SEND"
                        self.chan.send("x" * 2048)
                finally:
                    self.done_event.set()
                    self.watchdog_event.set()

        class ReceiveThread(threading.Thread):
            def __init__(self, chan, done_event):
                threading.Thread.__init__(
                    self, None, None, self.__class__.__name__
                )
                self.setDaemon(True)
                self.chan = chan
                self.done_event = done_event
                self.watchdog_event = threading.Event()

            def run(self):
                try:
                    while not self.done_event.is_set():
                        if self.chan.recv_ready():
                            chan.recv(65536)
                            self.watchdog_event.set()
                        else:
                            if random.randint(0, 1):
                                time.sleep(random.randint(0, 500) / 1000.0)
                finally:
                    self.done_event.set()
                    self.watchdog_event.set()

        self.setup_test_server()
        self.ts.packetizer.REKEY_BYTES = 2048

        chan = self.tc.open_session()
        chan.exec_command("yes")
        schan = self.ts.accept(1.0)

        # Monkey patch the client's Transport._handler_table so that the client
        # sends MSG_CHANNEL_WINDOW_ADJUST whenever it receives an initial
        # MSG_KEXINIT.  This is used to simulate the effect of network latency
        # on a real MSG_CHANNEL_WINDOW_ADJUST message.
        self.tc._handler_table = (
            self.tc._handler_table.copy()
        )  # copy per-class dictionary
        _negotiate_keys = self.tc._handler_table[MSG_KEXINIT]

        def _negotiate_keys_wrapper(self, m):
            if self.local_kex_init is None:  # Remote side sent KEXINIT
                # Simulate in-transit MSG_CHANNEL_WINDOW_ADJUST by sending it
                # before responding to the incoming MSG_KEXINIT.
                m2 = Message()
                m2.add_byte(cMSG_CHANNEL_WINDOW_ADJUST)
                m2.add_int(chan.remote_chanid)
                m2.add_int(1)  # bytes to add
                self._send_message(m2)
            return _negotiate_keys(self, m)

        self.tc._handler_table[MSG_KEXINIT] = _negotiate_keys_wrapper

        # Parameters for the test
        iterations = 500  # The deadlock does not happen every time, but it
        # should after many iterations.
        timeout = 5

        # This event is set when the test is completed
        done_event = threading.Event()

        # Start the sending thread
        st = SendThread(schan, iterations, done_event)
        st.start()

        # Start the receiving thread
        rt = ReceiveThread(chan, done_event)
        rt.start()

        # Act as a watchdog timer, checking
        deadlocked = False
        while not deadlocked and not done_event.is_set():
            for event in (st.watchdog_event, rt.watchdog_event):
                event.wait(timeout)
                if done_event.is_set():
                    break
                if not event.is_set():
                    deadlocked = True
                    break
                event.clear()

        # Tell the threads to stop (if they haven't already stopped).  Note
        # that if one or more threads are deadlocked, they might hang around
        # forever (until the process exits).
        done_event.set()

        # Assertion: We must not have detected a timeout.
        self.assertFalse(deadlocked)

        # Close the channels
        schan.close()
        chan.close()

    def test_sanitze_packet_size(self):
        """
        verify that we conform to the rfc of packet and window sizes.
        """
        for val, correct in [
            (4095, MIN_PACKET_SIZE),
            (None, DEFAULT_MAX_PACKET_SIZE),
            (2 ** 32, MAX_WINDOW_SIZE),
        ]:
            self.assertEqual(self.tc._sanitize_packet_size(val), correct)

    def test_sanitze_window_size(self):
        """
        verify that we conform to the rfc of packet and window sizes.
        """
        for val, correct in [
            (32767, MIN_WINDOW_SIZE),
            (None, DEFAULT_WINDOW_SIZE),
            (2 ** 32, MAX_WINDOW_SIZE),
        ]:
            self.assertEqual(self.tc._sanitize_window_size(val), correct)

    @slow
    def test_handshake_timeout(self):
        """
        verify that we can get a hanshake timeout.
        """
        # Tweak client Transport instance's Packetizer instance so
        # its read_message() sleeps a bit. This helps prevent race conditions
        # where the client Transport's timeout timer thread doesn't even have
        # time to get scheduled before the main client thread finishes
        # handshaking with the server.
        # (Doing this on the server's transport *sounds* more 'correct' but
        # actually doesn't work nearly as well for whatever reason.)
        class SlowPacketizer(Packetizer):
            def read_message(self):
                time.sleep(1)
                return super(SlowPacketizer, self).read_message()

        # NOTE: prettttty sure since the replaced .packetizer Packetizer is now
        # no longer doing anything with its copy of the socket...everything'll
        # be fine. Even tho it's a bit squicky.
        self.tc.packetizer = SlowPacketizer(self.tc.sock)
        # Continue with regular test red tape.
        host_key = RSAKey.from_private_key_file(_support("test_rsa.key"))
        public_host_key = RSAKey(data=host_key.asbytes())
        self.ts.add_server_key(host_key)
        event = threading.Event()
        server = NullServer()
        self.assertTrue(not event.is_set())
        self.tc.handshake_timeout = 0.000000000001
        self.ts.start_server(event, server)
        self.assertRaises(
            EOFError,
            self.tc.connect,
            hostkey=public_host_key,
            username="******",
            password="******",
        )

    def test_select_after_close(self):
        """
        verify that select works when a channel is already closed.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.invoke_shell()
        schan = self.ts.accept(1.0)
        schan.close()

        # give client a moment to receive close notification
        time.sleep(0.1)

        r, w, e = select.select([chan], [], [], 0.1)
        self.assertEqual([chan], r)
        self.assertEqual([], w)
        self.assertEqual([], e)

    def test_channel_send_misc(self):
        """
        verify behaviours sending various instances to a channel
        """
        self.setup_test_server()
        text = u"\xa7 slice me nicely"
        with self.tc.open_session() as chan:
            schan = self.ts.accept(1.0)
            if schan is None:
                self.fail("Test server transport failed to accept")
            sfile = schan.makefile()

            # TypeError raised on non string or buffer type
            self.assertRaises(TypeError, chan.send, object())
            self.assertRaises(TypeError, chan.sendall, object())

            # sendall() accepts a unicode instance
            chan.sendall(text)
            expected = text.encode("utf-8")
            self.assertEqual(sfile.read(len(expected)), expected)

    @needs_builtin("buffer")
    def test_channel_send_buffer(self):
        """
        verify sending buffer instances to a channel
        """
        self.setup_test_server()
        data = 3 * b"some test data\n whole"
        with self.tc.open_session() as chan:
            schan = self.ts.accept(1.0)
            if schan is None:
                self.fail("Test server transport failed to accept")
            sfile = schan.makefile()

            # send() accepts buffer instances
            sent = 0
            while sent < len(data):
                sent += chan.send(buffer(data, sent, 8))  # noqa
            self.assertEqual(sfile.read(len(data)), data)

            # sendall() accepts a buffer instance
            chan.sendall(buffer(data))  # noqa
            self.assertEqual(sfile.read(len(data)), data)

    @needs_builtin("memoryview")
    def test_channel_send_memoryview(self):
        """
        verify sending memoryview instances to a channel
        """
        self.setup_test_server()
        data = 3 * b"some test data\n whole"
        with self.tc.open_session() as chan:
            schan = self.ts.accept(1.0)
            if schan is None:
                self.fail("Test server transport failed to accept")
            sfile = schan.makefile()

            # send() accepts memoryview slices
            sent = 0
            view = memoryview(data)
            while sent < len(view):
                sent += chan.send(view[sent : sent + 8])
            self.assertEqual(sfile.read(len(data)), data)

            # sendall() accepts a memoryview instance
            chan.sendall(memoryview(data))
            self.assertEqual(sfile.read(len(data)), data)

    def test_server_rejects_open_channel_without_auth(self):
        try:
            self.setup_test_server(connect_kwargs={})
            self.tc.open_session()
        except ChannelException as e:
            assert e.code == OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
        else:
            assert False, "Did not raise ChannelException!"

    def test_server_rejects_arbitrary_global_request_without_auth(self):
        self.setup_test_server(connect_kwargs={})
        # NOTE: this dummy global request kind would normally pass muster
        # from the test server.
        self.tc.global_request("acceptable")
        # Global requests never raise exceptions, even on failure (not sure why
        # this was the original design...ugh.) Best we can do to tell failure
        # happened is that the client transport's global_response was set back
        # to None; if it had succeeded, it would be the response Message.
        err = "Unauthed global response incorrectly succeeded!"
        assert self.tc.global_response is None, err

    def test_server_rejects_port_forward_without_auth(self):
        # NOTE: at protocol level port forward requests are treated same as a
        # regular global request, but Paramiko server implements a special-case
        # method for it, so it gets its own test. (plus, THAT actually raises
        # an exception on the client side, unlike the general case...)
        self.setup_test_server(connect_kwargs={})
        try:
            self.tc.request_port_forward("localhost", 1234)
        except SSHException as e:
            assert "forwarding request denied" in str(e)
        else:
            assert False, "Did not raise SSHException!"

    def _send_unimplemented(self, server_is_sender):
        self.setup_test_server()
        sender, recipient = self.tc, self.ts
        if server_is_sender:
            sender, recipient = self.ts, self.tc
        recipient._send_message = Mock()
        msg = Message()
        msg.add_byte(cMSG_UNIMPLEMENTED)
        sender._send_message(msg)
        # TODO: I hate this but I literally don't see a good way to know when
        # the recipient has received the sender's message (there are no
        # existing threading events in play that work for this), esp in this
        # case where we don't WANT a response (as otherwise we could
        # potentially try blocking on the sender's receipt of a reply...maybe).
        time.sleep(0.1)
        assert not recipient._send_message.called

    def test_server_does_not_respond_to_MSG_UNIMPLEMENTED(self):
        self._send_unimplemented(server_is_sender=False)

    def test_client_does_not_respond_to_MSG_UNIMPLEMENTED(self):
        self._send_unimplemented(server_is_sender=True)

    def _send_client_message(self, message_type):
        self.setup_test_server(connect_kwargs={})
        self.ts._send_message = Mock()
        # NOTE: this isn't 100% realistic (most of these message types would
        # have actual other fields in 'em) but it suffices to test the level of
        # message dispatch we're interested in here.
        msg = Message()
        # TODO: really not liking the whole cMSG_XXX vs MSG_XXX duality right
        # now, esp since the former is almost always just byte_chr(the
        # latter)...but since that's the case...
        msg.add_byte(byte_chr(message_type))
        self.tc._send_message(msg)
        # No good way to actually wait for server action (see above tests re:
        # MSG_UNIMPLEMENTED). Grump.
        time.sleep(0.1)

    def _expect_unimplemented(self):
        # Ensure MSG_UNIMPLEMENTED was sent (implies it hit end of loop instead
        # of truly handling the given message).
        # NOTE: When bug present, this will actually be the first thing that
        # fails (since in many cases actual message handling doesn't involve
        # sending a message back right away).
        assert self.ts._send_message.call_count == 1
        reply = self.ts._send_message.call_args[0][0]
        reply.rewind()  # Because it's pre-send, not post-receive
        assert reply.get_byte() == cMSG_UNIMPLEMENTED

    def test_server_transports_reject_client_message_types(self):
        # TODO: handle Transport's own tables too, not just its inner auth
        # handler's table. See TODOs in auth_handler.py
        for message_type in AuthHandler._client_handler_table:
            self._send_client_message(message_type)
            self._expect_unimplemented()
            # Reset for rest of loop
            self.tearDown()
            self.setUp()

    def test_server_rejects_client_MSG_USERAUTH_SUCCESS(self):
        self._send_client_message(MSG_USERAUTH_SUCCESS)
        # Sanity checks
        assert not self.ts.authenticated
        assert not self.ts.auth_handler.authenticated
        # Real fix's behavior
        self._expect_unimplemented()
Beispiel #42
0
    def submitJobToFramework(self, **kwargs):
        jobCommand = 'job'
        
        daemonArgs = DaemonArgs(self.config)
        daemonArgs.command = jobCommand
        unScheduledJob = kwargs['unScheduledJob']
        
        is_fileFeeder = False
        fileFeederUploadedFile = None
        del daemonArgs.param[:]

        # go through all parameters
        for parameter in unScheduledJob.parameters.all():

            # add parameter to daemonArgs.param
            if parameter.service and parameter.param_key and parameter.param_value:

                # check if a file feeder is used
                if parameter.service == settings.FILE_FEEDER_ID:
                    is_fileFeeder = True
                    fileFeederUploadedFile = parameter.param_value

                    remoteFeederFile = os.path.join(self.sftpRemotePath, parameter.param_value)
                    parameterString = '%s.%s=%s' % ( parameter.service, parameter.param_key, remoteFeederFile )
                else:
                    parameterString = '%s.%s=%s' % ( parameter.service, parameter.param_key, parameter.param_value )

                self.logger.debug("add parameter string: %s" % parameterString)
                daemonArgs.param.append([parameterString])

        # in case of a filefeeder upload file to framework server
        if is_fileFeeder:
            self.logger.debug("is file feeder")
            sftp = None
            transport = None
            try:
                transport = Transport((self.sftpHost, self.sftpPort))
                if self.sftpPassword:
                    transport.connect(username=self.sftpUsername, password=self.sftpPassword)
                else:
                    privateKey = None
                    if self.sftpPrivateKeyType and self.sftpPrivateKeyType.lower() == 'rsa':
                        privateKey = RSAKey.from_private_key_file(self.sftpPrivateKey, password=self.sftpPrivateKeyPassword )
                    if self.sftpPrivateKeyType and self.sftpPrivateKeyType.lower() == 'dss':
                        privateKey = DSSKey.from_private_key_file(self.sftpPrivateKey, password=self.sftpPrivateKeyPassword )

                    transport.connect(username=self.sftpUsername, pkey=privateKey)

                sftp = SFTPClient.from_transport(transport)

                filePath = os.path.join( settings.MEDIA_ROOT, fileFeederUploadedFile )
                remotePath = os.path.join( self.sftpRemotePath, fileFeederUploadedFile )

                self.logger.debug("uploading file from %s to %s on remote machine" % (filePath, remotePath))

                sftp.put(filePath, remotePath)
#                            sftp.put(filePath, remotePath, confirm=False)
                sftp.chmod( remotePath, 0644 )

                self.logger.debug("put OK")

            except IOError as e:
                self.logger.error("IOError: %s. Will continue with next scheduled job." % e)
                self.saveJob(Job.FAILED_STATUS, None, unScheduledJob)
            except PasswordRequiredException as e:
                self.logger.error("PasswordRequiredException: %s. Will continue with next scheduled job." % e)
                self.saveJob(Job.FAILED_STATUS, None, unScheduledJob)
            except SSHException as e:
                self.logger.error("SSH Exception: %s. Will continue with next scheduled job." % e)
                self.saveJob(Job.FAILED_STATUS, None, unScheduledJob)
            except Exception as e:
                self.logger.error("Unkown SFTP problem. Will continue with next scheduled job. %s" % e)
                self.saveJob(Job.FAILED_STATUS, None, unScheduledJob)
            finally:
                if sftp is not None:
                    sftp.close()
                if transport is not None:
                    transport.close()
                
        # set job workflow
        daemonArgs.jd_workflow = unScheduledJob.workflow.name

        frameworkJobId = None
        
        try:
            setattr(daemonArgs, jobCommand, 'submit')
            frameworkJobId = self.sendFrameworkCommand(jobCommand, daemonArgs)
            self.saveJob(Job.PROCESSING_STATUS, frameworkJobId, unScheduledJob)
        except WorkflowNotDeployedException:
            # The workflow is not deployed in the framework. To prevent the scheduler retrying continuously
            # we disable this job
            unScheduledJob.status = Schedule.DEACTIVATE_STATUS
            unScheduledJob.save()
        except:
            self.saveJob(Job.FAILED_STATUS, None, unScheduledJob)
        finally:
            daemonArgs.clean(jobCommand)
        
        if unScheduledJob.scheduled_start is not None:
            unScheduledJob.status = Schedule.DEACTIVATED_STATUS
            unScheduledJob.save()
Beispiel #43
0
class AuthTest (unittest.TestCase):

    def setUp(self):
        self.socks = LoopSocket()
        self.sockc = LoopSocket()
        self.sockc.link(self.socks)
        self.tc = Transport(self.sockc)
        self.ts = Transport(self.socks)

    def tearDown(self):
        self.tc.close()
        self.ts.close()
        self.socks.close()
        self.sockc.close()

    def start_server(self):
        host_key = RSAKey.from_private_key_file(_support('test_rsa.key'))
        self.public_host_key = RSAKey(data=host_key.asbytes())
        self.ts.add_server_key(host_key)
        self.event = threading.Event()
        self.server = NullServer()
        self.assertTrue(not self.event.is_set())
        self.ts.start_server(self.event, self.server)

    def verify_finished(self):
        self.event.wait(1.0)
        self.assertTrue(self.event.is_set())
        self.assertTrue(self.ts.is_active())

    def test_bad_auth_type(self):
        """
        verify that we get the right exception when an unsupported auth
        type is requested.
        """
        self.start_server()
        try:
            self.tc.connect(hostkey=self.public_host_key,
                            username='******', password='******')
            self.assertTrue(False)
        except:
            etype, evalue, etb = sys.exc_info()
            self.assertEqual(BadAuthenticationType, etype)
            self.assertEqual(['publickey'], evalue.allowed_types)

    def test_bad_password(self):
        """
        verify that a bad password gets the right exception, and that a retry
        with the right password works.
        """
        self.start_server()
        self.tc.connect(hostkey=self.public_host_key)
        try:
            self.tc.auth_password(username='******', password='******')
            self.assertTrue(False)
        except:
            etype, evalue, etb = sys.exc_info()
            self.assertTrue(issubclass(etype, AuthenticationException))
        self.tc.auth_password(username='******', password='******')
        self.verify_finished()

    def test_no_auth(self):
        """
        Test that a no auth connection is created when not providing any
        credentials.
        """
        self.start_server()
        try:
            self.tc.connect(hostkey=self.public_host_key)
            remain = self.tc.auth_none(username='******')
            self.assertTrue(False)
        except:
            etype, evalue, etb = sys.exc_info()
            self.assertTrue(issubclass(etype, AuthenticationException))
        
        self.verify_finished()

    def test_multipart_auth(self):
        """
        verify that multipart auth works.
        """
        self.start_server()
        self.tc.connect(hostkey=self.public_host_key)
        remain = self.tc.auth_password(username='******', password='******')
        self.assertEqual(['publickey'], remain)
        key = DSSKey.from_private_key_file(_support('test_dss.key'))
        remain = self.tc.auth_publickey(username='******', key=key)
        self.assertEqual([], remain)
        self.verify_finished()

    def test_interactive_auth(self):
        """
        verify keyboard-interactive auth works.
        """
        self.start_server()
        self.tc.connect(hostkey=self.public_host_key)

        def handler(title, instructions, prompts):
            self.got_title = title
            self.got_instructions = instructions
            self.got_prompts = prompts
            return ['cat']
        remain = self.tc.auth_interactive('commie', handler)
        self.assertEqual(self.got_title, 'password')
        self.assertEqual(self.got_prompts, [('Password', False)])
        self.assertEqual([], remain)
        self.verify_finished()

    def test_interactive_auth_fallback(self):
        """
        verify that a password auth attempt will fallback to "interactive"
        if password auth isn't supported but interactive is.
        """
        self.start_server()
        self.tc.connect(hostkey=self.public_host_key)
        remain = self.tc.auth_password('commie', 'cat')
        self.assertEqual([], remain)
        self.verify_finished()

    def test_auth_utf8(self):
        """
        verify that utf-8 encoding happens in authentication.
        """
        self.start_server()
        self.tc.connect(hostkey=self.public_host_key)
        remain = self.tc.auth_password('utf8', _pwd)
        self.assertEqual([], remain)
        self.verify_finished()

    def test_auth_non_utf8(self):
        """
        verify that non-utf-8 encoded passwords can be used for broken
        servers.
        """
        self.start_server()
        self.tc.connect(hostkey=self.public_host_key)
        remain = self.tc.auth_password('non-utf8', '\xff')
        self.assertEqual([], remain)
        self.verify_finished()

    def test_auth_gets_disconnected(self):
        """
        verify that we catch a server disconnecting during auth, and report
        it as an auth failure.
        """
        self.start_server()
        self.tc.connect(hostkey=self.public_host_key)
        try:
            remain = self.tc.auth_password('bad-server', 'hello')
        except:
            etype, evalue, etb = sys.exc_info()
            self.assertTrue(issubclass(etype, AuthenticationException))

    @slow
    def test_auth_non_responsive(self):
        """
        verify that authentication times out if server takes to long to
        respond (or never responds).
        """
        self.tc.auth_timeout = 1  # 1 second, to speed up test
        self.start_server()
        self.tc.connect()
        try:
            remain = self.tc.auth_password('unresponsive-server', 'hello')
        except:
            etype, evalue, etb = sys.exc_info()
            self.assertTrue(issubclass(etype, AuthenticationException))
            self.assertTrue('Authentication timeout' in str(evalue))
Beispiel #44
0
class TransportTest(ParamikoTest):
    def setUp(self):
        self.socks = LoopSocket()
        self.sockc = LoopSocket()
        self.sockc.link(self.socks)
        self.tc = Transport(self.sockc)
        self.ts = Transport(self.socks)

    def tearDown(self):
        self.tc.close()
        self.ts.close()
        self.socks.close()
        self.sockc.close()

    def setup_test_server(self, client_options=None, server_options=None):
        host_key = RSAKey.from_private_key_file('tests/test_rsa.key')
        public_host_key = RSAKey(data=str(host_key))
        self.ts.add_server_key(host_key)

        if client_options is not None:
            client_options(self.tc.get_security_options())
        if server_options is not None:
            server_options(self.ts.get_security_options())

        event = threading.Event()
        self.server = NullServer()
        self.assert_(not event.isSet())
        self.ts.start_server(event, self.server)
        self.tc.connect(hostkey=public_host_key,
                        username='******',
                        password='******')
        event.wait(1.0)
        self.assert_(event.isSet())
        self.assert_(self.ts.is_active())

    def test_1_security_options(self):
        o = self.tc.get_security_options()
        self.assertEquals(type(o), SecurityOptions)
        self.assert_(('aes256-cbc', 'blowfish-cbc') != o.ciphers)
        o.ciphers = ('aes256-cbc', 'blowfish-cbc')
        self.assertEquals(('aes256-cbc', 'blowfish-cbc'), o.ciphers)
        try:
            o.ciphers = ('aes256-cbc', 'made-up-cipher')
            self.assert_(False)
        except ValueError:
            pass
        try:
            o.ciphers = 23
            self.assert_(False)
        except TypeError:
            pass

    def test_2_compute_key(self):
        self.tc.K = 123281095979686581523377256114209720774539068973101330872763622971399429481072519713536292772709507296759612401802191955568143056534122385270077606457721553469730659233569339356140085284052436697480759510519672848743794433460113118986816826624865291116513647975790797391795651716378444844877749505443714557929L
        self.tc.H = unhexlify('0C8307CDE6856FF30BA93684EB0F04C2520E9ED3')
        self.tc.session_id = self.tc.H
        key = self.tc._compute_key('C', 32)
        self.assertEquals(
            '207E66594CA87C44ECCBA3B3CD39FDDB378E6FDB0F97C54B2AA0CFBF900CD995',
            hexlify(key).upper())

    def test_3_simple(self):
        """
        verify that we can establish an ssh link with ourselves across the
        loopback sockets.  this is hardly "simple" but it's simpler than the
        later tests. :)
        """
        host_key = RSAKey.from_private_key_file('tests/test_rsa.key')
        public_host_key = RSAKey(data=str(host_key))
        self.ts.add_server_key(host_key)
        event = threading.Event()
        server = NullServer()
        self.assert_(not event.isSet())
        self.assertEquals(None, self.tc.get_username())
        self.assertEquals(None, self.ts.get_username())
        self.assertEquals(False, self.tc.is_authenticated())
        self.assertEquals(False, self.ts.is_authenticated())
        self.ts.start_server(event, server)
        self.tc.connect(hostkey=public_host_key,
                        username='******',
                        password='******')
        event.wait(1.0)
        self.assert_(event.isSet())
        self.assert_(self.ts.is_active())
        self.assertEquals('slowdive', self.tc.get_username())
        self.assertEquals('slowdive', self.ts.get_username())
        self.assertEquals(True, self.tc.is_authenticated())
        self.assertEquals(True, self.ts.is_authenticated())

    def test_3a_long_banner(self):
        """
        verify that a long banner doesn't mess up the handshake.
        """
        host_key = RSAKey.from_private_key_file('tests/test_rsa.key')
        public_host_key = RSAKey(data=str(host_key))
        self.ts.add_server_key(host_key)
        event = threading.Event()
        server = NullServer()
        self.assert_(not event.isSet())
        self.socks.send(LONG_BANNER)
        self.ts.start_server(event, server)
        self.tc.connect(hostkey=public_host_key,
                        username='******',
                        password='******')
        event.wait(1.0)
        self.assert_(event.isSet())
        self.assert_(self.ts.is_active())

    def test_4_special(self):
        """
        verify that the client can demand odd handshake settings, and can
        renegotiate keys in mid-stream.
        """
        def force_algorithms(options):
            options.ciphers = ('aes256-cbc', )
            options.digests = ('hmac-md5-96', )

        self.setup_test_server(client_options=force_algorithms)
        self.assertEquals('aes256-cbc', self.tc.local_cipher)
        self.assertEquals('aes256-cbc', self.tc.remote_cipher)
        self.assertEquals(12, self.tc.packetizer.get_mac_size_out())
        self.assertEquals(12, self.tc.packetizer.get_mac_size_in())

        self.tc.send_ignore(1024)
        self.tc.renegotiate_keys()
        self.ts.send_ignore(1024)

    def test_5_keepalive(self):
        """
        verify that the keepalive will be sent.
        """
        self.setup_test_server()
        self.assertEquals(None, getattr(self.server, '_global_request', None))
        self.tc.set_keepalive(1)
        time.sleep(2)
        self.assertEquals('*****@*****.**', self.server._global_request)

    def test_6_exec_command(self):
        """
        verify that exec_command() does something reasonable.
        """
        self.setup_test_server()

        chan = self.tc.open_session()
        schan = self.ts.accept(1.0)
        try:
            chan.exec_command('no')
            self.assert_(False)
        except SSHException, x:
            pass

        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)
        schan.send('Hello there.\n')
        schan.send_stderr('This is on stderr.\n')
        schan.close()

        f = chan.makefile()
        self.assertEquals('Hello there.\n', f.readline())
        self.assertEquals('', f.readline())
        f = chan.makefile_stderr()
        self.assertEquals('This is on stderr.\n', f.readline())
        self.assertEquals('', f.readline())

        # now try it with combined stdout/stderr
        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)
        schan.send('Hello there.\n')
        schan.send_stderr('This is on stderr.\n')
        schan.close()

        chan.set_combine_stderr(True)
        f = chan.makefile()
        self.assertEquals('Hello there.\n', f.readline())
        self.assertEquals('This is on stderr.\n', f.readline())
        self.assertEquals('', f.readline())
Beispiel #45
0
class SFTPStore(Store):
    """implements the sftp:// storage backend

        configuration via openssh/sftp style urls and
        .ssh/config files

        does not support password authentication or password
        protected authentication keys"""
    def __init__(self, url, **kw):
        if self.netloc.find('@') != -1:
            user, self.netloc = self.netloc.split('@')
        else:
            user = None

        self.config = SSHHostConfig(self.netloc, user)

        host_keys = paramiko.util.load_host_keys(os.path.expanduser('~/.ssh/known_hosts'))
        try:
            self.hostkey = list(host_keys[self.config['hostkeyalias']].values())[0]
        except:
            print(str(self.config))
            raise


        if('identityfile' in self.config):
            key_file = os.path.expanduser(self.config['identityfile'])
            #not really nice but i don't see a cleaner way atm...
            try:
                self.auth_key = RSAKey (key_file)
            except SSHException as e:
                if e.message == 'Unable to parse file':
                    self.auth_key = DSAKey (key_file)
                else:
                    raise
        else:
            filename = os.path.expanduser('~/.ssh/id_rsa')
            if os.path.exists(filename):
                self.auth_key = RSAKey(filename)
            else:
                filename = os.path.expanduser('~/.ssh/id_dsa')
                if (os.path.exists(filename)):
                    self.auth_key = DSSKey (filename)

        self.__connect()

    def __connect(self):
        self.t = Transport((self.config['hostname'], self.config['port']))
        self.t.connect(username = self.config['user'], pkey = self.auth_key)
        self.client = SFTPClient.from_transport(self.t)
        self.client.chdir(self.path)

    def __build_fn(self, name):
        return "%s/%s" % (self.path,  name)

    def list(self, type):
        return list(filter(type_patterns[type].match, self.client.listdir(self.path)))

    def get(self, type, name):
        return self.client.open(self.__build_fn(name), mode = 'rb')

    def put(self, type, name, fp):
        remote_file = self.client.open(self.__build_fn(name), mode = 'wb')
        buf = fp.read(4096)
        while (len(buf) > 0):
            remote_file.write(buf)
            buf = fp.read(4096)
        remote_file.close()

    def delete(self, type, name):
        self.client.remove(self.__build_fn(name))

    def stat(self, type, name):
        try:
            stat = self.client.stat(self.__build_fn(name))
            return {'size': stat.st_size}
        except IOError:
            raise NotFoundError

    def close(self):
        """connection has to be explicitly closed, otherwise
            it will hold the process running idefinitly"""
        self.client.close()
        self.t.close()
Beispiel #46
0
class sftp_client:

    logger = logging.getLogger('sftprobe.client')

    def __init__(self, servaddr, username="", password="", key=None):

        self.transport_ = Transport(servaddr)
        self.key_ = key
        self.user_ = username
        self.pwd_ = password
        self.session_ = None

    @classmethod
    def get_command(classobj, cmdstr):
        cmdustr = cmdstr.upper()
        if cmdustr == "PUT":
            return sftp_commands.Put
        elif cmdustr == "GET":
            return sftp_commands.Get
        elif cmdustr == "LS":
            return sftp_commands.List
        elif cmdustr == "CD":
            return sftp_commands.ChangeDir
        else:
            raise Exception("Unknown SFTP command {0}".format(cmdstr))

    def connect(self):
        if not self.session_ and not self.transport_.is_active():
            if self.key_:  # Try private key, if available
                self.transport_.connect(username=self.user_, pkey=self.key_)
            elif len(self.pwd_) > 0:  # Next, try password, if available
                self.transport_.connect(username=self.user_,
                                        password=self.pwd_)
            else:  # Try just the user name
                self.transport_.connect(username=self.user_)

            self.session_ = SFTPClient.from_transport(self.transport_)

    def close(self):
        if self.session_:
            self.session_.close()
            self.session_ = None
        self.transport_.close()
        self.transport_ = None

    def get_status(self):
        if self.transport_.is_active():
            peer = self.transport_.getpeername()
            return "Connected to host [{0}], port {1}.".format(
                peer[0], peer[1])
        else:
            return "Not connected."

    def exec_sftp_cmd(self, cmd, **kwargs):
        self.connect()

        if cmd == sftp_commands.List:
            return self.session_.listdir(kwargs["RemotePath"])

        elif cmd == sftp_commands.ChangeDir:
            return self.session_.chdir(kwargs["RemotePath"])

        elif cmd == sftp_commands.Get:
            file_attrs = self.session_.get(kwargs["RemotePath"],
                                           kwargs["LocalPath"])

        elif cmd == sftp_commands.Put:
            file_attrs = self.session_.put(kwargs["LocalPath"],
                                           kwargs["RemotePath"])

    def do_changedir(self, path):
        return self.exec_sftp_cmd(sftp_commands.ChangeDir,
                                  RemotePath=path if len(path) > 0 else None)

    def do_listdir(self, path):
        return self.exec_sftp_cmd(sftp_commands.List,
                                  RemotePath=path if len(path) > 0 else ".")

    def do_get(self, rpth, lpth):
        return self.exec_sftp_cmd(sftp_commands.Get,
                                  RemotePath=rpth,
                                  LocalPath=lpth)

    def do_put(self, lpth, rpth):
        return self.exec_sftp_cmd(sftp_commands.Put,
                                  LocalPath=lpth,
                                  RemotePath=rpth)
Beispiel #47
0
class TransportTest(ParamikoTest):
    def setUp(self):
        self.socks = LoopSocket()
        self.sockc = LoopSocket()
        self.sockc.link(self.socks)
        self.tc = Transport(self.sockc)
        self.ts = Transport(self.socks)

    def tearDown(self):
        self.tc.close()
        self.ts.close()
        self.socks.close()
        self.sockc.close()

    def setup_test_server(self, client_options=None, server_options=None):
        host_key = RSAKey.from_private_key_file('tests/test_rsa.key')

        public_host_key = RSAKey(data=bytes(host_key))
        self.ts.add_server_key(host_key)
        
        if client_options is not None:
            client_options(self.tc.get_security_options())
        if server_options is not None:
            server_options(self.ts.get_security_options())
        
        event = threading.Event()
        self.server = NullServer()
        self.assert_(not event.isSet())
        self.ts.start_server(event, self.server)

        self.tc.connect(hostkey=public_host_key,
                        username='******', password='******')

        event.wait(1.0)
        self.assert_(event.isSet())
        self.assert_(self.ts.is_active())

    def test_1_security_options(self):
        o = self.tc.get_security_options()
        self.assertEquals(type(o), SecurityOptions)
        self.assert_((b'aes256-cbc', b'blowfish-cbc') != o.ciphers)
        o.ciphers = (b'aes256-cbc', b'blowfish-cbc')
        self.assertEquals((b'aes256-cbc', b'blowfish-cbc'), o.ciphers)
        try:
            o.ciphers = (b'aes256-cbc', b'made-up-cipher')
            self.assert_(False)
        except ValueError:
            pass
        try:
            o.ciphers = 23
            self.assert_(False)
        except TypeError:
            pass
            
    def test_2_compute_key(self):
        self.tc.K = 123281095979686581523377256114209720774539068973101330872763622971399429481072519713536292772709507296759612401802191955568143056534122385270077606457721553469730659233569339356140085284052436697480759510519672848743794433460113118986816826624865291116513647975790797391795651716378444844877749505443714557929
        self.tc.H = unhexlify(b'0C8307CDE6856FF30BA93684EB0F04C2520E9ED3')
        self.tc.session_id = self.tc.H
        key = self.tc._compute_key(b'C', 32)
        self.assertEquals(b'207E66594CA87C44ECCBA3B3CD39FDDB378E6FDB0F97C54B2AA0CFBF900CD995',
                          hexlify(key).upper())

    def test_3_simple(self):
        """
        verify that we can establish an ssh link with ourselves across the
        loopback sockets.  this is hardly "simple" but it's simpler than the
        later tests. :)
        """
        host_key = RSAKey.from_private_key_file('tests/test_rsa.key')
        public_host_key = RSAKey(data=bytes(host_key))
        self.ts.add_server_key(host_key)
        event = threading.Event()
        server = NullServer()
        self.assert_(not event.isSet())
        self.assertEquals(None, self.tc.get_username())
        self.assertEquals(None, self.ts.get_username())
        self.assertEquals(False, self.tc.is_authenticated())
        self.assertEquals(False, self.ts.is_authenticated())
        self.ts.start_server(event, server)
        self.tc.connect(hostkey=public_host_key,
                        username='******', password='******')
        event.wait(1.0)
        self.assert_(event.isSet())
        self.assert_(self.ts.is_active())
        self.assertEquals('slowdive', self.tc.get_username())
        self.assertEquals('slowdive', self.ts.get_username())
        self.assertEquals(True, self.tc.is_authenticated())
        self.assertEquals(True, self.ts.is_authenticated())

    def test_3a_long_banner(self):
        """
        verify that a long banner doesn't mess up the handshake.
        """
        host_key = RSAKey.from_private_key_file('tests/test_rsa.key')
        public_host_key = RSAKey(data=bytes(host_key))
        self.ts.add_server_key(host_key)
        event = threading.Event()
        server = NullServer()
        self.assert_(not event.isSet())
        self.socks.send(LONG_BANNER)
        self.ts.start_server(event, server)
        self.tc.connect(hostkey=public_host_key,
                        username='******', password='******')
        event.wait(1.0)
        self.assert_(event.isSet())
        self.assert_(self.ts.is_active())
        
    def test_4_special(self):
        """
        verify that the client can demand odd handshake settings, and can
        renegotiate keys in mid-stream.
        """
        def force_algorithms(options):
            options.ciphers = (b'aes256-cbc',)
            options.digests = (b'hmac-md5-96',)
        self.setup_test_server(client_options=force_algorithms)
        self.assertEquals(b'aes256-cbc', self.tc.local_cipher)
        self.assertEquals(b'aes256-cbc', self.tc.remote_cipher)
        self.assertEquals(12, self.tc.packetizer.get_mac_size_out())
        self.assertEquals(12, self.tc.packetizer.get_mac_size_in())
        
        self.tc.send_ignore(1024)
        self.tc.renegotiate_keys()
        self.ts.send_ignore(1024)

    def test_5_keepalive(self):
        """
        verify that the keepalive will be sent.
        """
        self.setup_test_server()
        self.assertEquals(None, getattr(self.server, '_global_request', None))
        self.tc.set_keepalive(1)
        time.sleep(2)
        self.assertEquals(b'*****@*****.**', self.server._global_request)
        
    def test_6_exec_command(self):
        """
        verify that exec_command() does something reasonable.
        """
        self.setup_test_server()

        chan = self.tc.open_session()
        schan = self.ts.accept(1.0)
        try:
            chan.exec_command('no')
            self.assert_(False)
        except SSHException as x:
            pass
        
        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)
        schan.send(b'Hello there.\n')
        schan.send_stderr(b'This is on stderr.\n')
        schan.close()

        f = chan.makefile()
        self.assertEquals(b'Hello there.\n', f.readline())
        self.assertEquals(b'', f.readline())
        f = chan.makefile_stderr()
        self.assertEquals(b'This is on stderr.\n', f.readline())
        self.assertEquals(b'', f.readline())
        
        # now try it with combined stdout/stderr
        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)
        schan.send(b'Hello there.\n')
        schan.send_stderr(b'This is on stderr.\n')
        schan.close()

        chan.set_combine_stderr(True)        
        f = chan.makefile()
        self.assertEquals(b'Hello there.\n', f.readline())
        self.assertEquals(b'This is on stderr.\n', f.readline())
        self.assertEquals(b'', f.readline())

    def test_7_invoke_shell(self):
        """
        verify that invoke_shell() does something reasonable.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.invoke_shell()
        schan = self.ts.accept(1.0)
        chan.send(b'communist j. cat\n')
        f = schan.makefile()
        self.assertEquals(b'communist j. cat\n', f.readline())
        chan.close()
        self.assertEquals(b'', f.readline())

    def test_8_channel_exception(self):
        """
        verify that ChannelException is thrown for a bad open-channel request.
        """
        self.setup_test_server()
        try:
            chan = self.tc.open_channel(b'bogus')
            self.fail('expected exception')
        except ChannelException as x:
            self.assert_(x.code == OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED)

    def test_9_exit_status(self):
        """
        verify that get_exit_status() works.
        """
        self.setup_test_server()

        chan = self.tc.open_session()
        schan = self.ts.accept(1.0)
        chan.exec_command('yes')
        schan.send(b'Hello there.\n')
        self.assert_(not chan.exit_status_ready())
        # trigger an EOF
        schan.shutdown_read()
        schan.shutdown_write()
        schan.send_exit_status(23)
        schan.close()
        
        f = chan.makefile()
        self.assertEquals(b'Hello there.\n', f.readline())
        self.assertEquals(b'', f.readline())
        count = 0
        while not chan.exit_status_ready():
            time.sleep(0.1)
            count += 1
            if count > 50:
                raise Exception("timeout")
        self.assertEquals(23, chan.recv_exit_status())
        chan.close()

    def test_A_select(self):
        """
        verify that select() on a channel works.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.invoke_shell()
        schan = self.ts.accept(1.0)

        # nothing should be ready        
        r, w, e = select.select([chan], [], [], 0.1)
        self.assertEquals([], r)
        self.assertEquals([], w)
        self.assertEquals([], e)
        
        schan.send(b'hello\n')
        
        # something should be ready now (give it 1 second to appear)
        for i in range(10):
            r, w, e = select.select([chan], [], [], 0.1)
            if chan in r:
                break
            time.sleep(0.1)
        self.assertEquals([chan], r)
        self.assertEquals([], w)
        self.assertEquals([], e)

        self.assertEquals(b'hello\n', chan.recv(6))
        
        # and, should be dead again now
        r, w, e = select.select([chan], [], [], 0.1)
        self.assertEquals([], r)
        self.assertEquals([], w)
        self.assertEquals([], e)

        schan.close()
        
        # detect eof?
        for i in range(10):
            r, w, e = select.select([chan], [], [], 0.1)
            if chan in r:
                break
            time.sleep(0.1)
        self.assertEquals([chan], r)
        self.assertEquals([], w)
        self.assertEquals([], e)
        self.assertEquals(b'', chan.recv(16))
        
        # make sure the pipe is still open for now...
        p = chan._pipe
        self.assertEquals(False, p._closed)
        chan.close()
        # ...and now is closed.
        self.assertEquals(True, p._closed)
   
    def test_B_renegotiate(self):
        """
        verify that a transport can correctly renegotiate mid-stream.
        """
        self.setup_test_server()
        self.tc.packetizer.REKEY_BYTES = 16384
        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)

        self.assertEquals(self.tc.H, self.tc.session_id)
        for i in range(20):
            chan.send(b'x' * 1024)
        chan.close()
        
        # allow a few seconds for the rekeying to complete
        for i in range(50):
            if self.tc.H != self.tc.session_id:
                break
            time.sleep(0.1)
        self.assertNotEquals(self.tc.H, self.tc.session_id)

        schan.close()

    def test_C_compression(self):
        """
        verify that zlib compression is basically working.
        """
        def force_compression(o):
            o.compression = (b'zlib',)
        self.setup_test_server(force_compression, force_compression)
        chan = self.tc.open_session()
        chan.exec_command(b'yes')
        schan = self.ts.accept(1.0)

        bytes = self.tc.packetizer._Packetizer__sent_bytes
        chan.send(b'x' * 1024)
        bytes2 = self.tc.packetizer._Packetizer__sent_bytes
        # tests show this is actually compressed to *52 bytes*!  including packet overhead!  nice!! :)
        self.assert_(bytes2 - bytes < 1024)
        self.assertEquals(52, bytes2 - bytes)

        chan.close()
        schan.close()

    def test_D_x11(self):
        """
        verify that an x11 port can be requested and opened.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.exec_command(b'yes')
        schan = self.ts.accept(1.0)
        
        requested = []
        def handler(c, addr):
            requested.append(addr)
            self.tc._queue_incoming_channel(c)
            
        self.assertEquals(None, getattr(self.server, '_x11_screen_number', None))
        cookie = chan.request_x11(0, single_connection=True, handler=handler)
        self.assertEquals(0, self.server._x11_screen_number)
        self.assertEquals(b'MIT-MAGIC-COOKIE-1', self.server._x11_auth_protocol)
        self.assertEquals(cookie, self.server._x11_auth_cookie)
        self.assertEquals(True, self.server._x11_single_connection)
        
        x11_server = self.ts.open_x11_channel(('localhost', 6093))
        x11_client = self.tc.accept()
        self.assertEquals('localhost', requested[0][0])
        self.assertEquals(6093, requested[0][1])
        
        x11_server.send(b'hello')
        self.assertEquals(b'hello', x11_client.recv(5))
        
        x11_server.close()
        x11_client.close()
        chan.close()
        schan.close()

    def test_E_reverse_port_forwarding(self):
        """
        verify that a client can ask the server to open a reverse port for
        forwarding.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)
        
        requested = []
        def handler(c, origin_addr, server_addr):
            requested.append(origin_addr)
            requested.append(server_addr)
            self.tc._queue_incoming_channel(c)
            
        port = self.tc.request_port_forward('127.0.0.1', 0, handler)
        self.assertEquals(port, self.server._listen.getsockname()[1])

        cs = socket.socket()
        cs.connect((b'127.0.0.1', port))
        ss, _ = self.server._listen.accept()
        sch = self.ts.open_forwarded_tcpip_channel(ss.getsockname(), ss.getpeername())
        cch = self.tc.accept()
        
        sch.send(b'hello')
        self.assertEquals(b'hello', cch.recv(5))
        sch.close()
        cch.close()
        ss.close()
        cs.close()
        
        # now cancel it.
        self.tc.cancel_port_forward(b'127.0.0.1', port)
        self.assertTrue(self.server._listen is None)

    def test_F_port_forwarding(self):
        """
        verify that a client can forward new connections from a locally-
        forwarded port.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)
        
        # open a port on the "server" that the client will ask to forward to.
        greeting_server = socket.socket()
        greeting_server.bind(('127.0.0.1', 0))
        greeting_server.listen(1)
        greeting_port = greeting_server.getsockname()[1]

        cs = self.tc.open_channel(b'direct-tcpip', ('127.0.0.1', greeting_port), ('', 9000))
        sch = self.ts.accept(1.0)
        cch = socket.socket()
        cch.connect(self.server._tcpip_dest)
        
        ss, _ = greeting_server.accept()
        ss.send(b'Hello!\n')
        ss.close()
        sch.send(cch.recv(8192))
        sch.close()
        
        self.assertEquals(b'Hello!\n', cs.recv(7))
        cs.close()

    def test_G_stderr_select(self):
        """
        verify that select() on a channel works even if only stderr is
        receiving data.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.invoke_shell()
        schan = self.ts.accept(1.0)

        # nothing should be ready        
        r, w, e = select.select([chan], [], [], 0.1)
        self.assertEquals([], r)
        self.assertEquals([], w)
        self.assertEquals([], e)
        
        schan.send_stderr(b'hello\n')
        
        # something should be ready now (give it 1 second to appear)
        for i in range(10):
            r, w, e = select.select([chan], [], [], 0.1)
            if chan in r:
                break
            time.sleep(0.1)
        self.assertEquals([chan], r)
        self.assertEquals([], w)
        self.assertEquals([], e)

        self.assertEquals(b'hello\n', chan.recv_stderr(6))
        
        # and, should be dead again now
        r, w, e = select.select([chan], [], [], 0.1)
        self.assertEquals([], r)
        self.assertEquals([], w)
        self.assertEquals([], e)

        schan.close()
        chan.close()

    def test_H_send_ready(self):
        """
        verify that send_ready() indicates when a send would not block.
        """
        self.setup_test_server()
        chan = self.tc.open_session()
        chan.invoke_shell()
        schan = self.ts.accept(1.0)

        self.assertEquals(chan.send_ready(), True)
        total = 0
        K = b'*' * 1024
        while total < 1024 * 1024:
            chan.send(K)
            total += len(K)
            if not chan.send_ready():
                break
        self.assert_(total < 1024 * 1024)

        schan.close()
        chan.close()
        self.assertEquals(chan.send_ready(), True)

    def test_I_rekey_deadlock(self):
        """
        Regression test for deadlock when in-transit messages are received after MSG_KEXINIT is sent
        
        Note: When this test fails, it may leak threads.
        """
        
        # Test for an obscure deadlocking bug that can occur if we receive
        # certain messages while initiating a key exchange.
        #
        # The deadlock occurs as follows:
        #
        # In the main thread:
        #   1. The user's program calls Channel.send(), which sends
        #      MSG_CHANNEL_DATA to the remote host.
        #   2. Packetizer discovers that REKEY_BYTES has been exceeded, and
        #      sets the __need_rekey flag.
        #
        # In the Transport thread:
        #   3. Packetizer notices that the __need_rekey flag is set, and raises
        #      NeedRekeyException.
        #   4. In response to NeedRekeyException, the transport thread sends
        #      MSG_KEXINIT to the remote host.
        # 
        # On the remote host (using any SSH implementation):
        #   5. The MSG_CHANNEL_DATA is received, and MSG_CHANNEL_WINDOW_ADJUST is sent.
        #   6. The MSG_KEXINIT is received, and a corresponding MSG_KEXINIT is sent.
        #
        # In the main thread:
        #   7. The user's program calls Channel.send().
        #   8. Channel.send acquires Channel.lock, then calls Transport._send_user_message().
        #   9. Transport._send_user_message waits for Transport.clear_to_send
        #      to be set (i.e., it waits for re-keying to complete).
        #      Channel.lock is still held.
        #
        # In the Transport thread:
        #   10. MSG_CHANNEL_WINDOW_ADJUST is received; Channel._window_adjust
        #       is called to handle it.
        #   11. Channel._window_adjust tries to acquire Channel.lock, but it
        #       blocks because the lock is already held by the main thread.
        #
        # The result is that the Transport thread never processes the remote
        # host's MSG_KEXINIT packet, because it becomes deadlocked while
        # handling the preceding MSG_CHANNEL_WINDOW_ADJUST message.

        # We set up two separate threads for sending and receiving packets,
        # while the main thread acts as a watchdog timer.  If the timer
        # expires, a deadlock is assumed.

        class SendThread(threading.Thread):
            def __init__(self, chan, iterations, done_event):
                threading.Thread.__init__(self, None, None, self.__class__.__name__)
                self.setDaemon(True)
                self.chan = chan
                self.iterations = iterations
                self.done_event = done_event
                self.watchdog_event = threading.Event()
                self.last = None
            
            def run(self):
                try:
                    for i in range(1, 1+self.iterations):
                        if self.done_event.isSet():
                            break
                        self.watchdog_event.set()
                        #print i, "SEND"
                        self.chan.send(b"x" * 2048)
                finally:
                    self.done_event.set()
                    self.watchdog_event.set()
        
        class ReceiveThread(threading.Thread):
            def __init__(self, chan, done_event):
                threading.Thread.__init__(self, None, None, self.__class__.__name__)
                self.setDaemon(True)
                self.chan = chan
                self.done_event = done_event
                self.watchdog_event = threading.Event()
            
            def run(self):
                try:
                    while not self.done_event.isSet():
                        if self.chan.recv_ready():
                            chan.recv(65536)
                            self.watchdog_event.set()
                        else:
                            if random.randint(0, 1):
                                time.sleep(random.randint(0, 500) / 1000.0)
                finally:
                    self.done_event.set()
                    self.watchdog_event.set()
        
        self.setup_test_server()
        self.ts.packetizer.REKEY_BYTES = 2048
        
        chan = self.tc.open_session()
        chan.exec_command('yes')
        schan = self.ts.accept(1.0)

        # Monkey patch the client's Transport._handler_table so that the client
        # sends MSG_CHANNEL_WINDOW_ADJUST whenever it receives an initial
        # MSG_KEXINIT.  This is used to simulate the effect of network latency
        # on a real MSG_CHANNEL_WINDOW_ADJUST message.
        self.tc._handler_table = self.tc._handler_table.copy()  # copy per-class dictionary
        _negotiate_keys = self.tc._handler_table[MSG_KEXINIT]
        def _negotiate_keys_wrapper(self, m):
            if self.local_kex_init is None: # Remote side sent KEXINIT
                # Simulate in-transit MSG_CHANNEL_WINDOW_ADJUST by sending it
                # before responding to the incoming MSG_KEXINIT.
                m2 = Message()
                m2.add_byte(chr(MSG_CHANNEL_WINDOW_ADJUST).encode())
                m2.add_int(chan.remote_chanid)
                m2.add_int(1)    # bytes to add
                self._send_message(m2)
            return _negotiate_keys(self, m)
        self.tc._handler_table[MSG_KEXINIT] = _negotiate_keys_wrapper
        
        # Parameters for the test
        iterations = 500    # The deadlock does not happen every time, but it
                            # should after many iterations.
        timeout = 5

        # This event is set when the test is completed
        done_event = threading.Event()

        # Start the sending thread
        st = SendThread(schan, iterations, done_event)
        st.start()
        
        # Start the receiving thread
        rt = ReceiveThread(chan, done_event)
        rt.start()

        # Act as a watchdog timer, checking 
        deadlocked = False
        while not deadlocked and not done_event.isSet():
            for event in (st.watchdog_event, rt.watchdog_event):
                event.wait(timeout)
                if done_event.isSet():
                    break
                if not event.isSet():
                    deadlocked = True
                    break
                event.clear()
        
        # Tell the threads to stop (if they haven't already stopped).  Note
        # that if one or more threads are deadlocked, they might hang around
        # forever (until the process exits).
        done_event.set()

        # Assertion: We must not have detected a timeout.
        self.assertFalse(deadlocked)

        # Close the channels
        schan.close()
        chan.close()
Beispiel #48
0
class IrmaSFTP(FTPInterface):
    """Irma SFTP handler

    This class handles the connection with a sftp server
    functions for interacting with it.
    """

    _Exception = IrmaSFTPError

    # ==================================
    #  Constructor and Destructor stuff
    # ==================================

    def __init__(self, host, port, auth, key_path, user, passwd,
                 dst_user=None, upload_path='uploads', hash_check=False,
                 autoconnect=True):
        self._conn = None
        self._client = None
        super().__init__(host, port, auth, key_path, user, passwd, dst_user,
                         upload_path, hash_check, autoconnect)

    def connected(self):
        return self._conn is not None

    # ============================
    #  Overridden private methods
    # ============================

    def _connect(self):
        self._conn = Transport((self._host, self._port))
        self._conn.window_size = pow(2, 27)
        self._conn.packetizer.REKEY_BYTES = pow(2, 32)
        self._conn.packetizer.REKEY_PACKETS = pow(2, 32)
        if self._auth == 'key':
            pkey = RSAKey.from_private_key_file(self._key_path)
            self._conn.connect(username=self._user, pkey=pkey)
        else:
            self._conn.connect(username=self._user, password=self._passwd)

        self._client = SFTPClient.from_transport(self._conn)

    def _disconnect(self, *, force=False):
        self._client = None
        if not force:
            self._conn.close()
        self._conn = None

    def _upload(self, remote, fobj):
        self._client.putfo(fobj, remote)

    def _download(self, remote, fobj):
        self._client.getfo(remote, fobj)

    def _ls(self, remote):
        return self._client.listdir(remote)

    def _is_file(self, remote):
        return not self._is_dir(remote)

    def _is_dir(self, remote):
        st = self._client.stat(remote)
        return stat.S_ISDIR(st.st_mode)

    def _rm(self, remote):
        self._client.remove(remote)

    def _rmdir(self, remote):
        self._client.rmdir(remote)

    def _mkdir(self, remote):
        self._client.mkdir(remote)

    def _mv(self, oldremote, newremote):
        self._client.rename(oldremote, newremote)