1
# -*- test-case-name: twisted.conch.test.test_manhole -*-
2
# Copyright (c) 2001-2004 Twisted Matrix Laboratories.
3
# See LICENSE for details.
5
"""insults/SSH integration support.
7
API Stability: Unstable
9
@author: U{Jp Calderone<mailto:exarkun@twistedmatrix.com>}
12
from zope.interface import implements
14
from twisted.conch import avatar, interfaces as iconch, error as econch
15
from twisted.conch.ssh import factory, keys, session
16
from twisted.cred import credentials, checkers, portal
17
from twisted.python import components
19
from twisted.conch.insults import insults
22
"""A feeble class for making one attribute look like another.
24
This should be replaced with a real class at some point, probably.
25
Try not to write new code that uses it.
27
def __init__(self, **kw):
28
self.__dict__.update(kw)
30
def __getattr__(self, name):
31
raise AttributeError(self.name, "has no attribute", name)
33
class TerminalSessionTransport:
34
def __init__(self, proto, chainedProtocol, avatar, width, height):
37
self.chainedProtocol = chainedProtocol
39
session = self.proto.session
41
self.proto.makeConnection(
42
_Glue(write=self.chainedProtocol.dataReceived,
43
loseConnection=lambda: avatar.conn.sendClose(session),
44
name="SSH Proto Transport"))
47
self.proto.loseConnection()
49
self.chainedProtocol.makeConnection(
50
_Glue(write=self.proto.write,
51
loseConnection=loseConnection,
52
name="Chained Proto Transport"))
55
# chainedProtocol is supposed to be an ITerminalTransport,
56
# maybe. That means perhaps its terminalProtocol attribute is
57
# an ITerminalProtocol, it could be. So calling terminalSize
58
# on that should do the right thing But it'd be nice to clean
60
self.chainedProtocol.terminalProtocol.terminalSize(width, height)
62
class TerminalSession(components.Adapter):
63
implements(iconch.ISession)
65
transportFactory = TerminalSessionTransport
66
chainedProtocolFactory = insults.ServerProtocol
68
def getPty(self, term, windowSize, attrs):
69
self.height, self.width = windowSize[:2]
71
def openShell(self, proto):
72
self.transportFactory(
73
proto, self.chainedProtocolFactory(),
74
iconch.IConchUser(self.original),
75
self.width, self.height)
77
def execCommand(self, proto, cmd):
78
raise econch.ConchError("Cannot execute commands")
83
class TerminalUser(avatar.ConchUser, components.Adapter):
84
def __init__(self, original, avatarId):
85
components.Adapter.__init__(self, original)
86
avatar.ConchUser.__init__(self)
87
self.channelLookup['session'] = session.SSHSession
90
userFactory = TerminalUser
91
sessionFactory = TerminalSession
93
transportFactory = TerminalSessionTransport
94
chainedProtocolFactory = insults.ServerProtocol
96
def _getAvatar(self, avatarId):
97
comp = components.Componentized()
98
user = self.userFactory(comp, avatarId)
99
sess = self.sessionFactory(comp)
101
sess.transportFactory = self.transportFactory
102
sess.chainedProtocolFactory = self.chainedProtocolFactory
104
comp.setComponent(iconch.IConchUser, user)
105
comp.setComponent(iconch.ISession, sess)
109
def __init__(self, transportFactory=None):
110
if transportFactory is not None:
111
self.transportFactory = transportFactory
113
def requestAvatar(self, avatarId, mind, *interfaces):
115
if i is iconch.IConchUser:
116
return (iconch.IConchUser,
117
self._getAvatar(avatarId),
119
raise NotImplementedError()
121
class ConchFactory(factory.SSHFactory):
122
publicKey = 'ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAGEArzJx8OYOnJmzf4tfBEvLi8DVPrJ3/c9k2I/Az64fxjHf9imyRJbixtQhlH9lfNjUIx+4LmrJH5QNRsFporcHDKOTwTTYLh5KmRpslkYHRivcJSkbh/C+BR3utDS555mV'
125
'ssh-rsa' : keys.getPublicKeyString(data = publicKey)
129
privateKey = """-----BEGIN RSA PRIVATE KEY-----
130
MIIByAIBAAJhAK8ycfDmDpyZs3+LXwRLy4vA1T6yd/3PZNiPwM+uH8Yx3/YpskSW
131
4sbUIZR/ZXzY1CMfuC5qyR+UDUbBaaK3Bwyjk8E02C4eSpkabJZGB0Yr3CUpG4fw
132
vgUd7rQ0ueeZlQIBIwJgbh+1VZfr7WftK5lu7MHtqE1S1vPWZQYE3+VUn8yJADyb
133
Z4fsZaCrzW9lkIqXkE3GIY+ojdhZhkO1gbG0118sIgphwSWKRxK0mvh6ERxKqIt1
134
xJEJO74EykXZV4oNJ8sjAjEA3J9r2ZghVhGN6V8DnQrTk24Td0E8hU8AcP0FVP+8
135
PQm/g/aXf2QQkQT+omdHVEJrAjEAy0pL0EBH6EVS98evDCBtQw22OZT52qXlAwZ2
136
gyTriKFVoqjeEjt3SZKKqXHSApP/AjBLpF99zcJJZRq2abgYlf9lv1chkrWqDHUu
137
DZttmYJeEfiFBBavVYIF1dOlZT0G8jMCMBc7sOSZodFnAiryP+Qg9otSBjJ3bQML
138
pSTqy7c3a2AScC/YyOwkDaICHnnD3XyjMwIxALRzl0tQEKMXs6hH8ToUdlLROCrP
139
EhQ0wahUTCk1gKA4uPD6TMTChavbh4K63OvbKg==
140
-----END RSA PRIVATE KEY-----"""
142
'ssh-rsa' : keys.getPrivateKeyObject(data = privateKey)
146
def __init__(self, portal):