Skip to content

Commit

Permalink
Prevent recursive copy/move operations on the API level
Browse files Browse the repository at this point in the history
  • Loading branch information
aduffeck committed Jun 24, 2022
1 parent 0bcb90c commit 5d33e26
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 13 deletions.
26 changes: 19 additions & 7 deletions internal/http/services/owncloud/ocdav/copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,25 @@ func (s *svc) executeSpacesCopy(ctx context.Context, w http.ResponseWriter, clie
}

func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Request, srcRef, dstRef *provider.Reference, log *zerolog.Logger) *copy {
client, err := s.getClient()
if err != nil {
log.Error().Err(err).Msg("error getting grpc client")
w.WriteHeader(http.StatusInternalServerError)
return nil
}

isChild, err := s.referenceIsChildOf(ctx, client, dstRef, srcRef)
if err != nil {
log.Error().Err(err).Msg("error while trying to detect recursive move operation")
w.WriteHeader(http.StatusInternalServerError)
}
if isChild {
w.WriteHeader(http.StatusBadRequest)
b, err := errors.Marshal(http.StatusBadRequest, "can not copy a folder into one of its children", "")
errors.HandleWebdavError(log, w, b, err)
return nil
}

oh := r.Header.Get(net.HeaderOverwrite)
overwrite, err := net.ParseOverwrite(oh)
if err != nil {
Expand Down Expand Up @@ -513,13 +532,6 @@ func (s *svc) prepareCopy(ctx context.Context, w http.ResponseWriter, r *http.Re

log.Debug().Bool("overwrite", overwrite).Str("depth", depth.String()).Msg("copy")

client, err := s.getClient()
if err != nil {
log.Error().Err(err).Msg("error getting grpc client")
w.WriteHeader(http.StatusInternalServerError)
return nil
}

srcStatReq := &provider.StatRequest{Ref: srcRef}
srcStatRes, err := client.Stat(ctx, srcStatReq)
if err != nil {
Expand Down
24 changes: 18 additions & 6 deletions internal/http/services/owncloud/ocdav/move.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,19 +132,31 @@ func (s *svc) handleSpacesMove(w http.ResponseWriter, r *http.Request, srcSpaceI
}

func (s *svc) handleMove(ctx context.Context, w http.ResponseWriter, r *http.Request, src, dst *provider.Reference, log zerolog.Logger) {
oh := r.Header.Get(net.HeaderOverwrite)
log.Debug().Str("overwrite", oh).Msg("move")
client, err := s.getClient()
if err != nil {
log.Error().Err(err).Msg("error getting grpc client")
w.WriteHeader(http.StatusInternalServerError)
return
}

overwrite, err := net.ParseOverwrite(oh)
isChild, err := s.referenceIsChildOf(ctx, client, dst, src)
if err != nil {
log.Error().Err(err).Msg("error while trying to detect recursive move operation")
w.WriteHeader(http.StatusInternalServerError)
}
if isChild {
w.WriteHeader(http.StatusBadRequest)
b, err := errors.Marshal(http.StatusBadRequest, "can not move a folder into one of its children", "")
errors.HandleWebdavError(&log, w, b, err)
return
}

client, err := s.getClient()
oh := r.Header.Get(net.HeaderOverwrite)
log.Debug().Str("overwrite", oh).Msg("move")

overwrite, err := net.ParseOverwrite(oh)
if err != nil {
log.Error().Err(err).Msg("error getting grpc client")
w.WriteHeader(http.StatusInternalServerError)
w.WriteHeader(http.StatusBadRequest)
return
}

Expand Down
28 changes: 28 additions & 0 deletions internal/http/services/owncloud/ocdav/ocdav.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,10 @@ import (

"github.com/ReneKroon/ttlcache/v2"
gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
gatewayv1beta1 "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/cs3org/reva/v2/internal/http/services/owncloud/ocdav/net"
"github.com/cs3org/reva/v2/pkg/appctx"
ctxpkg "github.com/cs3org/reva/v2/pkg/ctx"
Expand All @@ -42,6 +44,7 @@ import (
"github.com/cs3org/reva/v2/pkg/storage/favorite/registry"
"github.com/cs3org/reva/v2/pkg/storage/utils/templates"
rtrace "github.com/cs3org/reva/v2/pkg/trace"
"github.com/cs3org/reva/v2/pkg/utils"
"github.com/mitchellh/mapstructure"
"github.com/rs/zerolog"
"go.opentelemetry.io/otel/trace"
Expand Down Expand Up @@ -384,3 +387,28 @@ func addAccessHeaders(w http.ResponseWriter, r *http.Request) {
headers.Set("Strict-Transport-Security", "max-age=63072000")
}
}

func (s *svc) referenceIsChildOf(ctx context.Context, client gatewayv1beta1.GatewayAPIClient, child, parent *provider.Reference) (bool, error) {
if utils.ResourceIDEqual(child.ResourceId, parent.ResourceId) {
return strings.HasPrefix(child.Path, parent.Path+"/"), nil // Relative to the same resource -> compare paths
}

if child.ResourceId.StorageId != parent.ResourceId.StorageId {
return false, nil // Not on the same storage -> not a child
}

// the references are on the same storage but relative to different resources
// -> we need to get the path for both resources
childPathRes, err := client.GetPath(ctx, &provider.GetPathRequest{ResourceId: child.ResourceId})
if err != nil {
return false, err
}
parentPathRes, err := client.GetPath(ctx, &provider.GetPathRequest{ResourceId: parent.ResourceId})
if err != nil {
return false, err
}

return strings.HasPrefix(
path.Join(childPathRes.Path, child.Path),
path.Join(parentPathRes.Path, parent.Path)+"/"), nil
}

0 comments on commit 5d33e26

Please sign in to comment.