686
687
raise BzrError('Unable to find path %s on SFTP server %s' % \
687
688
(self._path, self._host))
689
def _sftp_auth(self, transport, username, host):
690
def _sftp_auth(self, transport):
691
# paramiko requires a username, but it might be none if nothing was supplied
692
# use the local username, just in case.
693
# We don't override self._username, because if we aren't using paramiko,
694
# the username might be specified in ~/.ssh/config and we don't want to
695
# force it to something else
696
# Also, it would mess up the self.relpath() functionality
697
username = self._username or getpass.getuser()
690
699
agent = paramiko.Agent()
691
700
for key in agent.get_keys():
692
701
mutter('Trying SSH agent key %s' % paramiko.util.hexify(key.get_fingerprint()))
694
transport.auth_publickey(self._username, key)
703
transport.auth_publickey(username, key)
696
705
except paramiko.SSHException, e:
699
708
# okay, try finding id_rsa or id_dss? (posix only)
700
if self._try_pkey_auth(transport, paramiko.RSAKey, 'id_rsa'):
702
if self._try_pkey_auth(transport, paramiko.DSSKey, 'id_dsa'):
709
if self._try_pkey_auth(transport, paramiko.RSAKey, username, 'id_rsa'):
711
if self._try_pkey_auth(transport, paramiko.DSSKey, username, 'id_dsa'):
705
715
if self._password:
707
transport.auth_password(self._username, self._password)
717
transport.auth_password(username, self._password)
709
719
except paramiko.SSHException, e:
722
# FIXME: Don't keep a password held in memory if you can help it
723
#self._password = None
712
725
# give up and ask for a password
713
# FIXME: shouldn't be implementing UI this deep into bzrlib
714
enc = sys.stdout.encoding
715
password = getpass.getpass('SSH %s@%s password: ' %
716
(self._username.encode(enc, 'replace'), self._host.encode(enc, 'replace')))
726
password = ui_factory.get_password(prompt='SSH %(user)s@%(host)s password',
727
user=username, host=self._host)
718
transport.auth_password(self._username, password)
729
transport.auth_password(username, password)
719
730
except paramiko.SSHException:
720
731
raise SFTPTransportError('Unable to authenticate to SSH host as %s@%s' % \
721
(self._username, self._host))
732
(username, self._host))
723
def _try_pkey_auth(self, transport, pkey_class, filename):
734
def _try_pkey_auth(self, transport, pkey_class, username, filename):
724
735
filename = os.path.expanduser('~/.ssh/' + filename)
726
737
key = pkey_class.from_private_key_file(filename)
727
transport.auth_publickey(self._username, key)
738
transport.auth_publickey(username, key)
729
740
except paramiko.PasswordRequiredException:
730
# FIXME: shouldn't be implementing UI this deep into bzrlib
731
enc = sys.stdout.encoding
732
password = getpass.getpass('SSH %s password: ' %
733
(os.path.basename(filename).encode(enc, 'replace'),))
741
password = ui_factory.get_password(prompt='SSH %(filename)s password',
735
744
key = pkey_class.from_private_key_file(filename, password)
736
transport.auth_publickey(self._username, key)
745
transport.auth_publickey(username, key)
738
747
except paramiko.SSHException:
739
748
mutter('SSH authentication via %s key failed.' % (os.path.basename(filename),))