Commit 44f92e5c authored by Sam Rushing's avatar Sam Rushing

server: add some (currently unused) support for PTY's

parent 58a4214e
......@@ -57,35 +57,128 @@ class Interactive_Session_Client(Interactive_Session):
def exec_command(self, command):
self.send_channel_request('exec', EXEC_CHANNEL_REQUEST_PAYLOAD, (command,))
# I think to do anything useful here we'll need full terminal emulation like http://liftoff.github.io/GateOne/Developer/terminal.html
# from RFC4254 section 8
pty_modes = {
0: ('TTY_OP_END', "Indicates end of options."),
1: ('VINTR', "Interrupt character; 255 if none. Similarly for the other characters. Not all of these characters are supported on all systems."),
2: ('VQUIT', "The quit character (sends SIGQUIT signal on POSIX systems)."),
3: ('VERASE', "Erase the character to left of the cursor."),
4: ('VKILL', "Kill the current input line."),
5: ('VEOF', "End-of-file character (sends EOF from the terminal)."),
6: ('VEOL', "End-of-line character in addition to carriage return and/or linefeed."),
7: ('VEOL2', "Additional end-of-line character."),
8: ('VSTART', "Continues paused output (normally control-Q)."),
9: ('VSTOP', "Pauses output (normally control-S)."),
10: ('VSUSP', "Suspends the current program."),
11: ('VDSUSP', "Another suspend character."),
12: ('VREPRINT', "Reprints the current input line."),
13: ('VWERASE', "Erases a word left of cursor."),
14: ('VLNEXT', "Enter the next character typed literally, even if it is a special character"),
15: ('VFLUSH', "Character to flush output."),
16: ('VSWTCH', "Switch to a different shell layer."),
17: ('VSTATUS', "Prints system status line (load, command, pid, etc)."),
18: ('VDISCARD', "Toggles the flushing of terminal output."),
30: ('IGNPAR', "The ignore parity flag. The parameter SHOULD be 0 if this flag is FALSE, and 1 if it is TRUE."),
31: ('PARMRK', "Mark parity and framing errors."),
32: ('INPCK', "Enable checking of parity errors."),
33: ('ISTRIP', "Strip 8th bit off characters."),
34: ('INLCR', "Map NL into CR on input."),
35: ('IGNCR', "Ignore CR on input."),
36: ('ICRNL', "Map CR to NL on input."),
37: ('IUCLC', "Translate uppercase characters to lowercase."),
38: ('IXON', "Enable output flow control."),
39: ('IXANY', "Any char will restart after stop."),
40: ('IXOFF', "Enable input flow control."),
41: ('IMAXBEL', "Ring bell on input queue full."),
50: ('ISIG', "Enable signals INTR, QUIT, [D]SUSP."),
51: ('ICANON', "Canonicalize input lines."),
52: ('XCASE', "Enable input and output of uppercase characters by preceding their lowercase equivalents '\'."),
53: ('ECHO', "Enable echoing."),
54: ('ECHOE', "Visually erase chars."),
55: ('ECHOK', "Kill character discards current line."),
56: ('ECHONL', "Echo NL even if ECHO is off."),
57: ('NOFLSH', "Don't flush after interrupt."),
58: ('TOSTOP', "Stop background jobs from output."),
59: ('IEXTEN', "Enable extensions."),
60: ('ECHOCTL', "Echo control characters as ^(Char)."),
61: ('ECHOKE', "Visual erase for line kill."),
62: ('PENDIN', "Retype pending input."),
70: ('OPOST', "Enable output processing."),
71: ('OLCUC', "Convert lowercase to uppercase."),
72: ('ONLCR', "Map NL to CR-NL."),
73: ('OCRNL', "Translate carriage return to newline (output)."),
74: ('ONOCR', "Translate newline to carriage return-newline (output)."),
75: ('ONLRET', "Newline performs a carriage return (output)."),
90: ('CS7', "7 bit mode."),
91: ('CS8', "8 bit mode."),
92: ('PARENB', "Parity enable."),
93: ('PARODD', "Odd parity, else even."),
128: ('TTY_OP_ISPEED', "Specifies the input baud rate in bits per second."),
129: ('TTY_OP_OSPEED', "Specifies the output baud rate in bits per second."),
}
class PTY:
def __init__ (self, settings):
self.term, self.width_char, self.height_char, self.width_pixels, self.height_pixels, self.modes = settings
#self.unpack_modes()
def unpack_modes (self):
import struct
i = 0
modes = self.modes
while i < len (modes):
opcode = ord (modes[i])
i += 1
if opcode >= 160:
break
elif pty_modes.has_key (opcode):
name, description = pty_modes[opcode]
value, = struct.unpack ('>L', modes[i:i+4])
setattr (self, name, value)
i += 4
#W ('PTY setting: %r = %r\n' % (name, value))
else:
#W ('unknown PTY setting: %r = %r\n' % (opcode, struct.unpack ('>L', modes[i:i+4])))
i += 4
class Interactive_Session_Server(Interactive_Session):
def handle_request(self, request_type, want_reply, type_specific_packet_data):
W ('interactive_session_server: handle_request %r %r %r\n' % (request_type, want_reply, type_specific_packet_data))
#W ('interactive_session_server: handle_request %r %r %r\n' % (request_type, want_reply, type_specific_packet_data))
if self.request_handlers.has_key(request_type):
self.request_handlers[request_type] (self, want_reply, type_specific_packet_data)
else:
if want_reply:
packet = ssh_packet.pack_payload(SSH_MSG_CHANNEL_FAILURE_PAYLOAD, (self.remote_channel.channel_id,))
self.transport.send_packet(packet)
elif want_reply:
packet = ssh_packet.pack_payload(SSH_MSG_CHANNEL_FAILURE_PAYLOAD, (self.remote_channel.channel_id,))
self.transport.send_packet(packet)
# by default, refuse PTY requests, a lot of terminal smarts are needed to do it right.
accept_pty = False
def handle_pty_request(self, want_reply, type_specific_packet_data):
term, width_char, height_char, width_pixels, height_pixels, modes = ssh_packet.unpack_payload(PTY_CHANNEL_REQUEST_PAYLOAD, type_specific_packet_data)
# XXX do some PTY crap here
self.send_channel_request_failure()
self.pty = PTY (ssh_packet.unpack_payload(PTY_CHANNEL_REQUEST_PAYLOAD, type_specific_packet_data))
if want_reply:
if self.accept_pty:
self.send_channel_request_success()
else:
self.send_channel_request_failure()
def handle_x11_request(self, want_reply, type_specific_packet_data):
single_connection, auth_protocol, auth_cookie, screen_number = ssh_packet.unpack_payload(X11_CHANNEL_REQUEST_PAYLOAD, type_specific_packet_data)
# XXX fantasize about doing X11 forwarding here? I think not.
self.send_channel_request_failure()
if want_reply:
self.send_channel_request_failure()
def handle_shell_request(self, want_reply, type_specific_packet_data):
# XXX whatever, sure, it worked.
self.send_channel_request_success()
if want_reply:
self.send_channel_request_success()
request_handlers = {
'pty-req': handle_pty_request,
'x11-req': handle_x11_request,
'shell' : handle_shell_request,
# env :
# exec :
# subsystem :
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment