Monkeypatch sshim.expect, implement basic connect_handler, set default to localhost only
parent
4ee282e7d6
commit
ac11b1c359
25
main.py
25
main.py
|
@ -4,26 +4,25 @@ import sshim_patch as sshim
|
||||||
import lxd_interface
|
import lxd_interface
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import uuid
|
||||||
|
|
||||||
logging.basicConfig(level='DEBUG')
|
logging.basicConfig(level='DEBUG')
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
|
||||||
|
|
||||||
def connect_handler(script):
|
def connect_handler(script: sshim.Script):
|
||||||
# ask the SSH client to enter a name
|
instance_name = "instance-" + str(uuid.uuid4())
|
||||||
script.write('Please enter your name: ')
|
lxd_interface.create_instance(instance_name)
|
||||||
|
with paramiko.ProxyCommand(command_line=f'lxc exec {instance_name} -- /bin/bash') as proxy_command:
|
||||||
# match their input against a regular expression which will store the name in a capturing group called name
|
script.writeline(instance_name)
|
||||||
groups = script.expect(re.compile('(?P<name>.*)')).groupdict()
|
while True:
|
||||||
|
input_command = script.expect(None, echo=True) # TODO: change to false
|
||||||
# log on the server-side that the user has connected
|
proxy_command.send(input_command.encode())
|
||||||
logger.info('%(name)s just connected', **groups)
|
script.sendall(proxy_command.recv(100)) # TODO: fix
|
||||||
|
script.writeline("Sent!")
|
||||||
# send a message back to the SSH client greeting it by name
|
|
||||||
script.writeline('Hello %(name)s!' % groups)
|
|
||||||
|
|
||||||
|
|
||||||
server = sshim.Server(connect_handler, address='0.0.0.0', port=3000)
|
server = sshim.Server(connect_handler, address='127.0.0.1', port=3022)
|
||||||
try:
|
try:
|
||||||
server.run()
|
server.run()
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
|
|
|
@ -1,13 +1,60 @@
|
||||||
from sshim import *
|
from sshim import *
|
||||||
import paramiko
|
import paramiko
|
||||||
import os
|
import os
|
||||||
|
import six
|
||||||
|
import codecs
|
||||||
|
|
||||||
|
|
||||||
|
def expect(self, line, echo=True) -> str:
|
||||||
|
"""
|
||||||
|
Expect a line of input from the user. If this has the `match` method, it will call it on the input and return
|
||||||
|
the result, otherwise it will use the equality operator, ==. Notably, if a regular expression is passed in
|
||||||
|
its match method will be called and the matchdata returned. This allows you to use matching groups to pull
|
||||||
|
out interesting data and operate on it.
|
||||||
|
If ``echo`` is set to False, the server will not echo the input back to the client.
|
||||||
|
"""
|
||||||
|
buffer = six.BytesIO()
|
||||||
|
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
byte = self.fileobj.read(1)
|
||||||
|
|
||||||
|
if not byte or byte == '\x04':
|
||||||
|
raise EOFError()
|
||||||
|
elif byte == b'\t':
|
||||||
|
pass
|
||||||
|
elif byte == b'\x7f':
|
||||||
|
if buffer.tell() > 0:
|
||||||
|
self.sendall('\b \b')
|
||||||
|
buffer.truncate(buffer.tell() - 1)
|
||||||
|
elif byte == b'\x1b' and self.fileobj.read(1) == b'[':
|
||||||
|
command = self.fileobj.read(1)
|
||||||
|
if hasattr(self.delegate, 'cursor'):
|
||||||
|
self.delegate.cursor(command)
|
||||||
|
elif byte in (b'\r', b'\n'):
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
buffer.write(byte)
|
||||||
|
if echo:
|
||||||
|
self.sendall(byte)
|
||||||
|
|
||||||
|
if echo:
|
||||||
|
self.sendall('\r\n')
|
||||||
|
|
||||||
|
return codecs.decode(buffer.getvalue(), self.encoding)
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
raise
|
||||||
|
|
||||||
|
|
||||||
def check_auth_none(self, username):
|
def check_auth_none(self, username):
|
||||||
return paramiko.AUTH_PARTIALLY_SUCCESSFUL
|
if username == os.environ["ssh-username"]:
|
||||||
|
return paramiko.AUTH_PARTIALLY_SUCCESSFUL
|
||||||
|
return paramiko.AUTH_FAILED
|
||||||
|
|
||||||
|
|
||||||
def check_auth_password(self, username, password):
|
def check_auth_password(self, username, password):
|
||||||
|
print(os.environ["ssh-username"], os.environ["ssh-password"])
|
||||||
if username == os.environ["ssh-username"] and password == os.environ["ssh-password"]:
|
if username == os.environ["ssh-username"] and password == os.environ["ssh-password"]:
|
||||||
return paramiko.AUTH_SUCCESSFUL
|
return paramiko.AUTH_SUCCESSFUL
|
||||||
return paramiko.AUTH_FAILED
|
return paramiko.AUTH_FAILED
|
||||||
|
@ -17,13 +64,10 @@ def check_auth_publickey(self, username, key):
|
||||||
return paramiko.AUTH_FAILED
|
return paramiko.AUTH_FAILED
|
||||||
|
|
||||||
|
|
||||||
def enable_auth_gssapi(self):
|
Script.expect = expect
|
||||||
return paramiko.AUTH_FAILED
|
|
||||||
|
|
||||||
|
|
||||||
Handler.check_auth_none = check_auth_none
|
Handler.check_auth_none = check_auth_none
|
||||||
Handler.check_auth_password = check_auth_password
|
Handler.check_auth_password = check_auth_password
|
||||||
Handler.check_auth_publickey = check_auth_publickey
|
Handler.check_auth_publickey = check_auth_publickey
|
||||||
Handler.enable_auth_gssapi = enable_auth_gssapi
|
Handler.enable_auth_gssapi = paramiko.server.ServerInterface.enable_auth_gssapi
|
||||||
Handler.get_allowed_auths = paramiko.server.ServerInterface.get_allowed_auths
|
Handler.get_allowed_auths = paramiko.server.ServerInterface.get_allowed_auths
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue