From 9644600f0d76d1ad7bd6f6cb64c8c41658df6732 Mon Sep 17 00:00:00 2001 From: Yann Stepienik Date: Wed, 15 Nov 2023 15:32:26 +0000 Subject: [PATCH] [release] v0.12.6-unstable --- package.json | 2 +- src/httpServer.go | 9 +++++--- src/user/login.go | 6 +++++ src/user/password_reset.go | 6 +++++ src/utils/loggedIn.go | 12 ++++++++++ src/utils/middleware.go | 45 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 76 insertions(+), 4 deletions(-) diff --git a/package.json b/package.json index b6812d4..d9904b7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cosmos-server", - "version": "0.12.5", + "version": "0.12.6-unstable", "description": "", "main": "test-server.js", "bugs": { diff --git a/src/httpServer.go b/src/httpServer.go index ac39d8a..3a014a2 100644 --- a/src/httpServer.go +++ b/src/httpServer.go @@ -343,6 +343,10 @@ func InitServer() *mux.Router { srapi := router.PathPrefix("/cosmos").Subrouter() + + srapi.HandleFunc("/api/login", user.UserLogin) + srapi.HandleFunc("/api/password-reset", user.ResetPassword) + srapi.HandleFunc("/api/mfa", user.API2FA) srapi.HandleFunc("/api/dns", GetDNSRoute) srapi.HandleFunc("/api/dns-check", CheckDNSRoute) @@ -353,13 +357,10 @@ func InitServer() *mux.Router { srapi.HandleFunc("/api/favicon", GetFavicon) srapi.HandleFunc("/api/ping", PingURL) srapi.HandleFunc("/api/newInstall", NewInstallRoute) - srapi.HandleFunc("/api/login", user.UserLogin) srapi.HandleFunc("/api/logout", user.UserLogout) srapi.HandleFunc("/api/register", user.UserRegister) srapi.HandleFunc("/api/invite", user.UserResendInviteLink) srapi.HandleFunc("/api/me", user.Me) - srapi.HandleFunc("/api/mfa", user.API2FA) - srapi.HandleFunc("/api/password-reset", user.ResetPassword) srapi.HandleFunc("/api/config", configapi.ConfigRoute) srapi.HandleFunc("/api/restart", configapi.ConfigApiRestart) @@ -416,6 +417,8 @@ func InitServer() *mux.Router { if(!config.HTTPConfig.AcceptAllInsecureHostname) { srapi.Use(utils.EnsureHostname) } + + srapi.Use(utils.EnsureHostnameCosmosAPI) SecureAPI(srapi, false, false) diff --git a/src/user/login.go b/src/user/login.go index c47bcbc..f62ee9a 100644 --- a/src/user/login.go +++ b/src/user/login.go @@ -20,6 +20,12 @@ type LoginRequestJSON struct { func UserLogin(w http.ResponseWriter, req *http.Request) { if(req.Method == "POST") { time.Sleep(time.Duration(rand.Float64()*2)*time.Second) + + if utils.IsLoggedIn(req) { + utils.Error("UserLogin: User already logged ing", nil) + utils.HTTPError(w, "User is already logged in", http.StatusUnauthorized, "UL002") + return + } var request LoginRequestJSON err1 := json.NewDecoder(req.Body).Decode(&request) diff --git a/src/user/password_reset.go b/src/user/password_reset.go index 7b6e5e9..6ae4e3a 100644 --- a/src/user/password_reset.go +++ b/src/user/password_reset.go @@ -22,6 +22,12 @@ func ResetPassword(w http.ResponseWriter, req *http.Request) { } time.Sleep(time.Duration(rand.Float64()*2)*time.Second) + + if utils.IsLoggedIn(req) { + utils.Error("UserLogin: User already logged ing", nil) + utils.HTTPError(w, "User is already logged in", http.StatusUnauthorized, "UL002") + return + } var request PasswordResetRequestJSON err1 := json.NewDecoder(req.Body).Decode(&request) diff --git a/src/utils/loggedIn.go b/src/utils/loggedIn.go index 5294e30..636a46e 100644 --- a/src/utils/loggedIn.go +++ b/src/utils/loggedIn.go @@ -74,6 +74,18 @@ func LoggedInWeakOnly(w http.ResponseWriter, req *http.Request) error { return nil } +func IsLoggedIn(req *http.Request) bool { + userNickname := req.Header.Get("x-cosmos-user") + role, _ := strconv.Atoi(req.Header.Get("x-cosmos-role")) + isUserLoggedIn := role > 0 + + if !isUserLoggedIn || userNickname == "" { + return false + } + + return true +} + func LoggedInOnly(w http.ResponseWriter, req *http.Request) error { userNickname := req.Header.Get("x-cosmos-user") role, _ := strconv.Atoi(req.Header.Get("x-cosmos-role")) diff --git a/src/utils/middleware.go b/src/utils/middleware.go index 816b40d..a95cbff 100644 --- a/src/utils/middleware.go +++ b/src/utils/middleware.go @@ -346,6 +346,51 @@ func EnsureHostname(next http.Handler) http.Handler { }) } +func EnsureHostnameCosmosAPI(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + og := GetMainConfig().HTTPConfig.Hostname + ni := GetMainConfig().NewInstall + + isLogin := !strings.HasPrefix(r.URL.Path, "/cosmos/api") || + strings.HasPrefix(r.URL.Path, "/cosmos/api/login") || + strings.HasPrefix(r.URL.Path, "/cosmos/api/password-reset") || + strings.HasPrefix(r.URL.Path, "/cosmos/api/mfa") + + if ni || og == "0.0.0.0" || isLogin { + next.ServeHTTP(w, r) + return + } + + reqHostNoPort := strings.Split(r.Host, ":")[0] + + if og != reqHostNoPort { + PushShieldMetrics("hostname") + Error("Invalid Hostname " + r.Host + " for request.", nil) + w.WriteHeader(http.StatusBadRequest) + http.Error(w, "Bad Request: Invalid hostname. Use your domain instead of your IP to access your server. Check logs if more details are needed.", http.StatusBadRequest) + + ip, _, _ := net.SplitHostPort(r.RemoteAddr) + if ip != "" { + TriggerEvent( + "cosmos.proxy.shield.hostname", + "Proxy Shield hostname blocked", + "warning", + "", + map[string]interface{}{ + "clientID": ip, + "hostname": r.Host, + "url": r.URL.String(), + }) + IncrementIPAbuseCounter(ip) + } + + return + } + + next.ServeHTTP(w, r) + }) +} + func IsValidHostname(hostname string) bool { og := GetMainConfig().HTTPConfig.Hostname ni := GetMainConfig().NewInstall