sshsimpleclient.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155
  1. #!/usr/bin/env python
  2. # Copyright (c) Twisted Matrix Laboratories.
  3. # See LICENSE for details.
  4. from __future__ import print_function
  5. from twisted.conch.ssh import transport, userauth, connection, common, keys, channel
  6. from twisted.internet import defer, protocol, reactor
  7. from twisted.python import log
  8. import struct, sys, getpass, os
  9. """
  10. Example of using a simple SSH client.
  11. It will try to authenticate with a SSH key or ask for a password.
  12. Re-using a private key is dangerous, generate one.
  13. For this example you can use:
  14. $ ckeygen -t rsa -f ssh-keys/client_rsa
  15. """
  16. # Replace this with your username.
  17. # Default username and password will match the sshsimpleserver.py
  18. USER = b'user'
  19. HOST = 'localhost'
  20. PORT = 5022
  21. USER = b'bugz'
  22. HOST = 'bbs.red-green.com'
  23. PORT = 4022
  24. # SERVER_FINGERPRINT = b'55:55:66:24:6b:03:0e:f1:ec:f8:66:c3:51:df:27:4b'
  25. # Path to RSA SSH keys accepted by the server.
  26. # CLIENT_RSA_PUBLIC = 'ssh-keys/client_rsa.pub'
  27. # Set CLIENT_RSA_PUBLIC to empty to not use SSH key auth.
  28. # CLIENT_RSA_PUBLIC = ''
  29. # CLIENT_RSA_PRIVATE = 'ssh-keys/client_rsa'
  30. class SimpleTransport(transport.SSHClientTransport):
  31. def verifyHostKey(self, hostKey, fingerprint):
  32. print('Server host key fingerprint: %s' % fingerprint)
  33. if SERVER_FINGERPRINT == fingerprint:
  34. return defer.succeed(True)
  35. else:
  36. print('Bad host key. Expecting: %s' % SERVER_FINGERPRINT)
  37. return defer.fail(Exception('Bad server key'))
  38. def connectionSecure(self):
  39. self.requestService(
  40. SimpleUserAuth(USER,
  41. SimpleConnection()))
  42. class SimpleUserAuth(userauth.SSHUserAuthClient):
  43. def getPassword(self):
  44. return defer.succeed(getpass.getpass("%s@%s's password: " % (USER, HOST)))
  45. def getGenericAnswers(self, name, instruction, questions):
  46. print(name)
  47. print(instruction)
  48. answers = []
  49. for prompt, echo in questions:
  50. if echo:
  51. answer = raw_input(prompt)
  52. else:
  53. answer = getpass.getpass(prompt)
  54. answers.append(answer)
  55. return defer.succeed(answers)
  56. def getPublicKey(self):
  57. if (
  58. not CLIENT_RSA_PUBLIC or
  59. not os.path.exists(CLIENT_RSA_PUBLIC) or
  60. self.lastPublicKey
  61. ):
  62. # the file doesn't exist, or we've tried a public key
  63. return
  64. return keys.Key.fromFile(filename=CLIENT_RSA_PUBLIC)
  65. def getPrivateKey(self):
  66. """
  67. A deferred can also be returned.
  68. """
  69. return defer.succeed(keys.Key.fromFile(CLIENT_RSA_PRIVATE))
  70. class SimpleConnection(connection.SSHConnection):
  71. def serviceStarted(self):
  72. self.openChannel(TrueChannel(2**16, 2**15, self))
  73. self.openChannel(FalseChannel(2**16, 2**15, self))
  74. self.openChannel(CatChannel(2**16, 2**15, self))
  75. class TrueChannel(channel.SSHChannel):
  76. name = b'session' # needed for commands
  77. def openFailed(self, reason):
  78. print('true failed', reason)
  79. def channelOpen(self, ignoredData):
  80. self.conn.sendRequest(self, 'exec', common.NS('true'))
  81. def request_exit_status(self, data):
  82. status = struct.unpack('>L', data)[0]
  83. print('true status was: %s' % status)
  84. self.loseConnection()
  85. class FalseChannel(channel.SSHChannel):
  86. name = b'session'
  87. def openFailed(self, reason):
  88. print('false failed', reason)
  89. def channelOpen(self, ignoredData):
  90. self.conn.sendRequest(self, 'exec', common.NS('false'))
  91. def request_exit_status(self, data):
  92. status = struct.unpack('>L', data)[0]
  93. print('false status was: %s' % status)
  94. self.loseConnection()
  95. class CatChannel(channel.SSHChannel):
  96. name = b'session'
  97. def openFailed(self, reason):
  98. print('echo failed', reason)
  99. def channelOpen(self, ignoredData):
  100. self.data = b''
  101. d = self.conn.sendRequest(self, 'exec', common.NS('cat'), wantReply = 1)
  102. d.addCallback(self._cbRequest)
  103. def _cbRequest(self, ignored):
  104. self.write(b'hello conch\n')
  105. self.conn.sendEOF(self)
  106. def dataReceived(self, data):
  107. self.data += data
  108. def closed(self):
  109. print('got data from cat: %s' % repr(self.data))
  110. self.loseConnection()
  111. reactor.stop()
  112. log.startLogging(sys.stdout)
  113. protocol.ClientCreator(reactor, SimpleTransport).connectTCP(HOST, PORT)
  114. reactor.run()