diff --git a/.drone.star b/.drone.star index 9dcf440a178..54ab5b63c2f 100644 --- a/.drone.star +++ b/.drone.star @@ -29,7 +29,7 @@ PLUGINS_S3 = "plugins/s3:latest" PLUGINS_S3_CACHE = "plugins/s3-cache:1" PLUGINS_SLACK = "plugins/slack:1" REDIS = "redis:6-alpine" -SONARSOURCE_SONAR_SCANNER_CLI = "sonarsource/sonar-scanner-cli:5.0" +SONARSOURCE_SONAR_SCANNER_CLI = "sonarsource/sonar-scanner-cli:11.0" DEFAULT_PHP_VERSION = "8.2" DEFAULT_NODEJS_VERSION = "18" diff --git a/go.mod b/go.mod index 29431212a49..c854d9571ef 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/cenkalti/backoff v2.2.1+incompatible github.com/coreos/go-oidc/v3 v3.9.0 github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781 - github.com/cs3org/reva/v2 v2.19.7 + github.com/cs3org/reva/v2 v2.19.8-0.20240919093513-f9a75a1a9fd4 github.com/dhowden/tag v0.0.0-20230630033851-978a0926ee25 github.com/dutchcoders/go-clamd v0.0.0-20170520113014-b970184f4d9e github.com/egirna/icap-client v0.1.1 diff --git a/go.sum b/go.sum index 14f783fb2f6..f74e3d5f0a0 100644 --- a/go.sum +++ b/go.sum @@ -1019,8 +1019,8 @@ github.com/crewjam/saml v0.4.14 h1:g9FBNx62osKusnFzs3QTN5L9CVA/Egfgm+stJShzw/c= github.com/crewjam/saml v0.4.14/go.mod h1:UVSZCf18jJkk6GpWNVqcyQJMD5HsRugBPf4I1nl2mME= github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781 h1:BUdwkIlf8IS2FasrrPg8gGPHQPOrQ18MS1Oew2tmGtY= github.com/cs3org/go-cs3apis v0.0.0-20231023073225-7748710e0781/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= -github.com/cs3org/reva/v2 v2.19.7 h1:0hMIbCZq1VBSxAslEvDDkj1Si8RqxbxR0wx3JvIRXTE= -github.com/cs3org/reva/v2 v2.19.7/go.mod h1:GRUrOp5HbFVwZTgR9bVrMZ/MvVy+Jhxw1PdMmhhKP9E= +github.com/cs3org/reva/v2 v2.19.8-0.20240919093513-f9a75a1a9fd4 h1:TbgQEuy4sgI9Gr7ymEt56V1cj4Vy410/N3fnVBRAVg8= +github.com/cs3org/reva/v2 v2.19.8-0.20240919093513-f9a75a1a9fd4/go.mod h1:GRUrOp5HbFVwZTgR9bVrMZ/MvVy+Jhxw1PdMmhhKP9E= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= diff --git a/tests/acceptance/features/coreApiVersions/fileVersions.feature b/tests/acceptance/features/coreApiVersions/fileVersions.feature index 56e1180aa35..9658d6f6117 100644 --- a/tests/acceptance/features/coreApiVersions/fileVersions.feature +++ b/tests/acceptance/features/coreApiVersions/fileVersions.feature @@ -163,13 +163,13 @@ Feature: dav-versions Then the HTTP status code should be "200" And the following headers should be set | header | value | - | Content-Disposition | attachment; filename*=UTF-8''"textfile0.txt"; filename="textfile0.txt" | + | Content-Disposition | attachment; filename*=UTF-8''textfile0.txt; filename="textfile0.txt" | And the downloaded content should be "version 1" When user "Alice" downloads the version of file "textfile0.txt" with the index "2" Then the HTTP status code should be "200" And the following headers should be set | header | value | - | Content-Disposition | attachment; filename*=UTF-8''"textfile0.txt"; filename="textfile0.txt" | + | Content-Disposition | attachment; filename*=UTF-8''textfile0.txt; filename="textfile0.txt" | And the downloaded content should be "uploaded content" @skipOnStorage:ceph @skipOnStorage:scality @@ -182,13 +182,13 @@ Feature: dav-versions Then the HTTP status code should be "200" And the following headers should be set | header | value | - | Content-Disposition | attachment; filename*=UTF-8''"textfile0.txt"; filename="textfile0.txt" | + | Content-Disposition | attachment; filename*=UTF-8''textfile0.txt; filename="textfile0.txt" | And the downloaded content should be "version 2" When user "Alice" downloads the version of file "textfile0.txt" with the index "2" Then the HTTP status code should be "200" And the following headers should be set | header | value | - | Content-Disposition | attachment; filename*=UTF-8''"textfile0.txt"; filename="textfile0.txt" | + | Content-Disposition | attachment; filename*=UTF-8''textfile0.txt; filename="textfile0.txt" | And the downloaded content should be "uploaded content" diff --git a/tests/acceptance/features/coreApiWebdavOperations/downloadFile.feature b/tests/acceptance/features/coreApiWebdavOperations/downloadFile.feature index a028ceada2b..7aaeb79b300 100644 --- a/tests/acceptance/features/coreApiWebdavOperations/downloadFile.feature +++ b/tests/acceptance/features/coreApiWebdavOperations/downloadFile.feature @@ -270,7 +270,7 @@ Feature: download file Then the HTTP status code should be "200" And the following headers should be set | header | value | - | Content-Disposition | attachment; filename*=UTF-8''""; filename="" | + | Content-Disposition | attachment; filename*=UTF-8''; filename="" | | Content-Security-Policy | default-src 'none'; | | X-Content-Type-Options | nosniff | | X-Download-Options | noopen | @@ -280,20 +280,20 @@ Feature: download file | X-XSS-Protection | 1; mode=block | And the downloaded content should be "test file" Examples: - | dav-path-version | file | - | old | textfile.txt | - | old | comma,.txt | - | old | 'quote'single'.txt | - | new | textfile.txt | - | new | comma,.txt | - | new | 'quote'single'.txt | + | dav-path-version | file | encoded | + | old | textfile.txt | textfile.txt | + | old | comma,.txt | comma%2C.txt | + | old | 'quote'single'.txt | %27quote%27single%27.txt | + | new | textfile.txt | textfile.txt | + | new | comma,.txt | comma%2C.txt | + | new | 'quote'single'.txt | %27quote%27single%27.txt | @skipOnRevaMaster Examples: - | dav-path-version | file | - | spaces | textfile.txt | - | spaces | comma,.txt | - | spaces | 'quote'single'.txt | + | dav-path-version | file | encoded | + | spaces | textfile.txt | textfile.txt | + | spaces | comma,.txt | comma%2C.txt | + | spaces | 'quote'single'.txt | %27quote%27single%27.txt | @smokeTest @issue-8361 Scenario Outline: downloading a file should serve security headers (file with doubel quotes) @@ -302,15 +302,15 @@ Feature: download file When user "Alice" downloads file '/"quote"double".txt' using the WebDAV API Then the HTTP status code should be "200" And the following headers should be set - | header | value | - | Content-Disposition | attachment; filename*=UTF-8''""quote"double".txt"; filename=""quote"double".txt" | - | Content-Security-Policy | default-src 'none'; | - | X-Content-Type-Options | nosniff | - | X-Download-Options | noopen | - | X-Frame-Options | SAMEORIGIN | - | X-Permitted-Cross-Domain-Policies | none | - | X-Robots-Tag | none | - | X-XSS-Protection | 1; mode=block | + | header | value | + | Content-Disposition | attachment; filename*=UTF-8''%22quote%22double%22.txt; filename=""quote"double".txt" | + | Content-Security-Policy | default-src 'none'; | + | X-Content-Type-Options | nosniff | + | X-Download-Options | noopen | + | X-Frame-Options | SAMEORIGIN | + | X-Permitted-Cross-Domain-Policies | none | + | X-Robots-Tag | none | + | X-XSS-Protection | 1; mode=block | And the downloaded content should be "test file" Examples: | dav-path-version | diff --git a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/net/builders.go b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/net/builders.go index be7b8fdeecf..727c59c03f6 100644 --- a/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/net/builders.go +++ b/vendor/github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/net/builders.go @@ -19,6 +19,7 @@ package net import ( + "net/url" "time" cs3types "github.com/cs3org/go-cs3apis/cs3/types/v1beta1" @@ -27,7 +28,7 @@ import ( // ContentDispositionAttachment builds a ContentDisposition Attachment header with various filename encodings func ContentDispositionAttachment(filename string) string { - return "attachment; filename*=UTF-8''\"" + filename + "\"; filename=\"" + filename + "\"" + return "attachment; filename*=UTF-8''" + url.PathEscape(filename) + "; filename=\"" + filename + "\"" } // RFC1123Z formats a CS3 Timestamp to be used in HTTP headers like Last-Modified diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/node/permissions.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/node/permissions.go index 4e3459a9467..d15f28ffbde 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/node/permissions.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/node/permissions.go @@ -100,6 +100,7 @@ func ServiceAccountPermissions() provider.ResourcePermissions { RestoreRecycleItem: true, // for cli restore command Delete: true, // for cli restore command with replace option CreateContainer: true, // for space provisioning + AddGrant: true, // for initial project space member assignment } } diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/session.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/session.go index 279dfd71383..1e5a51442d1 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/session.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/session.go @@ -26,6 +26,8 @@ import ( "strconv" "time" + "github.com/google/renameio/v2" + "github.com/rogpeppe/go-internal/lockedfile" tusd "github.com/tus/tusd/pkg/handler" userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" @@ -73,7 +75,13 @@ func (s *OcisSession) executantUser() *userpb.User { // Purge deletes the upload session metadata and written binary data func (s *OcisSession) Purge(ctx context.Context) error { - if err := os.Remove(sessionPath(s.store.root, s.info.ID)); err != nil { + sessionPath := sessionPath(s.store.root, s.info.ID) + f, err := lockedfile.OpenFile(sessionPath+".lock", os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0600) + if err != nil { + return err + } + defer f.Close() + if err := os.Remove(sessionPath); err != nil { return err } if err := os.Remove(s.binPath()); err != nil { @@ -92,10 +100,12 @@ func (s *OcisSession) TouchBin() error { } // Persist writes the upload session metadata to disk +// events can update the scan outcome and the finished event might read an empty file because of race conditions +// so we need to lock the file while writing and use atomic writes func (s *OcisSession) Persist(ctx context.Context) error { - uploadPath := sessionPath(s.store.root, s.info.ID) + sessionPath := sessionPath(s.store.root, s.info.ID) // create folder structure (if needed) - if err := os.MkdirAll(filepath.Dir(uploadPath), 0700); err != nil { + if err := os.MkdirAll(filepath.Dir(sessionPath), 0700); err != nil { return err } @@ -104,8 +114,12 @@ func (s *OcisSession) Persist(ctx context.Context) error { if err != nil { return err } - - return os.WriteFile(uploadPath, d, 0600) + f, err := lockedfile.OpenFile(sessionPath+".lock", os.O_RDWR|os.O_TRUNC|os.O_CREATE, 0600) + if err != nil { + return err + } + defer f.Close() + return renameio.WriteFile(sessionPath, d, 0600) } // ToFileInfo returns tus compatible FileInfo so the tus handler can access the upload offset diff --git a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/store.go b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/store.go index aeab235de17..05ad0e5ca34 100644 --- a/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/store.go +++ b/vendor/github.com/cs3org/reva/v2/pkg/storage/utils/decomposedfs/upload/store.go @@ -110,7 +110,7 @@ func (store OcisStore) List(ctx context.Context) ([]*OcisSession, error) { // Get returns the upload session for the given upload id func (store OcisStore) Get(ctx context.Context, id string) (*OcisSession, error) { - sessionPath := filepath.Join(store.root, "uploads", id+".info") + sessionPath := sessionPath(store.root, id) match := _idRegexp.FindStringSubmatch(sessionPath) if match == nil || len(match) < 2 { return nil, fmt.Errorf("invalid upload path") @@ -120,6 +120,15 @@ func (store OcisStore) Get(ctx context.Context, id string) (*OcisSession, error) store: store, info: tusd.FileInfo{}, } + lock, err := lockedfile.Open(sessionPath + ".lock") + if err != nil { + if errors.Is(err, iofs.ErrNotExist) { + // Interpret os.ErrNotExist as 404 Not Found + err = tusd.ErrNotFound + } + return nil, err + } + defer lock.Close() data, err := os.ReadFile(sessionPath) if err != nil { if errors.Is(err, iofs.ErrNotExist) { @@ -128,6 +137,8 @@ func (store OcisStore) Get(ctx context.Context, id string) (*OcisSession, error) } return nil, err } + lock.Close() // release lock asap + if err := json.Unmarshal(data, &session.info); err != nil { return nil, err } diff --git a/vendor/modules.txt b/vendor/modules.txt index 1bf3cab1aac..65c4838a446 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -359,7 +359,7 @@ github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1 github.com/cs3org/go-cs3apis/cs3/storage/registry/v1beta1 github.com/cs3org/go-cs3apis/cs3/tx/v1beta1 github.com/cs3org/go-cs3apis/cs3/types/v1beta1 -# github.com/cs3org/reva/v2 v2.19.7 +# github.com/cs3org/reva/v2 v2.19.8-0.20240919093513-f9a75a1a9fd4 ## explicit; go 1.21 github.com/cs3org/reva/v2/cmd/revad/internal/grace github.com/cs3org/reva/v2/cmd/revad/runtime