288
282
def relpath(self, abspath):
289
283
username, password, host, port, path = self._split_url(abspath)
291
if (username != self._username):
292
error.append('username mismatch')
293
if (host != self._host):
294
error.append('host mismatch')
295
if (port != self._port):
296
error.append('port mismatch')
297
if (not path.startswith(self._path)):
298
error.append('path mismatch')
300
raise NonRelativePath('path %r is not under base URL %r: %s'
301
% (abspath, self.base, ', '.join(error)))
284
if (username != self._username or host != self._host or
285
port != self._port or not path.startswith(self._path)):
286
raise NonRelativePath('path %r is not under base URL %r'
287
% (abspath, self.base))
302
288
pl = len(self._path)
303
289
return path[pl:].lstrip('/')
698
686
raise BzrError('Unable to find path %s on SFTP server %s' % \
699
687
(self._path, self._host))
701
def _sftp_auth(self, transport):
702
# paramiko requires a username, but it might be none if nothing was supplied
703
# use the local username, just in case.
704
# We don't override self._username, because if we aren't using paramiko,
705
# the username might be specified in ~/.ssh/config and we don't want to
706
# force it to something else
707
# Also, it would mess up the self.relpath() functionality
708
username = self._username or getpass.getuser()
689
def _sftp_auth(self, transport, username, host):
710
690
agent = paramiko.Agent()
711
691
for key in agent.get_keys():
712
692
mutter('Trying SSH agent key %s' % paramiko.util.hexify(key.get_fingerprint()))
714
transport.auth_publickey(username, key)
694
transport.auth_publickey(self._username, key)
716
696
except paramiko.SSHException, e:
719
699
# okay, try finding id_rsa or id_dss? (posix only)
720
if self._try_pkey_auth(transport, paramiko.RSAKey, username, 'id_rsa'):
722
if self._try_pkey_auth(transport, paramiko.DSSKey, username, 'id_dsa'):
700
if self._try_pkey_auth(transport, paramiko.RSAKey, 'id_rsa'):
702
if self._try_pkey_auth(transport, paramiko.DSSKey, 'id_dsa'):
726
705
if self._password:
728
transport.auth_password(username, self._password)
707
transport.auth_password(self._username, self._password)
730
709
except paramiko.SSHException, e:
733
# FIXME: Don't keep a password held in memory if you can help it
734
#self._password = None
736
712
# give up and ask for a password
737
password = ui_factory.get_password(prompt='SSH %(user)s@%(host)s password',
738
user=username, host=self._host)
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')))
740
transport.auth_password(username, password)
718
transport.auth_password(self._username, password)
741
719
except paramiko.SSHException:
742
720
raise SFTPTransportError('Unable to authenticate to SSH host as %s@%s' % \
743
(username, self._host))
721
(self._username, self._host))
745
def _try_pkey_auth(self, transport, pkey_class, username, filename):
723
def _try_pkey_auth(self, transport, pkey_class, filename):
746
724
filename = os.path.expanduser('~/.ssh/' + filename)
748
726
key = pkey_class.from_private_key_file(filename)
749
transport.auth_publickey(username, key)
727
transport.auth_publickey(self._username, key)
751
729
except paramiko.PasswordRequiredException:
752
password = ui_factory.get_password(prompt='SSH %(filename)s password',
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'),))
755
735
key = pkey_class.from_private_key_file(filename, password)
756
transport.auth_publickey(username, key)
736
transport.auth_publickey(self._username, key)
758
738
except paramiko.SSHException:
759
739
mutter('SSH authentication via %s key failed.' % (os.path.basename(filename),))