mirror of
https://github.com/drakkan/sftpgo.git
synced 2025-12-09 16:25:15 +03:00
add hide policy to pattern filters
Disallowed files/dirs can be completly hidden. This may cause performance issues for large directories Signed-off-by: Nicola Murino <nicola.murino@gmail.com>
This commit is contained in:
@@ -92,7 +92,7 @@ func createUserDir(w http.ResponseWriter, r *http.Request) {
|
||||
return
|
||||
}
|
||||
}
|
||||
err = connection.CreateDir(name)
|
||||
err = connection.CreateDir(name, true)
|
||||
if err != nil {
|
||||
sendAPIResponse(w, r, err, fmt.Sprintf("Unable to create directory %#v", name), getMappedStatusCode(err))
|
||||
return
|
||||
|
||||
@@ -66,7 +66,7 @@ func (c *Connection) Stat(name string, mode int) (os.FileInfo, error) {
|
||||
return nil, c.GetPermissionDeniedError()
|
||||
}
|
||||
|
||||
fi, err := c.DoStat(name, mode)
|
||||
fi, err := c.DoStat(name, mode, true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -89,9 +89,9 @@ func (c *Connection) getFileReader(name string, offset int64, method string) (io
|
||||
return nil, c.GetPermissionDeniedError()
|
||||
}
|
||||
|
||||
if !c.User.IsFileAllowed(name) {
|
||||
if ok, policy := c.User.IsFileAllowed(name); !ok {
|
||||
c.Log(logger.LevelWarn, "reading file %#v is not allowed", name)
|
||||
return nil, c.GetPermissionDeniedError()
|
||||
return nil, c.GetErrorForDeniedFile(policy)
|
||||
}
|
||||
|
||||
fs, p, err := c.GetFsAndResolvedPath(name)
|
||||
@@ -120,7 +120,7 @@ func (c *Connection) getFileReader(name string, offset int64, method string) (io
|
||||
func (c *Connection) getFileWriter(name string) (io.WriteCloser, error) {
|
||||
c.UpdateLastActivity()
|
||||
|
||||
if !c.User.IsFileAllowed(name) {
|
||||
if ok, _ := c.User.IsFileAllowed(name); !ok {
|
||||
c.Log(logger.LevelWarn, "writing file %#v is not allowed", name)
|
||||
return nil, c.GetPermissionDeniedError()
|
||||
}
|
||||
|
||||
@@ -1482,6 +1482,15 @@ func TestAddUserInvalidFilters(t *testing.T) {
|
||||
}
|
||||
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
||||
assert.NoError(t, err)
|
||||
u.Filters.FilePatterns = []sdk.PatternsFilter{
|
||||
{
|
||||
Path: "/subdir",
|
||||
AllowedPatterns: []string{"*.*"},
|
||||
DenyPolicy: 100,
|
||||
},
|
||||
}
|
||||
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
||||
assert.NoError(t, err)
|
||||
u.Filters.DeniedProtocols = []string{"invalid"}
|
||||
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
||||
assert.NoError(t, err)
|
||||
@@ -2087,6 +2096,7 @@ func TestUpdateUser(t *testing.T) {
|
||||
Path: "/subdir",
|
||||
AllowedPatterns: []string{"*.zip", "*.rar"},
|
||||
DeniedPatterns: []string{"*.jpg", "*.png"},
|
||||
DenyPolicy: sdk.DenyPolicyHide,
|
||||
})
|
||||
user.Filters.MaxUploadFileSize = 4096
|
||||
user.UploadBandwidth = 1024
|
||||
@@ -13061,6 +13071,7 @@ func TestWebUserAddMock(t *testing.T) {
|
||||
form.Set("pattern_path0", "/dir2")
|
||||
form.Set("patterns0", "*.jpg,*.png")
|
||||
form.Set("pattern_type0", "allowed")
|
||||
form.Set("pattern_policy0", "1")
|
||||
form.Set("pattern_path1", "/dir1")
|
||||
form.Set("patterns1", "*.png")
|
||||
form.Set("pattern_type1", "allowed")
|
||||
@@ -13294,23 +13305,25 @@ func TestWebUserAddMock(t *testing.T) {
|
||||
}
|
||||
assert.Len(t, newUser.Filters.FilePatterns, 3)
|
||||
for _, filter := range newUser.Filters.FilePatterns {
|
||||
if filter.Path == "/dir1" {
|
||||
switch filter.Path {
|
||||
case "/dir1":
|
||||
assert.Len(t, filter.DeniedPatterns, 1)
|
||||
assert.Len(t, filter.AllowedPatterns, 1)
|
||||
assert.True(t, util.IsStringInSlice("*.png", filter.AllowedPatterns))
|
||||
assert.True(t, util.IsStringInSlice("*.zip", filter.DeniedPatterns))
|
||||
}
|
||||
if filter.Path == "/dir2" {
|
||||
assert.Equal(t, sdk.DenyPolicyDefault, filter.DenyPolicy)
|
||||
case "/dir2":
|
||||
assert.Len(t, filter.DeniedPatterns, 1)
|
||||
assert.Len(t, filter.AllowedPatterns, 2)
|
||||
assert.True(t, util.IsStringInSlice("*.jpg", filter.AllowedPatterns))
|
||||
assert.True(t, util.IsStringInSlice("*.png", filter.AllowedPatterns))
|
||||
assert.True(t, util.IsStringInSlice("*.mkv", filter.DeniedPatterns))
|
||||
}
|
||||
if filter.Path == "/dir3" {
|
||||
assert.Equal(t, sdk.DenyPolicyHide, filter.DenyPolicy)
|
||||
case "/dir3":
|
||||
assert.Len(t, filter.DeniedPatterns, 1)
|
||||
assert.Len(t, filter.AllowedPatterns, 0)
|
||||
assert.True(t, util.IsStringInSlice("*.rar", filter.DeniedPatterns))
|
||||
assert.Equal(t, sdk.DenyPolicyDefault, filter.DenyPolicy)
|
||||
}
|
||||
}
|
||||
if assert.Len(t, newUser.Filters.BandwidthLimits, 2) {
|
||||
@@ -14140,9 +14153,11 @@ func TestWebUserS3Mock(t *testing.T) {
|
||||
form.Set("pattern_path0", "/dir1")
|
||||
form.Set("patterns0", "*.jpg,*.png")
|
||||
form.Set("pattern_type0", "allowed")
|
||||
form.Set("pattern_policy0", "0")
|
||||
form.Set("pattern_path1", "/dir2")
|
||||
form.Set("patterns1", "*.zip")
|
||||
form.Set("pattern_type1", "denied")
|
||||
form.Set("pattern_policy1", "1")
|
||||
form.Set("max_upload_file_size", "0")
|
||||
form.Set("s3_force_path_style", "checked")
|
||||
form.Set("description", user.Description)
|
||||
@@ -14221,7 +14236,16 @@ func TestWebUserS3Mock(t *testing.T) {
|
||||
assert.Equal(t, updateUser.FsConfig.S3Config.DownloadPartSize, user.FsConfig.S3Config.DownloadPartSize)
|
||||
assert.Equal(t, updateUser.FsConfig.S3Config.DownloadConcurrency, user.FsConfig.S3Config.DownloadConcurrency)
|
||||
assert.True(t, updateUser.FsConfig.S3Config.ForcePathStyle)
|
||||
assert.Equal(t, 2, len(updateUser.Filters.FilePatterns))
|
||||
if assert.Equal(t, 2, len(updateUser.Filters.FilePatterns)) {
|
||||
for _, filter := range updateUser.Filters.FilePatterns {
|
||||
switch filter.Path {
|
||||
case "/dir1":
|
||||
assert.Equal(t, sdk.DenyPolicyDefault, filter.DenyPolicy)
|
||||
case "/dir2":
|
||||
assert.Equal(t, sdk.DenyPolicyHide, filter.DenyPolicy)
|
||||
}
|
||||
}
|
||||
}
|
||||
assert.Equal(t, sdkkms.SecretStatusSecretBox, updateUser.FsConfig.S3Config.AccessSecret.GetStatus())
|
||||
assert.NotEmpty(t, updateUser.FsConfig.S3Config.AccessSecret.GetPayload())
|
||||
assert.Empty(t, updateUser.FsConfig.S3Config.AccessSecret.GetKey())
|
||||
|
||||
@@ -797,11 +797,20 @@ func getBandwidthLimitsFromPostFields(r *http.Request) ([]sdk.BandwidthLimit, er
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func getPatterDenyPolicyFromString(policy string) int {
|
||||
denyPolicy := sdk.DenyPolicyDefault
|
||||
if policy == "1" {
|
||||
denyPolicy = sdk.DenyPolicyHide
|
||||
}
|
||||
return denyPolicy
|
||||
}
|
||||
|
||||
func getFilePatternsFromPostField(r *http.Request) []sdk.PatternsFilter {
|
||||
var result []sdk.PatternsFilter
|
||||
|
||||
allowedPatterns := make(map[string][]string)
|
||||
deniedPatterns := make(map[string][]string)
|
||||
patternPolicies := make(map[string]string)
|
||||
|
||||
for k := range r.Form {
|
||||
if strings.HasPrefix(k, "pattern_path") {
|
||||
@@ -810,12 +819,16 @@ func getFilePatternsFromPostField(r *http.Request) []sdk.PatternsFilter {
|
||||
filters := strings.TrimSpace(r.Form.Get(fmt.Sprintf("patterns%v", idx)))
|
||||
filters = strings.ReplaceAll(filters, " ", "")
|
||||
patternType := r.Form.Get(fmt.Sprintf("pattern_type%v", idx))
|
||||
patternPolicy := r.Form.Get(fmt.Sprintf("pattern_policy%v", idx))
|
||||
if p != "" && filters != "" {
|
||||
if patternType == "allowed" {
|
||||
allowedPatterns[p] = append(allowedPatterns[p], strings.Split(filters, ",")...)
|
||||
} else {
|
||||
deniedPatterns[p] = append(deniedPatterns[p], strings.Split(filters, ",")...)
|
||||
}
|
||||
if patternPolicy != "" && patternPolicy != "0" {
|
||||
patternPolicies[p] = patternPolicy
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -823,11 +836,12 @@ func getFilePatternsFromPostField(r *http.Request) []sdk.PatternsFilter {
|
||||
for dirAllowed, allowPatterns := range allowedPatterns {
|
||||
filter := sdk.PatternsFilter{
|
||||
Path: dirAllowed,
|
||||
AllowedPatterns: util.RemoveDuplicates(allowPatterns),
|
||||
AllowedPatterns: allowPatterns,
|
||||
DenyPolicy: getPatterDenyPolicyFromString(patternPolicies[dirAllowed]),
|
||||
}
|
||||
for dirDenied, denPatterns := range deniedPatterns {
|
||||
if dirAllowed == dirDenied {
|
||||
filter.DeniedPatterns = util.RemoveDuplicates(denPatterns)
|
||||
filter.DeniedPatterns = denPatterns
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -845,6 +859,7 @@ func getFilePatternsFromPostField(r *http.Request) []sdk.PatternsFilter {
|
||||
result = append(result, sdk.PatternsFilter{
|
||||
Path: dirDenied,
|
||||
DeniedPatterns: denPatterns,
|
||||
DenyPolicy: getPatterDenyPolicyFromString(patternPolicies[dirDenied]),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user