Skip to content
Draft
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 46 additions & 2 deletions db-connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"net/http"
"net/url"
"os"
"regexp"
"strconv"

"crypto/sha256"
Expand Down Expand Up @@ -5728,8 +5729,9 @@ func FindUser(ctx context.Context, username string) ([]User, error) {
return newUsers, nil
}

func GetUser(ctx context.Context, username string) (*User, error) {
func GetUser(ctx context.Context, username string, returnEncrypted ...bool) (*User, error) {
curUser := &User{}
uuidRegex := regexp.MustCompile(`^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$`)

parsedKey := strings.ToLower(username)
cacheKey := fmt.Sprintf("user_%s", parsedKey)
Expand All @@ -5739,6 +5741,21 @@ func GetUser(ctx context.Context, username string) (*User, error) {
cacheData := []byte(cache.([]uint8))
err = json.Unmarshal(cacheData, &curUser)
if err == nil {
// uuid or not
if len(returnEncrypted) == 0 || !returnEncrypted[0] {
if len(curUser.ApiKey) > 0 && !uuidRegex.MatchString(curUser.ApiKey) {
decryptedApiKey, decErr := HandleKeyDecryption([]byte(curUser.ApiKey), "apikey")
if decErr == nil {
curUser.ApiKey = string(decryptedApiKey)
}
}
if len(curUser.Session) > 0 && !uuidRegex.MatchString(curUser.Session) {
decryptedSession, decErr := HandleKeyDecryption([]byte(curUser.Session), "session")
if decErr == nil {
curUser.Session = string(decryptedSession)
}
}
}
return curUser, nil
}
} else {
Expand Down Expand Up @@ -5805,6 +5822,19 @@ func GetUser(ctx context.Context, username string) (*User, error) {
data, err := json.Marshal(curUser)
if err != nil {
log.Printf("[WARNING] Failed marshalling user: %s", err)
// uuid check
if len(returnEncrypted) == 0 || !returnEncrypted[0] {
if len(curUser.ApiKey) > 0 && !uuidRegex.MatchString(curUser.ApiKey) {
if decrypted, decErr := HandleKeyDecryption([]byte(curUser.ApiKey), "apikey"); decErr == nil {
curUser.ApiKey = string(decrypted)
}
}
if len(curUser.Session) > 0 && !uuidRegex.MatchString(curUser.Session) {
if decrypted, decErr := HandleKeyDecryption([]byte(curUser.Session), "session"); decErr == nil {
curUser.Session = string(decrypted)
}
}
}
return curUser, nil
}

Expand All @@ -5814,6 +5844,21 @@ func GetUser(ctx context.Context, username string) (*User, error) {
}
}

if len(returnEncrypted) == 0 || !returnEncrypted[0] {
if len(curUser.ApiKey) > 0 && !uuidRegex.MatchString(curUser.ApiKey) {
decryptedApiKey, err := HandleKeyDecryption([]byte(curUser.ApiKey), "apikey")
if err == nil {
curUser.ApiKey = string(decryptedApiKey)
}
}
if len(curUser.Session) > 0 && !uuidRegex.MatchString(curUser.Session) {
decryptedSession, err := HandleKeyDecryption([]byte(curUser.Session), "session")
if err == nil {
curUser.Session = string(decryptedSession)
}
}
}

return curUser, nil
}

Expand Down Expand Up @@ -9845,7 +9890,6 @@ func GetSessionNew(ctx context.Context, sessionId string) (User, error) {
}

} else {
// Datastore: try encrypted first, then plain (no IN filter support)
for _, sess := range sessionsToSearch {
q := datastore.NewQuery(nameKey).Filter("session =", sess).Limit(1)
_, err := project.Dbclient.GetAll(ctx, q, &users)
Expand Down
70 changes: 54 additions & 16 deletions shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -3562,10 +3562,22 @@ func HandleApiAuthentication(resp http.ResponseWriter, request *http.Request) (U

uuidRegex := regexp.MustCompile(`^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$`)

// Encrypt API key if it's plain UUID
if uuidRegex.MatchString(user.ApiKey) {
log.Printf("[AUDIT] API key is a UUID: %s", user.ApiKey)
// since GetSessionNew returns encrypted values
plainApiKey := user.ApiKey
if len(plainApiKey) > 0 && !uuidRegex.MatchString(plainApiKey) {
if decrypted, err := HandleKeyDecryption([]byte(plainApiKey), "apikey"); err == nil {
plainApiKey = string(decrypted)
}
}
plainSession := user.Session
if len(plainSession) > 0 && !uuidRegex.MatchString(plainSession) {
if decrypted, err := HandleKeyDecryption([]byte(plainSession), "session"); err == nil {
plainSession = string(decrypted)
}
}

// save encrypted to just db
if uuidRegex.MatchString(user.ApiKey) {
encryptedKey, err := HandleKeyEncryption([]byte(user.ApiKey), "apikey", true)
if err == nil {
user.ApiKey = string(encryptedKey)
Expand All @@ -3574,19 +3586,19 @@ func HandleApiAuthentication(resp http.ResponseWriter, request *http.Request) (U
}
}

// Encrypt session if matched on plain
if user.Session == sessionToken && uuidRegex.MatchString(sessionToken) {
log.Printf("[AUDIT] Encrypting session")
encryptedSession, err := HandleKeyEncryption([]byte(sessionToken), "session", true)
if err == nil {
user.Session = string(encryptedSession)
SetSession(ctx, user, user.Session)
} else {
log.Printf("[ERROR] Failed to encrypt session: %v", err)
}
}

// Means session exists, but
// we use user.Apikey throughout the codebase
// from the returned function value. Trying to keep the usage consistent.
user.ApiKey = plainApiKey
user.Session = plainSession

return user, nil
}

Expand Down Expand Up @@ -11998,7 +12010,14 @@ func HandleChangeUserOrg(resp http.ResponseWriter, request *http.Request) {

expiration := time.Now().Add(8 * time.Hour)

newCookie := ConstructSessionCookie(user.Session, expiration)
// Decrypt session if it's encrypted
sessionValue := user.Session
decryptedSession, err := HandleKeyDecryption([]byte(sessionValue), "session")
if err == nil {
sessionValue = string(decryptedSession)
}

newCookie := ConstructSessionCookie(sessionValue, expiration)
http.SetCookie(resp, newCookie)

newCookie.Name = "__session"
Expand Down Expand Up @@ -15289,24 +15308,31 @@ func HandleLogin(resp http.ResponseWriter, request *http.Request) {

if len(userdata.Session) != 0 && !changeActiveOrg {
log.Printf("[INFO] User session exists - resetting session")

// Decrypt session if it's encrypted
sessionValue := userdata.Session
decryptedSession, err := HandleKeyDecryption([]byte(sessionValue), "session")
if err == nil {
sessionValue = string(decryptedSession)
}

expiration := time.Now().Add(8 * time.Hour)

newCookie := ConstructSessionCookie(userdata.Session, expiration)
newCookie := ConstructSessionCookie(sessionValue, expiration)
http.SetCookie(resp, newCookie)

newCookie.Name = "__session"
http.SetCookie(resp, newCookie)

//log.Printf("SESSION LENGTH MORE THAN 0 IN LOGIN: %s", userdata.Session)
returnValue.Cookies = append(returnValue.Cookies, SessionCookie{
Key: "session_token",
Value: userdata.Session,
Value: sessionValue,
Expiration: expiration.Unix(),
})

returnValue.Cookies = append(returnValue.Cookies, SessionCookie{
Key: "__session",
Value: userdata.Session,
Value: sessionValue,
Expiration: expiration.Unix(),
})

Expand All @@ -15317,7 +15343,7 @@ func HandleLogin(resp http.ResponseWriter, request *http.Request) {
http.SetCookie(resp, newCookie)
}

loginData = fmt.Sprintf(`{"success": true, "cookies": [{"key": "session_token", "value": "%s", "expiration": %d}], "region_url": "%s"}`, userdata.Session, expiration.Unix(), regionUrl)
loginData = fmt.Sprintf(`{"success": true, "cookies": [{"key": "session_token", "value": "%s", "expiration": %d}], "region_url": "%s"}`, sessionValue, expiration.Unix(), regionUrl)
newData, err := json.Marshal(returnValue)
if err == nil {
loginData = string(newData)
Expand Down Expand Up @@ -22616,13 +22642,19 @@ func HandleOpenId(resp http.ResponseWriter, request *http.Request) {
} else {
log.Printf("[INFO] user have session resetting session and cookies for user: %v - (1)", userName)
sessionToken := user.Session
// Decrypt session if it's encrypted
decryptedSession, decErr := HandleKeyDecryption([]byte(sessionToken), "session")
if decErr == nil {
sessionToken = string(decryptedSession)
}

newCookie := ConstructSessionCookie(sessionToken, expiration)
http.SetCookie(resp, newCookie)

newCookie.Name = "__session"
http.SetCookie(resp, newCookie)

err = SetSession(ctx, user, sessionToken)
err = SetSession(ctx, user, user.Session)
if err != nil {
log.Printf("[WARNING] Error creating session for user: %s", err)
resp.WriteHeader(401)
Expand Down Expand Up @@ -22790,13 +22822,19 @@ func HandleOpenId(resp http.ResponseWriter, request *http.Request) {
} else {
log.Printf("[INFO] user have session resetting session and cookies for user: %v - (2)", userName)
sessionToken := user.Session
// Decrypt session if it's encrypted
decryptedSession, decErr := HandleKeyDecryption([]byte(sessionToken), "session")
if decErr == nil {
sessionToken = string(decryptedSession)
}

newCookie := ConstructSessionCookie(sessionToken, expiration)
http.SetCookie(resp, newCookie)

newCookie.Name = "__session"
http.SetCookie(resp, newCookie)

err = SetSession(ctx, user, sessionToken)
err = SetSession(ctx, user, user.Session)
if err != nil {
log.Printf("[WARNING] Error creating session for user: %s", err)
resp.WriteHeader(401)
Expand Down