OLD | NEW |
| (Empty) |
1 # -*- test-case-name: twisted.conch.test.test_manhole -*- | |
2 # Copyright (c) 2001-2004 Twisted Matrix Laboratories. | |
3 # See LICENSE for details. | |
4 | |
5 """ | |
6 insults/SSH integration support. | |
7 | |
8 @author: U{Jp Calderone<mailto:exarkun@twistedmatrix.com>} | |
9 """ | |
10 | |
11 from zope.interface import implements | |
12 | |
13 from twisted.conch import avatar, interfaces as iconch, error as econch | |
14 from twisted.conch.ssh import factory, keys, session | |
15 from twisted.cred import credentials, checkers, portal | |
16 from twisted.python import components | |
17 | |
18 from twisted.conch.insults import insults | |
19 | |
20 class _Glue: | |
21 """A feeble class for making one attribute look like another. | |
22 | |
23 This should be replaced with a real class at some point, probably. | |
24 Try not to write new code that uses it. | |
25 """ | |
26 def __init__(self, **kw): | |
27 self.__dict__.update(kw) | |
28 | |
29 def __getattr__(self, name): | |
30 raise AttributeError(self.name, "has no attribute", name) | |
31 | |
32 class TerminalSessionTransport: | |
33 def __init__(self, proto, chainedProtocol, avatar, width, height): | |
34 self.proto = proto | |
35 self.avatar = avatar | |
36 self.chainedProtocol = chainedProtocol | |
37 | |
38 session = self.proto.session | |
39 | |
40 self.proto.makeConnection( | |
41 _Glue(write=self.chainedProtocol.dataReceived, | |
42 loseConnection=lambda: avatar.conn.sendClose(session), | |
43 name="SSH Proto Transport")) | |
44 | |
45 def loseConnection(): | |
46 self.proto.loseConnection() | |
47 | |
48 self.chainedProtocol.makeConnection( | |
49 _Glue(write=self.proto.write, | |
50 loseConnection=loseConnection, | |
51 name="Chained Proto Transport")) | |
52 | |
53 # XXX TODO | |
54 # chainedProtocol is supposed to be an ITerminalTransport, | |
55 # maybe. That means perhaps its terminalProtocol attribute is | |
56 # an ITerminalProtocol, it could be. So calling terminalSize | |
57 # on that should do the right thing But it'd be nice to clean | |
58 # this bit up. | |
59 self.chainedProtocol.terminalProtocol.terminalSize(width, height) | |
60 | |
61 class TerminalSession(components.Adapter): | |
62 implements(iconch.ISession) | |
63 | |
64 transportFactory = TerminalSessionTransport | |
65 chainedProtocolFactory = insults.ServerProtocol | |
66 | |
67 def getPty(self, term, windowSize, attrs): | |
68 self.height, self.width = windowSize[:2] | |
69 | |
70 def openShell(self, proto): | |
71 self.transportFactory( | |
72 proto, self.chainedProtocolFactory(), | |
73 iconch.IConchUser(self.original), | |
74 self.width, self.height) | |
75 | |
76 def execCommand(self, proto, cmd): | |
77 raise econch.ConchError("Cannot execute commands") | |
78 | |
79 def closed(self): | |
80 pass | |
81 | |
82 class TerminalUser(avatar.ConchUser, components.Adapter): | |
83 def __init__(self, original, avatarId): | |
84 components.Adapter.__init__(self, original) | |
85 avatar.ConchUser.__init__(self) | |
86 self.channelLookup['session'] = session.SSHSession | |
87 | |
88 class TerminalRealm: | |
89 userFactory = TerminalUser | |
90 sessionFactory = TerminalSession | |
91 | |
92 transportFactory = TerminalSessionTransport | |
93 chainedProtocolFactory = insults.ServerProtocol | |
94 | |
95 def _getAvatar(self, avatarId): | |
96 comp = components.Componentized() | |
97 user = self.userFactory(comp, avatarId) | |
98 sess = self.sessionFactory(comp) | |
99 | |
100 sess.transportFactory = self.transportFactory | |
101 sess.chainedProtocolFactory = self.chainedProtocolFactory | |
102 | |
103 comp.setComponent(iconch.IConchUser, user) | |
104 comp.setComponent(iconch.ISession, sess) | |
105 | |
106 return user | |
107 | |
108 def __init__(self, transportFactory=None): | |
109 if transportFactory is not None: | |
110 self.transportFactory = transportFactory | |
111 | |
112 def requestAvatar(self, avatarId, mind, *interfaces): | |
113 for i in interfaces: | |
114 if i is iconch.IConchUser: | |
115 return (iconch.IConchUser, | |
116 self._getAvatar(avatarId), | |
117 lambda: None) | |
118 raise NotImplementedError() | |
119 | |
120 class ConchFactory(factory.SSHFactory): | |
121 publicKey = 'ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAGEArzJx8OYOnJmzf4tfBEvLi8DVPrJ
3/c9k2I/Az64fxjHf9imyRJbixtQhlH9lfNjUIx+4LmrJH5QNRsFporcHDKOTwTTYLh5KmRpslkYHRiv
cJSkbh/C+BR3utDS555mV' | |
122 | |
123 publicKeys = { | |
124 'ssh-rsa' : keys.Key.fromString(publicKey) | |
125 } | |
126 del publicKey | |
127 | |
128 privateKey = """-----BEGIN RSA PRIVATE KEY----- | |
129 MIIByAIBAAJhAK8ycfDmDpyZs3+LXwRLy4vA1T6yd/3PZNiPwM+uH8Yx3/YpskSW | |
130 4sbUIZR/ZXzY1CMfuC5qyR+UDUbBaaK3Bwyjk8E02C4eSpkabJZGB0Yr3CUpG4fw | |
131 vgUd7rQ0ueeZlQIBIwJgbh+1VZfr7WftK5lu7MHtqE1S1vPWZQYE3+VUn8yJADyb | |
132 Z4fsZaCrzW9lkIqXkE3GIY+ojdhZhkO1gbG0118sIgphwSWKRxK0mvh6ERxKqIt1 | |
133 xJEJO74EykXZV4oNJ8sjAjEA3J9r2ZghVhGN6V8DnQrTk24Td0E8hU8AcP0FVP+8 | |
134 PQm/g/aXf2QQkQT+omdHVEJrAjEAy0pL0EBH6EVS98evDCBtQw22OZT52qXlAwZ2 | |
135 gyTriKFVoqjeEjt3SZKKqXHSApP/AjBLpF99zcJJZRq2abgYlf9lv1chkrWqDHUu | |
136 DZttmYJeEfiFBBavVYIF1dOlZT0G8jMCMBc7sOSZodFnAiryP+Qg9otSBjJ3bQML | |
137 pSTqy7c3a2AScC/YyOwkDaICHnnD3XyjMwIxALRzl0tQEKMXs6hH8ToUdlLROCrP | |
138 EhQ0wahUTCk1gKA4uPD6TMTChavbh4K63OvbKg== | |
139 -----END RSA PRIVATE KEY-----""" | |
140 privateKeys = { | |
141 'ssh-rsa' : keys.Key.fromString(privateKey) | |
142 } | |
143 del privateKey | |
144 | |
145 def __init__(self, portal): | |
146 self.portal = portal | |
OLD | NEW |