321
321
return false, msg.Methods, nil
322
322
case msgUserAuthSuccess:
323
323
return true, nil, nil
325
return false, nil, io.EOF
327
325
return false, nil, unexpectedMessageError(msgUserAuthSuccess, packet[0])
441
type retryableAuthMethod struct {
442
authMethod AuthMethod
446
func (r *retryableAuthMethod) auth(session []byte, user string, c packetConn, rand io.Reader) (ok bool, methods []string, err error) {
447
for i := 0; r.maxTries <= 0 || i < r.maxTries; i++ {
448
ok, methods, err = r.authMethod.auth(session, user, c, rand)
449
if ok || err != nil { // either success or error terminate
450
return ok, methods, err
453
return ok, methods, err
456
func (r *retryableAuthMethod) method() string {
457
return r.authMethod.method()
460
// RetryableAuthMethod is a decorator for other auth methods enabling them to
461
// be retried up to maxTries before considering that AuthMethod itself failed.
462
// If maxTries is <= 0, will retry indefinitely
464
// This is useful for interactive clients using challenge/response type
465
// authentication (e.g. Keyboard-Interactive, Password, etc) where the user
466
// could mistype their response resulting in the server issuing a
467
// SSH_MSG_USERAUTH_FAILURE (rfc4252 #8 [password] and rfc4256 #3.4
468
// [keyboard-interactive]); Without this decorator, the non-retryable
469
// AuthMethod would be removed from future consideration, and never tried again
470
// (and so the user would never be able to retry their entry).
471
func RetryableAuthMethod(auth AuthMethod, maxTries int) AuthMethod {
472
return &retryableAuthMethod{authMethod: auth, maxTries: maxTries}