diff --git a/client/android/ssh_client.go b/client/android/ssh_client.go index 3ee81d624..f57a8f056 100644 --- a/client/android/ssh_client.go +++ b/client/android/ssh_client.go @@ -151,7 +151,8 @@ func (s *SSHClient) Connect(host string, port int, user, password string) error // one instead of failing. NetBird servers never use a password, so a // failure there is genuine. if err != nil && serverType != detection.ServerTypeNetBirdJWT && - serverType != detection.ServerTypeNetBirdNoJWT && isAuthFailure(err) { + serverType != detection.ServerTypeNetBirdNoJWT && isAuthFailure(err) && + passwordCouldHelp(err, password != "") { return errPasswordRequired } if err != nil { @@ -173,6 +174,18 @@ func isAuthFailure(err error) bool { return strings.Contains(err.Error(), "unable to authenticate") } +// passwordCouldHelp reports whether prompting for a password again can change +// the outcome. gossh lists a method under "attempted methods" only when the +// server offered it, so a supplied password that was never attempted means the +// server does not accept passwords and the real error should surface instead. +func passwordCouldHelp(err error, passwordOffered bool) bool { + if !passwordOffered { + return true + } + msg := err.Error() + return strings.Contains(msg, "password") || strings.Contains(msg, "keyboard-interactive") +} + // StartSession requests a PTY and starts an interactive shell. Output from // the session is forwarded to the listener via OnData. func (s *SSHClient) StartSession(cols, rows int) error {