diff --git a/httpd/auth_utils.go b/httpd/auth_utils.go index 47fef7bf..0b0f6fb0 100644 --- a/httpd/auth_utils.go +++ b/httpd/auth_utils.go @@ -49,16 +49,19 @@ type jwtTokenClaims struct { Username string Permissions []string Signature string - Audience string + Audience []string APIKeyID string MustSetTwoFactorAuth bool RequiredTwoFactorProtocols []string } func (c *jwtTokenClaims) hasUserAudience() bool { - if c.Audience == tokenAudienceWebClient || c.Audience == tokenAudienceAPIUser { - return true + for _, audience := range c.Audience { + if audience == tokenAudienceWebClient || audience == tokenAudienceAPIUser { + return true + } } + return false } @@ -97,9 +100,7 @@ func (c *jwtTokenClaims) Decode(token map[string]interface{}) { switch v := audience.(type) { case []string: - if len(v) > 0 { - c.Audience = v[0] - } + c.Audience = v } if val, ok := token[claimAPIKey]; ok { @@ -163,10 +164,10 @@ func (c *jwtTokenClaims) createToken(tokenAuth *jwtauth.JWTAuth, audience tokenA claims := c.asMap() now := time.Now().UTC() - claims[jwt.JwtIDKey] = fmt.Sprintf("%s%s", xid.New().String(), ip) + claims[jwt.JwtIDKey] = xid.New().String() claims[jwt.NotBeforeKey] = now.Add(-30 * time.Second) claims[jwt.ExpirationKey] = now.Add(tokenDuration) - claims[jwt.AudienceKey] = audience + claims[jwt.AudienceKey] = []string{audience, ip} return tokenAuth.Encode(claims) } @@ -299,14 +300,14 @@ func getAdminFromToken(r *http.Request) *dataprovider.Admin { return admin } -func createCSRFToken() string { +func createCSRFToken(ip string) string { claims := make(map[string]interface{}) now := time.Now().UTC() claims[jwt.JwtIDKey] = xid.New().String() claims[jwt.NotBeforeKey] = now.Add(-30 * time.Second) claims[jwt.ExpirationKey] = now.Add(csrfTokenDuration) - claims[jwt.AudienceKey] = tokenAudienceCSRF + claims[jwt.AudienceKey] = []string{tokenAudienceCSRF, ip} _, tokenString, err := csrfTokenAuth.Encode(claims) if err != nil { @@ -316,7 +317,7 @@ func createCSRFToken() string { return tokenString } -func verifyCSRFToken(tokenString string) error { +func verifyCSRFToken(tokenString, ip string) error { token, err := jwtauth.VerifyToken(csrfTokenAuth, tokenString) if err != nil || token == nil { logger.Debug(logSender, "", "error validating CSRF token %#v: %v", tokenString, err) @@ -328,5 +329,10 @@ func verifyCSRFToken(tokenString string) error { return errors.New("the form token is not valid") } + if !util.IsStringInSlice(ip, token.Audience()) { + logger.Debug(logSender, "", "error validating CSRF token IP audience") + return errors.New("the form token is not valid") + } + return nil } diff --git a/httpd/httpd_test.go b/httpd/httpd_test.go index 3ea2a7a7..4b098a0d 100644 --- a/httpd/httpd_test.go +++ b/httpd/httpd_test.go @@ -162,6 +162,7 @@ const ( webClientResetPwdPath = "/web/client/reset-password" webClientViewPDFPath = "/web/client/viewpdf" httpBaseURL = "http://127.0.0.1:8081" + defaultRemoteAddr = "127.0.0.1:1234" sftpServerAddr = "127.0.0.1:8022" smtpServerAddr = "127.0.0.1:3525" configDir = ".." @@ -4031,6 +4032,7 @@ func TestNamingRules(t *testing.T) { lastResetCode = "" req, err = http.NewRequest(http.MethodPost, webClientForgotPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusFound, rr.Code) @@ -4041,6 +4043,7 @@ func TestNamingRules(t *testing.T) { form.Set("password", defaultPassword) req, err = http.NewRequest(http.MethodPost, webClientResetPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -4087,6 +4090,7 @@ func TestNamingRules(t *testing.T) { form = make(url.Values) form.Set(csrfFormToken, csrfToken) req, _ = http.NewRequest(http.MethodPost, webAdminProfilePath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -4124,6 +4128,7 @@ func TestNamingRules(t *testing.T) { lastResetCode = "" req, err = http.NewRequest(http.MethodPost, webAdminForgotPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusFound, rr.Code) @@ -4134,6 +4139,7 @@ func TestNamingRules(t *testing.T) { form.Set("password", defaultPassword) req, err = http.NewRequest(http.MethodPost, webAdminResetPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -4229,6 +4235,7 @@ func TestSaveErrors(t *testing.T) { form := getLoginForm(a.Username, a.Password, csrfToken) req, err := http.NewRequest(http.MethodPost, webLoginPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr := executeRequest(req) assert.Equal(t, http.StatusFound, rr.Code) @@ -4242,6 +4249,7 @@ func TestSaveErrors(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webAdminTwoFactorRecoveryPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusInternalServerError, rr.Code) @@ -4252,6 +4260,7 @@ func TestSaveErrors(t *testing.T) { form = getLoginForm(u.Username, u.Password, csrfToken) req, err = http.NewRequest(http.MethodPost, webClientLoginPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusFound, rr.Code) @@ -4265,6 +4274,7 @@ func TestSaveErrors(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webClientTwoFactorRecoveryPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusInternalServerError, rr.Code) @@ -4395,6 +4405,7 @@ func TestProviderErrors(t *testing.T) { form.Set(csrfFormToken, csrfToken) req, err = http.NewRequest(http.MethodPost, webClientForgotPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -5541,6 +5552,7 @@ func TestAdminTwoFactorLogin(t *testing.T) { form := getLoginForm(altAdminUsername, altAdminPassword, csrfToken) req, err = http.NewRequest(http.MethodPost, webLoginPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusFound, rr.Code) @@ -5589,6 +5601,7 @@ func TestAdminTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webAdminTwoFactorPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -5599,6 +5612,7 @@ func TestAdminTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webAdminTwoFactorPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -5617,6 +5631,7 @@ func TestAdminTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webAdminTwoFactorPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusFound, rr.Code) @@ -5625,6 +5640,7 @@ func TestAdminTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webAdminTwoFactorPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusNotFound, rr.Code) @@ -5632,6 +5648,7 @@ func TestAdminTwoFactorLogin(t *testing.T) { form = getLoginForm(altAdminUsername, altAdminPassword, csrfToken) req, err = http.NewRequest(http.MethodPost, webLoginPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusFound, rr.Code) @@ -5646,6 +5663,7 @@ func TestAdminTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webAdminTwoFactorRecoveryPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -5656,6 +5674,7 @@ func TestAdminTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webAdminTwoFactorRecoveryPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -5665,6 +5684,7 @@ func TestAdminTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webAdminTwoFactorRecoveryPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusFound, rr.Code) @@ -5674,6 +5694,7 @@ func TestAdminTwoFactorLogin(t *testing.T) { //render MFA page req, err = http.NewRequest(http.MethodGet, webAdminMFAPath, nil) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, authenticatedCookie) rr = executeRequest(req) checkResponseCode(t, http.StatusOK, rr) @@ -5701,6 +5722,7 @@ func TestAdminTwoFactorLogin(t *testing.T) { form = getLoginForm(altAdminUsername, altAdminPassword, csrfToken) req, err = http.NewRequest(http.MethodPost, webLoginPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusFound, rr.Code) @@ -5713,6 +5735,7 @@ func TestAdminTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webAdminTwoFactorRecoveryPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -5722,6 +5745,7 @@ func TestAdminTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webAdminTwoFactorRecoveryPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -5730,6 +5754,7 @@ func TestAdminTwoFactorLogin(t *testing.T) { form = getLoginForm(altAdminUsername, altAdminPassword, csrfToken) req, err = http.NewRequest(http.MethodPost, webLoginPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusFound, rr.Code) @@ -5750,6 +5775,7 @@ func TestAdminTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webAdminTwoFactorRecoveryPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -5759,6 +5785,7 @@ func TestAdminTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webAdminTwoFactorPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -5770,6 +5797,7 @@ func TestAdminTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webAdminTwoFactorRecoveryPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -5778,6 +5806,7 @@ func TestAdminTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webAdminTwoFactorPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -5785,6 +5814,7 @@ func TestAdminTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodGet, webAdminMFAPath, nil) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, authenticatedCookie) rr = executeRequest(req) checkResponseCode(t, http.StatusInternalServerError, rr) @@ -6106,6 +6136,7 @@ func TestWebUserTwoFactorLogin(t *testing.T) { form := getLoginForm(defaultUsername, defaultPassword, csrfToken) req, err = http.NewRequest(http.MethodPost, webClientLoginPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusFound, rr.Code) @@ -6153,6 +6184,7 @@ func TestWebUserTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webClientTwoFactorPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -6163,6 +6195,7 @@ func TestWebUserTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webClientTwoFactorPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -6172,6 +6205,7 @@ func TestWebUserTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webClientTwoFactorPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -6181,6 +6215,7 @@ func TestWebUserTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webClientTwoFactorPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusFound, rr.Code) @@ -6189,6 +6224,7 @@ func TestWebUserTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webClientTwoFactorPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusNotFound, rr.Code) @@ -6196,6 +6232,7 @@ func TestWebUserTwoFactorLogin(t *testing.T) { form = getLoginForm(defaultUsername, defaultPassword, csrfToken) req, err = http.NewRequest(http.MethodPost, webClientLoginPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusFound, rr.Code) @@ -6220,6 +6257,7 @@ func TestWebUserTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webClientTwoFactorRecoveryPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -6229,6 +6267,7 @@ func TestWebUserTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webClientTwoFactorRecoveryPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusFound, rr.Code) @@ -6238,6 +6277,7 @@ func TestWebUserTwoFactorLogin(t *testing.T) { //render MFA page req, err = http.NewRequest(http.MethodGet, webClientMFAPath, nil) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, authenticatedCookie) rr = executeRequest(req) checkResponseCode(t, http.StatusOK, rr) @@ -6266,6 +6306,7 @@ func TestWebUserTwoFactorLogin(t *testing.T) { form = getLoginForm(defaultUsername, defaultPassword, csrfToken) req, err = http.NewRequest(http.MethodPost, webClientLoginPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusFound, rr.Code) @@ -6278,6 +6319,7 @@ func TestWebUserTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webClientTwoFactorRecoveryPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -6287,6 +6329,7 @@ func TestWebUserTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webClientTwoFactorRecoveryPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -6295,6 +6338,7 @@ func TestWebUserTwoFactorLogin(t *testing.T) { form = getLoginForm(defaultUsername, defaultPassword, csrfToken) req, err = http.NewRequest(http.MethodPost, webClientLoginPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusFound, rr.Code) @@ -6317,6 +6361,7 @@ func TestWebUserTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webClientTwoFactorRecoveryPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -6325,6 +6370,7 @@ func TestWebUserTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webClientTwoFactorPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -6338,6 +6384,7 @@ func TestWebUserTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webClientTwoFactorRecoveryPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -6346,6 +6393,7 @@ func TestWebUserTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webClientTwoFactorPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -6353,6 +6401,7 @@ func TestWebUserTwoFactorLogin(t *testing.T) { req, err = http.NewRequest(http.MethodGet, webClientMFAPath, nil) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, authenticatedCookie) rr = executeRequest(req) checkResponseCode(t, http.StatusInternalServerError, rr) @@ -6650,6 +6699,7 @@ func TestMFAInvalidSecret(t *testing.T) { form := getLoginForm(defaultUsername, defaultPassword, csrfToken) req, err = http.NewRequest(http.MethodPost, webClientLoginPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusFound, rr.Code) @@ -6662,6 +6712,7 @@ func TestMFAInvalidSecret(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webClientTwoFactorPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusInternalServerError, rr.Code) @@ -6672,6 +6723,7 @@ func TestMFAInvalidSecret(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webClientTwoFactorRecoveryPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusInternalServerError, rr.Code) @@ -6715,6 +6767,7 @@ func TestMFAInvalidSecret(t *testing.T) { form = getLoginForm(altAdminUsername, altAdminPassword, csrfToken) req, err = http.NewRequest(http.MethodPost, webLoginPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusFound, rr.Code) @@ -6727,6 +6780,7 @@ func TestMFAInvalidSecret(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webAdminTwoFactorPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusInternalServerError, rr.Code) @@ -6737,6 +6791,7 @@ func TestMFAInvalidSecret(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webAdminTwoFactorRecoveryPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) setJWTCookieForReq(req, cookie) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusInternalServerError, rr.Code) @@ -8564,10 +8619,12 @@ func TestWebClientLoginMock(t *testing.T) { assert.Equal(t, webClientLoginPath, rr.Header().Get("Location")) // now try to render client pages req, _ = http.NewRequest(http.MethodGet, webClientProfilePath, nil) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, webToken) rr = executeRequest(req) checkResponseCode(t, http.StatusOK, rr) req, _ = http.NewRequest(http.MethodGet, webClientFilesPath, nil) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, webToken) rr = executeRequest(req) checkResponseCode(t, http.StatusOK, rr) @@ -8595,21 +8652,25 @@ func TestWebClientLoginMock(t *testing.T) { req, _ = http.NewRequest(http.MethodGet, webClientProfilePath, nil) setJWTCookieForReq(req, webToken) + req.RemoteAddr = defaultRemoteAddr rr = executeRequest(req) checkResponseCode(t, http.StatusInternalServerError, rr) req, _ = http.NewRequest(http.MethodGet, webClientFilesPath, nil) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, webToken) rr = executeRequest(req) checkResponseCode(t, http.StatusNotFound, rr) assert.Contains(t, rr.Body.String(), "Unable to retrieve your user") req, _ = http.NewRequest(http.MethodGet, webClientDirsPath, nil) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, webToken) rr = executeRequest(req) checkResponseCode(t, http.StatusNotFound, rr) assert.Contains(t, rr.Body.String(), "Unable to retrieve your user") req, _ = http.NewRequest(http.MethodGet, webClientDownloadZipPath, nil) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, webToken) rr = executeRequest(req) checkResponseCode(t, http.StatusNotFound, rr) @@ -8651,6 +8712,7 @@ func TestWebClientLoginMock(t *testing.T) { form.Set("public_keys", testPubKey) form.Set(csrfFormToken, csrfToken) req, _ = http.NewRequest(http.MethodPost, webClientProfilePath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, webToken) rr = executeRequest(req) @@ -8660,6 +8722,7 @@ func TestWebClientLoginMock(t *testing.T) { func TestWebClientLoginErrorsMock(t *testing.T) { form := getLoginForm("", "", "") req, _ := http.NewRequest(http.MethodPost, webClientLoginPath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr := executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -8667,6 +8730,7 @@ func TestWebClientLoginErrorsMock(t *testing.T) { form = getLoginForm(defaultUsername, defaultPassword, "") req, _ = http.NewRequest(http.MethodPost, webClientLoginPath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -8717,14 +8781,14 @@ func TestTokenInvalidIPAddress(t *testing.T) { user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated) assert.NoError(t, err) - webToken, err := getJWTWebClientTokenFromTestServerWithAddr(defaultUsername, defaultPassword, "1.1.1.1") + webToken, err := getJWTWebClientTokenFromTestServer(defaultUsername, defaultPassword) assert.NoError(t, err) req, err := http.NewRequest(http.MethodGet, webClientFilesPath, nil) assert.NoError(t, err) - req.RemoteAddr = "1.1.1.2" req.RequestURI = webClientFilesPath setJWTCookieForReq(req, webToken) + req.RemoteAddr = "1.1.1.2" rr := executeRequest(req) checkResponseCode(t, http.StatusFound, rr) @@ -8767,9 +8831,9 @@ func TestDefender(t *testing.T) { assert.NoError(t, err) req, _ := http.NewRequest(http.MethodGet, webClientFilesPath, nil) - req.RemoteAddr = remoteAddr req.RequestURI = webClientFilesPath setJWTCookieForReq(req, webToken) + req.RemoteAddr = remoteAddr rr := executeRequest(req) checkResponseCode(t, http.StatusOK, rr) @@ -8781,25 +8845,25 @@ func TestDefender(t *testing.T) { _, err = getJWTWebClientTokenFromTestServerWithAddr(defaultUsername, defaultPassword, remoteAddr) assert.Error(t, err) req, _ = http.NewRequest(http.MethodGet, webClientFilesPath, nil) - req.RemoteAddr = remoteAddr req.RequestURI = webClientFilesPath setJWTCookieForReq(req, webToken) + req.RemoteAddr = remoteAddr rr = executeRequest(req) checkResponseCode(t, http.StatusForbidden, rr) assert.Contains(t, rr.Body.String(), "your IP address is banned") req, _ = http.NewRequest(http.MethodGet, webUsersPath, nil) - req.RemoteAddr = remoteAddr req.RequestURI = webUsersPath setJWTCookieForReq(req, webAdminToken) + req.RemoteAddr = remoteAddr rr = executeRequest(req) checkResponseCode(t, http.StatusForbidden, rr) assert.Contains(t, rr.Body.String(), "your IP address is banned") req, _ = http.NewRequest(http.MethodGet, webClientFilesPath, nil) - req.RemoteAddr = remoteAddr req.Header.Set("X-Real-IP", "127.0.0.1:2345") setJWTCookieForReq(req, webToken) + req.RemoteAddr = remoteAddr rr = executeRequest(req) checkResponseCode(t, http.StatusForbidden, rr) assert.Contains(t, rr.Body.String(), "your IP address is banned") @@ -8904,6 +8968,7 @@ func TestMaxSessions(t *testing.T) { lastResetCode = "" req, err := http.NewRequest(http.MethodPost, webClientForgotPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr := executeRequest(req) assert.Equal(t, http.StatusFound, rr.Code) @@ -8914,6 +8979,7 @@ func TestMaxSessions(t *testing.T) { form.Set("code", lastResetCode) req, err = http.NewRequest(http.MethodPost, webClientResetPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -8979,6 +9045,7 @@ func TestSFTPLoopError(t *testing.T) { lastResetCode = "" req, err := http.NewRequest(http.MethodPost, webClientForgotPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr := executeRequest(req) assert.Equal(t, http.StatusFound, rr.Code) @@ -8989,6 +9056,7 @@ func TestSFTPLoopError(t *testing.T) { form.Set("code", lastResetCode) req, err = http.NewRequest(http.MethodPost, webClientResetPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -9082,6 +9150,7 @@ func TestWebClientChangePwd(t *testing.T) { req, err := http.NewRequest(http.MethodGet, webChangeClientPwdPath, nil) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, webToken) rr := executeRequest(req) checkResponseCode(t, http.StatusOK, rr) @@ -9093,6 +9162,7 @@ func TestWebClientChangePwd(t *testing.T) { // no csrf token req, err = http.NewRequest(http.MethodPost, webChangeClientPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, webToken) rr = executeRequest(req) @@ -9101,6 +9171,7 @@ func TestWebClientChangePwd(t *testing.T) { form.Set(csrfFormToken, csrfToken) req, _ = http.NewRequest(http.MethodPost, webChangeClientPwdPath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, webToken) rr = executeRequest(req) @@ -9111,6 +9182,7 @@ func TestWebClientChangePwd(t *testing.T) { form.Set("new_password1", defaultPassword+"1") form.Set("new_password2", defaultPassword+"1") req, _ = http.NewRequest(http.MethodPost, webChangeClientPwdPath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, webToken) rr = executeRequest(req) @@ -9121,6 +9193,7 @@ func TestWebClientChangePwd(t *testing.T) { form.Set("new_password1", defaultPassword+"1") form.Set("new_password2", defaultPassword+"1") req, _ = http.NewRequest(http.MethodPost, webChangeClientPwdPath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, webToken) rr = executeRequest(req) @@ -9147,6 +9220,7 @@ func TestWebClientChangePwd(t *testing.T) { form.Set("new_password1", defaultPassword) form.Set("new_password2", defaultPassword) req, _ = http.NewRequest(http.MethodPost, webChangeClientPwdPath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, webToken) rr = executeRequest(req) @@ -12585,12 +12659,14 @@ func TestWebAdminSetupMock(t *testing.T) { form := make(url.Values) req, err = http.NewRequest(http.MethodPost, webAdminSetupPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) checkResponseCode(t, http.StatusForbidden, rr) form.Set(csrfFormToken, csrfToken) req, err = http.NewRequest(http.MethodPost, webAdminSetupPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) checkResponseCode(t, http.StatusOK, rr) @@ -12598,6 +12674,7 @@ func TestWebAdminSetupMock(t *testing.T) { form.Set("username", defaultTokenAuthUser) req, err = http.NewRequest(http.MethodPost, webAdminSetupPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) checkResponseCode(t, http.StatusOK, rr) @@ -12605,6 +12682,7 @@ func TestWebAdminSetupMock(t *testing.T) { form.Set("password", defaultTokenAuthPass) req, err = http.NewRequest(http.MethodPost, webAdminSetupPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) checkResponseCode(t, http.StatusOK, rr) @@ -12613,6 +12691,7 @@ func TestWebAdminSetupMock(t *testing.T) { // test a parse form error req, err = http.NewRequest(http.MethodPost, webAdminSetupPath+"?param=p%C3%AO%GH", bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) checkResponseCode(t, http.StatusOK, rr) @@ -12621,6 +12700,7 @@ func TestWebAdminSetupMock(t *testing.T) { assert.NoError(t, err) req, err = http.NewRequest(http.MethodPost, webAdminSetupPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) checkResponseCode(t, http.StatusOK, rr) @@ -12636,6 +12716,7 @@ func TestWebAdminSetupMock(t *testing.T) { assert.NoError(t, err) req, err = http.NewRequest(http.MethodPost, webAdminSetupPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) checkResponseCode(t, http.StatusFound, rr) @@ -12643,6 +12724,7 @@ func TestWebAdminSetupMock(t *testing.T) { // if we resubmit the form we get a bad request, an admin already exists req, err = http.NewRequest(http.MethodPost, webAdminSetupPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) checkResponseCode(t, http.StatusBadRequest, rr) @@ -12722,6 +12804,7 @@ func TestWebAdminLoginMock(t *testing.T) { checkResponseCode(t, http.StatusNotFound, rr) req, _ = http.NewRequest(http.MethodGet, webStatusPath, nil) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, webToken) rr = executeRequest(req) checkResponseCode(t, http.StatusOK, rr) @@ -12754,6 +12837,7 @@ func TestWebAdminLoginMock(t *testing.T) { // now try using wrong credentials form := getLoginForm(defaultTokenAuthUser, "wrong pwd", csrfToken) req, _ = http.NewRequest(http.MethodPost, webLoginPath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) checkResponseCode(t, http.StatusOK, rr) @@ -12766,23 +12850,34 @@ func TestWebAdminLoginMock(t *testing.T) { _, _, err = httpdtest.AddAdmin(a, http.StatusCreated) assert.NoError(t, err) + rAddr := "127.1.1.1:1234" + csrfToken, err = getCSRFTokenMock(webLoginPath, rAddr) + assert.NoError(t, err) form = getLoginForm(altAdminUsername, altAdminPassword, csrfToken) req, _ = http.NewRequest(http.MethodPost, webLoginPath, bytes.NewBuffer([]byte(form.Encode()))) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - req.RemoteAddr = "127.1.1.1:1234" + req.RemoteAddr = rAddr rr = executeRequest(req) checkResponseCode(t, http.StatusOK, rr) assert.Contains(t, rr.Body.String(), "login from IP 127.1.1.1 not allowed") + rAddr = "10.9.9.9:1234" + csrfToken, err = getCSRFTokenMock(webLoginPath, rAddr) + assert.NoError(t, err) + form = getLoginForm(altAdminUsername, altAdminPassword, csrfToken) req, _ = http.NewRequest(http.MethodPost, webLoginPath, bytes.NewBuffer([]byte(form.Encode()))) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - req.RemoteAddr = "10.9.9.9:1234" + req.RemoteAddr = rAddr rr = executeRequest(req) checkResponseCode(t, http.StatusFound, rr) + rAddr = "127.0.1.1:4567" + csrfToken, err = getCSRFTokenMock(webLoginPath, rAddr) + assert.NoError(t, err) + form = getLoginForm(altAdminUsername, altAdminPassword, csrfToken) req, _ = http.NewRequest(http.MethodPost, webLoginPath, bytes.NewBuffer([]byte(form.Encode()))) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") - req.RemoteAddr = "127.0.1.1:4567" + req.RemoteAddr = rAddr req.Header.Set("X-Forwarded-For", "10.9.9.9") rr = executeRequest(req) checkResponseCode(t, http.StatusOK, rr) @@ -12858,6 +12953,7 @@ func TestWebUserShare(t *testing.T) { // invalid expiration date req, err := http.NewRequest(http.MethodPost, webClientSharePath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr := executeRequest(req) @@ -12868,6 +12964,7 @@ func TestWebUserShare(t *testing.T) { // invalid scope req, err = http.NewRequest(http.MethodPost, webClientSharePath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -12878,6 +12975,7 @@ func TestWebUserShare(t *testing.T) { form.Set("max_tokens", "t") req, err = http.NewRequest(http.MethodPost, webClientSharePath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -12887,6 +12985,7 @@ func TestWebUserShare(t *testing.T) { // no csrf token req, err = http.NewRequest(http.MethodPost, webClientSharePath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -12897,6 +12996,7 @@ func TestWebUserShare(t *testing.T) { form.Set("scope", "100") req, err = http.NewRequest(http.MethodPost, webClientSharePath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -12906,6 +13006,7 @@ func TestWebUserShare(t *testing.T) { form.Set("scope", strconv.Itoa(int(share.Scope))) req, err = http.NewRequest(http.MethodPost, webClientSharePath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -12935,6 +13036,7 @@ func TestWebUserShare(t *testing.T) { form.Set("expiration_date", "123") req, err = http.NewRequest(http.MethodPost, webClientSharePath+"/unknowid", bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -12942,6 +13044,7 @@ func TestWebUserShare(t *testing.T) { req, err = http.NewRequest(http.MethodPost, webClientSharePath+"/"+share.ShareID, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -12952,6 +13055,7 @@ func TestWebUserShare(t *testing.T) { form.Set(csrfFormToken, "") req, err = http.NewRequest(http.MethodPost, webClientSharePath+"/"+share.ShareID, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -12962,6 +13066,7 @@ func TestWebUserShare(t *testing.T) { form.Set("allowed_ip", "1.1.1") req, err = http.NewRequest(http.MethodPost, webClientSharePath+"/"+share.ShareID, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -12971,6 +13076,7 @@ func TestWebUserShare(t *testing.T) { form.Set("allowed_ip", "") req, err = http.NewRequest(http.MethodPost, webClientSharePath+"/"+share.ShareID, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -13003,6 +13109,7 @@ func TestWebUserShare(t *testing.T) { req, err = http.NewRequest(http.MethodGet, webClientSharePath+"?path=%2F&files=a", nil) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, token) rr = executeRequest(req) checkResponseCode(t, http.StatusBadRequest, rr) @@ -13010,30 +13117,35 @@ func TestWebUserShare(t *testing.T) { req, err = http.NewRequest(http.MethodGet, webClientSharePath+"?path=%2F&files=%5B\"adir\"%5D", nil) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, token) rr = executeRequest(req) checkResponseCode(t, http.StatusOK, rr) req, err = http.NewRequest(http.MethodGet, webClientSharePath+"/unknown", nil) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, token) rr = executeRequest(req) checkResponseCode(t, http.StatusNotFound, rr) req, err = http.NewRequest(http.MethodGet, webClientSharePath+"/"+share.ShareID, nil) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, token) rr = executeRequest(req) checkResponseCode(t, http.StatusOK, rr) req, err = http.NewRequest(http.MethodGet, webClientSharesPath+"?qlimit=a", nil) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, token) rr = executeRequest(req) checkResponseCode(t, http.StatusOK, rr) req, err = http.NewRequest(http.MethodGet, webClientSharesPath+"?qlimit=1", nil) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, token) rr = executeRequest(req) checkResponseCode(t, http.StatusOK, rr) @@ -13069,6 +13181,7 @@ func TestWebUserShareNoPasswordDisabled(t *testing.T) { form.Set(csrfFormToken, csrfToken) req, err := http.NewRequest(http.MethodPost, webClientSharePath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr := executeRequest(req) @@ -13078,6 +13191,7 @@ func TestWebUserShareNoPasswordDisabled(t *testing.T) { form.Set("password", defaultPassword) req, err = http.NewRequest(http.MethodPost, webClientSharePath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -13102,6 +13216,7 @@ func TestWebUserShareNoPasswordDisabled(t *testing.T) { form.Set("password", "") req, err = http.NewRequest(http.MethodPost, webClientSharePath+"/"+share.ShareID, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -13135,6 +13250,7 @@ func TestWebUserProfile(t *testing.T) { // no csrf token req, err := http.NewRequest(http.MethodPost, webClientProfilePath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr := executeRequest(req) @@ -13143,6 +13259,7 @@ func TestWebUserProfile(t *testing.T) { form.Set(csrfFormToken, csrfToken) req, _ = http.NewRequest(http.MethodPost, webClientProfilePath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -13159,6 +13276,7 @@ func TestWebUserProfile(t *testing.T) { // set an invalid email form.Set("email", "not an email") req, _ = http.NewRequest(http.MethodPost, webClientProfilePath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -13168,6 +13286,7 @@ func TestWebUserProfile(t *testing.T) { form.Set("email", email) form.Set("public_keys", "invalid") req, _ = http.NewRequest(http.MethodPost, webClientProfilePath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -13184,6 +13303,7 @@ func TestWebUserProfile(t *testing.T) { form.Set("allow_api_key_auth", "0") form.Set(csrfFormToken, csrfToken) req, _ = http.NewRequest(http.MethodPost, webClientProfilePath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -13204,6 +13324,7 @@ func TestWebUserProfile(t *testing.T) { form.Set("public_keys", testPubKey) form.Add("public_keys", testPubKey1) req, _ = http.NewRequest(http.MethodPost, webClientProfilePath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -13224,6 +13345,7 @@ func TestWebUserProfile(t *testing.T) { form.Set("email", "newemail@user.com") form.Set("description", "new description") req, _ = http.NewRequest(http.MethodPost, webClientProfilePath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -13243,6 +13365,7 @@ func TestWebUserProfile(t *testing.T) { token, err = getJWTWebClientTokenFromTestServer(defaultUsername, defaultPassword) assert.NoError(t, err) req, _ = http.NewRequest(http.MethodPost, webClientProfilePath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -13256,6 +13379,7 @@ func TestWebUserProfile(t *testing.T) { form = make(url.Values) form.Set(csrfFormToken, csrfToken) req, _ = http.NewRequest(http.MethodPost, webClientProfilePath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -13274,6 +13398,7 @@ func TestWebAdminProfile(t *testing.T) { assert.NoError(t, err) req, err := http.NewRequest(http.MethodGet, webAdminProfilePath, nil) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, token) rr := executeRequest(req) checkResponseCode(t, http.StatusOK, rr) @@ -13285,6 +13410,7 @@ func TestWebAdminProfile(t *testing.T) { // no csrf token req, err = http.NewRequest(http.MethodPost, webAdminProfilePath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -13293,6 +13419,7 @@ func TestWebAdminProfile(t *testing.T) { form.Set(csrfFormToken, csrfToken) req, _ = http.NewRequest(http.MethodPost, webAdminProfilePath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -13308,6 +13435,7 @@ func TestWebAdminProfile(t *testing.T) { form = make(url.Values) form.Set(csrfFormToken, csrfToken) req, _ = http.NewRequest(http.MethodPost, webAdminProfilePath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -13326,6 +13454,7 @@ func TestWebAdminProfile(t *testing.T) { form = make(url.Values) form.Set(csrfFormToken, csrfToken) req, _ = http.NewRequest(http.MethodPost, webAdminProfilePath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -13345,6 +13474,7 @@ func TestWebAdminPwdChange(t *testing.T) { assert.NoError(t, err) req, err := http.NewRequest(http.MethodGet, webChangeAdminPwdPath, nil) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, token) rr := executeRequest(req) checkResponseCode(t, http.StatusOK, rr) @@ -13354,6 +13484,7 @@ func TestWebAdminPwdChange(t *testing.T) { form.Set("new_password2", altAdminPassword) // no csrf token req, _ = http.NewRequest(http.MethodPost, webChangeAdminPwdPath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -13362,6 +13493,7 @@ func TestWebAdminPwdChange(t *testing.T) { form.Set(csrfFormToken, csrfToken) req, _ = http.NewRequest(http.MethodPost, webChangeAdminPwdPath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -13371,6 +13503,7 @@ func TestWebAdminPwdChange(t *testing.T) { form.Set("new_password1", altAdminPassword+"1") form.Set("new_password2", altAdminPassword+"1") req, _ = http.NewRequest(http.MethodPost, webChangeAdminPwdPath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -13881,6 +14014,7 @@ func TestWebAdminBasicMock(t *testing.T) { form.Set("permissions", "*") form.Set("description", admin.Description) req, _ := http.NewRequest(http.MethodPost, webAdminPath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr := executeRequest(req) @@ -13890,6 +14024,7 @@ func TestWebAdminBasicMock(t *testing.T) { form.Set(csrfFormToken, csrfToken) form.Set("status", "a") req, _ = http.NewRequest(http.MethodPost, webAdminPath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -13897,6 +14032,7 @@ func TestWebAdminBasicMock(t *testing.T) { form.Set("status", "1") req, _ = http.NewRequest(http.MethodPost, webAdminPath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -13904,6 +14040,7 @@ func TestWebAdminBasicMock(t *testing.T) { form.Set("password", admin.Password) req, _ = http.NewRequest(http.MethodPost, webAdminPath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -13924,6 +14061,7 @@ func TestWebAdminBasicMock(t *testing.T) { // no CSRF token req, err = http.NewRequest(http.MethodPost, webAdminTOTPSavePath, bytes.NewBuffer(asJSON)) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, altToken) rr = executeRequest(req) checkResponseCode(t, http.StatusForbidden, rr) @@ -13933,6 +14071,7 @@ func TestWebAdminBasicMock(t *testing.T) { assert.NoError(t, err) setJWTCookieForReq(req, altToken) setCSRFHeaderForReq(req, csrfToken) + req.RemoteAddr = defaultRemoteAddr rr = executeRequest(req) checkResponseCode(t, http.StatusOK, rr) @@ -13951,6 +14090,7 @@ func TestWebAdminBasicMock(t *testing.T) { assert.NoError(t, err) req, err = http.NewRequest(http.MethodPost, webAdminTOTPSavePath, bytes.NewBuffer(asJSON)) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, altToken) setCSRFHeaderForReq(req, csrfToken) rr = executeRequest(req) @@ -13970,27 +14110,32 @@ func TestWebAdminBasicMock(t *testing.T) { assert.NoError(t, err) req, err = http.NewRequest(http.MethodPost, webAdminTOTPSavePath, bytes.NewBuffer(asJSON)) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, altToken) setCSRFHeaderForReq(req, csrfToken) rr = executeRequest(req) checkResponseCode(t, http.StatusOK, rr) req, _ = http.NewRequest(http.MethodGet, webAdminsPath+"?qlimit=a", nil) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, token) rr = executeRequest(req) checkResponseCode(t, http.StatusOK, rr) req, _ = http.NewRequest(http.MethodGet, webAdminsPath+"?qlimit=1", nil) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, token) rr = executeRequest(req) checkResponseCode(t, http.StatusOK, rr) req, _ = http.NewRequest(http.MethodGet, webAdminPath, nil) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, token) rr = executeRequest(req) checkResponseCode(t, http.StatusOK, rr) form.Set("password", "") req, _ = http.NewRequest(http.MethodPost, path.Join(webAdminPath, altAdminUsername), bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -13998,6 +14143,7 @@ func TestWebAdminBasicMock(t *testing.T) { form.Set(csrfFormToken, "invalid csrf") req, _ = http.NewRequest(http.MethodPost, path.Join(webAdminPath, altAdminUsername), bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -14007,6 +14153,7 @@ func TestWebAdminBasicMock(t *testing.T) { form.Set(csrfFormToken, csrfToken) form.Set("email", "not-an-email") req, _ = http.NewRequest(http.MethodPost, path.Join(webAdminPath, altAdminUsername), bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -14015,6 +14162,7 @@ func TestWebAdminBasicMock(t *testing.T) { form.Set("email", "") form.Set("status", "b") req, _ = http.NewRequest(http.MethodPost, path.Join(webAdminPath, altAdminUsername), bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -14023,6 +14171,7 @@ func TestWebAdminBasicMock(t *testing.T) { form.Set("email", "admin@example.com") form.Set("status", "0") req, _ = http.NewRequest(http.MethodPost, path.Join(webAdminPath, altAdminUsername), bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -14035,22 +14184,26 @@ func TestWebAdminBasicMock(t *testing.T) { assert.Equal(t, 0, admin.Status) req, _ = http.NewRequest(http.MethodPost, path.Join(webAdminPath, altAdminUsername+"1"), bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) checkResponseCode(t, http.StatusNotFound, rr) req, _ = http.NewRequest(http.MethodGet, path.Join(webAdminPath, altAdminUsername), nil) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, token) rr = executeRequest(req) checkResponseCode(t, http.StatusOK, rr) req, _ = http.NewRequest(http.MethodGet, path.Join(webAdminPath, altAdminUsername+"1"), nil) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, token) rr = executeRequest(req) checkResponseCode(t, http.StatusNotFound, rr) req, _ = http.NewRequest(http.MethodDelete, path.Join(webAdminPath, altAdminUsername), nil) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, token) setCSRFHeaderForReq(req, csrfToken) rr = executeRequest(req) @@ -14060,6 +14213,7 @@ func TestWebAdminBasicMock(t *testing.T) { assert.NoError(t, err) req, _ = http.NewRequest(http.MethodDelete, path.Join(webAdminPath, defaultTokenAuthUser), nil) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, token) setCSRFHeaderForReq(req, csrfToken) rr = executeRequest(req) @@ -14067,6 +14221,7 @@ func TestWebAdminBasicMock(t *testing.T) { assert.Contains(t, rr.Body.String(), "you cannot delete yourself") req, _ = http.NewRequest(http.MethodDelete, path.Join(webAdminPath, defaultTokenAuthUser), nil) + req.RemoteAddr = defaultRemoteAddr setJWTCookieForReq(req, token) rr = executeRequest(req) checkResponseCode(t, http.StatusForbidden, rr) @@ -14159,6 +14314,7 @@ func TestAdminUpdateSelfMock(t *testing.T) { form.Set("permissions", dataprovider.PermAdminCloseConnections) form.Set(csrfFormToken, csrfToken) req, _ := http.NewRequest(http.MethodPost, path.Join(webAdminPath, defaultTokenAuthUser), bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr := executeRequest(req) @@ -14167,6 +14323,7 @@ func TestAdminUpdateSelfMock(t *testing.T) { form.Set("permissions", dataprovider.PermAdminAny) req, _ = http.NewRequest(http.MethodPost, path.Join(webAdminPath, defaultTokenAuthUser), bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") setJWTCookieForReq(req, token) rr = executeRequest(req) @@ -16718,6 +16875,7 @@ func TestAdminForgotPassword(t *testing.T) { // no csrf token req, err = http.NewRequest(http.MethodPost, webAdminForgotPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusForbidden, rr.Code) @@ -16725,6 +16883,7 @@ func TestAdminForgotPassword(t *testing.T) { form.Set(csrfFormToken, csrfToken) req, err = http.NewRequest(http.MethodPost, webAdminForgotPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -16734,6 +16893,7 @@ func TestAdminForgotPassword(t *testing.T) { form.Set("username", altAdminUsername) req, err = http.NewRequest(http.MethodPost, webAdminForgotPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusFound, rr.Code) @@ -16742,6 +16902,7 @@ func TestAdminForgotPassword(t *testing.T) { form = make(url.Values) req, err = http.NewRequest(http.MethodPost, webAdminResetPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusForbidden, rr.Code) @@ -16749,6 +16910,7 @@ func TestAdminForgotPassword(t *testing.T) { form.Set(csrfFormToken, csrfToken) req, err = http.NewRequest(http.MethodPost, webAdminResetPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -16757,6 +16919,7 @@ func TestAdminForgotPassword(t *testing.T) { form.Set("password", defaultPassword) req, err = http.NewRequest(http.MethodPost, webAdminResetPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -16765,6 +16928,7 @@ func TestAdminForgotPassword(t *testing.T) { form.Set("code", lastResetCode) req, err = http.NewRequest(http.MethodPost, webAdminResetPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusFound, rr.Code) @@ -16772,6 +16936,7 @@ func TestAdminForgotPassword(t *testing.T) { form.Set("username", altAdminUsername) req, err = http.NewRequest(http.MethodPost, webAdminForgotPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusFound, rr.Code) @@ -16791,6 +16956,7 @@ func TestAdminForgotPassword(t *testing.T) { form.Set(csrfFormToken, csrfToken) req, err = http.NewRequest(http.MethodPost, webAdminForgotPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -16804,6 +16970,7 @@ func TestAdminForgotPassword(t *testing.T) { form.Set(csrfFormToken, csrfToken) req, err = http.NewRequest(http.MethodPost, webAdminForgotPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -16858,6 +17025,7 @@ func TestUserForgotPassword(t *testing.T) { // no csrf token req, err = http.NewRequest(http.MethodPost, webClientForgotPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusForbidden, rr.Code) @@ -16867,6 +17035,7 @@ func TestUserForgotPassword(t *testing.T) { form.Set(csrfFormToken, csrfToken) req, err = http.NewRequest(http.MethodPost, webClientForgotPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -16875,6 +17044,7 @@ func TestUserForgotPassword(t *testing.T) { form.Set("username", user.Username) req, err = http.NewRequest(http.MethodPost, webClientForgotPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -16886,6 +17056,7 @@ func TestUserForgotPassword(t *testing.T) { lastResetCode = "" req, err = http.NewRequest(http.MethodPost, webClientForgotPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusFound, rr.Code) @@ -16894,6 +17065,7 @@ func TestUserForgotPassword(t *testing.T) { form = make(url.Values) req, err = http.NewRequest(http.MethodPost, webClientResetPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusForbidden, rr.Code) @@ -16901,6 +17073,7 @@ func TestUserForgotPassword(t *testing.T) { form.Set(csrfFormToken, csrfToken) req, err = http.NewRequest(http.MethodPost, webClientResetPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -16909,6 +17082,7 @@ func TestUserForgotPassword(t *testing.T) { form.Set("password", altAdminPassword) req, err = http.NewRequest(http.MethodPost, webClientResetPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -16917,6 +17091,7 @@ func TestUserForgotPassword(t *testing.T) { form.Set("code", lastResetCode) req, err = http.NewRequest(http.MethodPost, webClientResetPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusFound, rr.Code) @@ -16927,6 +17102,7 @@ func TestUserForgotPassword(t *testing.T) { lastResetCode = "" req, err = http.NewRequest(http.MethodPost, webClientForgotPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusFound, rr.Code) @@ -16957,6 +17133,7 @@ func TestUserForgotPassword(t *testing.T) { form.Set("password", "pwd") req, err = http.NewRequest(http.MethodPost, webClientResetPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) @@ -17438,6 +17615,16 @@ func getUserAsJSON(t *testing.T, user dataprovider.User) []byte { return json } +func getCSRFTokenMock(loginURLPath, remoteAddr string) (string, error) { + req, err := http.NewRequest(http.MethodGet, loginURLPath, nil) + if err != nil { + return "", err + } + req.RemoteAddr = remoteAddr + rr := executeRequest(req) + return getCSRFTokenFromBody(bytes.NewBuffer(rr.Body.Bytes())) +} + func getCSRFToken(url string) (string, error) { req, err := http.NewRequest(http.MethodGet, url, nil) if err != nil { @@ -17450,7 +17637,11 @@ func getCSRFToken(url string) (string, error) { defer resp.Body.Close() - doc, err := html.Parse(resp.Body) + return getCSRFTokenFromBody(resp.Body) +} + +func getCSRFTokenFromBody(body io.Reader) (string, error) { + doc, err := html.Parse(body) if err != nil { return "", err } @@ -17509,6 +17700,7 @@ func setAPIKeyForReq(req *http.Request, apiKey, username string) { } func setJWTCookieForReq(req *http.Request, jwtToken string) { + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Cookie", fmt.Sprintf("jwt=%v", jwtToken)) } @@ -17573,8 +17765,16 @@ func getJWTWebToken(username, password string) (string, error) { return "", errors.New("no cookie found") } +func getCookieFromResponse(rr *httptest.ResponseRecorder) (string, error) { + cookie := strings.Split(rr.Header().Get("Set-Cookie"), ";") + if strings.HasPrefix(cookie[0], "jwt=") { + return cookie[0][4:], nil + } + return "", errors.New("no cookie found") +} + func getJWTWebClientTokenFromTestServerWithAddr(username, password, remoteAddr string) (string, error) { - csrfToken, err := getCSRFToken(httpBaseURL + webClientLoginPath) + csrfToken, err := getCSRFTokenMock(webClientLoginPath, remoteAddr) if err != nil { return "", err } @@ -17589,16 +17789,20 @@ func getJWTWebClientTokenFromTestServerWithAddr(username, password, remoteAddr s return getCookieFromResponse(rr) } -func getCookieFromResponse(rr *httptest.ResponseRecorder) (string, error) { - cookie := strings.Split(rr.Header().Get("Set-Cookie"), ";") - if strings.HasPrefix(cookie[0], "jwt=") { - return cookie[0][4:], nil - } - return "", errors.New("no cookie found") -} - func getJWTWebClientTokenFromTestServer(username, password string) (string, error) { - return getJWTWebClientTokenFromTestServerWithAddr(username, password, "") + csrfToken, err := getCSRFToken(httpBaseURL + webClientLoginPath) + if err != nil { + return "", err + } + form := getLoginForm(username, password, csrfToken) + req, _ := http.NewRequest(http.MethodPost, webClientLoginPath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + rr := executeRequest(req) + if rr.Code != http.StatusFound { + return "", fmt.Errorf("unexpected status code %v", rr) + } + return getCookieFromResponse(rr) } func getJWTWebTokenFromTestServer(username, password string) (string, error) { @@ -17608,6 +17812,7 @@ func getJWTWebTokenFromTestServer(username, password string) (string, error) { } form := getLoginForm(username, password, csrfToken) req, _ := http.NewRequest(http.MethodPost, webLoginPath, bytes.NewBuffer([]byte(form.Encode()))) + req.RemoteAddr = defaultRemoteAddr req.Header.Set("Content-Type", "application/x-www-form-urlencoded") rr := executeRequest(req) if rr.Code != http.StatusFound { diff --git a/httpd/internal_test.go b/httpd/internal_test.go index af05faf8..cb0fad68 100644 --- a/httpd/internal_test.go +++ b/httpd/internal_test.go @@ -633,7 +633,7 @@ func TestUpdateWebAdminInvalidClaims(t *testing.T) { assert.NoError(t, err) form := make(url.Values) - form.Set(csrfFormToken, createCSRFToken()) + form.Set(csrfFormToken, createCSRFToken("")) form.Set("status", "1") req, _ := http.NewRequest(http.MethodPost, path.Join(webAdminPath, "admin"), bytes.NewBuffer([]byte(form.Encode()))) rctx := chi.NewRouteContext() @@ -688,7 +688,7 @@ func TestRetentionInvalidTokenClaims(t *testing.T) { func TestCSRFToken(t *testing.T) { // invalid token - err := verifyCSRFToken("token") + err := verifyCSRFToken("token", "") if assert.Error(t, err) { assert.Contains(t, err.Error(), "unable to verify form token") } @@ -699,15 +699,29 @@ func TestCSRFToken(t *testing.T) { claims[jwt.JwtIDKey] = xid.New().String() claims[jwt.NotBeforeKey] = now.Add(-30 * time.Second) claims[jwt.ExpirationKey] = now.Add(tokenDuration) - claims[jwt.AudienceKey] = tokenAudienceAPI + claims[jwt.AudienceKey] = []string{tokenAudienceAPI} _, tokenString, err := csrfTokenAuth.Encode(claims) assert.NoError(t, err) - err = verifyCSRFToken(tokenString) + err = verifyCSRFToken(tokenString, "") if assert.Error(t, err) { assert.Contains(t, err.Error(), "form token is not valid") } + // bad IP + tokenString = createCSRFToken("127.1.1.1") + err = verifyCSRFToken(tokenString, "127.1.1.2") + if assert.Error(t, err) { + assert.Contains(t, err.Error(), "form token is not valid") + } + + claims[jwt.JwtIDKey] = xid.New().String() + claims[jwt.NotBeforeKey] = now.Add(-30 * time.Second) + claims[jwt.ExpirationKey] = now.Add(tokenDuration) + claims[jwt.AudienceKey] = []string{tokenAudienceAPI} + _, tokenString, err = csrfTokenAuth.Encode(claims) + assert.NoError(t, err) + r := GetHTTPRouter(Binding{ Address: "", Port: 8080, @@ -722,6 +736,15 @@ func TestCSRFToken(t *testing.T) { assert.Equal(t, http.StatusForbidden, rr.Code) assert.Contains(t, rr.Body.String(), "Invalid token") + // invalid audience + req.Header.Set(csrfHeaderToken, tokenString) + rr = httptest.NewRecorder() + fn.ServeHTTP(rr, req) + assert.Equal(t, http.StatusForbidden, rr.Code) + assert.Contains(t, rr.Body.String(), "the token is not valid") + + // invalid IP + tokenString = createCSRFToken("172.16.1.2") req.Header.Set(csrfHeaderToken, tokenString) rr = httptest.NewRecorder() fn.ServeHTTP(rr, req) @@ -729,7 +752,7 @@ func TestCSRFToken(t *testing.T) { assert.Contains(t, rr.Body.String(), "the token is not valid") csrfTokenAuth = jwtauth.New("PS256", util.GenerateRandomBytes(32), nil) - tokenString = createCSRFToken() + tokenString = createCSRFToken("") assert.Empty(t, tokenString) csrfTokenAuth = jwtauth.New(jwa.HS256.String(), util.GenerateRandomBytes(32), nil) @@ -765,7 +788,7 @@ func TestCreateTokenError(t *testing.T) { form := make(url.Values) form.Set("username", admin.Username) form.Set("password", admin.Password) - form.Set(csrfFormToken, createCSRFToken()) + form.Set(csrfFormToken, createCSRFToken("127.0.0.1")) req, _ = http.NewRequest(http.MethodPost, webAdminLoginPath, bytes.NewBuffer([]byte(form.Encode()))) req.RemoteAddr = "127.0.0.1:1234" req.Header.Set("Content-Type", "application/x-www-form-urlencoded") @@ -905,7 +928,7 @@ func TestCreateTokenError(t *testing.T) { form = make(url.Values) form.Set("username", user.Username) form.Set("password", "clientpwd") - form.Set(csrfFormToken, createCSRFToken()) + form.Set(csrfFormToken, createCSRFToken("127.0.0.1")) req, _ = http.NewRequest(http.MethodPost, webClientLoginPath, bytes.NewBuffer([]byte(form.Encode()))) req.RemoteAddr = "127.0.0.1:4567" req.Header.Set("Content-Type", "application/x-www-form-urlencoded") @@ -1086,7 +1109,7 @@ func TestCookieExpiration(t *testing.T) { claims[claimPermissionsKey] = admin.Permissions claims[jwt.SubjectKey] = admin.GetSignature() claims[jwt.ExpirationKey] = time.Now().Add(1 * time.Minute) - claims[jwt.AudienceKey] = tokenAudienceAPI + claims[jwt.AudienceKey] = []string{tokenAudienceAPI} token, _, err = server.tokenAuth.Encode(claims) assert.NoError(t, err) req, _ = http.NewRequest(http.MethodGet, tokenPath, nil) @@ -1121,7 +1144,7 @@ func TestCookieExpiration(t *testing.T) { claims[claimPermissionsKey] = admin.Permissions claims[jwt.SubjectKey] = admin.GetSignature() claims[jwt.ExpirationKey] = time.Now().Add(1 * time.Minute) - claims[jwt.AudienceKey] = tokenAudienceAPI + claims[jwt.AudienceKey] = []string{tokenAudienceAPI} token, _, err = server.tokenAuth.Encode(claims) assert.NoError(t, err) req, _ = http.NewRequest(http.MethodGet, tokenPath, nil) @@ -1159,7 +1182,7 @@ func TestCookieExpiration(t *testing.T) { claims[claimPermissionsKey] = user.Filters.WebClient claims[jwt.SubjectKey] = user.GetSignature() claims[jwt.ExpirationKey] = time.Now().Add(1 * time.Minute) - claims[jwt.AudienceKey] = tokenAudienceWebClient + claims[jwt.AudienceKey] = []string{tokenAudienceWebClient} token, _, err = server.tokenAuth.Encode(claims) assert.NoError(t, err) @@ -1191,7 +1214,7 @@ func TestCookieExpiration(t *testing.T) { claims[claimPermissionsKey] = user.Filters.WebClient claims[jwt.SubjectKey] = user.GetSignature() claims[jwt.ExpirationKey] = time.Now().Add(1 * time.Minute) - claims[jwt.AudienceKey] = tokenAudienceWebClient + claims[jwt.AudienceKey] = []string{tokenAudienceWebClient} token, _, err = server.tokenAuth.Encode(claims) assert.NoError(t, err) @@ -1520,7 +1543,7 @@ func TestProxyHeaders(t *testing.T) { form := make(url.Values) form.Set("username", username) form.Set("password", password) - form.Set(csrfFormToken, createCSRFToken()) + form.Set(csrfFormToken, createCSRFToken(testIP)) req, err = http.NewRequest(http.MethodPost, webAdminLoginPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) req.RemoteAddr = testIP @@ -1530,6 +1553,7 @@ func TestProxyHeaders(t *testing.T) { assert.Equal(t, http.StatusOK, rr.Code, rr.Body.String()) assert.Contains(t, rr.Body.String(), "login from IP 10.29.1.9 not allowed") + form.Set(csrfFormToken, createCSRFToken(validForwardedFor)) req, err = http.NewRequest(http.MethodPost, webAdminLoginPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) req.RemoteAddr = testIP @@ -2069,7 +2093,7 @@ func TestInvalidClaims(t *testing.T) { token, err := c.createTokenResponse(server.tokenAuth, tokenAudienceWebClient, "") assert.NoError(t, err) form := make(url.Values) - form.Set(csrfFormToken, createCSRFToken()) + form.Set(csrfFormToken, createCSRFToken("")) form.Set("public_keys", "") req, _ := http.NewRequest(http.MethodPost, webClientProfilePath, bytes.NewBuffer([]byte(form.Encode()))) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") @@ -2089,7 +2113,7 @@ func TestInvalidClaims(t *testing.T) { token, err = c.createTokenResponse(server.tokenAuth, tokenAudienceWebAdmin, "") assert.NoError(t, err) form = make(url.Values) - form.Set(csrfFormToken, createCSRFToken()) + form.Set(csrfFormToken, createCSRFToken("")) form.Set("allow_api_key_auth", "") req, _ = http.NewRequest(http.MethodPost, webAdminProfilePath, bytes.NewBuffer([]byte(form.Encode()))) req.Header.Set("Content-Type", "application/x-www-form-urlencoded") @@ -2400,7 +2424,7 @@ func TestWebAdminSetupWithInstallCode(t *testing.T) { } form := make(url.Values) - csrfToken := createCSRFToken() + csrfToken := createCSRFToken("") form.Set("_form_token", csrfToken) form.Set("install_code", "12345") form.Set("username", defaultAdminUsername) diff --git a/httpd/middleware.go b/httpd/middleware.go index 92975bd8..01106f99 100644 --- a/httpd/middleware.go +++ b/httpd/middleware.go @@ -77,7 +77,7 @@ func validateJWTToken(w http.ResponseWriter, r *http.Request, audience tokenAudi return errInvalidToken } ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) - if ipAddr != "" && !strings.Contains(token.JwtID(), ipAddr) { + if !util.IsStringInSlice(ipAddr, token.Audience()) { logger.Debug(logSender, "", "the token with id %#v is not valid for the ip address %#v", token.JwtID(), ipAddr) doRedirect("Your token is not valid", nil) return errInvalidToken @@ -278,7 +278,13 @@ func verifyCSRFHeader(next http.Handler) http.Handler { } if !util.IsStringInSlice(tokenAudienceCSRF, token.Audience()) { - logger.Debug(logSender, "", "error validating CSRF header audience") + logger.Debug(logSender, "", "error validating CSRF header token audience") + sendAPIResponse(w, r, errors.New("the token is not valid"), "", http.StatusForbidden) + return + } + + if !util.IsStringInSlice(util.GetIPFromRemoteAddress(r.RemoteAddr), token.Audience()) { + logger.Debug(logSender, "", "error validating CSRF header IP audience") sendAPIResponse(w, r, errors.New("the token is not valid"), "", http.StatusForbidden) return } diff --git a/httpd/oidc_test.go b/httpd/oidc_test.go index 8f62e69b..9f37a460 100644 --- a/httpd/oidc_test.go +++ b/httpd/oidc_test.go @@ -81,7 +81,10 @@ func setIDTokenClaims(idToken *oidc.IDToken, claims []byte) { } func TestOIDCInitialization(t *testing.T) { - config := OIDC{ + config := OIDC{} + err := config.initialize() + assert.NoError(t, err) + config = OIDC{ ClientID: "sftpgo-client", ClientSecret: "jRsmE0SWnuZjP7djBqNq0mrf8QN77j2c", ConfigURL: fmt.Sprintf("http://%v/", oidcMockAddr), @@ -89,7 +92,7 @@ func TestOIDCInitialization(t *testing.T) { UsernameField: "preferred_username", RoleField: "sftpgo_role", } - err := config.initialize() + err = config.initialize() if assert.Error(t, err) { assert.Contains(t, err.Error(), "oidc: unable to initialize provider") } diff --git a/httpd/server.go b/httpd/server.go index d15cb475..c3cfb1d9 100644 --- a/httpd/server.go +++ b/httpd/server.go @@ -133,12 +133,12 @@ func (s *httpdServer) refreshCookie(next http.Handler) http.Handler { }) } -func (s *httpdServer) renderClientLoginPage(w http.ResponseWriter, error string) { +func (s *httpdServer) renderClientLoginPage(w http.ResponseWriter, error, ip string) { data := loginPage{ CurrentURL: webClientLoginPath, Version: version.Get().Version, Error: error, - CSRFToken: createCSRFToken(), + CSRFToken: createCSRFToken(ip), StaticURL: webStaticFilesPath, ExtraCSS: s.binding.ExtraCSS, } @@ -170,7 +170,7 @@ func (s *httpdServer) handleWebClientChangePwdPost(w http.ResponseWriter, r *htt s.renderClientChangePasswordPage(w, r, err.Error()) return } - if err := verifyCSRFToken(r.Form.Get(csrfFormToken)); err != nil { + if err := verifyCSRFToken(r.Form.Get(csrfFormToken), util.GetIPFromRemoteAddress(r.RemoteAddr)); err != nil { s.renderClientForbiddenPage(w, r, err.Error()) return } @@ -189,48 +189,48 @@ func (s *httpdServer) handleClientWebLogin(w http.ResponseWriter, r *http.Reques http.Redirect(w, r, webAdminSetupPath, http.StatusFound) return } - s.renderClientLoginPage(w, getFlashMessage(w, r)) + s.renderClientLoginPage(w, getFlashMessage(w, r), util.GetIPFromRemoteAddress(r.RemoteAddr)) } func (s *httpdServer) handleWebClientLoginPost(w http.ResponseWriter, r *http.Request) { r.Body = http.MaxBytesReader(w, r.Body, maxLoginBodySize) + ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) if err := r.ParseForm(); err != nil { - s.renderClientLoginPage(w, err.Error()) + s.renderClientLoginPage(w, err.Error(), ipAddr) return } - ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) protocol := common.ProtocolHTTP username := r.Form.Get("username") password := r.Form.Get("password") if username == "" || password == "" { updateLoginMetrics(&dataprovider.User{BaseUser: sdk.BaseUser{Username: username}}, dataprovider.LoginMethodPassword, ipAddr, common.ErrNoCredentials) - s.renderClientLoginPage(w, "Invalid credentials") + s.renderClientLoginPage(w, "Invalid credentials", ipAddr) return } - if err := verifyCSRFToken(r.Form.Get(csrfFormToken)); err != nil { + if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil { updateLoginMetrics(&dataprovider.User{BaseUser: sdk.BaseUser{Username: username}}, dataprovider.LoginMethodPassword, ipAddr, err) - s.renderClientLoginPage(w, err.Error()) + s.renderClientLoginPage(w, err.Error(), ipAddr) return } if err := common.Config.ExecutePostConnectHook(ipAddr, protocol); err != nil { - s.renderClientLoginPage(w, fmt.Sprintf("access denied by post connect hook: %v", err)) + s.renderClientLoginPage(w, fmt.Sprintf("access denied by post connect hook: %v", err), ipAddr) return } user, err := dataprovider.CheckUserAndPass(username, password, ipAddr, protocol) if err != nil { updateLoginMetrics(&user, dataprovider.LoginMethodPassword, ipAddr, err) - s.renderClientLoginPage(w, dataprovider.ErrInvalidCredentials.Error()) + s.renderClientLoginPage(w, dataprovider.ErrInvalidCredentials.Error(), ipAddr) return } connectionID := fmt.Sprintf("%v_%v", protocol, xid.New().String()) if err := checkHTTPClientUser(&user, r, connectionID); err != nil { updateLoginMetrics(&user, dataprovider.LoginMethodPassword, ipAddr, err) - s.renderClientLoginPage(w, err.Error()) + s.renderClientLoginPage(w, err.Error(), ipAddr) return } @@ -239,7 +239,7 @@ func (s *httpdServer) handleWebClientLoginPost(w http.ResponseWriter, r *http.Re if err != nil { logger.Warn(logSender, connectionID, "unable to check fs root: %v", err) updateLoginMetrics(&user, dataprovider.LoginMethodPassword, ipAddr, common.ErrInternalFailure) - s.renderClientLoginPage(w, err.Error()) + s.renderClientLoginPage(w, err.Error(), ipAddr) return } s.loginUser(w, r, &user, connectionID, ipAddr, false, s.renderClientLoginPage) @@ -247,27 +247,29 @@ func (s *httpdServer) handleWebClientLoginPost(w http.ResponseWriter, r *http.Re func (s *httpdServer) handleWebClientPasswordResetPost(w http.ResponseWriter, r *http.Request) { r.Body = http.MaxBytesReader(w, r.Body, maxLoginBodySize) + + ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) err := r.ParseForm() if err != nil { - s.renderClientResetPwdPage(w, err.Error()) + s.renderClientResetPwdPage(w, err.Error(), ipAddr) return } - if err := verifyCSRFToken(r.Form.Get(csrfFormToken)); err != nil { + if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil { s.renderClientForbiddenPage(w, r, err.Error()) return } _, user, err := handleResetPassword(r, r.Form.Get("code"), r.Form.Get("password"), false) if err != nil { if e, ok := err.(*util.ValidationError); ok { - s.renderClientResetPwdPage(w, e.GetErrorString()) + s.renderClientResetPwdPage(w, e.GetErrorString(), ipAddr) return } - s.renderClientResetPwdPage(w, err.Error()) + s.renderClientResetPwdPage(w, err.Error(), ipAddr) return } connectionID := fmt.Sprintf("%v_%v", getProtocolFromRequest(r), xid.New().String()) if err := checkHTTPClientUser(user, r, connectionID); err != nil { - s.renderClientResetPwdPage(w, fmt.Sprintf("Password reset successfully but unable to login: %v", err.Error())) + s.renderClientResetPwdPage(w, fmt.Sprintf("Password reset successfully but unable to login: %v", err.Error()), ipAddr) return } @@ -275,10 +277,9 @@ func (s *httpdServer) handleWebClientPasswordResetPost(w http.ResponseWriter, r err = user.CheckFsRoot(connectionID) if err != nil { logger.Warn(logSender, connectionID, "unable to check fs root: %v", err) - s.renderClientResetPwdPage(w, fmt.Sprintf("Password reset successfully but unable to login: %v", err.Error())) + s.renderClientResetPwdPage(w, fmt.Sprintf("Password reset successfully but unable to login: %v", err.Error()), ipAddr) return } - ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) s.loginUser(w, r, user, connectionID, ipAddr, false, s.renderClientResetPwdPage) } @@ -289,27 +290,28 @@ func (s *httpdServer) handleWebClientTwoFactorRecoveryPost(w http.ResponseWriter s.renderNotFoundPage(w, r, nil) return } + ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) if err := r.ParseForm(); err != nil { - s.renderClientTwoFactorRecoveryPage(w, err.Error()) + s.renderClientTwoFactorRecoveryPage(w, err.Error(), ipAddr) return } username := claims.Username recoveryCode := r.Form.Get("recovery_code") if username == "" || recoveryCode == "" { - s.renderClientTwoFactorRecoveryPage(w, "Invalid credentials") + s.renderClientTwoFactorRecoveryPage(w, "Invalid credentials", ipAddr) return } - if err := verifyCSRFToken(r.Form.Get(csrfFormToken)); err != nil { - s.renderClientTwoFactorRecoveryPage(w, err.Error()) + if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil { + s.renderClientTwoFactorRecoveryPage(w, err.Error(), ipAddr) return } user, err := dataprovider.UserExists(username) if err != nil { - s.renderClientTwoFactorRecoveryPage(w, "Invalid credentials") + s.renderClientTwoFactorRecoveryPage(w, "Invalid credentials", ipAddr) return } if !user.Filters.TOTPConfig.Enabled || !util.IsStringInSlice(common.ProtocolHTTP, user.Filters.TOTPConfig.Protocols) { - s.renderClientTwoFactorPage(w, "Two factory authentication is not enabled") + s.renderClientTwoFactorPage(w, "Two factory authentication is not enabled", ipAddr) return } for idx, code := range user.Filters.RecoveryCodes { @@ -319,23 +321,23 @@ func (s *httpdServer) handleWebClientTwoFactorRecoveryPost(w http.ResponseWriter } if code.Secret.GetPayload() == recoveryCode { if code.Used { - s.renderClientTwoFactorRecoveryPage(w, "This recovery code was already used") + s.renderClientTwoFactorRecoveryPage(w, "This recovery code was already used", ipAddr) return } user.Filters.RecoveryCodes[idx].Used = true - err = dataprovider.UpdateUser(&user, dataprovider.ActionExecutorSelf, util.GetIPFromRemoteAddress(r.RemoteAddr)) + err = dataprovider.UpdateUser(&user, dataprovider.ActionExecutorSelf, ipAddr) if err != nil { logger.Warn(logSender, "", "unable to set the recovery code %#v as used: %v", recoveryCode, err) s.renderClientInternalServerErrorPage(w, r, errors.New("unable to set the recovery code as used")) return } connectionID := fmt.Sprintf("%v_%v", getProtocolFromRequest(r), xid.New().String()) - s.loginUser(w, r, &user, connectionID, util.GetIPFromRemoteAddress(r.RemoteAddr), true, + s.loginUser(w, r, &user, connectionID, ipAddr, true, s.renderClientTwoFactorRecoveryPage) return } } - s.renderClientTwoFactorRecoveryPage(w, "Invalid recovery code") + s.renderClientTwoFactorRecoveryPage(w, "Invalid recovery code", ipAddr) } func (s *httpdServer) handleWebClientTwoFactorPost(w http.ResponseWriter, r *http.Request) { @@ -345,27 +347,28 @@ func (s *httpdServer) handleWebClientTwoFactorPost(w http.ResponseWriter, r *htt s.renderNotFoundPage(w, r, nil) return } + ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) if err := r.ParseForm(); err != nil { - s.renderClientTwoFactorPage(w, err.Error()) + s.renderClientTwoFactorPage(w, err.Error(), ipAddr) return } username := claims.Username passcode := r.Form.Get("passcode") if username == "" || passcode == "" { - s.renderClientTwoFactorPage(w, "Invalid credentials") + s.renderClientTwoFactorPage(w, "Invalid credentials", ipAddr) return } - if err := verifyCSRFToken(r.Form.Get(csrfFormToken)); err != nil { - s.renderClientTwoFactorPage(w, err.Error()) + if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil { + s.renderClientTwoFactorPage(w, err.Error(), ipAddr) return } user, err := dataprovider.UserExists(username) if err != nil { - s.renderClientTwoFactorPage(w, "Invalid credentials") + s.renderClientTwoFactorPage(w, "Invalid credentials", ipAddr) return } if !user.Filters.TOTPConfig.Enabled || !util.IsStringInSlice(common.ProtocolHTTP, user.Filters.TOTPConfig.Protocols) { - s.renderClientTwoFactorPage(w, "Two factory authentication is not enabled") + s.renderClientTwoFactorPage(w, "Two factory authentication is not enabled", ipAddr) return } err = user.Filters.TOTPConfig.Secret.Decrypt() @@ -376,44 +379,45 @@ func (s *httpdServer) handleWebClientTwoFactorPost(w http.ResponseWriter, r *htt match, err := mfa.ValidateTOTPPasscode(user.Filters.TOTPConfig.ConfigName, passcode, user.Filters.TOTPConfig.Secret.GetPayload()) if !match || err != nil { - s.renderClientTwoFactorPage(w, "Invalid authentication code") + s.renderClientTwoFactorPage(w, "Invalid authentication code", ipAddr) return } connectionID := fmt.Sprintf("%v_%v", getProtocolFromRequest(r), xid.New().String()) - s.loginUser(w, r, &user, connectionID, util.GetIPFromRemoteAddress(r.RemoteAddr), true, s.renderClientTwoFactorPage) + s.loginUser(w, r, &user, connectionID, ipAddr, true, s.renderClientTwoFactorPage) } func (s *httpdServer) handleWebAdminTwoFactorRecoveryPost(w http.ResponseWriter, r *http.Request) { r.Body = http.MaxBytesReader(w, r.Body, maxLoginBodySize) + claims, err := getTokenClaims(r) if err != nil { s.renderNotFoundPage(w, r, nil) return } + ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) if err := r.ParseForm(); err != nil { - s.renderTwoFactorRecoveryPage(w, err.Error()) + s.renderTwoFactorRecoveryPage(w, err.Error(), ipAddr) return } username := claims.Username recoveryCode := r.Form.Get("recovery_code") if username == "" || recoveryCode == "" { - s.renderTwoFactorRecoveryPage(w, "Invalid credentials") + s.renderTwoFactorRecoveryPage(w, "Invalid credentials", ipAddr) return } - if err := verifyCSRFToken(r.Form.Get(csrfFormToken)); err != nil { - s.renderTwoFactorRecoveryPage(w, err.Error()) + if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil { + s.renderTwoFactorRecoveryPage(w, err.Error(), ipAddr) return } admin, err := dataprovider.AdminExists(username) if err != nil { - s.renderTwoFactorRecoveryPage(w, "Invalid credentials") + s.renderTwoFactorRecoveryPage(w, "Invalid credentials", ipAddr) return } if !admin.Filters.TOTPConfig.Enabled { - s.renderTwoFactorRecoveryPage(w, "Two factory authentication is not enabled") + s.renderTwoFactorRecoveryPage(w, "Two factory authentication is not enabled", ipAddr) return } - ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) for idx, code := range admin.Filters.RecoveryCodes { if err := code.Secret.Decrypt(); err != nil { s.renderInternalServerErrorPage(w, r, fmt.Errorf("unable to decrypt recovery code: %w", err)) @@ -421,7 +425,7 @@ func (s *httpdServer) handleWebAdminTwoFactorRecoveryPost(w http.ResponseWriter, } if code.Secret.GetPayload() == recoveryCode { if code.Used { - s.renderTwoFactorRecoveryPage(w, "This recovery code was already used") + s.renderTwoFactorRecoveryPage(w, "This recovery code was already used", ipAddr) return } admin.Filters.RecoveryCodes[idx].Used = true @@ -435,7 +439,7 @@ func (s *httpdServer) handleWebAdminTwoFactorRecoveryPost(w http.ResponseWriter, return } } - s.renderTwoFactorRecoveryPage(w, "Invalid recovery code") + s.renderTwoFactorRecoveryPage(w, "Invalid recovery code", ipAddr) } func (s *httpdServer) handleWebAdminTwoFactorPost(w http.ResponseWriter, r *http.Request) { @@ -445,27 +449,28 @@ func (s *httpdServer) handleWebAdminTwoFactorPost(w http.ResponseWriter, r *http s.renderNotFoundPage(w, r, nil) return } + ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) if err := r.ParseForm(); err != nil { - s.renderTwoFactorPage(w, err.Error()) + s.renderTwoFactorPage(w, err.Error(), ipAddr) return } username := claims.Username passcode := r.Form.Get("passcode") if username == "" || passcode == "" { - s.renderTwoFactorPage(w, "Invalid credentials") + s.renderTwoFactorPage(w, "Invalid credentials", ipAddr) return } - if err := verifyCSRFToken(r.Form.Get(csrfFormToken)); err != nil { - s.renderTwoFactorPage(w, err.Error()) + if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil { + s.renderTwoFactorPage(w, err.Error(), ipAddr) return } admin, err := dataprovider.AdminExists(username) if err != nil { - s.renderTwoFactorPage(w, "Invalid credentials") + s.renderTwoFactorPage(w, "Invalid credentials", ipAddr) return } if !admin.Filters.TOTPConfig.Enabled { - s.renderTwoFactorPage(w, "Two factory authentication is not enabled") + s.renderTwoFactorPage(w, "Two factory authentication is not enabled", ipAddr) return } err = admin.Filters.TOTPConfig.Secret.Decrypt() @@ -476,43 +481,44 @@ func (s *httpdServer) handleWebAdminTwoFactorPost(w http.ResponseWriter, r *http match, err := mfa.ValidateTOTPPasscode(admin.Filters.TOTPConfig.ConfigName, passcode, admin.Filters.TOTPConfig.Secret.GetPayload()) if !match || err != nil { - s.renderTwoFactorPage(w, "Invalid authentication code") + s.renderTwoFactorPage(w, "Invalid authentication code", ipAddr) return } - s.loginAdmin(w, r, &admin, true, s.renderTwoFactorPage, util.GetIPFromRemoteAddress(r.RemoteAddr)) + s.loginAdmin(w, r, &admin, true, s.renderTwoFactorPage, ipAddr) } func (s *httpdServer) handleWebAdminLoginPost(w http.ResponseWriter, r *http.Request) { r.Body = http.MaxBytesReader(w, r.Body, maxLoginBodySize) + + ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) if err := r.ParseForm(); err != nil { - s.renderAdminLoginPage(w, err.Error()) + s.renderAdminLoginPage(w, err.Error(), ipAddr) return } username := r.Form.Get("username") password := r.Form.Get("password") if username == "" || password == "" { - s.renderAdminLoginPage(w, "Invalid credentials") + s.renderAdminLoginPage(w, "Invalid credentials", ipAddr) return } - if err := verifyCSRFToken(r.Form.Get(csrfFormToken)); err != nil { - s.renderAdminLoginPage(w, err.Error()) + if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil { + s.renderAdminLoginPage(w, err.Error(), ipAddr) return } - ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) admin, err := dataprovider.CheckAdminAndPass(username, password, ipAddr) if err != nil { - s.renderAdminLoginPage(w, err.Error()) + s.renderAdminLoginPage(w, err.Error(), ipAddr) return } s.loginAdmin(w, r, &admin, false, s.renderAdminLoginPage, ipAddr) } -func (s *httpdServer) renderAdminLoginPage(w http.ResponseWriter, error string) { +func (s *httpdServer) renderAdminLoginPage(w http.ResponseWriter, error, ip string) { data := loginPage{ CurrentURL: webAdminLoginPath, Version: version.Get().Version, Error: error, - CSRFToken: createCSRFToken(), + CSRFToken: createCSRFToken(ip), StaticURL: webStaticFilesPath, ExtraCSS: s.binding.ExtraCSS, } @@ -534,7 +540,7 @@ func (s *httpdServer) handleWebAdminLogin(w http.ResponseWriter, r *http.Request http.Redirect(w, r, webAdminSetupPath, http.StatusFound) return } - s.renderAdminLoginPage(w, getFlashMessage(w, r)) + s.renderAdminLoginPage(w, getFlashMessage(w, r), util.GetIPFromRemoteAddress(r.RemoteAddr)) } func (s *httpdServer) handleWebAdminLogout(w http.ResponseWriter, r *http.Request) { @@ -553,7 +559,7 @@ func (s *httpdServer) handleWebAdminChangePwdPost(w http.ResponseWriter, r *http s.renderChangePasswordPage(w, r, err.Error()) return } - if err := verifyCSRFToken(r.Form.Get(csrfFormToken)); err != nil { + if err := verifyCSRFToken(r.Form.Get(csrfFormToken), util.GetIPFromRemoteAddress(r.RemoteAddr)); err != nil { s.renderForbiddenPage(w, r, err.Error()) return } @@ -568,26 +574,28 @@ func (s *httpdServer) handleWebAdminChangePwdPost(w http.ResponseWriter, r *http func (s *httpdServer) handleWebAdminPasswordResetPost(w http.ResponseWriter, r *http.Request) { r.Body = http.MaxBytesReader(w, r.Body, maxLoginBodySize) + + ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) err := r.ParseForm() if err != nil { - s.renderResetPwdPage(w, err.Error()) + s.renderResetPwdPage(w, err.Error(), ipAddr) return } - if err := verifyCSRFToken(r.Form.Get(csrfFormToken)); err != nil { + if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil { s.renderForbiddenPage(w, r, err.Error()) return } admin, _, err := handleResetPassword(r, r.Form.Get("code"), r.Form.Get("password"), true) if err != nil { if e, ok := err.(*util.ValidationError); ok { - s.renderResetPwdPage(w, e.GetErrorString()) + s.renderResetPwdPage(w, e.GetErrorString(), ipAddr) return } - s.renderResetPwdPage(w, err.Error()) + s.renderResetPwdPage(w, err.Error(), ipAddr) return } - s.loginAdmin(w, r, admin, false, s.renderResetPwdPage, util.GetIPFromRemoteAddress(r.RemoteAddr)) + s.loginAdmin(w, r, admin, false, s.renderResetPwdPage, ipAddr) } func (s *httpdServer) handleWebAdminSetupPost(w http.ResponseWriter, r *http.Request) { @@ -601,7 +609,8 @@ func (s *httpdServer) handleWebAdminSetupPost(w http.ResponseWriter, r *http.Req s.renderAdminSetupPage(w, r, "", err.Error()) return } - if err := verifyCSRFToken(r.Form.Get(csrfFormToken)); err != nil { + ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) + if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil { s.renderForbiddenPage(w, r, err.Error()) return } @@ -631,7 +640,6 @@ func (s *httpdServer) handleWebAdminSetupPost(w http.ResponseWriter, r *http.Req Status: 1, Permissions: []string{dataprovider.PermAdminAny}, } - ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) err = dataprovider.AddAdmin(&admin, username, ipAddr) if err != nil { s.renderAdminSetupPage(w, r, username, err.Error()) @@ -642,7 +650,7 @@ func (s *httpdServer) handleWebAdminSetupPost(w http.ResponseWriter, r *http.Req func (s *httpdServer) loginUser( w http.ResponseWriter, r *http.Request, user *dataprovider.User, connectionID, ipAddr string, - isSecondFactorAuth bool, errorFunc func(w http.ResponseWriter, error string), + isSecondFactorAuth bool, errorFunc func(w http.ResponseWriter, error, ip string), ) { c := jwtTokenClaims{ Username: user.Username, @@ -662,7 +670,7 @@ func (s *httpdServer) loginUser( if err != nil { logger.Warn(logSender, connectionID, "unable to set user login cookie %v", err) updateLoginMetrics(user, dataprovider.LoginMethodPassword, ipAddr, common.ErrInternalFailure) - errorFunc(w, err.Error()) + errorFunc(w, err.Error(), ipAddr) return } if isSecondFactorAuth { @@ -679,7 +687,8 @@ func (s *httpdServer) loginUser( func (s *httpdServer) loginAdmin( w http.ResponseWriter, r *http.Request, admin *dataprovider.Admin, - isSecondFactorAuth bool, errorFunc func(w http.ResponseWriter, error string), ip string, + isSecondFactorAuth bool, errorFunc func(w http.ResponseWriter, error, ip string), + ipAddr string, ) { c := jwtTokenClaims{ Username: admin.Username, @@ -692,14 +701,14 @@ func (s *httpdServer) loginAdmin( audience = tokenAudienceWebAdminPartial } - err := c.createAndSetCookie(w, r, s.tokenAuth, audience, ip) + err := c.createAndSetCookie(w, r, s.tokenAuth, audience, ipAddr) if err != nil { logger.Warn(logSender, "", "unable to set admin login cookie %v", err) if errorFunc == nil { s.renderAdminSetupPage(w, r, admin.Username, err.Error()) return } - errorFunc(w, err.Error()) + errorFunc(w, err.Error(), ipAddr) return } if isSecondFactorAuth { diff --git a/httpd/webadmin.go b/httpd/webadmin.go index 7af3d283..3756d1f7 100644 --- a/httpd/webadmin.go +++ b/httpd/webadmin.go @@ -376,7 +376,7 @@ func loadAdminTemplates(templatesPath string) { func (s *httpdServer) getBasePageData(title, currentURL string, r *http.Request) basePage { var csrfToken string if currentURL != "" { - csrfToken = createCSRFToken() + csrfToken = createCSRFToken(util.GetIPFromRemoteAddress(r.RemoteAddr)) } return basePage{ Title: title, @@ -458,11 +458,11 @@ func (s *httpdServer) renderNotFoundPage(w http.ResponseWriter, r *http.Request, s.renderMessagePage(w, r, page404Title, page404Body, http.StatusNotFound, err, "") } -func (s *httpdServer) renderForgotPwdPage(w http.ResponseWriter, error string) { +func (s *httpdServer) renderForgotPwdPage(w http.ResponseWriter, error, ip string) { data := forgotPwdPage{ CurrentURL: webAdminForgotPwdPath, Error: error, - CSRFToken: createCSRFToken(), + CSRFToken: createCSRFToken(ip), StaticURL: webStaticFilesPath, Title: pageForgotPwdTitle, ExtraCSS: s.binding.ExtraCSS, @@ -470,11 +470,11 @@ func (s *httpdServer) renderForgotPwdPage(w http.ResponseWriter, error string) { renderAdminTemplate(w, templateForgotPassword, data) } -func (s *httpdServer) renderResetPwdPage(w http.ResponseWriter, error string) { +func (s *httpdServer) renderResetPwdPage(w http.ResponseWriter, error, ip string) { data := resetPwdPage{ CurrentURL: webAdminResetPwdPath, Error: error, - CSRFToken: createCSRFToken(), + CSRFToken: createCSRFToken(ip), StaticURL: webStaticFilesPath, Title: pageResetPwdTitle, ExtraCSS: s.binding.ExtraCSS, @@ -482,12 +482,12 @@ func (s *httpdServer) renderResetPwdPage(w http.ResponseWriter, error string) { renderAdminTemplate(w, templateResetPassword, data) } -func (s *httpdServer) renderTwoFactorPage(w http.ResponseWriter, error string) { +func (s *httpdServer) renderTwoFactorPage(w http.ResponseWriter, error, ip string) { data := twoFactorPage{ CurrentURL: webAdminTwoFactorPath, Version: version.Get().Version, Error: error, - CSRFToken: createCSRFToken(), + CSRFToken: createCSRFToken(ip), StaticURL: webStaticFilesPath, RecoveryURL: webAdminTwoFactorRecoveryPath, ExtraCSS: s.binding.ExtraCSS, @@ -495,12 +495,12 @@ func (s *httpdServer) renderTwoFactorPage(w http.ResponseWriter, error string) { renderAdminTemplate(w, templateTwoFactor, data) } -func (s *httpdServer) renderTwoFactorRecoveryPage(w http.ResponseWriter, error string) { +func (s *httpdServer) renderTwoFactorRecoveryPage(w http.ResponseWriter, error, ip string) { data := twoFactorPage{ CurrentURL: webAdminTwoFactorRecoveryPath, Version: version.Get().Version, Error: error, - CSRFToken: createCSRFToken(), + CSRFToken: createCSRFToken(ip), StaticURL: webStaticFilesPath, ExtraCSS: s.binding.ExtraCSS, } @@ -1376,27 +1376,29 @@ func (s *httpdServer) handleWebAdminForgotPwd(w http.ResponseWriter, r *http.Req s.renderNotFoundPage(w, r, errors.New("this page does not exist")) return } - s.renderForgotPwdPage(w, "") + s.renderForgotPwdPage(w, "", util.GetIPFromRemoteAddress(r.RemoteAddr)) } func (s *httpdServer) handleWebAdminForgotPwdPost(w http.ResponseWriter, r *http.Request) { r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize) + + ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) err := r.ParseForm() if err != nil { - s.renderForgotPwdPage(w, err.Error()) + s.renderForgotPwdPage(w, err.Error(), ipAddr) return } - if err := verifyCSRFToken(r.Form.Get(csrfFormToken)); err != nil { + if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil { s.renderForbiddenPage(w, r, err.Error()) return } err = handleForgotPassword(r, r.Form.Get("username"), true) if err != nil { if e, ok := err.(*util.ValidationError); ok { - s.renderForgotPwdPage(w, e.GetErrorString()) + s.renderForgotPwdPage(w, e.GetErrorString(), ipAddr) return } - s.renderForgotPwdPage(w, err.Error()) + s.renderForgotPwdPage(w, err.Error(), ipAddr) return } http.Redirect(w, r, webAdminResetPwdPath, http.StatusFound) @@ -1408,17 +1410,17 @@ func (s *httpdServer) handleWebAdminPasswordReset(w http.ResponseWriter, r *http s.renderNotFoundPage(w, r, errors.New("this page does not exist")) return } - s.renderResetPwdPage(w, "") + s.renderResetPwdPage(w, "", util.GetIPFromRemoteAddress(r.RemoteAddr)) } func (s *httpdServer) handleWebAdminTwoFactor(w http.ResponseWriter, r *http.Request) { r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize) - s.renderTwoFactorPage(w, "") + s.renderTwoFactorPage(w, "", util.GetIPFromRemoteAddress(r.RemoteAddr)) } func (s *httpdServer) handleWebAdminTwoFactorRecovery(w http.ResponseWriter, r *http.Request) { r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize) - s.renderTwoFactorRecoveryPage(w, "") + s.renderTwoFactorRecoveryPage(w, "", util.GetIPFromRemoteAddress(r.RemoteAddr)) } func (s *httpdServer) handleWebAdminMFA(w http.ResponseWriter, r *http.Request) { @@ -1443,7 +1445,8 @@ func (s *httpdServer) handleWebAdminProfilePost(w http.ResponseWriter, r *http.R s.renderProfilePage(w, r, err.Error()) return } - if err := verifyCSRFToken(r.Form.Get(csrfFormToken)); err != nil { + ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) + if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil { s.renderForbiddenPage(w, r, err.Error()) return } @@ -1460,7 +1463,7 @@ func (s *httpdServer) handleWebAdminProfilePost(w http.ResponseWriter, r *http.R admin.Filters.AllowAPIKeyAuth = len(r.Form.Get("allow_api_key_auth")) > 0 admin.Email = r.Form.Get("email") admin.Description = r.Form.Get("description") - err = dataprovider.UpdateAdmin(&admin, dataprovider.ActionExecutorSelf, util.GetIPFromRemoteAddress(r.RemoteAddr)) + err = dataprovider.UpdateAdmin(&admin, dataprovider.ActionExecutorSelf, ipAddr) if err != nil { s.renderProfilePage(w, r, err.Error()) return @@ -1487,7 +1490,9 @@ func (s *httpdServer) handleWebRestore(w http.ResponseWriter, r *http.Request) { return } defer r.MultipartForm.RemoveAll() //nolint:errcheck - if err := verifyCSRFToken(r.Form.Get(csrfFormToken)); err != nil { + + ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) + if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil { s.renderForbiddenPage(w, r, err.Error()) return } @@ -1517,7 +1522,7 @@ func (s *httpdServer) handleWebRestore(w http.ResponseWriter, r *http.Request) { return } - if err := restoreBackup(backupContent, "", scanQuota, restoreMode, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)); err != nil { + if err := restoreBackup(backupContent, "", scanQuota, restoreMode, claims.Username, ipAddr); err != nil { s.renderMaintenancePage(w, r, err.Error()) return } @@ -1594,11 +1599,12 @@ func (s *httpdServer) handleWebAddAdminPost(w http.ResponseWriter, r *http.Reque s.renderAddUpdateAdminPage(w, r, &admin, err.Error(), true) return } - if err := verifyCSRFToken(r.Form.Get(csrfFormToken)); err != nil { + ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) + if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil { s.renderForbiddenPage(w, r, err.Error()) return } - err = dataprovider.AddAdmin(&admin, claims.Username, util.GetIPFromRemoteAddress(r.Method)) + err = dataprovider.AddAdmin(&admin, claims.Username, ipAddr) if err != nil { s.renderAddUpdateAdminPage(w, r, &admin, err.Error(), true) return @@ -1624,7 +1630,8 @@ func (s *httpdServer) handleWebUpdateAdminPost(w http.ResponseWriter, r *http.Re s.renderAddUpdateAdminPage(w, r, &updatedAdmin, err.Error(), false) return } - if err := verifyCSRFToken(r.Form.Get(csrfFormToken)); err != nil { + ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) + if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil { s.renderForbiddenPage(w, r, err.Error()) return } @@ -1650,7 +1657,7 @@ func (s *httpdServer) handleWebUpdateAdminPost(w http.ResponseWriter, r *http.Re return } } - err = dataprovider.UpdateAdmin(&updatedAdmin, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) + err = dataprovider.UpdateAdmin(&updatedAdmin, claims.Username, ipAddr) if err != nil { s.renderAddUpdateAdminPage(w, r, &admin, err.Error(), false) return @@ -1733,7 +1740,8 @@ func (s *httpdServer) handleWebTemplateFolderPost(w http.ResponseWriter, r *http } defer r.MultipartForm.RemoveAll() //nolint:errcheck - if err := verifyCSRFToken(r.Form.Get(csrfFormToken)); err != nil { + ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) + if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil { s.renderForbiddenPage(w, r, err.Error()) return } @@ -1772,7 +1780,7 @@ func (s *httpdServer) handleWebTemplateFolderPost(w http.ResponseWriter, r *http render.JSON(w, r, dump) return } - if err = RestoreFolders(dump.Folders, "", 1, 0, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)); err != nil { + if err = RestoreFolders(dump.Folders, "", 1, 0, claims.Username, ipAddr); err != nil { s.renderMessagePage(w, r, "Unable to save folders", "Cannot save the defined folders:", getRespStatus(err), err, "") return @@ -1819,7 +1827,8 @@ func (s *httpdServer) handleWebTemplateUserPost(w http.ResponseWriter, r *http.R s.renderMessagePage(w, r, "Error parsing user fields", "", http.StatusBadRequest, err, "") return } - if err := verifyCSRFToken(r.Form.Get(csrfFormToken)); err != nil { + ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) + if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil { s.renderForbiddenPage(w, r, err.Error()) return } @@ -1854,7 +1863,7 @@ func (s *httpdServer) handleWebTemplateUserPost(w http.ResponseWriter, r *http.R render.JSON(w, r, dump) return } - if err = RestoreUsers(dump.Users, "", 1, 0, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)); err != nil { + if err = RestoreUsers(dump.Users, "", 1, 0, claims.Username, ipAddr); err != nil { s.renderMessagePage(w, r, "Unable to save users", "Cannot save the defined users:", getRespStatus(err), err, "") return @@ -1898,11 +1907,12 @@ func (s *httpdServer) handleWebAddUserPost(w http.ResponseWriter, r *http.Reques s.renderUserPage(w, r, &user, userPageModeAdd, err.Error()) return } - if err := verifyCSRFToken(r.Form.Get(csrfFormToken)); err != nil { + ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) + if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil { s.renderForbiddenPage(w, r, err.Error()) return } - err = dataprovider.AddUser(&user, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) + err = dataprovider.AddUser(&user, claims.Username, ipAddr) if err == nil { http.Redirect(w, r, webUsersPath, http.StatusSeeOther) } else { @@ -1931,7 +1941,8 @@ func (s *httpdServer) handleWebUpdateUserPost(w http.ResponseWriter, r *http.Req s.renderUserPage(w, r, &user, userPageModeUpdate, err.Error()) return } - if err := verifyCSRFToken(r.Form.Get(csrfFormToken)); err != nil { + ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) + if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil { s.renderForbiddenPage(w, r, err.Error()) return } @@ -1947,7 +1958,7 @@ func (s *httpdServer) handleWebUpdateUserPost(w http.ResponseWriter, r *http.Req user.FsConfig.AzBlobConfig.SASURL, user.FsConfig.GCSConfig.Credentials, user.FsConfig.CryptConfig.Passphrase, user.FsConfig.SFTPConfig.Password, user.FsConfig.SFTPConfig.PrivateKey) - err = dataprovider.UpdateUser(&updatedUser, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) + err = dataprovider.UpdateUser(&updatedUser, claims.Username, ipAddr) if err == nil { if len(r.Form.Get("disconnect")) > 0 { disconnectUser(user.Username) @@ -1992,7 +2003,8 @@ func (s *httpdServer) handleWebAddFolderPost(w http.ResponseWriter, r *http.Requ } defer r.MultipartForm.RemoveAll() //nolint:errcheck - if err := verifyCSRFToken(r.Form.Get(csrfFormToken)); err != nil { + ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) + if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil { s.renderForbiddenPage(w, r, err.Error()) return } @@ -2051,7 +2063,8 @@ func (s *httpdServer) handleWebUpdateFolderPost(w http.ResponseWriter, r *http.R } defer r.MultipartForm.RemoveAll() //nolint:errcheck - if err := verifyCSRFToken(r.Form.Get(csrfFormToken)); err != nil { + ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) + if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil { s.renderForbiddenPage(w, r, err.Error()) return } @@ -2072,7 +2085,7 @@ func (s *httpdServer) handleWebUpdateFolderPost(w http.ResponseWriter, r *http.R folder.FsConfig.AzBlobConfig.SASURL, folder.FsConfig.GCSConfig.Credentials, folder.FsConfig.CryptConfig.Passphrase, folder.FsConfig.SFTPConfig.Password, folder.FsConfig.SFTPConfig.PrivateKey) - err = dataprovider.UpdateFolder(updatedFolder, folder.Users, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) + err = dataprovider.UpdateFolder(updatedFolder, folder.Users, claims.Username, ipAddr) if err != nil { s.renderFolderPage(w, r, folder, folderPageModeUpdate, err.Error()) return diff --git a/httpd/webclient.go b/httpd/webclient.go index c0637dba..ab2130b6 100644 --- a/httpd/webclient.go +++ b/httpd/webclient.go @@ -314,7 +314,7 @@ func loadClientTemplates(templatesPath string) { func (s *httpdServer) getBaseClientPageData(title, currentURL string, r *http.Request) baseClientPage { var csrfToken string if currentURL != "" { - csrfToken = createCSRFToken() + csrfToken = createCSRFToken(util.GetIPFromRemoteAddress(r.RemoteAddr)) } v := version.Get() @@ -341,11 +341,11 @@ func (s *httpdServer) getBaseClientPageData(title, currentURL string, r *http.Re } } -func (s *httpdServer) renderClientForgotPwdPage(w http.ResponseWriter, error string) { +func (s *httpdServer) renderClientForgotPwdPage(w http.ResponseWriter, error, ip string) { data := forgotPwdPage{ CurrentURL: webClientForgotPwdPath, Error: error, - CSRFToken: createCSRFToken(), + CSRFToken: createCSRFToken(ip), StaticURL: webStaticFilesPath, Title: pageClientForgotPwdTitle, ExtraCSS: s.binding.ExtraCSS, @@ -353,11 +353,11 @@ func (s *httpdServer) renderClientForgotPwdPage(w http.ResponseWriter, error str renderClientTemplate(w, templateForgotPassword, data) } -func (s *httpdServer) renderClientResetPwdPage(w http.ResponseWriter, error string) { +func (s *httpdServer) renderClientResetPwdPage(w http.ResponseWriter, error, ip string) { data := resetPwdPage{ CurrentURL: webClientResetPwdPath, Error: error, - CSRFToken: createCSRFToken(), + CSRFToken: createCSRFToken(ip), StaticURL: webStaticFilesPath, Title: pageClientResetPwdTitle, ExtraCSS: s.binding.ExtraCSS, @@ -405,12 +405,12 @@ func (s *httpdServer) renderClientNotFoundPage(w http.ResponseWriter, r *http.Re s.renderClientMessagePage(w, r, page404Title, page404Body, http.StatusNotFound, err, "") } -func (s *httpdServer) renderClientTwoFactorPage(w http.ResponseWriter, error string) { +func (s *httpdServer) renderClientTwoFactorPage(w http.ResponseWriter, error, ip string) { data := twoFactorPage{ CurrentURL: webClientTwoFactorPath, Version: version.Get().Version, Error: error, - CSRFToken: createCSRFToken(), + CSRFToken: createCSRFToken(ip), StaticURL: webStaticFilesPath, RecoveryURL: webClientTwoFactorRecoveryPath, ExtraCSS: s.binding.ExtraCSS, @@ -418,12 +418,12 @@ func (s *httpdServer) renderClientTwoFactorPage(w http.ResponseWriter, error str renderClientTemplate(w, templateTwoFactor, data) } -func (s *httpdServer) renderClientTwoFactorRecoveryPage(w http.ResponseWriter, error string) { +func (s *httpdServer) renderClientTwoFactorRecoveryPage(w http.ResponseWriter, error, ip string) { data := twoFactorPage{ CurrentURL: webClientTwoFactorRecoveryPath, Version: version.Get().Version, Error: error, - CSRFToken: createCSRFToken(), + CSRFToken: createCSRFToken(ip), StaticURL: webStaticFilesPath, ExtraCSS: s.binding.ExtraCSS, } @@ -972,7 +972,8 @@ func (s *httpdServer) handleClientAddSharePost(w http.ResponseWriter, r *http.Re s.renderAddUpdateSharePage(w, r, share, err.Error(), true) return } - if err := verifyCSRFToken(r.Form.Get(csrfFormToken)); err != nil { + ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) + if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil { s.renderClientForbiddenPage(w, r, err.Error()) return } @@ -986,7 +987,7 @@ func (s *httpdServer) handleClientAddSharePost(w http.ResponseWriter, r *http.Re return } } - err = dataprovider.AddShare(share, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) + err = dataprovider.AddShare(share, claims.Username, ipAddr) if err == nil { http.Redirect(w, r, webClientSharesPath, http.StatusSeeOther) } else { @@ -1015,7 +1016,8 @@ func (s *httpdServer) handleClientUpdateSharePost(w http.ResponseWriter, r *http s.renderAddUpdateSharePage(w, r, updatedShare, err.Error(), false) return } - if err := verifyCSRFToken(r.Form.Get(csrfFormToken)); err != nil { + ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) + if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil { s.renderClientForbiddenPage(w, r, err.Error()) return } @@ -1030,7 +1032,7 @@ func (s *httpdServer) handleClientUpdateSharePost(w http.ResponseWriter, r *http return } } - err = dataprovider.UpdateShare(updatedShare, claims.Username, util.GetIPFromRemoteAddress(r.RemoteAddr)) + err = dataprovider.UpdateShare(updatedShare, claims.Username, ipAddr) if err == nil { http.Redirect(w, r, webClientSharesPath, http.StatusSeeOther) } else { @@ -1090,7 +1092,8 @@ func (s *httpdServer) handleWebClientProfilePost(w http.ResponseWriter, r *http. s.renderClientProfilePage(w, r, err.Error()) return } - if err := verifyCSRFToken(r.Form.Get(csrfFormToken)); err != nil { + ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) + if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil { s.renderClientForbiddenPage(w, r, err.Error()) return } @@ -1118,7 +1121,7 @@ func (s *httpdServer) handleWebClientProfilePost(w http.ResponseWriter, r *http. user.Email = r.Form.Get("email") user.Description = r.Form.Get("description") } - err = dataprovider.UpdateUser(&user, dataprovider.ActionExecutorSelf, util.GetIPFromRemoteAddress(r.RemoteAddr)) + err = dataprovider.UpdateUser(&user, dataprovider.ActionExecutorSelf, ipAddr) if err != nil { s.renderClientProfilePage(w, r, err.Error()) return @@ -1134,12 +1137,12 @@ func (s *httpdServer) handleWebClientMFA(w http.ResponseWriter, r *http.Request) func (s *httpdServer) handleWebClientTwoFactor(w http.ResponseWriter, r *http.Request) { r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize) - s.renderClientTwoFactorPage(w, "") + s.renderClientTwoFactorPage(w, "", util.GetIPFromRemoteAddress(r.RemoteAddr)) } func (s *httpdServer) handleWebClientTwoFactorRecovery(w http.ResponseWriter, r *http.Request) { r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize) - s.renderClientTwoFactorRecoveryPage(w, "") + s.renderClientTwoFactorRecoveryPage(w, "", util.GetIPFromRemoteAddress(r.RemoteAddr)) } func getShareFromPostFields(r *http.Request) (*dataprovider.Share, error) { @@ -1181,17 +1184,19 @@ func (s *httpdServer) handleWebClientForgotPwd(w http.ResponseWriter, r *http.Re s.renderClientNotFoundPage(w, r, errors.New("this page does not exist")) return } - s.renderClientForgotPwdPage(w, "") + s.renderClientForgotPwdPage(w, "", util.GetIPFromRemoteAddress(r.RemoteAddr)) } func (s *httpdServer) handleWebClientForgotPwdPost(w http.ResponseWriter, r *http.Request) { r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize) + + ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) err := r.ParseForm() if err != nil { - s.renderClientForgotPwdPage(w, err.Error()) + s.renderClientForgotPwdPage(w, err.Error(), ipAddr) return } - if err := verifyCSRFToken(r.Form.Get(csrfFormToken)); err != nil { + if err := verifyCSRFToken(r.Form.Get(csrfFormToken), ipAddr); err != nil { s.renderClientForbiddenPage(w, r, err.Error()) return } @@ -1199,10 +1204,10 @@ func (s *httpdServer) handleWebClientForgotPwdPost(w http.ResponseWriter, r *htt err = handleForgotPassword(r, username, false) if err != nil { if e, ok := err.(*util.ValidationError); ok { - s.renderClientForgotPwdPage(w, e.GetErrorString()) + s.renderClientForgotPwdPage(w, e.GetErrorString(), ipAddr) return } - s.renderClientForgotPwdPage(w, err.Error()) + s.renderClientForgotPwdPage(w, err.Error(), ipAddr) return } http.Redirect(w, r, webClientResetPwdPath, http.StatusFound) @@ -1214,7 +1219,7 @@ func (s *httpdServer) handleWebClientPasswordReset(w http.ResponseWriter, r *htt s.renderClientNotFoundPage(w, r, errors.New("this page does not exist")) return } - s.renderClientResetPwdPage(w, "") + s.renderClientResetPwdPage(w, "", util.GetIPFromRemoteAddress(r.RemoteAddr)) } func (s *httpdServer) handleClientViewPDF(w http.ResponseWriter, r *http.Request) {