diff --git a/webdavd/server.go b/webdavd/server.go index 878a0be5..0bdc7c72 100644 --- a/webdavd/server.go +++ b/webdavd/server.go @@ -27,7 +27,6 @@ import ( var ( err401 = errors.New("Unauthorized") - err403 = errors.New("Forbidden") xForwardedFor = http.CanonicalHeaderKey("X-Forwarded-For") xRealIP = http.CanonicalHeaderKey("X-Real-IP") ) @@ -105,11 +104,11 @@ func (s *webDavServer) verifyTLSConnection(state tls.ConnectionState) error { return nil } -// returns true if a response was sent -func (s *webDavServer) checkRequestMethod(ctx context.Context, r *http.Request, connection *Connection, prefix string) bool { +// returns true if we have to handle a HEAD response, for a directory, ourself +func (s *webDavServer) checkRequestMethod(ctx context.Context, r *http.Request, connection *Connection) bool { // see RFC4918, section 9.4 if r.Method == http.MethodGet || r.Method == http.MethodHead { - p := strings.TrimPrefix(path.Clean(r.URL.Path), prefix) + p := path.Clean(r.URL.Path) info, err := connection.Stat(ctx, p) if err == nil && info.IsDir() { if r.Method == http.MethodHead { @@ -154,11 +153,6 @@ func (s *webDavServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } - if path.Clean(r.URL.Path) == "/" && (r.Method == http.MethodGet || r.Method == "PROPFIND" || r.Method == http.MethodOptions) { - http.Redirect(w, r, path.Join("/", user.Username), http.StatusMovedPermanently) - return - } - connectionID, err := s.validateUser(&user, r) if err != nil { updateLoginMetrics(&user, ipAddr, err) @@ -187,8 +181,7 @@ func (s *webDavServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { dataprovider.UpdateLastLogin(user) //nolint:errcheck - prefix := path.Join("/", user.Username) - if s.checkRequestMethod(ctx, r, connection, prefix) { + if s.checkRequestMethod(ctx, r, connection) { w.Header().Set("Content-Type", "text/xml; charset=utf-8") w.WriteHeader(http.StatusMultiStatus) w.Write([]byte("")) //nolint:errcheck @@ -196,7 +189,6 @@ func (s *webDavServer) ServeHTTP(w http.ResponseWriter, r *http.Request) { } handler := webdav.Handler{ - Prefix: prefix, FileSystem: connection, LockSystem: lockSystem, Logger: writeLog, @@ -257,12 +249,6 @@ func (s *webDavServer) validateUser(user *dataprovider.User, r *http.Request) (s connID := xid.New().String() connectionID := fmt.Sprintf("%v_%v", common.ProtocolWebDAV, connID) - uriSegments := strings.Split(path.Clean(r.URL.Path), "/") - if len(uriSegments) < 2 || uriSegments[1] != user.Username { - logger.Debug(logSender, connectionID, "URI %#v not allowed for user %#v", r.URL.Path, user.Username) - return connID, err403 - } - if !filepath.IsAbs(user.HomeDir) { logger.Warn(logSender, connectionID, "user %#v has an invalid home dir: %#v. Home dir must be an absolute path, login not allowed", user.Username, user.HomeDir) diff --git a/webdavd/webdavd_test.go b/webdavd/webdavd_test.go index 778cf343..a6c17ff2 100644 --- a/webdavd/webdavd_test.go +++ b/webdavd/webdavd_test.go @@ -4,7 +4,6 @@ import ( "bytes" "crypto/rand" "encoding/json" - "errors" "fmt" "io" "io/ioutil" @@ -472,7 +471,7 @@ func TestPropPatch(t *testing.T) { assert.NoError(t, err) httpClient := httpclient.GetHTTPClient() propatchBody := `Wed, 04 Nov 2020 13:25:51 GMTSat, 05 Dec 2020 21:16:12 GMTWed, 04 Nov 2020 13:25:51 GMT00000000` - req, err := http.NewRequest("PROPPATCH", fmt.Sprintf("http://%v/%v/%v", webDavServerAddr, user.Username, testFileName), bytes.NewReader([]byte(propatchBody))) + req, err := http.NewRequest("PROPPATCH", fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName), bytes.NewReader([]byte(propatchBody))) assert.NoError(t, err) req.SetBasicAuth(u.Username, u.Password) resp, err := httpClient.Do(req) @@ -554,68 +553,6 @@ func TestDefender(t *testing.T) { assert.NoError(t, err) } -func TestLoginInvalidURL(t *testing.T) { - u := getTestUser() - user, _, err := httpdtest.AddUser(u, http.StatusCreated) - assert.NoError(t, err) - u1 := getTestUser() - u1.Username = user.Username + "1" - user1, _, err := httpdtest.AddUser(u1, http.StatusCreated) - assert.NoError(t, err) - rootPath := fmt.Sprintf("http://%v/%v", webDavServerAddr, user.Username+"1") - client := gowebdav.NewClient(rootPath, user.Username, defaultPassword) - client.SetTimeout(5 * time.Second) - assert.Error(t, checkBasicFunc(client)) - _, err = httpdtest.RemoveUser(user, http.StatusOK) - assert.NoError(t, err) - _, err = httpdtest.RemoveUser(user1, http.StatusOK) - assert.NoError(t, err) -} - -func TestRootRedirect(t *testing.T) { - errRedirect := errors.New("redirect error") - u := getTestUser() - user, _, err := httpdtest.AddUser(u, http.StatusCreated) - assert.NoError(t, err) - client := getWebDavClient(user) - assert.NoError(t, checkBasicFunc(client)) - rootPath := fmt.Sprintf("http://%v/", webDavServerAddr) - httpClient := httpclient.GetHTTPClient() - httpClient.CheckRedirect = func(req *http.Request, via []*http.Request) error { - return errRedirect - } - req, err := http.NewRequest(http.MethodOptions, rootPath, nil) - assert.NoError(t, err) - req.SetBasicAuth(u.Username, u.Password) - resp, err := httpClient.Do(req) - if assert.Error(t, err) { - assert.Contains(t, err.Error(), errRedirect.Error()) - } - err = resp.Body.Close() - assert.NoError(t, err) - req, err = http.NewRequest(http.MethodGet, rootPath, nil) - assert.NoError(t, err) - req.SetBasicAuth(u.Username, u.Password) - resp, err = httpClient.Do(req) - if assert.Error(t, err) { - assert.Contains(t, err.Error(), errRedirect.Error()) - } - err = resp.Body.Close() - assert.NoError(t, err) - req, err = http.NewRequest("PROPFIND", rootPath, nil) - assert.NoError(t, err) - req.SetBasicAuth(u.Username, u.Password) - resp, err = httpClient.Do(req) - if assert.Error(t, err) { - assert.Contains(t, err.Error(), errRedirect.Error()) - } - err = resp.Body.Close() - assert.NoError(t, err) - - _, err = httpdtest.RemoveUser(user, http.StatusOK) - assert.NoError(t, err) -} - func TestLoginExternalAuth(t *testing.T) { if runtime.GOOS == osWindows { t.Skip("this test is not available on Windows") @@ -1275,7 +1212,7 @@ func TestBytesRangeRequests(t *testing.T) { client := getWebDavClient(user) err = uploadFile(testFilePath, testFileName, int64(len(fileContent)), client) assert.NoError(t, err) - remotePath := fmt.Sprintf("http://%v/%v/%v", webDavServerAddr, user.Username, testFileName) + remotePath := fmt.Sprintf("http://%v/%v", webDavServerAddr, testFileName) req, err := http.NewRequest(http.MethodGet, remotePath, nil) if assert.NoError(t, err) { httpClient := httpclient.GetHTTPClient() @@ -1318,7 +1255,7 @@ func TestHEAD(t *testing.T) { u := getTestUser() user, _, err := httpdtest.AddUser(u, http.StatusCreated) assert.NoError(t, err) - rootPath := fmt.Sprintf("http://%v/%v", webDavServerAddr, user.Username) + rootPath := fmt.Sprintf("http://%v", webDavServerAddr) httpClient := httpclient.GetHTTPClient() req, err := http.NewRequest(http.MethodHead, rootPath, nil) if assert.NoError(t, err) { @@ -1343,7 +1280,7 @@ func TestGETAsPROPFIND(t *testing.T) { u.Permissions[subDir1] = []string{dataprovider.PermUpload, dataprovider.PermCreateDirs} user, _, err := httpdtest.AddUser(u, http.StatusCreated) assert.NoError(t, err) - rootPath := fmt.Sprintf("http://%v/%v", webDavServerAddr, user.Username) + rootPath := fmt.Sprintf("http://%v/", webDavServerAddr) httpClient := httpclient.GetHTTPClient() req, err := http.NewRequest(http.MethodGet, rootPath, nil) if assert.NoError(t, err) { @@ -1357,7 +1294,7 @@ func TestGETAsPROPFIND(t *testing.T) { client := getWebDavClient(user) err = client.MkdirAll(path.Join(subDir1, "sub", "sub1"), os.ModePerm) assert.NoError(t, err) - subPath := fmt.Sprintf("http://%v/%v", webDavServerAddr, path.Join(user.Username, subDir1)) + subPath := fmt.Sprintf("http://%v/%v", webDavServerAddr, subDir1) req, err = http.NewRequest(http.MethodGet, subPath, nil) if assert.NoError(t, err) { req.SetBasicAuth(u.Username, u.Password) @@ -1370,7 +1307,7 @@ func TestGETAsPROPFIND(t *testing.T) { } } // we cannot stat the sub at all - subPath1 := fmt.Sprintf("http://%v/%v", webDavServerAddr, path.Join(user.Username, subDir1, "sub")) + subPath1 := fmt.Sprintf("http://%v/%v", webDavServerAddr, path.Join(subDir1, "sub")) req, err = http.NewRequest(http.MethodGet, subPath1, nil) if assert.NoError(t, err) { req.SetBasicAuth(u.Username, u.Password) @@ -1622,7 +1559,7 @@ func downloadFile(remoteSourcePath string, localDestPath string, expectedSize in } func getWebDavClient(user dataprovider.User) *gowebdav.Client { - rootPath := fmt.Sprintf("http://%v/%v", webDavServerAddr, user.Username) + rootPath := fmt.Sprintf("http://%v/", webDavServerAddr) pwd := defaultPassword if len(user.Password) > 0 { pwd = user.Password