Browse Source

pattern filters: don't allow files in hidden dirs

Signed-off-by: Nicola Murino <[email protected]>
Nicola Murino 3 years ago
parent
commit
a6ed6fc721
2 changed files with 38 additions and 2 deletions
  1. 15 1
      common/protocol_test.go
  2. 23 1
      dataprovider/user.go

+ 15 - 1
common/protocol_test.go

@@ -496,15 +496,19 @@ func TestHiddenPatternFilter(t *testing.T) {
 	assert.NoError(t, err)
 
 	dirName := "beta"
+	subDirName := "testDir"
 	testFile := filepath.Join(u.GetHomeDir(), deniedDir, "file.txt")
 	testFile1 := filepath.Join(u.GetHomeDir(), deniedDir, "beta.txt")
+	testHiddenFile := filepath.Join(u.GetHomeDir(), deniedDir, dirName, subDirName, "hidden.jpg")
 	err = os.MkdirAll(filepath.Join(u.GetHomeDir(), deniedDir), os.ModePerm)
 	assert.NoError(t, err)
 	err = os.WriteFile(testFile, testFileContent, os.ModePerm)
 	assert.NoError(t, err)
 	err = os.WriteFile(testFile1, testFileContent, os.ModePerm)
 	assert.NoError(t, err)
-	err = os.MkdirAll(filepath.Join(u.GetHomeDir(), deniedDir, dirName), os.ModePerm)
+	err = os.MkdirAll(filepath.Join(u.GetHomeDir(), deniedDir, dirName, subDirName), os.ModePerm)
+	assert.NoError(t, err)
+	err = os.WriteFile(testHiddenFile, testFileContent, os.ModePerm)
 	assert.NoError(t, err)
 
 	conn, client, err := getSftpClient(user)
@@ -529,6 +533,10 @@ func TestHiddenPatternFilter(t *testing.T) {
 		assert.ErrorIs(t, err, os.ErrPermission)
 		err = writeSFTPFile(path.Join(deniedDir, "afile.txt"), 1024, client)
 		assert.ErrorIs(t, err, os.ErrPermission)
+		err = writeSFTPFile(path.Join(deniedDir, dirName, subDirName, "afile.jpg"), 1024, client)
+		assert.ErrorIs(t, err, os.ErrPermission)
+		_, err = client.Open(path.Join(deniedDir, dirName, subDirName, filepath.Base(testHiddenFile)))
+		assert.ErrorIs(t, err, os.ErrNotExist)
 		err = client.Symlink(path.Join(deniedDir, dirName), dirName)
 		assert.ErrorIs(t, err, os.ErrNotExist)
 		err = writeSFTPFile(path.Join(deniedDir, testFileName), 1024, client)
@@ -568,6 +576,12 @@ func TestHiddenPatternFilter(t *testing.T) {
 		assert.ErrorIs(t, err, os.ErrPermission)
 		err = client.Symlink(path.Join(deniedDir, testFileName), path.Join(deniedDir, "link.txt"))
 		assert.ErrorIs(t, err, os.ErrPermission)
+		err = writeSFTPFile(path.Join(deniedDir, dirName, subDirName, "afile.jpg"), 1024, client)
+		assert.NoError(t, err)
+		f, err := client.Open(path.Join(deniedDir, dirName, subDirName, filepath.Base(testHiddenFile)))
+		assert.NoError(t, err)
+		err = f.Close()
+		assert.NoError(t, err)
 	}
 
 	_, err = httpdtest.RemoveUser(user, http.StatusOK)

+ 23 - 1
dataprovider/user.go

@@ -854,10 +854,32 @@ func (u *User) getPatternsFilterForPath(virtualPath string) sdk.PatternsFilter {
 	return filter
 }
 
+func (u *User) isDirHidden(virtualPath string) bool {
+	if len(u.Filters.FilePatterns) == 0 {
+		return false
+	}
+	for _, dirPath := range util.GetDirsForVirtualPath(virtualPath) {
+		if dirPath == "/" {
+			return false
+		}
+		filter := u.getPatternsFilterForPath(dirPath)
+		if filter.DenyPolicy == sdk.DenyPolicyHide {
+			if !filter.CheckAllowed(path.Base(dirPath)) {
+				return true
+			}
+		}
+	}
+	return false
+}
+
 // IsFileAllowed returns true if the specified file is allowed by the file restrictions filters.
 // The second parameter returned is the deny policy
 func (u *User) IsFileAllowed(virtualPath string) (bool, int) {
-	filter := u.getPatternsFilterForPath(path.Dir(virtualPath))
+	dirPath := path.Dir(virtualPath)
+	if u.isDirHidden(dirPath) {
+		return false, sdk.DenyPolicyHide
+	}
+	filter := u.getPatternsFilterForPath(dirPath)
 	return filter.CheckAllowed(path.Base(virtualPath)), filter.DenyPolicy
 }