Advertisement
Guest User

Untitled

a guest
Jul 15th, 2017
100
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.70 KB | None | 0 0
  1. from __future__ import print_function
  2.  
  3. import os
  4.  
  5. from pexpect import TIMEOUT, EOF, spawn
  6. from pexpect.pxssh import pxssh as orig_pxssh, ExceptionPxssh
  7.  
  8. __all__ = ['ExceptionPxssh', 'pxssh']
  9.  
  10.  
  11. class ExceptionPxsshHostKey(ExceptionPxssh):
  12. pass
  13.  
  14.  
  15. # noinspection PyPep8Naming
  16. class pxssh(orig_pxssh):
  17. # a mix of pexpect.spawn (specify command) and pexpect.pxssh (specify options)
  18. def __init__(self, command=None, args=None, timeout=30, maxread=2000,
  19. searchwindowsize=None, logfile=None, cwd=None, env=None,
  20. ignore_sighup=False, echo=True, preexec_fn=None,
  21. encoding=None, codec_errors='strict', dimensions=None,
  22. options=None,
  23. config_file=None):
  24.  
  25. self.ssh_cmd = command if command else 'ssh'
  26. self.ssh_args = [] if not args else args
  27. self.config_file = config_file
  28.  
  29. # preexec_fn and dimensions get passed to _spawn directly unless command is None
  30. self.preexec_fn = preexec_fn
  31. self.dimensions = dimensions
  32.  
  33. options = options if options else {}
  34. orig_pxssh.__init__(
  35. self,
  36. # None, args=[],
  37. timeout=timeout, maxread=maxread,
  38. searchwindowsize=searchwindowsize, logfile=logfile, cwd=cwd, env=env,
  39. ignore_sighup=ignore_sighup, echo=echo, # preexec_fn=preexec_fn,
  40. encoding=encoding, codec_errors=codec_errors, # dimensions=dimensions
  41. options=options,
  42. )
  43.  
  44. def login(self, server, username=None, password='', terminal_type='ansi',
  45. original_prompt=r"[#$]", login_timeout=10, port=None,
  46. auto_prompt_reset=True, ssh_key=None, quiet=True,
  47. sync_multiplier=1, check_local_ip=True,
  48. config_file=None, save_host_key=True):
  49.  
  50. ssh_options = ''.join([" -o '%s=%s'" % (o, v) for (o, v) in self.options.items()])
  51. if not check_local_ip:
  52. ssh_options = ssh_options + " -o'NoHostAuthenticationForLocalhost=yes'"
  53. if self.force_password:
  54. ssh_options = ssh_options + ' ' + self.SSH_OPTS
  55.  
  56. ssh_args = ' '.join(self.ssh_args)
  57. if quiet:
  58. ssh_args = ssh_args + ' -q'
  59. if port is not None:
  60. ssh_args = ssh_args + ' -p %s' % (str(port))
  61. if username is not None:
  62. ssh_args = ssh_args + ' -l %s' % (str(username))
  63. if config_file is not None or self.config_file is not None:
  64. if not config_file:
  65. config_file = self.config_file
  66. ssh_args = ssh_args + ' -F %s' % config_file
  67. if ssh_key is not None:
  68. try:
  69. os.path.isfile(ssh_key)
  70. except:
  71. raise ExceptionPxssh('private ssh key does not exist')
  72. ssh_args = ssh_args + ' -i %s' % ssh_key
  73.  
  74. cmd = "%s %s %s %s" % (self.ssh_cmd, ssh_options, ssh_args, server)
  75.  
  76. # This does not distinguish between a remote server 'password' prompt
  77. # and a local ssh 'passphrase' prompt (for unlocking a private key).
  78. self._spawn(cmd, preexec_fn=self.preexec_fn, dimensions=self.dimensions)
  79. connect_prompts = ["(?i)are you sure you want to continue connecting",
  80. original_prompt,
  81. "(?i)(?:password)|(?:passphrase for key)",
  82. "(?i)permission denied",
  83. "(?i)terminal type",
  84. TIMEOUT]
  85. i = self.expect(connect_prompts + ["(?i)connection closed by remote host", EOF], timeout=login_timeout)
  86.  
  87. # First phase
  88. if i == 0:
  89. # New certificate -- always accept it.
  90. # This is what you get if SSH does not have the remote host's
  91. # public key stored in the 'known_hosts' cache.
  92. if not save_host_key:
  93. self.close()
  94. raise ExceptionPxsshHostKey('Host key not in known_hosts!')
  95. self.sendline("yes")
  96. i = self.expect(connect_prompts)
  97. if i == 2: # password or passphrase
  98. self.sendline(password)
  99. i = self.expect(connect_prompts)
  100. if i == 4:
  101. self.sendline(terminal_type)
  102. i = self.expect(connect_prompts)
  103. if i == 7:
  104. self.close()
  105. raise ExceptionPxssh('Could not establish connection to host')
  106.  
  107. # Second phase
  108. if i == 0:
  109. # This is weird. This should not happen twice in a row.
  110. self.close()
  111. raise ExceptionPxssh('Weird error. Got "are you sure" prompt twice.')
  112. elif i == 1: # can occur if you have a public key pair set to authenticate.
  113. # # TODO: May NOT be OK if expect() got tricked and matched a false prompt.
  114. pass
  115. elif i == 2: # password prompt again
  116. # For incorrect passwords, some ssh servers will
  117. # ask for the password again, others return 'denied' right away.
  118. # If we get the password prompt again then this means
  119. # we didn't get the password right the first time.
  120. self.close()
  121. raise ExceptionPxssh('password refused')
  122. elif i == 3: # permission denied -- password was bad.
  123. self.close()
  124. raise ExceptionPxssh('permission denied')
  125. elif i == 4: # terminal type again? WTF?
  126. self.close()
  127. raise ExceptionPxssh('Weird error. Got "terminal type" prompt twice.')
  128. elif i == 5: # Timeout
  129. # This is tricky... I presume that we are at the command-line prompt.
  130. # It may be that the shell prompt was so weird that we couldn't match
  131. # it. Or it may be that we couldn't log in for some other reason. I
  132. # can't be sure, but it's safe to guess that we did login because if
  133. # I presume wrong and we are not logged in then this should be caught
  134. # later when I try to set the shell prompt.
  135. pass
  136. elif i == 6: # Connection closed by remote host
  137. self.close()
  138. raise ExceptionPxssh('connection closed')
  139. else: # Unexpected
  140. self.close()
  141. raise ExceptionPxssh('unexpected login response')
  142. if not self.sync_original_prompt(sync_multiplier):
  143. self.close()
  144. raise ExceptionPxssh('could not synchronize with original prompt')
  145. # We appear to be in.
  146. # set shell prompt to something unique.
  147. if auto_prompt_reset:
  148. if not self.set_unique_prompt():
  149. self.close()
  150. raise ExceptionPxssh('could not set shell prompt '
  151. '(received: %r, expected: %r).' % (
  152. self.before, self.PROMPT,))
  153. return True
  154.  
  155. login.__doc__ = orig_pxssh.login.__doc__
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement