mirror of
https://github.com/drakkan/sftpgo.git
synced 2025-11-23 22:04:50 +02:00
subdir perms: allow empty perms
empty perms will allow nothing on the specified subdir. Non empty permissions for the "/" dir are still required. Fixes #70
This commit is contained in:
@@ -505,7 +505,7 @@ func validatePermissions(user *User) error {
|
|||||||
return &ValidationError{err: fmt.Sprintf("permissions for the root dir \"/\" must be set")}
|
return &ValidationError{err: fmt.Sprintf("permissions for the root dir \"/\" must be set")}
|
||||||
}
|
}
|
||||||
for dir, perms := range user.Permissions {
|
for dir, perms := range user.Permissions {
|
||||||
if len(perms) == 0 {
|
if len(perms) == 0 && dir == "/" {
|
||||||
return &ValidationError{err: fmt.Sprintf("no permissions granted for the directory: %#v", dir)}
|
return &ValidationError{err: fmt.Sprintf("no permissions granted for the directory: %#v", dir)}
|
||||||
}
|
}
|
||||||
for _, p := range perms {
|
for _, p := range perms {
|
||||||
@@ -520,6 +520,9 @@ func validatePermissions(user *User) error {
|
|||||||
if !path.IsAbs(cleanedDir) {
|
if !path.IsAbs(cleanedDir) {
|
||||||
return &ValidationError{err: fmt.Sprintf("cannot set permissions for non absolute path: %#v", dir)}
|
return &ValidationError{err: fmt.Sprintf("cannot set permissions for non absolute path: %#v", dir)}
|
||||||
}
|
}
|
||||||
|
if dir != cleanedDir && cleanedDir == "/" {
|
||||||
|
return &ValidationError{err: fmt.Sprintf("cannot set permissions for invalid subdirectory: %#v is an alias for \"/\"", dir)}
|
||||||
|
}
|
||||||
if utils.IsStringInSlice(PermAny, perms) {
|
if utils.IsStringInSlice(PermAny, perms) {
|
||||||
permissions[cleanedDir] = []string{PermAny}
|
permissions[cleanedDir] = []string{PermAny}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -285,11 +285,18 @@ func TestAddUserInvalidPerms(t *testing.T) {
|
|||||||
t.Errorf("unexpected error adding user with invalid perms: %v", err)
|
t.Errorf("unexpected error adding user with invalid perms: %v", err)
|
||||||
}
|
}
|
||||||
// permissions for root dir are mandatory
|
// permissions for root dir are mandatory
|
||||||
|
u.Permissions["/"] = []string{}
|
||||||
u.Permissions["/somedir"] = []string{dataprovider.PermAny}
|
u.Permissions["/somedir"] = []string{dataprovider.PermAny}
|
||||||
_, _, err = httpd.AddUser(u, http.StatusBadRequest)
|
_, _, err = httpd.AddUser(u, http.StatusBadRequest)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unexpected error adding user with no root dir perms: %v", err)
|
t.Errorf("unexpected error adding user with no root dir perms: %v", err)
|
||||||
}
|
}
|
||||||
|
u.Permissions["/"] = []string{dataprovider.PermAny}
|
||||||
|
u.Permissions["/subdir/.."] = []string{dataprovider.PermAny}
|
||||||
|
_, _, err = httpd.AddUser(u, http.StatusBadRequest)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unexpected error adding user with invalid dir perms: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAddUserInvalidFilters(t *testing.T) {
|
func TestAddUserInvalidFilters(t *testing.T) {
|
||||||
@@ -407,6 +414,14 @@ func TestUpdateUser(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unable to update user: %v", err)
|
t.Errorf("unable to update user: %v", err)
|
||||||
}
|
}
|
||||||
|
user.Permissions["/subdir"] = []string{}
|
||||||
|
user, _, err = httpd.UpdateUser(user, http.StatusOK)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("unable to update user: %v", err)
|
||||||
|
}
|
||||||
|
if len(user.Permissions["/subdir"]) > 0 {
|
||||||
|
t.Errorf("unexpected subdir permissions, must be empty")
|
||||||
|
}
|
||||||
_, err = httpd.RemoveUser(user, http.StatusOK)
|
_, err = httpd.RemoveUser(user, http.StatusOK)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("unable to remove: %v", err)
|
t.Errorf("unable to remove: %v", err)
|
||||||
@@ -1136,12 +1151,18 @@ func TestUserPermissionsMock(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("Error get user: %v", err)
|
t.Errorf("Error get user: %v", err)
|
||||||
}
|
}
|
||||||
user.Permissions["/somedir"] = []string{}
|
user.Permissions["/somedir"] = []string{"invalid"}
|
||||||
userAsJSON = getUserAsJSON(t, user)
|
userAsJSON = getUserAsJSON(t, user)
|
||||||
req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(user.ID, 10), bytes.NewBuffer(userAsJSON))
|
req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(user.ID, 10), bytes.NewBuffer(userAsJSON))
|
||||||
rr = executeRequest(req)
|
rr = executeRequest(req)
|
||||||
checkResponseCode(t, http.StatusBadRequest, rr.Code)
|
checkResponseCode(t, http.StatusBadRequest, rr.Code)
|
||||||
delete(user.Permissions, "/somedir")
|
delete(user.Permissions, "/somedir")
|
||||||
|
user.Permissions["/somedir/.."] = []string{dataprovider.PermAny}
|
||||||
|
userAsJSON = getUserAsJSON(t, user)
|
||||||
|
req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(user.ID, 10), bytes.NewBuffer(userAsJSON))
|
||||||
|
rr = executeRequest(req)
|
||||||
|
checkResponseCode(t, http.StatusBadRequest, rr.Code)
|
||||||
|
delete(user.Permissions, "/somedir/..")
|
||||||
user.Permissions["not_abs_path"] = []string{dataprovider.PermAny}
|
user.Permissions["not_abs_path"] = []string{dataprovider.PermAny}
|
||||||
userAsJSON = getUserAsJSON(t, user)
|
userAsJSON = getUserAsJSON(t, user)
|
||||||
req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(user.ID, 10), bytes.NewBuffer(userAsJSON))
|
req, _ = http.NewRequest(http.MethodPut, userPath+"/"+strconv.FormatInt(user.ID, 10), bytes.NewBuffer(userAsJSON))
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ func getUserPermissionsFromPostFields(r *http.Request) map[string][]string {
|
|||||||
perms = append(perms, cleanedPerm)
|
perms = append(perms, cleanedPerm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(dir) > 0 && len(perms) > 0 {
|
if len(dir) > 0 {
|
||||||
permissions[dir] = perms
|
permissions[dir] = perms
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -111,7 +111,7 @@ class SFTPGoApiRequests:
|
|||||||
directory = value
|
directory = value
|
||||||
else:
|
else:
|
||||||
values = [v.strip() for v in value.split(',') if v.strip()]
|
values = [v.strip() for v in value.split(',') if v.strip()]
|
||||||
if directory and values:
|
if directory:
|
||||||
permissions.update({directory:values})
|
permissions.update({directory:values})
|
||||||
return permissions
|
return permissions
|
||||||
|
|
||||||
|
|||||||
@@ -3250,6 +3250,17 @@ func TestUserPerms(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUserEmptySubDirPerms(t *testing.T) {
|
||||||
|
user := getTestUser(true)
|
||||||
|
user.Permissions = make(map[string][]string)
|
||||||
|
user.Permissions["/emptyperms"] = []string{}
|
||||||
|
for _, p := range dataprovider.ValidPerms {
|
||||||
|
if user.HasPerm(p, "/emptyperms") {
|
||||||
|
t.Errorf("unexpected permission %#v for dir /emptyperms", p)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestUserFiltersIPMaskConditions(t *testing.T) {
|
func TestUserFiltersIPMaskConditions(t *testing.T) {
|
||||||
user := getTestUser(true)
|
user := getTestUser(true)
|
||||||
// with no filter login must be allowed even if the remoteIP is invalid
|
// with no filter login must be allowed even if the remoteIP is invalid
|
||||||
|
|||||||
Reference in New Issue
Block a user