diff --git a/ocs/pkg/server/http/svc_test.go b/ocs/pkg/server/http/svc_test.go index 9a284d0c11..428550352a 100644 --- a/ocs/pkg/server/http/svc_test.go +++ b/ocs/pkg/server/http/svc_test.go @@ -650,7 +650,7 @@ func mintToken(ctx context.Context, su *User, roleIds []string) (token string, e }, }, }, - Groups: []string{}, + Groups: []string{}, UidNumber: int64(su.UIDNumber), GidNumber: int64(su.GIDNumber), } diff --git a/ocs/pkg/service/v0/users.go b/ocs/pkg/service/v0/users.go index 3cabff9773..eef8ed5354 100644 --- a/ocs/pkg/service/v0/users.go +++ b/ocs/pkg/service/v0/users.go @@ -486,9 +486,9 @@ func (o Ocs) mintTokenForUser(ctx context.Context, account *accounts.Account) (s OpaqueId: account.Id, Idp: o.config.IdentityManagement.Address, }, - Groups: []string{}, - UidNumber: account.UidNumber, - GidNumber: account.GidNumber, + Groups: []string{}, + UidNumber: account.UidNumber, + GidNumber: account.GidNumber, } s, err := scope.GetOwnerScope() if err != nil { diff --git a/proxy/pkg/middleware/basic_auth.go b/proxy/pkg/middleware/basic_auth.go index 83e562da58..f7a107f6a7 100644 --- a/proxy/pkg/middleware/basic_auth.go +++ b/proxy/pkg/middleware/basic_auth.go @@ -1,7 +1,6 @@ package middleware import ( - "encoding/xml" "fmt" "net/http" "strings" @@ -9,6 +8,7 @@ import ( "github.com/owncloud/ocis/ocis-pkg/log" "github.com/owncloud/ocis/ocis-pkg/oidc" "github.com/owncloud/ocis/proxy/pkg/user/backend" + "github.com/owncloud/ocis/proxy/pkg/webdav" ) const publicFilesEndpoint = "/remote.php/dav/public-files/" @@ -69,12 +69,17 @@ func BasicAuth(optionSetters ...Option) func(next http.Handler) http.Handler { w.WriteHeader(http.StatusUnauthorized) - b, err := Marshal(exception{ - code: SabredavPermissionDenied, - message: "Authentication error", - }) + if webdav.IsWebdavRequest(req) { + b, err := webdav.Marshal(webdav.Exception{ + Code: webdav.SabredavPermissionDenied, + Message: "Authentication error", + }) - HandleWebdavError(w, b, err) + webdav.HandleWebdavError(w, b, err) + return + } + + w.WriteHeader(http.StatusUnauthorized) return } @@ -106,76 +111,3 @@ func (m basicAuth) isBasicAuth(req *http.Request) bool { _, _, ok := req.BasicAuth() return m.enabled && ok } - -type code int - -const ( - // SabredavBadRequest maps to HTTP 400 - SabredavBadRequest code = iota - // SabredavMethodNotAllowed maps to HTTP 405 - SabredavMethodNotAllowed - // SabredavNotAuthenticated maps to HTTP 401 - SabredavNotAuthenticated - // SabredavPreconditionFailed maps to HTTP 412 - SabredavPreconditionFailed - // SabredavPermissionDenied maps to HTTP 403 - SabredavPermissionDenied - // SabredavNotFound maps to HTTP 404 - SabredavNotFound - // SabredavConflict maps to HTTP 409 - SabredavConflict -) - -var ( - codesEnum = []string{ - "Sabre\\DAV\\Exception\\BadRequest", - "Sabre\\DAV\\Exception\\MethodNotAllowed", - "Sabre\\DAV\\Exception\\NotAuthenticated", - "Sabre\\DAV\\Exception\\PreconditionFailed", - "Sabre\\DAV\\Exception\\PermissionDenied", - "Sabre\\DAV\\Exception\\NotFound", - "Sabre\\DAV\\Exception\\Conflict", - } -) - -type exception struct { - code code - message string - header string -} - -// Marshal just calls the xml marshaller for a given exception. -func Marshal(e exception) ([]byte, error) { - xmlstring, err := xml.Marshal(&errorXML{ - Xmlnsd: "DAV", - Xmlnss: "http://sabredav.org/ns", - Exception: codesEnum[e.code], - Message: e.message, - Header: e.header, - }) - if err != nil { - return []byte(""), err - } - return []byte(xml.Header + string(xmlstring)), err -} - -// http://www.webdav.org/specs/rfc4918.html#ELEMENT_error -type errorXML struct { - XMLName xml.Name `xml:"d:error"` - Xmlnsd string `xml:"xmlns:d,attr"` - Xmlnss string `xml:"xmlns:s,attr"` - Exception string `xml:"s:exception"` - Message string `xml:"s:message"` - InnerXML []byte `xml:",innerxml"` - Header string `xml:"s:header,omitempty"` -} - -func HandleWebdavError(w http.ResponseWriter, b []byte, err error) { - if err != nil { - w.WriteHeader(http.StatusInternalServerError) - return - } - _, err = w.Write(b) - if err != nil { - } -} diff --git a/proxy/pkg/webdav/response.go b/proxy/pkg/webdav/response.go new file mode 100644 index 0000000000..0eb9a573e1 --- /dev/null +++ b/proxy/pkg/webdav/response.go @@ -0,0 +1,79 @@ +package webdav + +import ( + "encoding/xml" + "net/http" +) + +type code int + +const ( + // SabredavBadRequest maps to HTTP 400 + SabredavBadRequest code = iota + // SabredavMethodNotAllowed maps to HTTP 405 + SabredavMethodNotAllowed + // SabredavNotAuthenticated maps to HTTP 401 + SabredavNotAuthenticated + // SabredavPreconditionFailed maps to HTTP 412 + SabredavPreconditionFailed + // SabredavPermissionDenied maps to HTTP 403 + SabredavPermissionDenied + // SabredavNotFound maps to HTTP 404 + SabredavNotFound + // SabredavConflict maps to HTTP 409 + SabredavConflict +) + +var ( + codesEnum = []string{ + "Sabre\\DAV\\Exception\\BadRequest", + "Sabre\\DAV\\Exception\\MethodNotAllowed", + "Sabre\\DAV\\Exception\\NotAuthenticated", + "Sabre\\DAV\\Exception\\PreconditionFailed", + "Sabre\\DAV\\Exception\\PermissionDenied", + "Sabre\\DAV\\Exception\\NotFound", + "Sabre\\DAV\\Exception\\Conflict", + } +) + +type Exception struct { + Code code + Message string + Header string +} + +// Marshal just calls the xml marshaller for a given Exception. +func Marshal(e Exception) ([]byte, error) { + xmlstring, err := xml.Marshal(&errorXML{ + Xmlnsd: "DAV", + Xmlnss: "http://sabredav.org/ns", + Exception: codesEnum[e.Code], + Message: e.Message, + Header: e.Header, + }) + if err != nil { + return []byte(""), err + } + return []byte(xml.Header + string(xmlstring)), err +} + +// http://www.webdav.org/specs/rfc4918.html#ELEMENT_error +type errorXML struct { + XMLName xml.Name `xml:"d:error"` + Xmlnsd string `xml:"xmlns:d,attr"` + Xmlnss string `xml:"xmlns:s,attr"` + Exception string `xml:"s:Exception"` + Message string `xml:"s:Message"` + InnerXML []byte `xml:",innerxml"` + Header string `xml:"s:Header,omitempty"` +} + +func HandleWebdavError(w http.ResponseWriter, b []byte, err error) { + if err != nil { + w.WriteHeader(http.StatusInternalServerError) + return + } + _, err = w.Write(b) + if err != nil { + } +} diff --git a/proxy/pkg/webdav/webdav.go b/proxy/pkg/webdav/webdav.go new file mode 100644 index 0000000000..cfb59329a3 --- /dev/null +++ b/proxy/pkg/webdav/webdav.go @@ -0,0 +1,18 @@ +package webdav + +import "net/http" + +var methods = []string{"PROPFIND", "DELETE", "PROPPATCH", "MKCOL", "COPY", "MOVE", "LOCK", "UNLOCK"} + +// This is a non exhaustive way to detect if a request is directed to a webdav server. This naïve implementation +// only deals with the set of methods exclusive to WebDAV. Since WebDAV is a superset of HTTP, GET, POST and so on +// are valid methods, but this implementation would require a larger effort than we can build upon in this file. +// This is needed because the proxy might need to create a response with a webdav body; such as unauthorized. +func IsWebdavRequest(r *http.Request) bool { + for i := range methods { + if methods[i] == r.Method { + return true + } + } + return false +}