Audit logins with new LoginAttempt event (fixes #2377)

This commit is contained in:
Tyler Brazier 2015-11-08 15:05:36 -05:00
parent 59565fd1d1
commit 97b9690711
4 changed files with 27 additions and 1 deletions

View File

@ -65,6 +65,7 @@ Tim Abell <tim@timwise.co.uk>
Tobias Nygren <tnn@nygren.pp.se> Tobias Nygren <tnn@nygren.pp.se>
Tomas Cerveny <kozec@kozec.com> Tomas Cerveny <kozec@kozec.com>
Tully Robinson <tully@tojr.org> Tully Robinson <tully@tojr.org>
Tyler Brazier <tyler@tylerbrazier.com>
Veeti Paananen <veeti.paananen@rojekti.fi> Veeti Paananen <veeti.paananen@rojekti.fi>
Vil Brekin <vilbrekin@gmail.com> Vil Brekin <vilbrekin@gmail.com>
Yannic A. <eipiminusone+github@gmail.com> <eipiminus1@users.noreply.github.com> Yannic A. <eipiminusone+github@gmail.com> <eipiminus1@users.noreply.github.com>

View File

@ -15,6 +15,7 @@ import (
"time" "time"
"github.com/syncthing/syncthing/lib/config" "github.com/syncthing/syncthing/lib/config"
"github.com/syncthing/syncthing/lib/events"
"github.com/syncthing/syncthing/lib/sync" "github.com/syncthing/syncthing/lib/sync"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
) )
@ -24,6 +25,13 @@ var (
sessionsMut = sync.NewMutex() sessionsMut = sync.NewMutex()
) )
func emitLoginAttempt(success bool, username string) {
events.Default.Log(events.LoginAttempt, map[string]interface{}{
"success": success,
"username": username,
})
}
func basicAuthAndSessionMiddleware(cookieName string, cfg config.GUIConfiguration, next http.Handler) http.Handler { func basicAuthAndSessionMiddleware(cookieName string, cfg config.GUIConfiguration, next http.Handler) http.Handler {
apiKey := cfg.APIKey() apiKey := cfg.APIKey()
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
@ -70,12 +78,15 @@ func basicAuthAndSessionMiddleware(cookieName string, cfg config.GUIConfiguratio
return return
} }
if string(fields[0]) != cfg.User { username := string(fields[0])
if username != cfg.User {
emitLoginAttempt(false, username)
error() error()
return return
} }
if err := bcrypt.CompareHashAndPassword([]byte(cfg.Password), fields[1]); err != nil { if err := bcrypt.CompareHashAndPassword([]byte(cfg.Password), fields[1]); err != nil {
emitLoginAttempt(false, username)
error() error()
return return
} }
@ -90,6 +101,7 @@ func basicAuthAndSessionMiddleware(cookieName string, cfg config.GUIConfiguratio
MaxAge: 0, MaxAge: 0,
}) })
emitLoginAttempt(true, username)
next.ServeHTTP(w, r) next.ServeHTTP(w, r)
}) })
} }

View File

@ -149,6 +149,16 @@ func (s *verboseSvc) formatEvent(ev events.Event) string {
data := ev.Data.(map[string][]string) data := ev.Data.(map[string][]string)
newRelays := data["new"] newRelays := data["new"]
return fmt.Sprintf("Relay state changed; connected relay(s) are %s.", strings.Join(newRelays, ", ")) return fmt.Sprintf("Relay state changed; connected relay(s) are %s.", strings.Join(newRelays, ", "))
case events.LoginAttempt:
data := ev.Data.(map[string]interface{})
username := data["username"].(string)
var success string
if data["success"].(bool) {
success = "successful"
} else {
success = "failed"
}
return fmt.Sprintf("Login %s for username %s.", success, username)
} }

View File

@ -41,6 +41,7 @@ const (
FolderScanProgress FolderScanProgress
ExternalPortMappingChanged ExternalPortMappingChanged
RelayStateChanged RelayStateChanged
LoginAttempt
AllEvents = (1 << iota) - 1 AllEvents = (1 << iota) - 1
) )
@ -93,6 +94,8 @@ func (t EventType) String() string {
return "ExternalPortMappingChanged" return "ExternalPortMappingChanged"
case RelayStateChanged: case RelayStateChanged:
return "RelayStateChanged" return "RelayStateChanged"
case LoginAttempt:
return "LoginAttempt"
default: default:
return "Unknown" return "Unknown"
} }