OLD | NEW |
| (Empty) |
1 # Copyright (c) 2001-2008 Twisted Matrix Laboratories. | |
2 # See LICENSE for details. | |
3 | |
4 | |
5 import os | |
6 | |
7 from twisted.internet import defer, protocol, reactor | |
8 from twisted.conch import error | |
9 from twisted.conch.ssh import transport | |
10 from twisted.python import log | |
11 | |
12 from twisted.conch.client import unix | |
13 | |
14 | |
15 | |
16 class SSHClientFactory(protocol.ClientFactory): | |
17 | |
18 def __init__(self, d, options, verifyHostKey, userAuthObject): | |
19 self.d = d | |
20 self.options = options | |
21 self.verifyHostKey = verifyHostKey | |
22 self.userAuthObject = userAuthObject | |
23 | |
24 | |
25 def clientConnectionLost(self, connector, reason): | |
26 if self.options['reconnect']: | |
27 connector.connect() | |
28 | |
29 | |
30 def clientConnectionFailed(self, connector, reason): | |
31 if self.d is None: | |
32 return | |
33 d, self.d = self.d, None | |
34 d.errback(reason) | |
35 | |
36 | |
37 def buildProtocol(self, addr): | |
38 trans = SSHClientTransport(self) | |
39 if self.options['ciphers']: | |
40 trans.supportedCiphers = self.options['ciphers'] | |
41 if self.options['macs']: | |
42 trans.supportedMACs = self.options['macs'] | |
43 if self.options['compress']: | |
44 trans.supportedCompressions[0:1] = ['zlib'] | |
45 if self.options['host-key-algorithms']: | |
46 trans.supportedPublicKeys = self.options['host-key-algorithms'] | |
47 return trans | |
48 | |
49 | |
50 | |
51 class SSHClientTransport(transport.SSHClientTransport): | |
52 | |
53 def __init__(self, factory): | |
54 self.factory = factory | |
55 self.unixServer = None | |
56 | |
57 | |
58 def connectionLost(self, reason): | |
59 if self.unixServer: | |
60 d = self.unixServer.stopListening() | |
61 self.unixServer = None | |
62 else: | |
63 d = defer.succeed(None) | |
64 d.addCallback(lambda x: | |
65 transport.SSHClientTransport.connectionLost(self, reason)) | |
66 | |
67 | |
68 def receiveError(self, code, desc): | |
69 if self.factory.d is None: | |
70 return | |
71 d, self.factory.d = self.factory.d, None | |
72 d.errback(error.ConchError(desc, code)) | |
73 | |
74 | |
75 def sendDisconnect(self, code, reason): | |
76 if self.factory.d is None: | |
77 return | |
78 d, self.factory.d = self.factory.d, None | |
79 transport.SSHClientTransport.sendDisconnect(self, code, reason) | |
80 d.errback(error.ConchError(reason, code)) | |
81 | |
82 | |
83 def receiveDebug(self, alwaysDisplay, message, lang): | |
84 log.msg('Received Debug Message: %s' % message) | |
85 if alwaysDisplay: # XXX what should happen here? | |
86 print message | |
87 | |
88 | |
89 def verifyHostKey(self, pubKey, fingerprint): | |
90 return self.factory.verifyHostKey(self, self.transport.getPeer().host, p
ubKey, | |
91 fingerprint) | |
92 | |
93 | |
94 def setService(self, service): | |
95 log.msg('setting client server to %s' % service) | |
96 transport.SSHClientTransport.setService(self, service) | |
97 if service.name == 'ssh-connection': | |
98 # listen for UNIX | |
99 if not self.factory.options['nocache']: | |
100 user = self.factory.userAuthObject.user | |
101 peer = self.transport.getPeer() | |
102 filename = os.path.expanduser("~/.conch-%s-%s-%i" % (user, peer.
host, peer.port)) | |
103 u = unix.SSHUnixServerFactory(service) | |
104 try: | |
105 self.unixServer = reactor.listenUNIX(filename, u, mode=0600,
wantPID=1) | |
106 except: | |
107 if self.factory.d is not None: | |
108 d, self.factory.d = self.factory.d, None | |
109 d.errback(None) | |
110 if service.name != 'ssh-userauth' and self.factory.d is not None: | |
111 d, self.factory.d = self.factory.d, None | |
112 d.callback(None) | |
113 | |
114 | |
115 def connectionSecure(self): | |
116 self.requestService(self.factory.userAuthObject) | |
117 | |
118 | |
119 | |
120 def connect(host, port, options, verifyHostKey, userAuthObject): | |
121 d = defer.Deferred() | |
122 factory = SSHClientFactory(d, options, verifyHostKey, userAuthObject) | |
123 reactor.connectTCP(host, port, factory) | |
124 return d | |
OLD | NEW |