add support for 2 factor authentication (key+password)

(cherry picked from commit be19c273bbe77d58fd67edeabf344ff253997b23)
This commit is contained in:
Andrew 2012-08-02 12:10:41 -07:00 committed by Jeff Forcier
parent 25942dbd90
commit 33176b90f7
1 changed files with 42 additions and 30 deletions

View File

@ -419,6 +419,8 @@ class SSHClient (object):
- Plain username/password auth, if a password was given. - Plain username/password auth, if a password was given.
(The password might be needed to unlock a private key.) (The password might be needed to unlock a private key.)
The password is required for two-factor authentication.
""" """
saved_exception = None saved_exception = None
@ -440,6 +442,7 @@ class SSHClient (object):
except SSHException, e: except SSHException, e:
saved_exception = e saved_exception = e
two_factor = False
if allow_agent: if allow_agent:
if self._agent == None: if self._agent == None:
self._agent = Agent() self._agent = Agent()
@ -447,11 +450,14 @@ class SSHClient (object):
for key in self._agent.get_keys(): for key in self._agent.get_keys():
try: try:
self._log(DEBUG, 'Trying SSH agent key %s' % hexlify(key.get_fingerprint())) self._log(DEBUG, 'Trying SSH agent key %s' % hexlify(key.get_fingerprint()))
self._transport.auth_publickey(username, key) # for 2-factor auth a successfully auth'd key will result in ['password']
remaining_auth_types = self._transport.auth_publickey(username, key)
if not remaining_auth_types:
return return
two_factor = True
except SSHException, e: except SSHException, e:
saved_exception = e saved_exception = e
else:
keyfiles = [] keyfiles = []
rsa_key = os.path.expanduser('~/.ssh/id_rsa') rsa_key = os.path.expanduser('~/.ssh/id_rsa')
dsa_key = os.path.expanduser('~/.ssh/id_dsa') dsa_key = os.path.expanduser('~/.ssh/id_dsa')
@ -474,8 +480,11 @@ class SSHClient (object):
try: try:
key = pkey_class.from_private_key_file(filename, password) key = pkey_class.from_private_key_file(filename, password)
self._log(DEBUG, 'Trying discovered key %s in %s' % (hexlify(key.get_fingerprint()), filename)) self._log(DEBUG, 'Trying discovered key %s in %s' % (hexlify(key.get_fingerprint()), filename))
self._transport.auth_publickey(username, key) # for 2-factor auth a successfully auth'd key will result in ['password']
remaining_auth_types = self._transport.auth_publickey(username, key)
if not remaining_auth_types:
return return
two_factor = True
except SSHException, e: except SSHException, e:
saved_exception = e saved_exception = e
except IOError, e: except IOError, e:
@ -487,6 +496,9 @@ class SSHClient (object):
return return
except SSHException, e: except SSHException, e:
saved_exception = e saved_exception = e
elif two_factor:
# for 2-factor auth requires a password
raise SSHException('Two-factor authentication requires a password')
# if we got an auth-failed exception earlier, re-raise it # if we got an auth-failed exception earlier, re-raise it
if saved_exception is not None: if saved_exception is not None: