Skip to content

Commit

Permalink
Add support for host-based authentication
Browse files Browse the repository at this point in the history
This commit adds client and server side support for host-based SSH
authentication. The server-side support is probably more interesting
here, allowing AsyncSSH to authenticate connections from all users on
a host without each user needing to have their own keys. If AsyncSSH
is given access to a trusted key for a client host, though, this
support can be used to allow AsyncSSH to connect as any user on that
client.

Potential future work could include supporting ssh-keysign on systems
which have it enabled, to avoid AsyncSSH needing to have direct access
to the host key when acting as a client.
In addition to the above, this commit fixes a minor issue with
enforcing the source-address option in OpenSSH user certificates and
with error handling when canonicalizing usernames with SASLPrep. It
also fixes a couple of doc string issues.
  • Loading branch information
ronf committed Jun 17, 2018
1 parent aae6ecc commit 6a92930
Show file tree
Hide file tree
Showing 8 changed files with 790 additions and 195 deletions.
4 changes: 3 additions & 1 deletion README.rst
Expand Up @@ -47,7 +47,9 @@ Features

* Including OpenSSH variant to delay compression until after auth

* Password, public key, and keyboard-interactive user authentication methods
* User and host-based public key, password, and keyboard-interactive
authentication methods

* Many types and formats of `public keys and certificates`__

* Including support for X.509 certificates as defined in RFC 6187
Expand Down
68 changes: 68 additions & 0 deletions asyncssh/auth.py
Expand Up @@ -264,6 +264,30 @@ def _process_error_token(self, pkttype, pktid, packet):
}


class _ClientHostBasedAuth(_ClientAuth):
"""Client side implementation of host based auth"""

@asyncio.coroutine
def _start(self):
"""Start client host based authentication"""

keypair, client_host, client_username = \
yield from self._conn.host_based_auth_requested()

if keypair is None:
self._conn.try_next_auth()
return

self.logger.debug1('Trying host based auth of user %s on host %s '
'with %s host key', client_username, client_host,
keypair.algorithm)

yield from self.send_request(String(keypair.algorithm),
String(keypair.public_data),
String(client_host),
String(client_username), key=keypair)


class _ClientPublicKeyAuth(_ClientAuth):
"""Client side implementation of public key auth"""

Expand Down Expand Up @@ -683,6 +707,49 @@ def _process_mic(self, pkttype, pktid, packet):
}


class _ServerHostBasedAuth(_ServerAuth):
"""Server side implementation of host based auth"""

@classmethod
def supported(cls, conn):
"""Return whether host based authentication is supported"""

return conn.host_based_auth_supported()

@asyncio.coroutine
def _start(self, packet):
"""Start server host based authentication"""

algorithm = packet.get_string()
key_data = packet.get_string()
client_host = packet.get_string()
client_username = packet.get_string()
msg = packet.get_consumed_payload()
signature = packet.get_string()

packet.check_end()

try:
client_host = client_host.decode('utf-8')
client_username = saslprep(client_username.decode('utf-8'))
except (UnicodeDecodeError, SASLPrepError):
raise DisconnectError(DISC_PROTOCOL_ERROR, 'Invalid host-based '
'auth request') from None

self.logger.debug1('Verifying host based auth of user %s '
'on host %s with %s host key', client_username,
client_host, algorithm)

if (yield from self._conn.validate_host_based_auth(self._username,
key_data,
client_host,
client_username,
msg, signature)):
self.send_success()
else:
self.send_failure()


class _ServerPublicKeyAuth(_ServerAuth):
"""Server side implementation of public key auth"""

Expand Down Expand Up @@ -908,6 +975,7 @@ def lookup_server_auth(conn, username, method, packet):
(b'none', _ClientNullAuth, _ServerNullAuth),
(b'gssapi-keyex', _ClientGSSKexAuth, _ServerGSSKexAuth),
(b'gssapi-with-mic', _ClientGSSMICAuth, _ServerGSSMICAuth),
(b'hostbased', _ClientHostBasedAuth, _ServerHostBasedAuth),
(b'publickey', _ClientPublicKeyAuth, _ServerPublicKeyAuth),
(b'keyboard-interactive', _ClientKbdIntAuth, _ServerKbdIntAuth),
(b'password', _ClientPasswordAuth, _ServerPasswordAuth)
Expand Down

0 comments on commit 6a92930

Please sign in to comment.