diff --git a/changelog/unreleased/fix-publiclink-resharing.md b/changelog/unreleased/fix-publiclink-resharing.md new file mode 100644 index 0000000000..63df64c615 --- /dev/null +++ b/changelog/unreleased/fix-publiclink-resharing.md @@ -0,0 +1,8 @@ +Bugfix: Forbid resharing with higher permissions + +When creating a public link from a viewer share a user was able to set editor permissions on that link. +This was because of a missing check that is added now + +https://github.com/owncloud/ocis/issues/4061 +https://github.com/owncloud/ocis/issues/3881 +https://github.com/owncloud/ocis/pull/4077 diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/public.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/public.go index 463aaad62c..8a76ebca08 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/public.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/public.go @@ -119,6 +119,14 @@ func (h *Handler) createPublicLinkShare(w http.ResponseWriter, r *http.Request, newPermissions = conversions.RoleFromOCSPermissions(permissions).CS3ResourcePermissions() } + if !sufficientPermissions(statInfo.PermissionSet, newPermissions) { + return nil, &ocsError{ + Code: http.StatusNotFound, + Message: "Cannot set the requested share permissions", + Error: errors.New("cannot set the requested share permissions"), + } + } + req := link.CreatePublicShareRequest{ ResourceInfo: statInfo, Grant: &link.Grant{ @@ -342,6 +350,19 @@ func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, shar } } + statReq := provider.StatRequest{Ref: &provider.Reference{ResourceId: before.Share.ResourceId}} + statRes, err := gwC.Stat(r.Context(), &statReq) + if err != nil { + log.Debug().Err(err).Str("shares", "update public share").Msg("error during stat") + response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "missing resource information", fmt.Errorf("error getting resource information")) + return + } + + if !sufficientPermissions(statRes.Info.PermissionSet, newPermissions) { + response.WriteOCSError(w, r, response.MetaBadRequest.StatusCode, "no share permission", nil) + return + } + // ExpireDate expireTimeString, ok := r.Form["expireDate"] // check if value is set and must be updated or cleared @@ -411,15 +432,6 @@ func (h *Handler) updatePublicShare(w http.ResponseWriter, r *http.Request, shar return } - statReq := provider.StatRequest{Ref: &provider.Reference{ResourceId: before.Share.ResourceId}} - - statRes, err := gwC.Stat(r.Context(), &statReq) - if err != nil { - log.Debug().Err(err).Str("shares", "update public share").Msg("error during stat") - response.WriteOCSError(w, r, response.MetaServerError.StatusCode, "missing resource information", fmt.Errorf("error getting resource information")) - return - } - s := conversions.PublicShare2ShareData(publicShare, r, h.publicURL) err = h.addFileInfo(r.Context(), s, statRes.Info) if err != nil { diff --git a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go index f66c22c3b9..71e767d3ab 100644 --- a/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go +++ b/internal/http/services/owncloud/ocs/handlers/apps/sharing/shares/shares.go @@ -455,8 +455,7 @@ func (h *Handler) extractPermissions(reqRole string, reqPermissions string, ri * role = conversions.RoleFromOCSPermissions(permissions) } - existingPermissions := conversions.RoleFromResourcePermissions(ri.PermissionSet).OCSPermissions() - if !existingPermissions.Contain(permissions) { + if !sufficientPermissions(ri.PermissionSet, role.CS3ResourcePermissions()) { return nil, nil, &ocsError{ Code: http.StatusNotFound, Message: "Cannot set the requested share permissions", @@ -1399,3 +1398,10 @@ func (h *Handler) getPoolClient() (gateway.GatewayAPIClient, error) { func (h *Handler) getHomeNamespace(u *userpb.User) string { return templates.WithUser(u, h.homeNamespace) } + +// sufficientPermissions returns true if the `existing` permissions contain the `requested` permissions +func sufficientPermissions(existing, requested *provider.ResourcePermissions) bool { + ep := conversions.RoleFromResourcePermissions(existing).OCSPermissions() + rp := conversions.RoleFromResourcePermissions(requested).OCSPermissions() + return ep.Contain(rp) +}