ssh/tailssh: add password-forcing workaround for buggy SSH clients

If the username includes a suffix of +password, then we accept
password auth and just let them in like it were no auth.

This exists purely for SSH clients that get confused by seeing success
to their initial auth type "none".

Co-authored-by: Maisem Ali <maisem@tailscale.com>
Change-Id: I616d4c64d042449fb164f615012f3bae246e91ec
Signed-off-by: Brad Fitzpatrick <bradfitz@tailscale.com>
This commit is contained in:
Brad Fitzpatrick
2022-10-11 14:48:01 -07:00
committed by Brad Fitzpatrick
parent c070d39287
commit e24de8a617
5 changed files with 91 additions and 16 deletions

View File

@@ -335,10 +335,12 @@ func TestSSHAuthFlow(t *testing.T) {
})
tests := []struct {
name string
state *localState
wantBanners []string
authErr bool
name string
sshUser string // defaults to alice
state *localState
wantBanners []string
usesPassword bool
authErr bool
}{
{
name: "no-policy",
@@ -410,6 +412,16 @@ func TestSSHAuthFlow(t *testing.T) {
wantBanners: []string{"First", "Go Away!"},
authErr: true,
},
{
name: "force-password-auth",
sshUser: "alice+password",
state: &localState{
sshEnabled: true,
matchingRule: acceptRule,
},
usesPassword: true,
wantBanners: []string{"Welcome to Tailscale SSH!"},
},
}
s := &server{
logf: logger.Discard,
@@ -420,9 +432,24 @@ func TestSSHAuthFlow(t *testing.T) {
t.Run(tc.name, func(t *testing.T) {
sc, dc := nettest.NewTCPConn(src, dst, 1024)
s.lb = tc.state
sshUser := "alice"
if tc.sshUser != "" {
sshUser = tc.sshUser
}
var passwordUsed atomic.Bool
cfg := &gossh.ClientConfig{
User: "alice",
User: sshUser,
HostKeyCallback: gossh.InsecureIgnoreHostKey(),
Auth: []gossh.AuthMethod{
gossh.PasswordCallback(func() (secret string, err error) {
if !tc.usesPassword {
t.Error("unexpected use of PasswordCallback")
return "", errors.New("unexpected use of PasswordCallback")
}
passwordUsed.Store(true)
return "any-pass", nil
}),
},
BannerCallback: func(message string) error {
if len(tc.wantBanners) == 0 {
t.Errorf("unexpected banner: %q", message)