summaryrefslogtreecommitdiffhomepage
path: root/channel.py
diff options
context:
space:
mode:
authorRobey Pointer <robey@lag.net>2003-11-10 04:54:02 +0000
committerRobey Pointer <robey@lag.net>2003-11-10 04:54:02 +0000
commitaad7b859f194451a0529c4d8aa20cdc724ae33a2 (patch)
tree24b19c05626e547f3f3bc4a12c7a8c64578dbed5 /channel.py
parent0e1ef2c65c80bd76eb62f5dfd953cb987d36ce3a (diff)
[project @ Arch-1:robey@lag.net--2003-public%secsh--dev--1.0--patch-7]
cleaned up server code, renamed some files & classes renamed demo-server.py and demo-host-key to demo_server.py and demo_host_key, just to be consistent. renamed SSHException -> SecshException. generalized the mechanism where Channel decides whether to allow different channel requests: 4 of the main ones (pty, window-change, shell, and subsystem) go through easily override-able methods now. you could probably make an actual ssh shell server. gave ChannelFile a repr(). turned off ultra debugging in the demos. demo_server creates a subclass of Channel to allow pty/shell and sets an event when the shell request is made, so that it knows when it can start sending the fake bbs. renamed to charmander and updated some of the distutils files.
Diffstat (limited to 'channel.py')
-rw-r--r--channel.py57
1 files changed, 44 insertions, 13 deletions
diff --git a/channel.py b/channel.py
index 8f53d379..8bbe22a5 100644
--- a/channel.py
+++ b/channel.py
@@ -1,5 +1,5 @@
from message import Message
-from secsh import SSHException
+from secsh import SecshException
from transport import MSG_CHANNEL_REQUEST, MSG_CHANNEL_CLOSE, MSG_CHANNEL_WINDOW_ADJUST, MSG_CHANNEL_DATA, \
MSG_CHANNEL_EOF, MSG_CHANNEL_SUCCESS, MSG_CHANNEL_FAILURE
@@ -100,6 +100,22 @@ class Channel(object):
finally:
self.lock.release()
+ def check_pty_request(self, term, width, height, pixelwidth, pixelheight, modes):
+ "override me! return True if a pty of the given dimensions (for shell access, usually) can be provided"
+ return False
+
+ def check_shell_request(self):
+ "override me! return True if shell access will be provided"
+ return False
+
+ def check_subsystem_request(self, name):
+ "override me! return True if the given subsystem can be provided"
+ return False
+
+ def check_window_change_request(self, width, height, pixelwidth, pixelheight):
+ "override me! return True if the pty was resized"
+ return False
+
def handle_request(self, m):
key = m.get_string()
want_reply = m.get_boolean()
@@ -110,10 +126,25 @@ class Channel(object):
elif key == 'xon-xoff':
# ignore
ok = True
- elif (key == 'pty-req') or (key == 'shell'):
- if self.transport.server_mode:
- # humor them
- ok = True
+ elif key == 'pty-req':
+ term = m.get_string()
+ width = m.get_int()
+ height = m.get_int()
+ pixelwidth = m.get_int()
+ pixelheight = m.get_int()
+ modes = m.get_string()
+ ok = self.check_pty_request(term, width, height, pixelwidth, pixelheight, modes)
+ elif key == 'shell':
+ ok = self.check_shell_request()
+ elif key == 'subsystem':
+ name = m.get_string()
+ ok = self.check_subsystem_request(name)
+ elif key == 'window-change':
+ width = m.get_int()
+ height = m.get_int()
+ pixelwidth = m.get_int()
+ pixelheight = m.get_int()
+ ok = self.check_window_change_request(width, height, pixelwidth, pixelheight)
else:
self.log(DEBUG, 'Unhandled channel request "%s"' % key)
ok = False
@@ -155,7 +186,7 @@ class Channel(object):
def get_pty(self, term='vt100', width=80, height=24):
if self.closed or self.eof_received or self.eof_sent or not self.active:
- raise SSHException('Channel is not open')
+ raise SecshException('Channel is not open')
m = Message()
m.add_byte(chr(MSG_CHANNEL_REQUEST))
m.add_int(self.remote_chanid)
@@ -171,7 +202,7 @@ class Channel(object):
def invoke_shell(self):
if self.closed or self.eof_received or self.eof_sent or not self.active:
- raise SSHException('Channel is not open')
+ raise SecshException('Channel is not open')
m = Message()
m.add_byte(chr(MSG_CHANNEL_REQUEST))
m.add_int(self.remote_chanid)
@@ -181,7 +212,7 @@ class Channel(object):
def exec_command(self, command):
if self.closed or self.eof_received or self.eof_sent or not self.active:
- raise SSHException('Channel is not open')
+ raise SecshException('Channel is not open')
m = Message()
m.add_byte(chr(MSG_CHANNEL_REQUEST))
m.add_int(self.remote_chanid)
@@ -192,7 +223,7 @@ class Channel(object):
def invoke_subsystem(self, subsystem):
if self.closed or self.eof_received or self.eof_sent or not self.active:
- raise SSHException('Channel is not open')
+ raise SecshException('Channel is not open')
m = Message()
m.add_byte(chr(MSG_CHANNEL_REQUEST))
m.add_int(self.remote_chanid)
@@ -203,7 +234,7 @@ class Channel(object):
def resize_pty(self, width=80, height=24):
if self.closed or self.eof_received or self.eof_sent or not self.active:
- raise SSHException('Channel is not open')
+ raise SecshException('Channel is not open')
m = Message()
m.add_byte(chr(MSG_CHANNEL_REQUEST))
m.add_int(self.remote_chanid)
@@ -500,9 +531,6 @@ class ChannelFile(object):
XXX Todo: the channel and its file-wrappers should be able to be closed or
garbage-collected independently, for compatibility with real sockets and
their file-wrappers. Currently, closing does nothing but flush the buffer.
- XXX Todo: translation of the various forms of newline is not implemented,
- let alone the universal newline. Line buffering (for writing) is
- implemented, though, which makes little sense without text mode support.
"""
def __init__(self, channel, mode = "r", buf_size = -1):
@@ -528,6 +556,9 @@ class ChannelFile(object):
self.newlines = None
self.softspace = False
+ def __repr__(self):
+ return '<secsh.ChannelFile from ' + repr(self.channel) + '>'
+
def __iter__(self):
return self