On 2021-01-19 at 06:17:21, Harley Paterson wrote: > Hello, > > I've noticed an edge case in Git when a user has two Git accounts on a > single server - as might be common for a personal account and a work > account on a Git forge (Github, GitLab, Bitbucket...) > > When attempting SSH login, `ssh` and Git will eagerly connect with the > first matching key. This may or may not be the key right key for the > repository the user needs. As a result, Git clones, pulls, and pushes > will fail with the `Repository not found` if the wrong key is tried > first. > > For example, the user `alice` has two accounts on the host > `git-server.com`. `alice`'s accounts are `alice-work`, and > `alice-personal`. `alice-work` has access to the `foo` repository, and > `alice-personal` has access to the `bar` repository. Yes, this is because SSH authentication happens before any command is run. The server never knows what resource is being requested until the user is already authenticated. > `alice` attempts to clone `foo` with both her `alice-work` and > `alice-personal` keys in her SSH Agent. SSH Agent does not define > which key it will attempt first, so SSH may connect successfully to > `git-server.com` with her `alice-personal` keys, which do not have > access to the `foo` repository. > > I'd be interested in your opinions for fixes to this. I am willing to > make a patch, although my knowledge of the Git codebase isn't perfect. We've documented how to deal with situation properly in the FAQ, which you can see at gitfaq(7) or https://git-scm.com/docs/gitfaq#Documentation/gitfaq.txt-HowdoIusemultipleaccountswiththesamehostingproviderusingSSH Is there some reason that this doesn't work for you? > - Should Git servers provide distinctly different error messages for > `access denied`, and `repository does not exist`? Currently the > server immediately closes the connection in this case, so > `transport.c:handshake()` with fail when attempting to > `discover_version()` because the reader hits the EOF. Perhaps the > server could send a hypothetical access denied packet here, and a > more appropriate error generated? Unfortunately, this leaks whether a repository exists. If Company XYZ has a repository for each of its clients, it then becomes easy to see if Company XYZ is doing work for a particular client by trying to see if a repository exists. This would be bad and a huge violation of privacy, so nobody is likely do to that. I can tell you as one of the staff who maintains the GitHub Git service, we're not likely to change the behavior, and I suspect nobody else is, either. > Can anyone point me to where in the Git codebase the daemon receives > and responds to these requests? I haven't found it yet, if I wanted to > patch this. > > - Should Git provide a `-i` option to allow the user to choose an SSH > key, which could be added to the SSH subprocess's command line? You can use GIT_SSH_COMMAND or `core.sshcommand` to set this. We don't provide such an option because the user is not necessarily using OpenSSH and different SSH programs provide this feature differently. > - Should Git attempt to iterate over all keys in the SSH Agent when > the connection is setup, testing the connection to check if each > connected key has access to the target repository, before giving up > and reporting an error? This may be difficult looking at the current > behavior of `ssh` and `ssh-agent`. `ssh-add -l` no longer lists > paths to files (which could be plugged into `ssh -i`), just the key > signature. Does anyone know of any SSH/SSH-Agent tricks which might > help with this? For historical reasons, we retry SSH connections in Git LFS and users frequently complain about being prompted for their password multiple times before giving up, so I suspect this would not be a good experience for the user. Users may also have multiple keys and have configured their agent to prompt them for a passphrase before using the key, and I'm pretty sure those users will complain very loudly if we do this. -- brian m. carlson (he/him or they/them) Houston, Texas, US