58
59
# connect to an agent if we are on win32 and using Paramiko older than 1.6
59
60
_use_ssh_agent = (sys.platform != 'win32' or _paramiko_version >= (1, 6, 0))
63
def register_ssh_vendor(name, vendor):
64
"""Register SSH vendor."""
65
_ssh_vendors[name] = vendor
69
def _get_ssh_vendor():
70
"""Find out what version of SSH is on the system."""
72
if _ssh_vendor is not None:
75
if 'BZR_SSH' in os.environ:
76
vendor_name = os.environ['BZR_SSH']
63
class SSHVendorManager(object):
64
"""Manager for manage SSH vendors."""
67
self._ssh_vendors = {}
68
self.ssh_vendor = None
70
def register_vendor(self, name, vendor):
71
"""Register new SSH vendor."""
72
self._ssh_vendors[name] = vendor
74
def _get_vendor_by_environment(self, environment=None):
75
if environment is None:
76
environment = os.environ
77
if 'BZR_SSH' in environment:
78
vendor_name = environment['BZR_SSH']
80
vendor = self._ssh_vendors[vendor_name]
82
raise UnknownSSH(vendor_name)
86
def _get_ssh_version_string(self, args):
78
_ssh_vendor = _ssh_vendors[vendor_name]
80
raise UnknownSSH(vendor_name)
84
p = subprocess.Popen(['ssh', '-V'],
85
stdin=subprocess.PIPE,
86
stdout=subprocess.PIPE,
87
stderr=subprocess.PIPE,
88
**os_specific_subprocess_params())
89
returncode = p.returncode
90
stdout, stderr = p.communicate()
94
if 'OpenSSH' in stderr:
95
mutter('ssh implementation is OpenSSH')
96
_ssh_vendor = OpenSSHSubprocessVendor()
97
elif 'SSH Secure Shell' in stderr:
98
mutter('ssh implementation is SSH Corp.')
99
_ssh_vendor = SSHCorpSubprocessVendor()
101
if _ssh_vendor is not None:
104
# XXX: 20051123 jamesh
105
# A check for putty's plink or lsh would go here.
107
mutter('falling back to paramiko implementation')
108
_ssh_vendor = ParamikoVendor()
88
p = subprocess.Popen(args,
89
stdout=subprocess.PIPE,
90
stderr=subprocess.PIPE,
91
**os_specific_subprocess_params())
92
stdout, stderr = p.communicate()
95
return stdout + stderr
97
def _get_vendor_by_version_string(self, version):
99
if 'OpenSSH' in version:
100
mutter('ssh implementation is OpenSSH')
101
vendor = OpenSSHSubprocessVendor()
102
elif 'SSH Secure Shell' in version:
103
mutter('ssh implementation is SSH Corp.')
104
vendor = SSHCorpSubprocessVendor()
105
elif 'plink' in version:
106
mutter("ssh implementation is Putty's plink.")
107
vendor = PLinkSubprocessVendor()
110
def _get_vendor_by_inspection(self):
111
for args in [['ssh', '-V'], ['plink', '-V']]:
112
version = self._get_ssh_version_string(args)
113
vendor = self._get_vendor_by_version_string(version)
114
if vendor is not None:
118
def get_vendor(self, environment=None):
119
"""Find out what version of SSH is on the system."""
120
if self.ssh_vendor is None:
121
vendor = self._get_vendor_by_environment(environment)
123
vendor = self._get_vendor_by_inspection()
125
mutter('falling back to default implementation')
126
vendor = self._ssh_vendors.get('default', None)
128
raise SSHVendorNotFound()
129
self.ssh_vendor = vendor
130
return self.ssh_vendor
132
_ssh_vendor_manager = SSHVendorManager()
133
_get_ssh_vendor = _ssh_vendor_manager.get_vendor
134
register_ssh_vendor = _ssh_vendor_manager.register_vendor
112
137
def _ignore_sigint():
366
392
args.extend([host] + command)
369
395
register_ssh_vendor('ssh', SSHCorpSubprocessVendor())
398
class PLinkSubprocessVendor(SubprocessVendor):
399
"""SSH vendor that uses the 'plink' executable from Putty."""
401
def _get_vendor_specific_argv(self, username, host, port, subsystem=None,
403
assert subsystem is not None or command is not None, (
404
'Must specify a command or subsystem')
405
if subsystem is not None:
406
assert command is None, (
407
'subsystem and command are mutually exclusive')
408
args = ['plink', '-x', '-a', '-ssh', '-2']
410
args.extend(['-P', str(port)])
411
if username is not None:
412
args.extend(['-l', username])
413
if subsystem is not None:
414
args.extend(['-s', subsystem, host])
416
args.extend([host] + command)
419
register_ssh_vendor('plink', PLinkSubprocessVendor())
372
422
def _paramiko_auth(username, password, host, paramiko_transport):
373
423
# paramiko requires a username, but it might be none if nothing was supplied
374
424
# use the local username, just in case.