diff --git a/changelog/unreleased/s3ng-download-validation.md b/changelog/unreleased/s3ng-download-validation.md new file mode 100644 index 0000000000..a5cf1b95aa --- /dev/null +++ b/changelog/unreleased/s3ng-download-validation.md @@ -0,0 +1,6 @@ +Bugfix: validate s3ng downloads + +The s3ng download func now returns an error in cases where the requested node blob is unknown +or the blob size does not match the node meta blob size. + +https://github.com/cs3org/reva/pull/3341 diff --git a/internal/http/services/owncloud/ocdav/get.go b/internal/http/services/owncloud/ocdav/get.go index e5750dbaa7..5a711c4663 100644 --- a/internal/http/services/owncloud/ocdav/get.go +++ b/internal/http/services/owncloud/ocdav/get.go @@ -72,6 +72,25 @@ func (s *svc) handleGet(ctx context.Context, w http.ResponseWriter, r *http.Requ return } + sReq := &provider.StatRequest{ + Ref: ref, + } + sRes, err := client.Stat(ctx, sReq) + if err != nil { + log.Error().Err(err).Msg("error stat resource") + w.WriteHeader(http.StatusInternalServerError) + return + } else if sRes.Status.Code != rpc.Code_CODE_OK { + errors.HandleErrorStatus(&log, w, sRes.Status) + return + } + + if sRes.Info.Type != provider.ResourceType_RESOURCE_TYPE_FILE { + w.Header().Set("Content-Length", "0") + w.WriteHeader(http.StatusOK) + return + } + dReq := &provider.InitiateFileDownloadRequest{Ref: ref} dRes, err := client.InitiateFileDownload(ctx, dReq) if err != nil { diff --git a/pkg/rhttp/datatx/utils/download/download.go b/pkg/rhttp/datatx/utils/download/download.go index bf9cd76dd6..3e9e1e8342 100644 --- a/pkg/rhttp/datatx/utils/download/download.go +++ b/pkg/rhttp/datatx/utils/download/download.go @@ -206,7 +206,7 @@ func GetOrHeadFile(w http.ResponseWriter, r *http.Request, fs storage.FS, spaceI var c int64 c, err = io.CopyN(w, sendContent, sendSize) if err != nil { - sublog.Error().Err(err).Msg("error copying data to response") + sublog.Error().Err(err).Interface("resourceid", md.Id).Msg("error copying data to response") return } if c != sendSize { diff --git a/pkg/storage/fs/s3ng/blobstore/blobstore.go b/pkg/storage/fs/s3ng/blobstore/blobstore.go index 071fdc38cc..e5e51eb0d0 100644 --- a/pkg/storage/fs/s3ng/blobstore/blobstore.go +++ b/pkg/storage/fs/s3ng/blobstore/blobstore.go @@ -20,6 +20,7 @@ package blobstore import ( "context" + "fmt" "io" "net/url" "os" @@ -87,6 +88,16 @@ func (bs *Blobstore) Download(node *node.Node) (io.ReadCloser, error) { if err != nil { return nil, errors.Wrapf(err, "could not download object '%s' from bucket '%s'", bs.path(node), bs.bucket) } + + stat, err := reader.Stat() + if err != nil { + return nil, errors.Wrapf(err, "blob path: %s", bs.path(node)) + } + + if node.Blobsize != stat.Size { + return nil, fmt.Errorf("blob has unexpected size. %d bytes expected, got %d bytes", node.Blobsize, stat.Size) + } + return reader, nil }