Allow end-users to select their own SSH username

Defaulting the SSH username to the local part of the email address
is very confusing for an end-user.  Instead let each user select
their own username, ensuring it is unique on the system.

During the schema upgrade, if there are multiple users with the same
username, we assign the SSH username to the user who last logged
in with it.  All other users will need to login through the web
interface and select a new username before being able to use the
SSH interface.

The unique SSH username policy also fixes a possible MITM attack:

  Attacker knows another public key that Alice's SSH client will
  submit during the authentication phase (SSH allows you to propose
  several public keys in a single packet) but that has not yet been
  added by Alice to her Gerrit Code Review account.

  Alice's other public key(s) can be found by monitoring the network,
  such as by running an SSH server that Alice will connect to by
  some other means.  This requires an active MITM attack, since
  public keys are sent after data encryption is enabled.

  The attacker adds one or more of these collected public keys to his
  own account, and arranges for his SSH username to match Alice's
  SSH username, by changing his preferred email address.  The next
  time Alice SSHs to the Gerrit Code Review instance, she may very
  well get logged-in to the attacker's account, rather than her own.

This commit fixes this particular attack vector by ensuring that the
SSH username supplied by the client matches exactly one account on
the server.  Since the username matches exactly one account, only
one SSH key list is searched.  If an attacker does know another
of Alice's public keys, adding it to his own account will never
confuse Alice's access.

Users who wish to avoid this problem on Gerrit instances prior to
this fix may be able to protect themselves by exactly specifying
exactly the key in their ~/.ssh/config, such as:

  Host review.example.com:
    User alice
	IdentityFile ~/.ssh/id_review

This limits the client to presenting exactly one key to the server,
even if additional keys are available through an agent process,
or in ~/.ssh.

Another approach a user can take is to upload *all* of their public
keys to the Gerrit instance.  Gerrit has always refused access if
a username and public key pair match more than one account.

Bug: GERRIT-104, GERRIT-254
Signed-off-by: Shawn O. Pearce <sop@google.com>
20 files changed