Backend: fix IPv6 address parsing erroneous (#28585)

* Backend: Fix parsing of client IP address

Signed-off-by: Arve Knudsen <arve.knudsen@gmail.com>

Co-authored-by: Arve Knudsen <arve.knudsen@gmail.com>
This commit is contained in:
taciomcosta
2020-11-25 07:55:22 +01:00
committed by GitHub
co-authored by Arve Knudsen
parent 3d33de1751
commit 10ff4eecef
15 changed files with 228 additions and 147 deletions
+14 -14
View File
@@ -4,6 +4,7 @@ import (
"context"
"crypto/sha256"
"encoding/hex"
"net"
"strings"
"time"
@@ -53,12 +54,7 @@ func (s *UserAuthTokenService) ActiveTokenCount(ctx context.Context) (int64, err
return count, err
}
func (s *UserAuthTokenService) CreateToken(ctx context.Context, userId int64, clientAddr, userAgent string) (*models.UserToken, error) {
clientIP, err := util.ParseIPAddress(clientAddr)
if err != nil {
s.log.Debug("Failed to parse client IP address", "clientAddr", clientAddr, "err", err)
clientIP = ""
}
func (s *UserAuthTokenService) CreateToken(ctx context.Context, userId int64, clientIP net.IP, userAgent string) (*models.UserToken, error) {
token, err := util.RandomHex(16)
if err != nil {
return nil, err
@@ -67,12 +63,16 @@ func (s *UserAuthTokenService) CreateToken(ctx context.Context, userId int64, cl
hashedToken := hashToken(token)
now := getTime().Unix()
clientIPStr := clientIP.String()
if len(clientIP) == 0 {
clientIPStr = ""
}
userAuthToken := userAuthToken{
UserId: userId,
AuthToken: hashedToken,
PrevAuthToken: hashedToken,
ClientIp: clientIP,
ClientIp: clientIPStr,
UserAgent: userAgent,
RotatedAt: now,
CreatedAt: now,
@@ -193,7 +193,7 @@ func (s *UserAuthTokenService) LookupToken(ctx context.Context, unhashedToken st
}
func (s *UserAuthTokenService) TryRotateToken(ctx context.Context, token *models.UserToken,
clientAddr, userAgent string) (bool, error) {
clientIP net.IP, userAgent string) (bool, error) {
if token == nil {
return false, nil
}
@@ -219,12 +219,10 @@ func (s *UserAuthTokenService) TryRotateToken(ctx context.Context, token *models
s.log.Debug("token needs rotation", "tokenId", model.Id, "authTokenSeen", model.AuthTokenSeen, "rotatedAt", rotatedAt)
clientIP, err := util.ParseIPAddress(clientAddr)
if err != nil {
s.log.Debug("Failed to parse client IP address", "clientAddr", clientAddr, "err", err)
clientIP = ""
clientIPStr := clientIP.String()
if len(clientIP) == 0 {
clientIPStr = ""
}
newToken, err := util.RandomHex(16)
if err != nil {
return false, err
@@ -246,7 +244,9 @@ func (s *UserAuthTokenService) TryRotateToken(ctx context.Context, token *models
var affected int64
err = s.SQLStore.WithTransactionalDbSession(ctx, func(dbSession *sqlstore.DBSession) error {
res, err := dbSession.Exec(sql, userAgent, clientIP, s.SQLStore.Dialect.BooleanStr(true), hashedToken, s.SQLStore.Dialect.BooleanStr(false), now.Unix(), model.Id, s.SQLStore.Dialect.BooleanStr(true), now.Add(-30*time.Second).Unix())
res, err := dbSession.Exec(sql, userAgent, clientIPStr, s.SQLStore.Dialect.BooleanStr(true), hashedToken,
s.SQLStore.Dialect.BooleanStr(false), now.Unix(), model.Id, s.SQLStore.Dialect.BooleanStr(true),
now.Add(-30*time.Second).Unix())
if err != nil {
return err
}
+33 -16
View File
@@ -3,6 +3,7 @@ package auth
import (
"context"
"encoding/json"
"net"
"testing"
"time"
@@ -27,7 +28,8 @@ func TestUserAuthToken(t *testing.T) {
}
Convey("When creating token", func() {
userToken, err := userAuthTokenService.CreateToken(context.Background(), userID, "192.168.10.11:1234", "some user agent")
userToken, err := userAuthTokenService.CreateToken(context.Background(), userID,
net.ParseIP("192.168.10.11"), "some user agent")
So(err, ShouldBeNil)
So(userToken, ShouldNotBeNil)
So(userToken.AuthTokenSeen, ShouldBeFalse)
@@ -78,7 +80,8 @@ func TestUserAuthToken(t *testing.T) {
})
Convey("When creating an additional token", func() {
userToken2, err := userAuthTokenService.CreateToken(context.Background(), userID, "192.168.10.11:1234", "some user agent")
userToken2, err := userAuthTokenService.CreateToken(context.Background(), userID,
net.ParseIP("192.168.10.11"), "some user agent")
So(err, ShouldBeNil)
So(userToken2, ShouldNotBeNil)
@@ -124,7 +127,8 @@ func TestUserAuthToken(t *testing.T) {
for i := 0; i < 3; i++ {
userId := userID + int64(i+1)
userIds = append(userIds, userId)
_, err := userAuthTokenService.CreateToken(context.Background(), userId, "192.168.10.11:1234", "some user agent")
_, err := userAuthTokenService.CreateToken(context.Background(), userId,
net.ParseIP("192.168.10.11"), "some user agent")
So(err, ShouldBeNil)
}
@@ -141,7 +145,8 @@ func TestUserAuthToken(t *testing.T) {
})
Convey("expires correctly", func() {
userToken, err := userAuthTokenService.CreateToken(context.Background(), userID, "192.168.10.11:1234", "some user agent")
userToken, err := userAuthTokenService.CreateToken(context.Background(), userID,
net.ParseIP("192.168.10.11"), "some user agent")
So(err, ShouldBeNil)
userToken, err = userAuthTokenService.LookupToken(context.Background(), userToken.UnhashedToken)
@@ -151,7 +156,8 @@ func TestUserAuthToken(t *testing.T) {
return t.Add(time.Hour)
}
rotated, err := userAuthTokenService.TryRotateToken(context.Background(), userToken, "192.168.10.11:1234", "some user agent")
rotated, err := userAuthTokenService.TryRotateToken(context.Background(), userToken,
net.ParseIP("192.168.10.11"), "some user agent")
So(err, ShouldBeNil)
So(rotated, ShouldBeTrue)
@@ -221,13 +227,15 @@ func TestUserAuthToken(t *testing.T) {
})
Convey("can properly rotate tokens", func() {
userToken, err := userAuthTokenService.CreateToken(context.Background(), userID, "192.168.10.11:1234", "some user agent")
userToken, err := userAuthTokenService.CreateToken(context.Background(), userID,
net.ParseIP("192.168.10.11"), "some user agent")
So(err, ShouldBeNil)
prevToken := userToken.AuthToken
unhashedPrev := userToken.UnhashedToken
rotated, err := userAuthTokenService.TryRotateToken(context.Background(), userToken, "192.168.10.12:1234", "a new user agent")
rotated, err := userAuthTokenService.TryRotateToken(context.Background(), userToken,
net.ParseIP("192.168.10.12"), "a new user agent")
So(err, ShouldBeNil)
So(rotated, ShouldBeFalse)
@@ -246,7 +254,8 @@ func TestUserAuthToken(t *testing.T) {
return t.Add(time.Hour)
}
rotated, err = userAuthTokenService.TryRotateToken(context.Background(), &tok, "192.168.10.12:1234", "a new user agent")
rotated, err = userAuthTokenService.TryRotateToken(context.Background(), &tok,
net.ParseIP("192.168.10.12"), "a new user agent")
So(err, ShouldBeNil)
So(rotated, ShouldBeTrue)
@@ -291,7 +300,8 @@ func TestUserAuthToken(t *testing.T) {
So(lookedUpModel, ShouldNotBeNil)
So(lookedUpModel.AuthTokenSeen, ShouldBeFalse)
rotated, err = userAuthTokenService.TryRotateToken(context.Background(), userToken, "192.168.10.12:1234", "a new user agent")
rotated, err = userAuthTokenService.TryRotateToken(context.Background(), userToken,
net.ParseIP("192.168.10.12"), "a new user agent")
So(err, ShouldBeNil)
So(rotated, ShouldBeTrue)
@@ -302,7 +312,8 @@ func TestUserAuthToken(t *testing.T) {
})
Convey("keeps prev token valid for 1 minute after it is confirmed", func() {
userToken, err := userAuthTokenService.CreateToken(context.Background(), userID, "192.168.10.11:1234", "some user agent")
userToken, err := userAuthTokenService.CreateToken(context.Background(), userID,
net.ParseIP("192.168.10.11"), "some user agent")
So(err, ShouldBeNil)
So(userToken, ShouldNotBeNil)
@@ -315,7 +326,8 @@ func TestUserAuthToken(t *testing.T) {
}
prevToken := userToken.UnhashedToken
rotated, err := userAuthTokenService.TryRotateToken(context.Background(), userToken, "1.1.1.1", "firefox")
rotated, err := userAuthTokenService.TryRotateToken(context.Background(), userToken,
net.ParseIP("1.1.1.1"), "firefox")
So(err, ShouldBeNil)
So(rotated, ShouldBeTrue)
@@ -333,7 +345,8 @@ func TestUserAuthToken(t *testing.T) {
})
Convey("will not mark token unseen when prev and current are the same", func() {
userToken, err := userAuthTokenService.CreateToken(context.Background(), userID, "192.168.10.11:1234", "some user agent")
userToken, err := userAuthTokenService.CreateToken(context.Background(), userID,
net.ParseIP("192.168.10.11"), "some user agent")
So(err, ShouldBeNil)
So(userToken, ShouldNotBeNil)
@@ -352,7 +365,8 @@ func TestUserAuthToken(t *testing.T) {
})
Convey("Rotate token", func() {
userToken, err := userAuthTokenService.CreateToken(context.Background(), userID, "192.168.10.11:1234", "some user agent")
userToken, err := userAuthTokenService.CreateToken(context.Background(), userID,
net.ParseIP("192.168.10.11"), "some user agent")
So(err, ShouldBeNil)
So(userToken, ShouldNotBeNil)
@@ -367,7 +381,8 @@ func TestUserAuthToken(t *testing.T) {
return t.Add(10 * time.Minute)
}
rotated, err := userAuthTokenService.TryRotateToken(context.Background(), userToken, "1.1.1.1", "firefox")
rotated, err := userAuthTokenService.TryRotateToken(context.Background(), userToken,
net.ParseIP("1.1.1.1"), "firefox")
So(err, ShouldBeNil)
So(rotated, ShouldBeTrue)
@@ -388,7 +403,8 @@ func TestUserAuthToken(t *testing.T) {
return t.Add(20 * time.Minute)
}
rotated, err = userAuthTokenService.TryRotateToken(context.Background(), userToken, "1.1.1.1", "firefox")
rotated, err = userAuthTokenService.TryRotateToken(context.Background(), userToken,
net.ParseIP("1.1.1.1"), "firefox")
So(err, ShouldBeNil)
So(rotated, ShouldBeTrue)
@@ -407,7 +423,8 @@ func TestUserAuthToken(t *testing.T) {
return t.Add(2 * time.Minute)
}
rotated, err := userAuthTokenService.TryRotateToken(context.Background(), userToken, "1.1.1.1", "firefox")
rotated, err := userAuthTokenService.TryRotateToken(context.Background(), userToken,
net.ParseIP("1.1.1.1"), "firefox")
So(err, ShouldBeNil)
So(rotated, ShouldBeTrue)
+9 -6
View File
@@ -2,13 +2,14 @@ package auth
import (
"context"
"net"
"github.com/grafana/grafana/pkg/models"
)
type FakeUserAuthTokenService struct {
CreateTokenProvider func(ctx context.Context, userId int64, clientIP, userAgent string) (*models.UserToken, error)
TryRotateTokenProvider func(ctx context.Context, token *models.UserToken, clientIP, userAgent string) (bool, error)
CreateTokenProvider func(ctx context.Context, userId int64, clientIP net.IP, userAgent string) (*models.UserToken, error)
TryRotateTokenProvider func(ctx context.Context, token *models.UserToken, clientIP net.IP, userAgent string) (bool, error)
LookupTokenProvider func(ctx context.Context, unhashedToken string) (*models.UserToken, error)
RevokeTokenProvider func(ctx context.Context, token *models.UserToken) error
RevokeAllUserTokensProvider func(ctx context.Context, userId int64) error
@@ -20,13 +21,13 @@ type FakeUserAuthTokenService struct {
func NewFakeUserAuthTokenService() *FakeUserAuthTokenService {
return &FakeUserAuthTokenService{
CreateTokenProvider: func(ctx context.Context, userId int64, clientIP, userAgent string) (*models.UserToken, error) {
CreateTokenProvider: func(ctx context.Context, userId int64, clientIP net.IP, userAgent string) (*models.UserToken, error) {
return &models.UserToken{
UserId: 0,
UnhashedToken: "",
}, nil
},
TryRotateTokenProvider: func(ctx context.Context, token *models.UserToken, clientIP, userAgent string) (bool, error) {
TryRotateTokenProvider: func(ctx context.Context, token *models.UserToken, clientIP net.IP, userAgent string) (bool, error) {
return false, nil
},
LookupTokenProvider: func(ctx context.Context, unhashedToken string) (*models.UserToken, error) {
@@ -56,7 +57,8 @@ func NewFakeUserAuthTokenService() *FakeUserAuthTokenService {
}
}
func (s *FakeUserAuthTokenService) CreateToken(ctx context.Context, userId int64, clientIP, userAgent string) (*models.UserToken, error) {
func (s *FakeUserAuthTokenService) CreateToken(ctx context.Context, userId int64, clientIP net.IP,
userAgent string) (*models.UserToken, error) {
return s.CreateTokenProvider(context.Background(), userId, clientIP, userAgent)
}
@@ -64,7 +66,8 @@ func (s *FakeUserAuthTokenService) LookupToken(ctx context.Context, unhashedToke
return s.LookupTokenProvider(context.Background(), unhashedToken)
}
func (s *FakeUserAuthTokenService) TryRotateToken(ctx context.Context, token *models.UserToken, clientIP, userAgent string) (bool, error) {
func (s *FakeUserAuthTokenService) TryRotateToken(ctx context.Context, token *models.UserToken, clientIP net.IP,
userAgent string) (bool, error) {
return s.TryRotateTokenProvider(context.Background(), token, clientIP, userAgent)
}
-1
View File
@@ -88,7 +88,6 @@ func (ns *NotificationService) setFiles(
func (ns *NotificationService) createDialer() (*gomail.Dialer, error) {
host, port, err := net.SplitHostPort(ns.Cfg.Smtp.Host)
if err != nil {
return nil, err
}
+3 -1
View File
@@ -211,7 +211,9 @@ func (ss *SQLStore) buildConnectionString() (string, error) {
if ss.dbCfg.User == "" {
ss.dbCfg.User = "''"
}
cnnstr = fmt.Sprintf("user=%s password=%s host=%s port=%s dbname=%s sslmode=%s sslcert=%s sslkey=%s sslrootcert=%s", ss.dbCfg.User, ss.dbCfg.Pwd, addr.Host, addr.Port, ss.dbCfg.Name, ss.dbCfg.SslMode, ss.dbCfg.ClientCertPath, ss.dbCfg.ClientKeyPath, ss.dbCfg.CaCertPath)
cnnstr = fmt.Sprintf("user=%s password=%s host=%s port=%s dbname=%s sslmode=%s sslcert=%s sslkey=%s sslrootcert=%s",
ss.dbCfg.User, ss.dbCfg.Pwd, addr.Host, addr.Port, ss.dbCfg.Name, ss.dbCfg.SslMode, ss.dbCfg.ClientCertPath,
ss.dbCfg.ClientKeyPath, ss.dbCfg.CaCertPath)
cnnstr += ss.buildExtraConnectionString(' ')
case migrator.SQLite: