diff --git a/server/authserver.go b/server/authserver.go index c22f6583da9aa839276363142bbcc3b6ccab4e9c..c480142d90e9e8d4fde49b119ae474062f45d596 100644 --- a/server/authserver.go +++ b/server/authserver.go @@ -389,7 +389,14 @@ func (s *Server) Authenticate(ctx context.Context, req *auth.Request) *auth.Resp return newError() } - resp := s.authenticateUser(req, serviceConfig, user) + resp, err := s.authenticateUser(req, serviceConfig, user) + if err != nil { + resp = newError() + log.Printf("auth: user=%s status=%s error=%s", req.Username, resp.Status.String(), err) + } else { + // Log the request and response. + log.Printf("auth: user=%s status=%s", req.Username, resp.Status.String()) + } // Notify blacklists of the result. serviceConfig.notifyBlacklists(user, req, resp) @@ -397,19 +404,23 @@ func (s *Server) Authenticate(ctx context.Context, req *auth.Request) *auth.Resp return resp } -func (s *Server) authenticateUser(req *auth.Request, serviceConfig *ServiceConfig, user *User) *auth.Response { +// Authenticate a user. Returning an error should result in an +// AuthResponse with StatusError. +func (s *Server) authenticateUser(req *auth.Request, serviceConfig *ServiceConfig, user *User) (resp *auth.Response, err error) { // Verify different credentials depending on whether the user // has 2FA enabled or not, and on whether the service itself // supports challenge-response authentication. - var resp *auth.Response if serviceConfig.Enforce2FA || user.Has2FA() { if serviceConfig.ChallengeResponse { - resp = s.authenticateUserWith2FA(user, req) + resp, err = s.authenticateUserWith2FA(user, req) } else { - resp = s.authenticateUserWithASP(user, req) + resp, err = s.authenticateUserWithASP(user, req) } } else { - resp = s.authenticateUserWithPassword(user, req) + resp, err = s.authenticateUserWithPassword(user, req) + } + if err != nil { + return } // Process the response through filters (device info checks, @@ -425,34 +436,30 @@ func (s *Server) authenticateUser(req *auth.Request, serviceConfig *ServiceConfi if resp.Status == auth.StatusOK { resp.UserInfo = user.UserInfo() } - - return resp + return } -func (s *Server) authenticateUserWithPassword(user *User, req *auth.Request) *auth.Response { +func (s *Server) authenticateUserWithPassword(user *User, req *auth.Request) (*auth.Response, error) { // Ok we only need to check the password here. if checkPassword(req.Password, user.EncryptedPassword) { - return newOK() + return newOK(), nil } - log.Printf("wrong password") - return newError() + return nil, errors.New("wrong password") } -func (s *Server) authenticateUserWithASP(user *User, req *auth.Request) *auth.Response { +func (s *Server) authenticateUserWithASP(user *User, req *auth.Request) (*auth.Response, error) { for _, asp := range user.AppSpecificPasswords { if asp.Service == req.Service && checkPassword(req.Password, asp.EncryptedPassword) { - return newOK() + return newOK(), nil } } - log.Printf("wrong app-specific password") - return newError() + return nil, errors.New("wrong app-specific password") } -func (s *Server) authenticateUserWith2FA(user *User, req *auth.Request) *auth.Response { +func (s *Server) authenticateUserWith2FA(user *User, req *auth.Request) (*auth.Response, error) { // First of all verify the password. if !checkPassword(req.Password, user.EncryptedPassword) { - log.Printf("wrong password") - return newError() + return nil, errors.New("wrong password") } // If the request contains one of the 2FA attributes, verify @@ -462,16 +469,14 @@ func (s *Server) authenticateUserWith2FA(user *User, req *auth.Request) *auth.Re switch { case req.U2FResponse != nil: if user.HasU2F() && s.checkU2F(user, req.U2FResponse) { - return newOK() + return newOK(), nil } - log.Printf("bad U2F response") - return newError() + return nil, errors.New("bad U2F response") case req.OTP != "": if user.HasOTP() && checkOTP(req.OTP, user.TOTPSecret) { - return newOK() + return newOK(), nil } - log.Printf("bad OTP") - return newError() + return nil, errors.New("bad OTP") default: resp := &auth.Response{ Status: auth.StatusInsufficientCredentials, @@ -480,13 +485,13 @@ func (s *Server) authenticateUserWith2FA(user *User, req *auth.Request) *auth.Re resp.TFAMethod = auth.TFAMethodU2F signReq, err := s.u2fSignRequest(user, req.U2FAppID) if err != nil { - return newError() + return nil, err } resp.U2FSignRequest = signReq } else if user.HasOTP() { resp.TFAMethod = auth.TFAMethodOTP } - return resp + return resp, nil } } diff --git a/server/devices.go b/server/devices.go index 4ccf3c7f191be41677ae0a2ccef8559442a5ab4e..8e29d00a79e04c472ed817b3ed3cfefff9bec7b6 100644 --- a/server/devices.go +++ b/server/devices.go @@ -11,12 +11,12 @@ import ( ) // Inject an interface for testing purposes. -type userMetaDB interface { +type checkDeviceClient interface { CheckDevice(context.Context, string, *auth.DeviceInfo) (bool, error) } type deviceFilter struct { - client userMetaDB + client checkDeviceClient } var usermetadbTimeout = 3 * time.Second