Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use the user in request for deciding the layout for non-home DAV requests #1401

Merged
merged 2 commits into from
Jan 15, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions changelog/unreleased/fix-dav-namespace.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Bugfix: Use the user in request for deciding the layout for non-home DAV requests

For the incoming /dav/files/userID requests, we have different namespaces
depending on whether the request is for the logged-in user's namespace or not.
Since in the storage drivers, we specify the layout depending only on the user
whose resources are to be accessed, this fails when a user wants to access
another user's namespace when the storage provider depends on the logged in
user's namespace. This PR fixes that.

For example, consider the following case. The owncloud fs uses a layout
{{substr 0 1 .Id.OpaqueId}}/{{.Id.OpaqueId}}. The user einstein sends a request
to access a resource shared with him, say /dav/files/marie/abcd, which should be
allowed. However, based on the way we applied the layout, there's no way in
which this can be translated to /m/marie/.

https://github.com/cs3org/reva/pull/1401
2 changes: 0 additions & 2 deletions internal/http/services/owncloud/ocdav/copy.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ func (s *svc) handleCopy(w http.ResponseWriter, r *http.Request, ns string) {
ctx, span := trace.StartSpan(ctx, "head")
defer span.End()

ns = applyLayout(ctx, ns)

src := path.Join(ns, r.URL.Path)
dstHeader := r.Header.Get("Destination")
overwrite := r.Header.Get("Overwrite")
Expand Down
6 changes: 3 additions & 3 deletions internal/http/services/owncloud/ocdav/dav.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,11 @@ func (h *DavHandler) init(c *Config) error {
return err
}
h.FilesHandler = new(WebDavHandler)
if err := h.FilesHandler.init(c.FilesNamespace); err != nil {
if err := h.FilesHandler.init(c.FilesNamespace, false); err != nil {
return err
}
h.FilesHomeHandler = new(WebDavHandler)
if err := h.FilesHomeHandler.init(c.WebdavNamespace); err != nil {
if err := h.FilesHomeHandler.init(c.WebdavNamespace, true); err != nil {
return err
}
h.MetaHandler = new(MetaHandler)
Expand All @@ -71,7 +71,7 @@ func (h *DavHandler) init(c *Config) error {
h.TrashbinHandler = new(TrashbinHandler)

h.PublicFolderHandler = new(WebDavHandler)
if err := h.PublicFolderHandler.init("public"); err != nil { // jail public file requests to /public/ prefix
if err := h.PublicFolderHandler.init("public", true); err != nil { // jail public file requests to /public/ prefix
return err
}

Expand Down
2 changes: 0 additions & 2 deletions internal/http/services/owncloud/ocdav/delete.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,6 @@ func (s *svc) handleDelete(w http.ResponseWriter, r *http.Request, ns string) {
ctx, span := trace.StartSpan(ctx, "head")
defer span.End()

ns = applyLayout(ctx, ns)

fn := path.Join(ns, r.URL.Path)

sublog := appctx.GetLogger(ctx).With().Str("path", fn).Logger()
Expand Down
2 changes: 0 additions & 2 deletions internal/http/services/owncloud/ocdav/get.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ func (s *svc) handleGet(w http.ResponseWriter, r *http.Request, ns string) {
ctx, span := trace.StartSpan(ctx, "get")
defer span.End()

ns = applyLayout(ctx, ns)

fn := path.Join(ns, r.URL.Path)

sublog := appctx.GetLogger(ctx).With().Str("path", fn).Str("svc", "ocdav").Str("handler", "get").Logger()
Expand Down
2 changes: 0 additions & 2 deletions internal/http/services/owncloud/ocdav/head.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,6 @@ func (s *svc) handleHead(w http.ResponseWriter, r *http.Request, ns string) {
ctx, span := trace.StartSpan(ctx, "head")
defer span.End()

ns = applyLayout(ctx, ns)

fn := path.Join(ns, r.URL.Path)

sublog := appctx.GetLogger(ctx).With().Str("path", fn).Logger()
Expand Down
2 changes: 0 additions & 2 deletions internal/http/services/owncloud/ocdav/mkcol.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ func (s *svc) handleMkcol(w http.ResponseWriter, r *http.Request, ns string) {
ctx, span := trace.StartSpan(ctx, "mkcol")
defer span.End()

ns = applyLayout(ctx, ns)

fn := path.Join(ns, r.URL.Path)

sublog := appctx.GetLogger(ctx).With().Str("path", fn).Logger()
Expand Down
2 changes: 0 additions & 2 deletions internal/http/services/owncloud/ocdav/move.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ func (s *svc) handleMove(w http.ResponseWriter, r *http.Request, ns string) {
ctx, span := trace.StartSpan(ctx, "move")
defer span.End()

ns = applyLayout(ctx, ns)

src := path.Join(ns, r.URL.Path)
dstHeader := r.Header.Get("Destination")
overwrite := r.Header.Get("Overwrite")
Expand Down
19 changes: 16 additions & 3 deletions internal/http/services/owncloud/ocdav/ocdav.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ import (
"time"

gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1"
userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1"
"github.com/cs3org/reva/pkg/appctx"
"github.com/cs3org/reva/pkg/rgrpc/todo/pool"
Expand Down Expand Up @@ -102,7 +103,7 @@ func New(m map[string]interface{}, log *zerolog.Logger) (global.Service, error)
),
}
// initialize handlers and set default configs
if err := s.webDavHandler.init(conf.WebdavNamespace); err != nil {
if err := s.webDavHandler.init(conf.WebdavNamespace, true); err != nil {
return nil, err
}
if err := s.davHandler.init(conf); err != nil {
Expand Down Expand Up @@ -186,8 +187,20 @@ func (s *svc) getClient() (gateway.GatewayAPIClient, error) {
return pool.GetGatewayServiceClient(s.c.GatewaySvc)
}

func applyLayout(ctx context.Context, ns string) string {
return templates.WithUser(ctxuser.ContextMustGetUser(ctx), ns)
func applyLayout(ctx context.Context, ns string, useLoggedInUserNS bool, requestPath string) string {
// If useLoggedInUserNS is false, that implies that the request is coming from
// the FilesHandler method invoked by a /dav/files/fileOwner where fileOwner
// is not the same as the logged in user. In that case, we'll treat fileOwner
// as the username whose files are to be accessed and use that in the
// namespace template.
u, ok := ctxuser.ContextGetUser(ctx)
if !ok || !useLoggedInUserNS {
requestUserID, _ := router.ShiftPath(requestPath)
u = &userpb.User{
Username: requestUserID,
}
}
return templates.WithUser(u, ns)
}

func wrapResourceID(r *provider.ResourceId) string {
Expand Down
2 changes: 0 additions & 2 deletions internal/http/services/owncloud/ocdav/propfind.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,6 @@ func (s *svc) handlePropfind(w http.ResponseWriter, r *http.Request, ns string)
ctx, span := trace.StartSpan(ctx, "propfind")
defer span.End()

ns = applyLayout(ctx, ns)

fn := path.Join(ns, r.URL.Path)
depth := r.Header.Get("Depth")
if depth == "" {
Expand Down
2 changes: 0 additions & 2 deletions internal/http/services/owncloud/ocdav/proppatch.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ func (s *svc) handleProppatch(w http.ResponseWriter, r *http.Request, ns string)
acceptedProps := []xml.Name{}
removedProps := []xml.Name{}

ns = applyLayout(ctx, ns)

fn := path.Join(ns, r.URL.Path)

sublog := appctx.GetLogger(ctx).With().Str("path", fn).Logger()
Expand Down
2 changes: 0 additions & 2 deletions internal/http/services/owncloud/ocdav/put.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,6 @@ func isContentRange(r *http.Request) bool {

func (s *svc) handlePut(w http.ResponseWriter, r *http.Request, ns string) {
ctx := r.Context()

ns = applyLayout(ctx, ns)
fn := path.Join(ns, r.URL.Path)

sublog := appctx.GetLogger(ctx).With().Str("path", fn).Logger()
Expand Down
2 changes: 0 additions & 2 deletions internal/http/services/owncloud/ocdav/tus.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,6 @@ func (s *svc) handleTusPost(w http.ResponseWriter, r *http.Request, ns string) {
return
}

ns = applyLayout(ctx, ns)

// append filename to current dir
fn := path.Join(ns, r.URL.Path, meta["filename"])

Expand Down
35 changes: 19 additions & 16 deletions internal/http/services/owncloud/ocdav/webdav.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,46 +25,49 @@ import (

// WebDavHandler implements a dav endpoint
type WebDavHandler struct {
namespace string
namespace string
useLoggedInUserNS bool
}

func (h *WebDavHandler) init(ns string) error {
func (h *WebDavHandler) init(ns string, useLoggedInUserNS bool) error {
h.namespace = path.Join("/", ns)
h.useLoggedInUserNS = useLoggedInUserNS
return nil
}

// Handler handles requests
func (h *WebDavHandler) Handler(s *svc) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
ns := applyLayout(r.Context(), h.namespace, h.useLoggedInUserNS, r.URL.Path)
switch r.Method {
case "PROPFIND":
s.handlePropfind(w, r, h.namespace)
s.handlePropfind(w, r, ns)
case "LOCK":
s.handleLock(w, r, h.namespace)
s.handleLock(w, r, ns)
case "UNLOCK":
s.handleUnlock(w, r, h.namespace)
s.handleUnlock(w, r, ns)
case "PROPPATCH":
s.handleProppatch(w, r, h.namespace)
s.handleProppatch(w, r, ns)
case "MKCOL":
s.handleMkcol(w, r, h.namespace)
s.handleMkcol(w, r, ns)
case "MOVE":
s.handleMove(w, r, h.namespace)
s.handleMove(w, r, ns)
case "COPY":
s.handleCopy(w, r, h.namespace)
s.handleCopy(w, r, ns)
case "REPORT":
s.handleReport(w, r, h.namespace)
s.handleReport(w, r, ns)
case http.MethodGet:
s.handleGet(w, r, h.namespace)
s.handleGet(w, r, ns)
case http.MethodPut:
s.handlePut(w, r, h.namespace)
s.handlePut(w, r, ns)
case http.MethodPost:
s.handleTusPost(w, r, h.namespace)
s.handleTusPost(w, r, ns)
case http.MethodOptions:
s.handleOptions(w, r, h.namespace)
s.handleOptions(w, r, ns)
case http.MethodHead:
s.handleHead(w, r, h.namespace)
s.handleHead(w, r, ns)
case http.MethodDelete:
s.handleDelete(w, r, h.namespace)
s.handleDelete(w, r, ns)
default:
w.WriteHeader(http.StatusNotFound)
}
Expand Down