CaiWuXiTong/tests/scripts/deploy-auth-server.py

87 lines
2.9 KiB
Python

"""Loopback-only SSH/SFTP fixture; password arrives through stdin, never logs."""
import io
import socket
import sys
import threading
import time
import paramiko
password = sys.stdin.readline().rstrip('\n')
key = paramiko.RSAKey.generate(2048)
class Server(paramiko.ServerInterface):
def __init__(self):
self.direct = set()
def check_auth_password(self, username, supplied):
return paramiko.AUTH_SUCCESSFUL if supplied == password else paramiko.AUTH_FAILED
def get_allowed_auths(self, username):
return 'password'
def check_channel_request(self, kind, chanid):
return paramiko.OPEN_SUCCEEDED if kind == 'session' else paramiko.OPEN_FAILED_ADMINISTRATIVELY_PROHIBITED
def check_channel_direct_tcpip_request(self, chanid, origin, destination):
self.direct.add(chanid)
return paramiko.OPEN_SUCCEEDED
def check_channel_exec_request(self, channel, command):
def finish():
time.sleep(0.1)
channel.send_exit_status(0)
channel.close()
threading.Thread(target=finish, daemon=True).start()
return True
class SFTP(paramiko.SFTPServerInterface):
def stat(self, path):
return paramiko.SFTP_NO_SUCH_FILE
def open(self, path, flags, attr):
class Handle(paramiko.SFTPHandle):
def chattr(self, attr):
return paramiko.SFTP_OK
handle = Handle(flags)
handle.writefile = io.BytesIO()
return handle
def connection(client):
transport = paramiko.Transport(client)
transport.add_server_key(key)
class SFTPSubsystem(paramiko.SFTPServer):
def start_subsystem(self, name, transport, channel):
super().start_subsystem(name, transport, channel)
channel.send_exit_status(0)
transport.set_subsystem_handler('sftp', SFTPSubsystem, SFTP)
try:
server = Server()
channels = []
transport.start_server(server=server)
while transport.is_active():
channel = transport.accept(0.5)
if channel:
channels.append(channel)
if channel.chanid not in server.direct:
continue
def echo(c):
while not c.closed:
if c.recv_ready():
data = c.recv(1024)
if data:
c.sendall(data)
time.sleep(0.01)
threading.Thread(target=echo, args=(channel,), daemon=True).start()
except (EOFError, OSError, paramiko.SSHException):
pass
finally:
transport.close()
listener = socket.socket()
listener.bind(('127.0.0.1', 0))
listener.listen(10)
print(listener.getsockname()[1], flush=True)
while True:
client, _ = listener.accept()
threading.Thread(target=connection, args=(client,), daemon=True).start()