From 672013e702cb44c3bc1b46807703295448dc0afc Mon Sep 17 00:00:00 2001 From: Stan Hu Date: Wed, 10 Nov 2021 12:31:58 -0800 Subject: Relax key and username matching for sshd Due to the way sshd works, gitlab-shell could be called with a single string in the form: ``` /path/to/gitlab-shell -c key-id ``` However, due to the tightening of the regular expressions in fcff692b this string no longer matches, so logins would fail with: ``` Failed to get username: who='' is invalid ``` This can be reproduced by changing the user's shell to point to gitlab-shell. For example: ``` usermod git -s /opt/gitlab/embedded/service/gitlab-shell/bin/gitlab-shell ``` While setting gitlab-shell as the user's shell isn't officially supported, gitlab-shell still should be able to cope with the key being specified as the last argument. We now split the argument list and use the last value. Relates to https://gitlab.com/gitlab-org/gitlab-shell/-/issues/530 --- internal/command/commandargs/shell.go | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) (limited to 'internal/command/commandargs') diff --git a/internal/command/commandargs/shell.go b/internal/command/commandargs/shell.go index 7a76be5..a783f93 100644 --- a/internal/command/commandargs/shell.go +++ b/internal/command/commandargs/shell.go @@ -3,6 +3,7 @@ package commandargs import ( "fmt" "regexp" + "strings" "github.com/mattn/go-shellwords" "gitlab.com/gitlab-org/gitlab-shell/internal/sshenv" @@ -73,26 +74,29 @@ func (s *Shell) parseWho() { } } -func tryParseKeyId(argument string) string { - matchInfo := whoKeyRegex.FindStringSubmatch(argument) +func tryParse(r *regexp.Regexp, argument string) string { + // sshd may execute the session for AuthorizedKeysCommand in multiple ways: + // 1. key-id + // 2. /path/to/shell -c key-id + args := strings.Split(argument, " ") + lastArg := args[len(args)-1] + + matchInfo := r.FindStringSubmatch(lastArg) if len(matchInfo) == 2 { // The first element is the full matched string - // The second element is the named `keyid` + // The second element is the named `keyid` or `username` return matchInfo[1] } return "" } -func tryParseUsername(argument string) string { - matchInfo := whoUsernameRegex.FindStringSubmatch(argument) - if len(matchInfo) == 2 { - // The first element is the full matched string - // The second element is the named `username` - return matchInfo[1] - } +func tryParseKeyId(argument string) string { + return tryParse(whoKeyRegex, argument) +} - return "" +func tryParseUsername(argument string) string { + return tryParse(whoUsernameRegex, argument) } func (s *Shell) ParseCommand(commandString string) error { -- cgit v1.2.1