VYPR
Medium severity5.4NVD Advisory· Published Jun 20, 2024· Updated Apr 15, 2026

CVE-2024-37897

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.

PackageAffected versionsPatched versions
github.com/drakkan/sftpgo/v2Go
>= 2.2.0, < 2.6.12.6.1

Patches

2
1f8ac8bfe161

REST API: fix token invalidation after password change

https://github.com/drakkan/sftpgoNicola MurinoJun 7, 2024via ghsa
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
    
3462bba3f41c

backport from main branch

https://github.com/drakkan/sftpgoNicola MurinoJun 15, 2024via ghsa
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

News mentions

0

No linked articles in our index yet.