CVE-2024-37897
Description
SFTPGo is a full-featured and highly configurable SFTP, HTTP/S, FTP/S and WebDAV server - S3, Google Cloud Storage, Azure Blob. SFTPGo WebAdmin and WebClient support password reset. This feature is disabled in the default configuration. In SFTPGo versions prior to v2.6.1, if the feature is enabled, even users with access restrictions (e.g. expired) can reset their password and log in. Users are advised to upgrade to version 2.6.1. Users unable to upgrade may keep the password reset feature disabled or set a blank email address for users and admins with access restrictions so they cannot receive the email with the reset code and exploit the vulnerability.
Affected packages
Versions sourced from the GitHub Security Advisory.
| Package | Affected versions | Patched versions |
|---|---|---|
github.com/drakkan/sftpgo/v2Go | >= 2.2.0, < 2.6.1 | 2.6.1 |
Patches
21f8ac8bfe161REST API: fix token invalidation after password change
7 files changed · +56 −18
go.mod+5 −5 modified@@ -4,7 +4,7 @@ go 1.22.2 require ( cloud.google.com/go/storage v1.41.0 - github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.2 github.com/GehirnInc/crypt v0.0.0-20230320061759-8cc1b52080c5 github.com/alexedwards/argon2id v1.0.0 @@ -13,9 +13,9 @@ require ( github.com/aws/aws-sdk-go-v2/config v1.27.17 github.com/aws/aws-sdk-go-v2/credentials v1.17.17 github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.4 - github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.22 + github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.23 github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.21.9 - github.com/aws/aws-sdk-go-v2/service/s3 v1.54.4 + github.com/aws/aws-sdk-go-v2/service/s3 v1.55.0 github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.29.2 github.com/aws/aws-sdk-go-v2/service/sts v1.28.11 github.com/bmatcuk/doublestar/v4 v4.6.1 @@ -84,7 +84,7 @@ require ( cloud.google.com/go/compute/metadata v0.3.0 // indirect cloud.google.com/go/iam v1.1.8 // indirect filippo.io/edwards25519 v1.1.0 // indirect - github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0 // indirect github.com/ajg/form v1.5.1 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 // indirect github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.8 // indirect @@ -126,7 +126,7 @@ require ( github.com/hashicorp/yamux v0.1.1 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/jackc/pgpassfile v1.0.0 // indirect - github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 // indirect + github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect github.com/jackc/puddle/v2 v2.2.1 // indirect github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/kr/fs v0.1.0 // indirect
go.sum+10 −10 modified@@ -18,12 +18,12 @@ cloud.google.com/go/storage v1.41.0/go.mod h1:J1WCa/Z2FcgdEDuPUY8DxT5I+d9mFKsCep filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1 h1:E+OJmp2tPvt1W+amx48v1eqbjDYsgN+RzP4q16yV5eM= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.11.1/go.mod h1:a6xsAQUZg+VsS3TJ05SRp524Hs4pZ/AeFSr5ENf0Yjo= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0 h1:1nGuui+4POelzDwI7RG56yfQJHCnKvwfMoU7VsEp+Zg= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0/go.mod h1:99EvauvlcJ1U06amZiksfYz/3aFGyIhWGHVyiZXtBAI= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2 h1:FDif4R1+UUR+00q6wquyX90K7A8dN+R5E8GEadoP7sU= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2/go.mod h1:aiYBYui4BJ/BJCAIKs92XiPyQfTaBWqvHujDwKb6CBU= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0 h1:jBQA3cKT4L2rWMpgE7Yt3Hwh2aUj8KXjIGLxjHeYNNo= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.8.0/go.mod h1:4OG6tQ9EOP/MT0NMjDlRzWoVFxfu9rN9B2X+tlSVktg= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0 h1:H+U3Gk9zY56G3u872L82bk4thcsy2Gghb9ExT4Zvm1o= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0/go.mod h1:mgrmMSgaLp9hmax62XQTd0N4aAqSE5E0DulSpVYK7vc= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.5.0 h1:AifHbc4mg0x9zW52WOpKbsHaDKuRhlI7TVl47thgQ70= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.5.0/go.mod h1:T5RfihdXtBDxt1Ch2wobif3TvzTdumDy29kahv6AV9A= github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.2 h1:YUUxeiOWgdAQE3pXt2H7QXzZs0q8UBjgRbl56qo8GYM= @@ -49,8 +49,8 @@ github.com/aws/aws-sdk-go-v2/credentials v1.17.17 h1:b3Dk9uxQByS9sc6r0sc2jmxsJKO github.com/aws/aws-sdk-go-v2/credentials v1.17.17/go.mod h1:e4khg9iY08LnFK/HXQDWMf9GDaiMari7jWPnXvKAuBU= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.4 h1:0cSfTYYL9qiRcdi4Dvz+8s3JUgNR2qvbgZkXcwPEEEk= github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.4/go.mod h1:Wjn5O9eS7uSi7vlPKt/v0MLTncANn9EMmoDvnzJli6o= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.22 h1:1CO+m67soQzw6hfkfSS0hQzS/o05bCswr+gQfBfQgLQ= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.22/go.mod h1:XUetvjVEuGFl1ABsTZ/5tufz0WXT+MpR9qcMnEJm0dw= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.23 h1:g6IHovcexw51hcP0hxsT7Mr3/PG76hZvoodm9tuKuUc= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.23/go.mod h1:8KSZ0CibxgOaPk28CFL4DGBdGrscHJr8FuxB+jnJBaM= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.8 h1:RnLB7p6aaFMRfyQkD6ckxR7myCC9SABIqSz4czYUUbU= github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.8/go.mod h1:XH7dQJd+56wEbP1I4e4Duo+QhSMxNArE8VP7NuUOTeM= github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.8 h1:jzApk2f58L9yW9q1GEab3BMMFWUkkiZhyrRUtbwUbKU= @@ -69,8 +69,8 @@ github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.8 h1:iQNXVs1vtaq+y9 github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.8/go.mod h1:yUQPRlWqGG0lfNsmjbRWKVwgilfBtZTOFSLEYALlAig= github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.21.9 h1:1Y6NAaK/9Wjxb4VAlUOMUQuTrOKNXfLrhaSzNdLKkwo= github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.21.9/go.mod h1:KpgKQ+ZF5kssRykR4yxANtddzYFatCqlv8yHddRHne4= -github.com/aws/aws-sdk-go-v2/service/s3 v1.54.4 h1:4p9SCdZBO0PdEXLTF2fcQuxOEkEiqPQpK824cP2VKRo= -github.com/aws/aws-sdk-go-v2/service/s3 v1.54.4/go.mod h1:oSkRFuHVWmUY4Ssk16ErGzBqvYEbvORJFzFXzWhTB2s= +github.com/aws/aws-sdk-go-v2/service/s3 v1.55.0 h1:6kq0Xql9qiwNGL/Go87ZqR4otg9jnKs71OfWCVbPxLM= +github.com/aws/aws-sdk-go-v2/service/s3 v1.55.0/go.mod h1:oSkRFuHVWmUY4Ssk16ErGzBqvYEbvORJFzFXzWhTB2s= github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.29.2 h1:vnONgeMo5TuAtGjVNjieDyaI6tzMDNm0TuBgkKzqkX4= github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.29.2/go.mod h1:OR529kEc7Ty9nsqvMuDBBHq5AZVih/MYd5/G9TcL5bQ= github.com/aws/aws-sdk-go-v2/service/sso v1.20.10 h1:ItKVmFwbyb/ZnCWf+nu3XBVmUirpO9eGEQd7urnBA0s= @@ -231,8 +231,8 @@ github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2 github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= -github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9 h1:L0QtFUgDarD7Fpv9jeVMgy/+Ec0mtnmYuImjTz6dtDA= -github.com/jackc/pgservicefile v0.0.0-20231201235250-de7065d80cb9/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo= +github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM= github.com/jackc/pgx/v5 v5.6.0 h1:SWJzexBzPL5jb0GEsrPMLIsi/3jOo7RHlzTjcAeDrPY= github.com/jackc/pgx/v5 v5.6.0/go.mod h1:DNZ/vlrUnhWCoFGxHAG8U2ljioxukquj7utPDgtQdTw= github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk=
internal/httpd/api_admin.go+1 −0 modified@@ -297,6 +297,7 @@ func changeAdminPassword(w http.ResponseWriter, r *http.Request) { sendAPIResponse(w, r, err, "", getRespStatus(err)) return } + invalidateToken(r) sendAPIResponse(w, r, err, "Password updated", http.StatusOK) }
internal/httpd/api_http_user.go+1 −0 modified@@ -531,6 +531,7 @@ func changeUserPassword(w http.ResponseWriter, r *http.Request) { sendAPIResponse(w, r, err, "", getRespStatus(err)) return } + invalidateToken(r) sendAPIResponse(w, r, err, "Password updated", http.StatusOK) }
internal/httpd/httpd.go+4 −0 modified@@ -664,6 +664,10 @@ func (b *Binding) showClientLoginURL() bool { return true } +func (b *Binding) isMutualTLSEnabled() bool { + return b.ClientAuthType == 1 +} + type defenderStatus struct { IsActive bool `json:"is_active"` }
internal/httpd/httpd_test.go+34 −2 modified@@ -11372,11 +11372,17 @@ func TestWebAPIChangeUserPwdMock(t *testing.T) { assert.NoError(t, err) token, err := getJWTAPIUserTokenFromTestServer(defaultUsername, defaultPassword) assert.NoError(t, err) - // invalid json - req, err := http.NewRequest(http.MethodPut, userPwdPath, bytes.NewBuffer([]byte("{"))) + + req, err := http.NewRequest(http.MethodGet, userProfilePath, nil) assert.NoError(t, err) setBearerForReq(req, token) rr := executeRequest(req) + checkResponseCode(t, http.StatusOK, rr) + // invalid json + req, err = http.NewRequest(http.MethodPut, userPwdPath, bytes.NewBuffer([]byte("{"))) + assert.NoError(t, err) + setBearerForReq(req, token) + rr = executeRequest(req) checkResponseCode(t, http.StatusBadRequest, rr) pwd := make(map[string]string) @@ -11399,6 +11405,13 @@ func TestWebAPIChangeUserPwdMock(t *testing.T) { setBearerForReq(req, token) rr = executeRequest(req) checkResponseCode(t, http.StatusOK, rr) + + req, err = http.NewRequest(http.MethodGet, userProfilePath, nil) + assert.NoError(t, err) + setBearerForReq(req, token) + rr = executeRequest(req) + checkResponseCode(t, http.StatusUnauthorized, rr) + _, err = getJWTAPIUserTokenFromTestServer(defaultUsername, defaultPassword) assert.Error(t, err) token, err = getJWTAPIUserTokenFromTestServer(defaultUsername, altAdminPassword) @@ -11548,6 +11561,12 @@ func TestChangeAdminPwdMock(t *testing.T) { setBearerForReq(req, altToken) rr = executeRequest(req) checkResponseCode(t, http.StatusOK, rr) + // try using the old token + req, err = http.NewRequest(http.MethodGet, versionPath, nil) + assert.NoError(t, err) + setBearerForReq(req, altToken) + rr = executeRequest(req) + checkResponseCode(t, http.StatusUnauthorized, rr) _, err = getJWTAPITokenFromTestServer(altAdminUsername, altAdminPassword) assert.Error(t, err) @@ -13599,6 +13618,13 @@ func TestWebClientChangePwd(t *testing.T) { checkResponseCode(t, http.StatusFound, rr) assert.Equal(t, webClientLoginPath, rr.Header().Get("Location")) + req, err = http.NewRequest(http.MethodGet, webClientPingPath, nil) + assert.NoError(t, err) + req.RemoteAddr = defaultRemoteAddr + setJWTCookieForReq(req, webToken) + rr = executeRequest(req) + checkResponseCode(t, http.StatusFound, rr) + _, err = getJWTWebClientTokenFromTestServer(defaultUsername, defaultPassword) assert.Error(t, err) _, err = getJWTWebClientTokenFromTestServer(defaultUsername+"1", defaultPassword+"1") @@ -18850,6 +18876,12 @@ func TestWebAdminLoginMock(t *testing.T) { cookie := rr.Header().Get("Cookie") assert.Empty(t, cookie) + req, _ = http.NewRequest(http.MethodGet, webStatusPath, nil) + req.RemoteAddr = defaultRemoteAddr + setJWTCookieForReq(req, webToken) + rr = executeRequest(req) + checkResponseCode(t, http.StatusFound, rr) + req, _ = http.NewRequest(http.MethodGet, logoutPath, nil) setBearerForReq(req, apiToken) rr = executeRequest(req)
internal/httpd/server.go+1 −1 modified@@ -120,7 +120,7 @@ func (s *httpdServer) listenAndServe() error { httpServer.TLSConfig = config logger.Debug(logSender, "", "configured TLS cipher suites for binding %q: %v, certID: %v", s.binding.GetAddress(), httpServer.TLSConfig.CipherSuites, certID) - if s.binding.ClientAuthType == 1 { + if s.binding.isMutualTLSEnabled() { httpServer.TLSConfig.ClientCAs = certMgr.GetRootCAs() httpServer.TLSConfig.ClientAuth = tls.RequireAndVerifyClientCert httpServer.TLSConfig.VerifyConnection = s.verifyTLSConnection
3462bba3f41cbackport from main branch
8 files changed · +217 −108
go.mod+29 −29 modified@@ -3,29 +3,29 @@ module github.com/drakkan/sftpgo/v2 go 1.22.2 require ( - cloud.google.com/go/storage v1.41.0 + cloud.google.com/go/storage v1.42.0 github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.3.2 github.com/GehirnInc/crypt v0.0.0-20230320061759-8cc1b52080c5 github.com/alexedwards/argon2id v1.0.0 github.com/amoghe/go-crypt v0.0.0-20220222110647-20eada5f5964 - github.com/aws/aws-sdk-go-v2 v1.27.1 - github.com/aws/aws-sdk-go-v2/config v1.27.17 - github.com/aws/aws-sdk-go-v2/credentials v1.17.17 - github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.4 - github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.23 - github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.21.9 - github.com/aws/aws-sdk-go-v2/service/s3 v1.55.0 - github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.29.2 - github.com/aws/aws-sdk-go-v2/service/sts v1.28.11 + github.com/aws/aws-sdk-go-v2 v1.27.2 + github.com/aws/aws-sdk-go-v2/config v1.27.18 + github.com/aws/aws-sdk-go-v2/credentials v1.17.18 + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.5 + github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.24 + github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.21.10 + github.com/aws/aws-sdk-go-v2/service/s3 v1.55.1 + github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.30.0 + github.com/aws/aws-sdk-go-v2/service/sts v1.28.12 github.com/bmatcuk/doublestar/v4 v4.6.1 github.com/cockroachdb/cockroach-go/v2 v2.3.8 github.com/coreos/go-oidc/v3 v3.10.0 github.com/drakkan/webdav v0.0.0-20240503091431-218ec83910bb github.com/eikenb/pipeat v0.0.0-20210730190139-06b3e6902001 github.com/fclairamb/ftpserverlib v0.24.1 github.com/fclairamb/go-log v0.5.0 - github.com/go-acme/lego/v4 v4.17.3 + github.com/go-acme/lego/v4 v4.17.4 github.com/go-chi/chi/v5 v5.0.12 github.com/go-chi/jwtauth/v5 v5.3.1 github.com/go-chi/render v1.0.3 @@ -37,7 +37,7 @@ require ( github.com/hashicorp/go-retryablehttp v0.7.7 github.com/jackc/pgx/v5 v5.6.0 github.com/jlaffaye/ftp v0.2.0 - github.com/klauspost/compress v1.17.8 + github.com/klauspost/compress v1.17.9 github.com/lestrrat-go/jwx/v2 v2.0.21 github.com/lithammer/shortuuid/v3 v3.0.7 github.com/mattn/go-sqlite3 v1.14.22 @@ -55,7 +55,7 @@ require ( github.com/sftpgo/sdk v0.1.8 github.com/shirou/gopsutil/v3 v3.24.5 github.com/spf13/afero v1.11.0 - github.com/spf13/cobra v1.8.0 + github.com/spf13/cobra v1.8.1 github.com/spf13/viper v1.19.0 github.com/stretchr/testify v1.9.0 github.com/studio-b12/gowebdav v0.9.0 @@ -73,12 +73,12 @@ require ( golang.org/x/sys v0.21.0 golang.org/x/term v0.21.0 golang.org/x/time v0.5.0 - google.golang.org/api v0.183.0 + google.golang.org/api v0.184.0 gopkg.in/natefinch/lumberjack.v2 v2.2.1 ) require ( - cloud.google.com/go v0.114.0 // indirect + cloud.google.com/go v0.115.0 // indirect cloud.google.com/go/auth v0.5.1 // indirect cloud.google.com/go/auth/oauth2adapt v0.2.2 // indirect cloud.google.com/go/compute/metadata v0.3.0 // indirect @@ -87,16 +87,16 @@ require ( github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0 // indirect github.com/ajg/form v1.5.1 // indirect github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 // indirect - github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.8 // indirect - github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.8 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.9 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.9 // indirect github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect - github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.8 // indirect + github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.9 // indirect github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.10 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.10 // indirect - github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.8 // indirect - github.com/aws/aws-sdk-go-v2/service/sso v1.20.10 // indirect - github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.4 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.11 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.11 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.9 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.20.11 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5 // indirect github.com/aws/smithy-go v1.20.2 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/boombuler/barcode v1.0.1 // indirect @@ -139,7 +139,7 @@ require ( github.com/magiconair/properties v1.8.7 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.20 // indirect - github.com/miekg/dns v1.1.59 // indirect + github.com/miekg/dns v1.1.61 // indirect github.com/mitchellh/go-testing-interface v1.14.1 // indirect github.com/mitchellh/mapstructure v1.5.0 // indirect github.com/oklog/run v1.1.0 // indirect @@ -167,17 +167,17 @@ require ( go.opentelemetry.io/otel/metric v1.27.0 // indirect go.opentelemetry.io/otel/trace v1.27.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8 // indirect + golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect golang.org/x/mod v0.18.0 // indirect golang.org/x/sync v0.7.0 // indirect golang.org/x/text v0.16.0 // indirect golang.org/x/tools v0.22.0 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect - google.golang.org/genproto v0.0.0-20240604185151-ef581f913117 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 // indirect + google.golang.org/genproto v0.0.0-20240610135401-a8a62080eff3 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240610135401-a8a62080eff3 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3 // indirect google.golang.org/grpc v1.64.0 // indirect - google.golang.org/protobuf v1.34.1 // indirect + google.golang.org/protobuf v1.34.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect )
go.sum+60 −61 modified@@ -1,6 +1,6 @@ cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= -cloud.google.com/go v0.114.0 h1:OIPFAdfrFDFO2ve2U7r/H5SwSbBzEdrBdE7xkgwc+kY= -cloud.google.com/go v0.114.0/go.mod h1:ZV9La5YYxctro1HTPug5lXH/GefROyW8PPD4T8n9J8E= +cloud.google.com/go v0.115.0 h1:CnFSK6Xo3lDYRoBKEcAtia6VSC837/ZkJuRduSFnr14= +cloud.google.com/go v0.115.0/go.mod h1:8jIM5vVgoAEoiVxQ/O4BFTfHqulPZgs/ufEzMcFMdWU= cloud.google.com/go/auth v0.5.1 h1:0QNO7VThG54LUzKiQxv8C6x1YX7lUrzlAa1nVLF8CIw= cloud.google.com/go/auth v0.5.1/go.mod h1:vbZT8GjzDf3AVqCcQmqeeM32U9HBFc32vVVAbwDsa6s= cloud.google.com/go/auth/oauth2adapt v0.2.2 h1:+TTV8aXpjeChS9M+aTtN/TjdQnzJvmzKFt//oWu7HX4= @@ -13,15 +13,15 @@ cloud.google.com/go/kms v1.17.1 h1:5k0wXqkxL+YcXd4viQzTqCgzzVKKxzgrK+rCZJytEQs= cloud.google.com/go/kms v1.17.1/go.mod h1:DCMnCF/apA6fZk5Cj4XsD979OyHAqFasPuA5Sd0kGlQ= cloud.google.com/go/longrunning v0.5.7 h1:WLbHekDbjK1fVFD3ibpFFVoyizlLRl73I7YKuAKilhU= cloud.google.com/go/longrunning v0.5.7/go.mod h1:8GClkudohy1Fxm3owmBGid8W0pSgodEMwEAztp38Xng= -cloud.google.com/go/storage v1.41.0 h1:RusiwatSu6lHeEXe3kglxakAmAbfV+rhtPqA6i8RBx0= -cloud.google.com/go/storage v1.41.0/go.mod h1:J1WCa/Z2FcgdEDuPUY8DxT5I+d9mFKsCepp5vR6Sq80= +cloud.google.com/go/storage v1.42.0 h1:4QtGpplCVt1wz6g5o1ifXd656P5z+yNgzdw1tVfp0cU= +cloud.google.com/go/storage v1.42.0/go.mod h1:HjMXRFq65pGKFn6hxj6x3HCyR41uSB72Z0SO/Vn6JFQ= filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0 h1:1nGuui+4POelzDwI7RG56yfQJHCnKvwfMoU7VsEp+Zg= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.12.0/go.mod h1:99EvauvlcJ1U06amZiksfYz/3aFGyIhWGHVyiZXtBAI= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2 h1:FDif4R1+UUR+00q6wquyX90K7A8dN+R5E8GEadoP7sU= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.2/go.mod h1:aiYBYui4BJ/BJCAIKs92XiPyQfTaBWqvHujDwKb6CBU= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0 h1:U2rTu3Ef+7w9FHKIAXM6ZyqF3UOWJZ12zIm8zECAFfg= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.6.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg= github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0 h1:H+U3Gk9zY56G3u872L82bk4thcsy2Gghb9ExT4Zvm1o= github.com/Azure/azure-sdk-for-go/sdk/internal v1.9.0/go.mod h1:mgrmMSgaLp9hmax62XQTd0N4aAqSE5E0DulSpVYK7vc= github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.5.0 h1:AifHbc4mg0x9zW52WOpKbsHaDKuRhlI7TVl47thgQ70= @@ -39,46 +39,46 @@ github.com/alexedwards/argon2id v1.0.0 h1:wJzDx66hqWX7siL/SRUmgz3F8YMrd/nfX/xHHc github.com/alexedwards/argon2id v1.0.0/go.mod h1:tYKkqIjzXvZdzPvADMWOEZ+l6+BD6CtBXMj5fnJppiw= github.com/amoghe/go-crypt v0.0.0-20220222110647-20eada5f5964 h1:I9YN9WMo3SUh7p/4wKeNvD/IQla3U3SUa61U7ul+xM4= github.com/amoghe/go-crypt v0.0.0-20220222110647-20eada5f5964/go.mod h1:eFiR01PwTcpbzXtdMces7zxg6utvFM5puiWHpWB8D/k= -github.com/aws/aws-sdk-go-v2 v1.27.1 h1:xypCL2owhog46iFxBKKpBcw+bPTX/RJzwNj8uSilENw= -github.com/aws/aws-sdk-go-v2 v1.27.1/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM= +github.com/aws/aws-sdk-go-v2 v1.27.2 h1:pLsTXqX93rimAOZG2FIYraDQstZaaGVVN4tNw65v0h8= +github.com/aws/aws-sdk-go-v2 v1.27.2/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2 h1:x6xsQXGSmW6frevwDA+vi/wqhp1ct18mVXYN08/93to= github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.2/go.mod h1:lPprDr1e6cJdyYeGXnRaJoP4Md+cDBvi2eOj00BlGmg= -github.com/aws/aws-sdk-go-v2/config v1.27.17 h1:L0JZN7Gh7pT6u5CJReKsLhGKparqNKui+mcpxMXjDZc= -github.com/aws/aws-sdk-go-v2/config v1.27.17/go.mod h1:MzM3balLZeaafYcPz8IihAmam/aCz6niPQI0FdprxW0= -github.com/aws/aws-sdk-go-v2/credentials v1.17.17 h1:b3Dk9uxQByS9sc6r0sc2jmxsJKO75eOcb9nNEiaUBLM= -github.com/aws/aws-sdk-go-v2/credentials v1.17.17/go.mod h1:e4khg9iY08LnFK/HXQDWMf9GDaiMari7jWPnXvKAuBU= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.4 h1:0cSfTYYL9qiRcdi4Dvz+8s3JUgNR2qvbgZkXcwPEEEk= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.4/go.mod h1:Wjn5O9eS7uSi7vlPKt/v0MLTncANn9EMmoDvnzJli6o= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.23 h1:g6IHovcexw51hcP0hxsT7Mr3/PG76hZvoodm9tuKuUc= -github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.23/go.mod h1:8KSZ0CibxgOaPk28CFL4DGBdGrscHJr8FuxB+jnJBaM= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.8 h1:RnLB7p6aaFMRfyQkD6ckxR7myCC9SABIqSz4czYUUbU= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.8/go.mod h1:XH7dQJd+56wEbP1I4e4Duo+QhSMxNArE8VP7NuUOTeM= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.8 h1:jzApk2f58L9yW9q1GEab3BMMFWUkkiZhyrRUtbwUbKU= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.8/go.mod h1:WqO+FftfO3tGePUtQxPXM6iODVfqMwsVMgTbG/ZXIdQ= +github.com/aws/aws-sdk-go-v2/config v1.27.18 h1:wFvAnwOKKe7QAyIxziwSKjmer9JBMH1vzIL6W+fYuKk= +github.com/aws/aws-sdk-go-v2/config v1.27.18/go.mod h1:0xz6cgdX55+kmppvPm2IaKzIXOheGJhAufacPJaXZ7c= +github.com/aws/aws-sdk-go-v2/credentials v1.17.18 h1:D/ALDWqK4JdY3OFgA2thcPO1c9aYTT5STS/CvnkqY1c= +github.com/aws/aws-sdk-go-v2/credentials v1.17.18/go.mod h1:JuitCWq+F5QGUrmMPsk945rop6bB57jdscu+Glozdnc= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.5 h1:dDgptDO9dxeFkXy+tEgVkzSClHZje/6JkPW5aZyEvrQ= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.5/go.mod h1:gjvE2KBUgUQhcv89jqxrIxH9GaKs1JbZzWejj/DaHGA= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.24 h1:FzNwpVTZDCvm597Ty6mGYvxTolyC1oup0waaKntZI4E= +github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.16.24/go.mod h1:wM9NElT/Wn6n3CT1eyVcXtfCy8lSVjjQXfdawQbSShc= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.9 h1:cy8ahBJuhtM8GTTSyOkfy6WVPV1IE+SS5/wfXUYuulw= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.9/go.mod h1:CZBXGLaJnEZI6EVNcPd7a6B5IC5cA/GkRWtu9fp3S6Y= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.9 h1:A4SYk07ef04+vxZToz9LWvAXl9LW0NClpPpMsi31cz0= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.9/go.mod h1:5jJcHuwDagxN+ErjQ3PU3ocf6Ylc/p9x+BLO/+X4iXw= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU= github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.8 h1:jH33S0y5Bo5ZVML62JgZhjd/LrtU+vbR8W7XnIE3Srk= -github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.8/go.mod h1:hD5YwHLOy6k7d6kqcn3me1bFWHOtzhaXstMd6BpdB68= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.9 h1:vHyZxoLVOgrI8GqX7OMHLXp4YYoxeEsrjweXKpye+ds= +github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.9/go.mod h1:z9VXZsWA2BvZNH1dT0ToUYwMu/CR9Skkj/TBX+mceZw= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1xUsUr3I8cHps0G+XM3WWU16lP6yG8qu1GAZAs= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2/go.mod h1:5CsjAbs3NlGQyZNFACh+zztPDI7fU6eW9QsxjfnuBKg= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.10 h1:pkYC5zTOSPXEYJj56b2SOik9AL432i5MT1YVTQbKOK0= -github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.10/go.mod h1:/WNsBOlKWZCG3PMh2aSp8vkyyT/clpMZqOtrnIKqGfk= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.10 h1:7kZqP7akv0enu6ykJhb9OYlw16oOrSy+Epus8o/VqMY= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.10/go.mod h1:gYVF3nM1ApfTRDj9pvdhootBb8WbiIejuqn4w8ruMes= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.8 h1:iQNXVs1vtaq+y9M90M4ZIVNORje0qXTscqHLqoOnFS0= -github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.8/go.mod h1:yUQPRlWqGG0lfNsmjbRWKVwgilfBtZTOFSLEYALlAig= -github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.21.9 h1:1Y6NAaK/9Wjxb4VAlUOMUQuTrOKNXfLrhaSzNdLKkwo= -github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.21.9/go.mod h1:KpgKQ+ZF5kssRykR4yxANtddzYFatCqlv8yHddRHne4= -github.com/aws/aws-sdk-go-v2/service/s3 v1.55.0 h1:6kq0Xql9qiwNGL/Go87ZqR4otg9jnKs71OfWCVbPxLM= -github.com/aws/aws-sdk-go-v2/service/s3 v1.55.0/go.mod h1:oSkRFuHVWmUY4Ssk16ErGzBqvYEbvORJFzFXzWhTB2s= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.29.2 h1:vnONgeMo5TuAtGjVNjieDyaI6tzMDNm0TuBgkKzqkX4= -github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.29.2/go.mod h1:OR529kEc7Ty9nsqvMuDBBHq5AZVih/MYd5/G9TcL5bQ= -github.com/aws/aws-sdk-go-v2/service/sso v1.20.10 h1:ItKVmFwbyb/ZnCWf+nu3XBVmUirpO9eGEQd7urnBA0s= -github.com/aws/aws-sdk-go-v2/service/sso v1.20.10/go.mod h1:5XKooCTi9VB/xZmJDvh7uZ+v3uQ7QdX6diOyhvPA+/w= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.4 h1:QMSCYDg3Iyls0KZc/dk3JtS2c1lFfqbmYO10qBPPkJk= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.4/go.mod h1:MZ/PVYU/mRbmSF6WK3ybCYHjA2mig8utVokDEVLDgE0= -github.com/aws/aws-sdk-go-v2/service/sts v1.28.11 h1:HYS0csS7UJxdYRoG+bGgUYrSwVnV3/ece/wHm90TApM= -github.com/aws/aws-sdk-go-v2/service/sts v1.28.11/go.mod h1:QXnthRM35zI92048MMwfFChjFmoufTdhtHmouwNfhhU= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.11 h1:4vt9Sspk59EZyHCAEMaktHKiq0C09noRTQorXD/qV+s= +github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.3.11/go.mod h1:5jHR79Tv+Ccq6rwYh+W7Nptmw++WiFafMfR42XhwNl8= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.11 h1:o4T+fKxA3gTMcluBNZZXE9DNaMkJuUL1O3mffCUjoJo= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.11/go.mod h1:84oZdJ+VjuJKs9v1UTC9NaodRZRseOXCTgku+vQJWR8= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.9 h1:TE2i0A9ErH1YfRSvXfCr2SQwfnqsoJT9nPQ9kj0lkxM= +github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.17.9/go.mod h1:9TzXX3MehQNGPwCZ3ka4CpwQsoAMWSF48/b+De9rfVM= +github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.21.10 h1:ScjyYTUx0mHcW6ThHCdHIIsih1jpSLdQ2Q8rf7jthCY= +github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.21.10/go.mod h1:7Ob1csQEzlr5jqJ+Mzp4NeuNRtqFUlWxkjX91Isty0g= +github.com/aws/aws-sdk-go-v2/service/s3 v1.55.1 h1:UAxBuh0/8sFJk1qOkvOKewP5sWeWaTPDknbQz0ZkDm0= +github.com/aws/aws-sdk-go-v2/service/s3 v1.55.1/go.mod h1:hWjsYGjVuqCgfoveVcVFPXIWgz0aByzwaxKlN1StKcM= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.30.0 h1:nqR1mkoDntCpOwdlEfa2pZLiwvQeF4Mi56WzOTyuF/s= +github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.30.0/go.mod h1:M9TqBwpQ7AC6zu1Yji7vijRliqir7hxjuRcnxIk7jCc= +github.com/aws/aws-sdk-go-v2/service/sso v1.20.11 h1:gEYM2GSpr4YNWc6hCd5nod4+d4kd9vWIAWrmGuLdlMw= +github.com/aws/aws-sdk-go-v2/service/sso v1.20.11/go.mod h1:gVvwPdPNYehHSP9Rs7q27U1EU+3Or2ZpXvzAYJNh63w= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5 h1:iXjh3uaH3vsVcnyZX7MqCoCfcyxIrVE9iOQruRaWPrQ= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.24.5/go.mod h1:5ZXesEuy/QcO0WUnt+4sDkxhdXRHTu2yG0uCSH8B6os= +github.com/aws/aws-sdk-go-v2/service/sts v1.28.12 h1:M/1u4HBpwLuMtjlxuI2y6HoVLzF5e2mfxHCg7ZVMYmk= +github.com/aws/aws-sdk-go-v2/service/sts v1.28.12/go.mod h1:kcfd+eTdEi/40FIbLq4Hif3XMXnl5b/+t/KTfLt9xIk= github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q= github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= @@ -103,7 +103,6 @@ github.com/coreos/go-oidc/v3 v3.10.0 h1:tDnXHnLyiTVyT/2zLDGj09pFPkhND8Gl8lnTRhoE github.com/coreos/go-oidc/v3 v3.10.0/go.mod h1:5j11xcw0D3+SGxn6Z/WFADsgcWVMyNAlSQupk0KK3ac= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/cpuguy83/go-md2man/v2 v2.0.4 h1:wfIWP927BUkWJb2NmU/kNDYIBTh/ziUX91+lVfRxZq4= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -139,8 +138,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/go-acme/lego/v4 v4.17.3 h1:5our7Qdyik0abag40abdmQuytq97iweaNHFMT4pYDnQ= -github.com/go-acme/lego/v4 v4.17.3/go.mod h1:Ol6l04hnmavqVHKYS/ByhXXqE64x8yVYhomha82uAUk= +github.com/go-acme/lego/v4 v4.17.4 h1:h0nePd3ObP6o7kAkndtpTzCw8shOZuWckNYeUQwo36Q= +github.com/go-acme/lego/v4 v4.17.4/go.mod h1:dU94SvPNqimEeb7EVilGGSnS0nU1O5Exir0pQ4QFL4U= github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s= github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8= github.com/go-chi/jwtauth/v5 v5.3.1 h1:1ePWrjVctvp1tyBq5b/2ER8Th/+RbYc7x4qNsc5rh5A= @@ -243,8 +242,8 @@ github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9Y github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= -github.com/klauspost/compress v1.17.8 h1:YcnTYrq7MikUT7k0Yb5eceMmALQPYBW/Xltxn0NAMnU= -github.com/klauspost/compress v1.17.8/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= +github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= +github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw= github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8= github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -287,8 +286,8 @@ github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= github.com/mhale/smtpd v0.8.3 h1:8j8YNXajksoSLZja3HdwvYVZPuJSqAxFsib3adzRRt8= github.com/mhale/smtpd v0.8.3/go.mod h1:MQl+y2hwIEQCXtNhe5+55n0GZOjSmeqORDIXbqUL3x4= -github.com/miekg/dns v1.1.59 h1:C9EXc/UToRwKLhK5wKU/I4QVsBUc8kE6MkHBkeypWZs= -github.com/miekg/dns v1.1.59/go.mod h1:nZpewl5p6IvctfgrckopVx2OlSEHPRO/U4SYkRklrEk= +github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs= +github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ= github.com/minio/sio v0.4.0 h1:u4SWVEm5lXSqU42ZWawV0D9I5AZ5YMmo2RXpEQ/kRhc= github.com/minio/sio v0.4.0/go.mod h1:oBSjJeGbBdRMZZwna07sX9EFzZy+ywu5aofRiV1g79I= github.com/mitchellh/go-testing-interface v1.14.1 h1:jrgshOhYAUVNMAJiKbEu7EqAwgJJ2JqpQmpLJOu07cU= @@ -360,8 +359,8 @@ github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8= github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY= github.com/spf13/cast v1.6.0 h1:GEiTHELF+vaR5dhz3VqZfFSzZjYbgeKDpBxQVS4GYJ0= github.com/spf13/cast v1.6.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo= -github.com/spf13/cobra v1.8.0 h1:7aJaZx1B85qltLMc546zn58BxxfZdR/W22ej9CFoEf0= -github.com/spf13/cobra v1.8.0/go.mod h1:WXLWApfZ71AjXPya3WOlMsY9yMs7YeiHhFVlvLyhcho= +github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= +github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI= @@ -422,8 +421,8 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8 gocloud.dev v0.37.0 h1:XF1rN6R0qZI/9DYjN16Uy0durAmSlf58DHOcb28GPro= gocloud.dev v0.37.0/go.mod h1:7/O4kqdInCNsc6LqgmuFnS0GRew4XNNYWpA44yQnwco= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= -golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8 h1:LoYXNGAShUG3m/ehNk4iFctuhGX/+R1ZpfJ4/ia80JM= -golang.org/x/exp v0.0.0-20240604190554-fc45aab8b7f8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= +golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 h1:yixxcjnhBmY0nkL253HFVIm0JsFHwrHdT3Yh6szTnfY= +golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8/go.mod h1:jj3sYF3dwk5D+ghuXyeI3r5MFf+NT2An6/9dOA95KSI= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -517,19 +516,19 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= -google.golang.org/api v0.183.0 h1:PNMeRDwo1pJdgNcFQ9GstuLe/noWKIc89pRWRLMvLwE= -google.golang.org/api v0.183.0/go.mod h1:q43adC5/pHoSZTx5h2mSmdF7NcyfW9JuDyIOJAgS9ZQ= +google.golang.org/api v0.184.0 h1:dmEdk6ZkJNXy1JcDhn/ou0ZUq7n9zropG2/tR4z+RDg= +google.golang.org/api v0.184.0/go.mod h1:CeDTtUEiYENAf8PPG5VZW2yNp2VM3VWbCeTioAZBTBA= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20240604185151-ef581f913117 h1:HCZ6DlkKtCDAtD8ForECsY3tKuaR+p4R3grlK80uCCc= -google.golang.org/genproto v0.0.0-20240604185151-ef581f913117/go.mod h1:lesfX/+9iA+3OdqeCpoDddJaNxVB1AB6tD7EfqMmprc= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117 h1:+rdxYoE3E5htTEWIe15GlN6IfvbURM//Jt0mmkmm6ZU= -google.golang.org/genproto/googleapis/api v0.0.0-20240604185151-ef581f913117/go.mod h1:OimBR/bc1wPO9iV4NC2bpyjy3VnAwZh5EBPQdtaE5oo= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117 h1:1GBuWVLM/KMVUv1t1En5Gs+gFZCNd360GGb4sSxtrhU= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240604185151-ef581f913117/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= +google.golang.org/genproto v0.0.0-20240610135401-a8a62080eff3 h1:8RTI1cmuvdY9J7q/jpJWEj5UfgWjhV5MCoXaYmwLBYQ= +google.golang.org/genproto v0.0.0-20240610135401-a8a62080eff3/go.mod h1:qb66gsewNb7Ghv1enkhJiRfYGWUklv3n6G8UvprOhzA= +google.golang.org/genproto/googleapis/api v0.0.0-20240610135401-a8a62080eff3 h1:QW9+G6Fir4VcRXVH8x3LilNAb6cxBGLa6+GM4hRwexE= +google.golang.org/genproto/googleapis/api v0.0.0-20240610135401-a8a62080eff3/go.mod h1:kdrSS/OiLkPrNUpzD4aHgCq2rVuC/YRxok32HXZ4vRE= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3 h1:9Xyg6I9IWQZhRVfCWjKK+l6kI0jHcPesVlMnT//aHNo= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240610135401-a8a62080eff3/go.mod h1:EfXuqaE1J41VCDicxHzUDm+8rk+7ZdXzHV0IhO/I6s0= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= @@ -546,8 +545,8 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2 google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= -google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= -google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg= +google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
internal/httpd/api_utils.go+33 −6 modified@@ -36,6 +36,7 @@ import ( "github.com/go-chi/chi/v5/middleware" "github.com/go-chi/render" "github.com/klauspost/compress/zip" + "github.com/rs/xid" "github.com/sftpgo/sdk/plugin/notifier" "github.com/drakkan/sftpgo/v2/internal/common" @@ -748,6 +749,31 @@ func checkHTTPClientUser(user *dataprovider.User, r *http.Request, connectionID return nil } +func getActiveAdmin(username, ipAddr string) (dataprovider.Admin, error) { + admin, err := dataprovider.AdminExists(username) + if err != nil { + return admin, err + } + if err := admin.CanLogin(ipAddr); err != nil { + return admin, util.NewRecordNotFoundError(fmt.Sprintf("admin %q cannot login: %v", username, err)) + } + return admin, nil +} + +func getActiveUser(username string, r *http.Request) (dataprovider.User, error) { + user, err := dataprovider.GetUserWithGroupSettings(username, "") + if err != nil { + return user, err + } + if err := user.CheckLoginConditions(); err != nil { + return user, util.NewRecordNotFoundError(fmt.Sprintf("user %q cannot login: %v", username, err)) + } + if err := checkHTTPClientUser(&user, r, xid.New().String(), false); err != nil { + return user, util.NewRecordNotFoundError(fmt.Sprintf("user %q cannot login: %v", username, err)) + } + return user, nil +} + func handleForgotPassword(r *http.Request, username string, isAdmin bool) error { var email, subject string var err error @@ -758,11 +784,11 @@ func handleForgotPassword(r *http.Request, username string, isAdmin bool) error return util.NewI18nError(util.NewValidationError("username is mandatory"), util.I18nErrorUsernameRequired) } if isAdmin { - admin, err = dataprovider.AdminExists(username) + admin, err = getActiveAdmin(username, util.GetIPFromRemoteAddress(r.RemoteAddr)) email = admin.Email subject = fmt.Sprintf("Email Verification Code for admin %q", username) } else { - user, err = dataprovider.GetUserWithGroupSettings(username, "") + user, err = getActiveUser(username, r) email = user.Email subject = fmt.Sprintf("Email Verification Code for user %q", username) if err == nil { @@ -777,8 +803,9 @@ func handleForgotPassword(r *http.Request, username string, isAdmin bool) error if err != nil { if errors.Is(err, util.ErrNotFound) { handleDefenderEventLoginFailed(util.GetIPFromRemoteAddress(r.RemoteAddr), err) //nolint:errcheck - logger.Debug(logSender, middleware.GetReqID(r.Context()), "username %q does not exists, reset password request silently ignored, is admin? %v", - username, isAdmin) + logger.Debug(logSender, middleware.GetReqID(r.Context()), + "username %q does not exists or cannot login, reset password request silently ignored, is admin? %t, err: %v", + username, isAdmin, err) return nil } return util.NewI18nError(util.NewGenericError("Error retrieving your account, please try again later"), util.I18nErrorGetUser) @@ -838,7 +865,7 @@ func handleResetPassword(r *http.Request, code, newPassword, confirmPassword str return &admin, &user, util.NewValidationError("invalid confirmation code") } if isAdmin { - admin, err = dataprovider.AdminExists(resetCode.Username) + admin, err = getActiveAdmin(resetCode.Username, ipAddr) if err != nil { return &admin, &user, util.NewValidationError("unable to associate the confirmation code with an existing admin") } @@ -851,7 +878,7 @@ func handleResetPassword(r *http.Request, code, newPassword, confirmPassword str err = resetCodesMgr.Delete(code) return &admin, &user, err } - user, err = dataprovider.GetUserWithGroupSettings(resetCode.Username, "") + user, err = getActiveUser(resetCode.Username, r) if err != nil { return &admin, &user, util.NewValidationError("Unable to associate the confirmation code with an existing user") }
internal/httpd/httpd_test.go+61 −3 modified@@ -25180,6 +25180,23 @@ func TestAdminForgotPassword(t *testing.T) { lastResetCode = "" form.Set("username", altAdminUsername) + // disable the admin + admin.Status = 0 + admin, _, err = httpdtest.UpdateAdmin(admin, http.StatusOK) + assert.NoError(t, err) + + 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) + assert.GreaterOrEqual(t, len(lastResetCode), 0) + + admin.Status = 1 + admin, _, err = httpdtest.UpdateAdmin(admin, http.StatusOK) + assert.NoError(t, err) + req, err = http.NewRequest(http.MethodPost, webAdminForgotPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) req.RemoteAddr = defaultRemoteAddr @@ -25214,13 +25231,28 @@ func TestAdminForgotPassword(t *testing.T) { rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) assert.Contains(t, rr.Body.String(), util.I18nErrorChangePwdGeneric) - // ok + // disable the admin + admin.Status = 0 + admin, _, err = httpdtest.UpdateAdmin(admin, http.StatusOK) + assert.NoError(t, err) 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.StatusOK, rr.Code) + assert.Contains(t, rr.Body.String(), util.I18nErrorChangePwdGeneric) + + admin.Status = 1 + admin, _, err = httpdtest.UpdateAdmin(admin, http.StatusOK) + assert.NoError(t, err) + // ok + 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) form.Set("username", altAdminUsername) @@ -25345,17 +25377,29 @@ func TestUserForgotPassword(t *testing.T) { rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) assert.Contains(t, rr.Body.String(), util.I18nErrorPwdResetForbidded) + user.ExpirationDate = util.GetTimeAsMsSinceEpoch(time.Now().Add(-1 * time.Hour)) user.Filters.WebClient = []string{sdk.WebClientAPIKeyAuthChangeDisabled} user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "") assert.NoError(t, err) - + // user is expired 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) + assert.GreaterOrEqual(t, len(lastResetCode), 0) + + user.ExpirationDate = util.GetTimeAsMsSinceEpoch(time.Now().Add(24 * time.Hour)) + user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "") + assert.NoError(t, err) + 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) assert.GreaterOrEqual(t, len(lastResetCode), 20) // no csrf token form = make(url.Values) @@ -25396,8 +25440,22 @@ func TestUserForgotPassword(t *testing.T) { rr = executeRequest(req) assert.Equal(t, http.StatusOK, rr.Code) assert.Contains(t, rr.Body.String(), util.I18nErrorChangePwdGeneric) - // ok + // Invalid login condition form.Set("code", lastResetCode) + user.Filters.DeniedProtocols = []string{common.ProtocolHTTP} + user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "") + assert.NoError(t, err) + 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) + assert.Contains(t, rr.Body.String(), util.I18nErrorChangePwdGeneric) + // ok + user.Filters.DeniedProtocols = []string{common.ProtocolFTP} + user, _, err = httpdtest.UpdateUser(user, http.StatusOK, "") + assert.NoError(t, err) req, err = http.NewRequest(http.MethodPost, webClientResetPwdPath, bytes.NewBuffer([]byte(form.Encode()))) assert.NoError(t, err) req.RemoteAddr = defaultRemoteAddr
internal/httpd/internal_test.go+23 −0 modified@@ -1741,6 +1741,29 @@ func TestCookieExpiration(t *testing.T) { cookie = rr.Header().Get("Set-Cookie") assert.NotEmpty(t, cookie) + // test a disabled user + user.Status = 0 + err = dataprovider.UpdateUser(&user, "", "", "") + assert.NoError(t, err) + user, err = dataprovider.UserExists(user.Username, "") + assert.NoError(t, err) + + claims = make(map[string]any) + claims[claimUsernameKey] = user.Username + claims[claimPermissionsKey] = user.Filters.WebClient + claims[jwt.SubjectKey] = user.GetSignature() + claims[jwt.ExpirationKey] = time.Now().Add(1 * time.Minute) + claims[jwt.AudienceKey] = []string{tokenAudienceWebClient} + token, _, err = server.tokenAuth.Encode(claims) + assert.NoError(t, err) + + rr = httptest.NewRecorder() + req, _ = http.NewRequest(http.MethodGet, webClientFilesPath, nil) + ctx = jwtauth.NewContext(req.Context(), token, nil) + server.checkCookieExpiration(rr, req.WithContext(ctx)) + cookie = rr.Header().Get("Set-Cookie") + assert.Empty(t, cookie) + err = dataprovider.DeleteUser(user.Username, "", "", "") assert.NoError(t, err) }
internal/httpd/oidc.go+1 −0 modified@@ -594,6 +594,7 @@ func (s *httpdServer) handleOIDCRedirect(w http.ResponseWriter, r *http.Request) authReq, err := oidcMgr.getPendingAuth(state) if err != nil { logger.Debug(logSender, "", "oidc authentication state did not match") + oidcMgr.removePendingAuth(state) s.renderClientMessagePage(w, r, util.I18nInvalidAuthReqTitle, http.StatusBadRequest, util.NewI18nError(err, util.I18nInvalidAuth), "") return
internal/httpd/server.go+7 −7 modified@@ -309,7 +309,7 @@ func (s *httpdServer) handleWebClientPasswordResetPost(w http.ResponseWriter, r } connectionID := fmt.Sprintf("%v_%v", getProtocolFromRequest(r), xid.New().String()) if err := checkHTTPClientUser(user, r, connectionID, true); err != nil { - s.renderClientResetPwdPage(w, r, util.NewI18nError(err, util.I18nErrorDirList403), ipAddr) + s.renderClientResetPwdPage(w, r, util.NewI18nError(err, util.I18nErrorLoginAfterReset), ipAddr) return } @@ -1037,6 +1037,10 @@ func (s *httpdServer) refreshClientToken(w http.ResponseWriter, r *http.Request, logger.Debug(logSender, "", "signature mismatch for user %q, unable to refresh cookie", user.Username) return } + if err := user.CheckLoginConditions(); err != nil { + logger.Debug(logSender, "", "unable to refresh cookie for user %q: %v", user.Username, err) + return + } if err := checkHTTPClientUser(&user, r, xid.New().String(), true); err != nil { logger.Debug(logSender, "", "unable to refresh cookie for user %q: %v", user.Username, err) return @@ -1053,17 +1057,13 @@ func (s *httpdServer) refreshAdminToken(w http.ResponseWriter, r *http.Request, if err != nil { return } - if admin.Status != 1 { - logger.Debug(logSender, "", "admin %q is disabled, unable to refresh cookie", admin.Username) - return - } if admin.GetSignature() != tokenClaims.Signature { logger.Debug(logSender, "", "signature mismatch for admin %q, unable to refresh cookie", admin.Username) return } ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr) - if !admin.CanLoginFromIP(ipAddr) { - logger.Debug(logSender, "", "admin %q cannot login from %v, unable to refresh cookie", admin.Username, r.RemoteAddr) + if err := admin.CanLogin(ipAddr); err != nil { + logger.Debug(logSender, "", "unable to refresh cookie for admin %q, err: %v", admin.Username, err) return } tokenClaims.Permissions = admin.Permissions
internal/httpd/webadmin.go+3 −2 modified@@ -4268,14 +4268,15 @@ func (s *httpdServer) handleOAuth2TokenRedirect(w http.ResponseWriter, r *http.R return } - defer oauth2Mgr.removePendingAuth(state) - pendingAuth, err := oauth2Mgr.getPendingAuth(state) if err != nil { + oauth2Mgr.removePendingAuth(state) s.renderMessagePage(w, r, util.I18nOAuth2ErrorTitle, http.StatusInternalServerError, util.NewI18nError(err, util.I18nOAuth2ErrorValidateState), "") return } + oauth2Mgr.removePendingAuth(state) + oauth2Config := smtp.OAuth2Config{ Provider: pendingAuth.Provider, ClientID: pendingAuth.ClientID,
Vulnerability mechanics
Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.
References
6- github.com/advisories/GHSA-hw5f-6wvv-xcrhghsaADVISORY
- nvd.nist.gov/vuln/detail/CVE-2024-37897ghsaADVISORY
- github.com/drakkan/sftpgo/commit/1f8ac8bfe16100b0484d6c91e1e8361687324423nvdWEB
- github.com/drakkan/sftpgo/commit/3462bba3f41cbc75486474991b9e3ac1b5f1e583ghsaWEB
- github.com/drakkan/sftpgo/releases/tag/v2.6.1ghsaWEB
- github.com/drakkan/sftpgo/security/advisories/GHSA-hw5f-6wvv-xcrhnvdWEB
News mentions
0No linked articles in our index yet.