mirror of
https://github.com/mickael-kerjean/filestash.git
synced 2025-11-02 11:57:04 +08:00
feature (nfs): 16 group limit sorting
This commit is contained in:
@ -19,13 +19,13 @@ func init() {
|
||||
cacheForGroup = NewAppCache(120, 60)
|
||||
}
|
||||
|
||||
func extractUserInfo(uidHint string, gidHint string, gidsHint string) (uint32, uint32, []uint32) {
|
||||
func extractUserInfo(uidHint string, gidHint string, gidsHint string) (uint32, uint32, []groupLabel) {
|
||||
// case 1: everything is being sent as "uid=number, gid=number and gids=number,number,number"
|
||||
if _uid, err := strconv.Atoi(uidHint); err == nil {
|
||||
var (
|
||||
uid uint32 = uint32(_uid)
|
||||
gid uint32
|
||||
gids []uint32
|
||||
gids []groupLabel
|
||||
)
|
||||
if _gid, err := strconv.Atoi(gidHint); err == nil {
|
||||
gid = uint32(_gid)
|
||||
@ -33,8 +33,9 @@ func extractUserInfo(uidHint string, gidHint string, gidsHint string) (uint32, u
|
||||
gid = uid
|
||||
}
|
||||
for _, t := range strings.Split(gidsHint, ",") {
|
||||
if gid, err := strconv.Atoi(strings.TrimSpace(t)); err == nil {
|
||||
gids = append(gids, uint32(gid))
|
||||
tmp := strings.TrimSpace(t)
|
||||
if gid, err := strconv.Atoi(tmp); err == nil {
|
||||
gids = append(gids, groupLabel{uint32(gid), tmp, 0})
|
||||
}
|
||||
}
|
||||
return uid, gid, gids
|
||||
@ -44,7 +45,7 @@ func extractUserInfo(uidHint string, gidHint string, gidsHint string) (uint32, u
|
||||
return _uid, _gid, extractFromEtcGroup(uidHint, _gid)
|
||||
}
|
||||
// case 3: base case
|
||||
return 0, 0, []uint32{}
|
||||
return 0, 0, []groupLabel{}
|
||||
}
|
||||
|
||||
func extractFromEtcPasswd(username string) (uint32, uint32, error) {
|
||||
@ -83,16 +84,22 @@ func extractFromEtcPasswd(username string) (uint32, uint32, error) {
|
||||
return 0, 0, ErrNotFound
|
||||
}
|
||||
|
||||
func extractFromEtcGroup(username string, primary uint32) []uint32 {
|
||||
type groupLabel struct {
|
||||
id uint32
|
||||
label string
|
||||
priority int
|
||||
}
|
||||
|
||||
func extractFromEtcGroup(username string, primary uint32) []groupLabel {
|
||||
if v := cacheForGroup.Get(map[string]string{"username": username}); v != nil {
|
||||
return v.([]uint32)
|
||||
return v.([]groupLabel)
|
||||
}
|
||||
f, err := os.OpenFile("/etc/group", os.O_RDONLY, os.ModePerm)
|
||||
if err != nil {
|
||||
return []uint32{}
|
||||
return []groupLabel{}
|
||||
}
|
||||
defer f.Close()
|
||||
gids := []uint32{}
|
||||
gids := []groupLabel{}
|
||||
lines := bufio.NewReader(f)
|
||||
for {
|
||||
line, _, err := lines.ReadLine()
|
||||
@ -116,7 +123,7 @@ func extractFromEtcGroup(username string, primary uint32) []uint32 {
|
||||
if gid, err := strconv.Atoi(s[2]); err == nil {
|
||||
ugid := uint32(gid)
|
||||
if ugid != primary {
|
||||
gids = append(gids, ugid)
|
||||
gids = append(gids, groupLabel{ugid, s[0], 0})
|
||||
}
|
||||
}
|
||||
cacheForGroup.Set(map[string]string{"username": username}, gids)
|
||||
|
||||
@ -3,6 +3,8 @@ package plg_backend_nfs
|
||||
import (
|
||||
"bytes"
|
||||
"math/rand"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/vmware/go-nfs-client/nfs/rpc"
|
||||
@ -21,17 +23,34 @@ type AuthUnix struct {
|
||||
}
|
||||
|
||||
// ref: RFC5531 - page25
|
||||
func NewAuthUnix(machineName string, uid, gid uint32, gids []uint32) rpc.Auth {
|
||||
func NewAuthUnix(machineName string, uid, gid uint32, gids []groupLabel, gidsHint string) rpc.Auth {
|
||||
w := new(bytes.Buffer)
|
||||
if len(gids) > 16 { // limit of NFS in AUTH_UNIX
|
||||
gids = gids[len(gids)-16 : len(gids)]
|
||||
if len(gids) > 16 { // https://www.rfc-editor.org/rfc/rfc5531.html#page-25
|
||||
// when the limit of AUTH_UNIX is reached, we want to filter out the
|
||||
// groups that are of less of importance
|
||||
for i, _ := range gids {
|
||||
score := 0
|
||||
for _, h := range strings.Split(gidsHint, ",") {
|
||||
if strings.Contains(gids[i].label, strings.TrimSpace(h)) {
|
||||
score += 1
|
||||
}
|
||||
}
|
||||
gids[i].priority = score
|
||||
}
|
||||
sort.Slice(gids, func(i, j int) bool {
|
||||
return gids[i].priority > gids[j].priority
|
||||
})
|
||||
gids = gids[0:16]
|
||||
sort.Slice(gids, func(i, j int) bool {
|
||||
return gids[i].id < gids[j].id
|
||||
})
|
||||
}
|
||||
xdr.Write(w, AuthUnix{
|
||||
Stamp: rand.New(rand.NewSource(time.Now().UnixNano())).Uint32(),
|
||||
Machinename: machineName,
|
||||
Uid: uid,
|
||||
Gid: gid,
|
||||
Gids: gids,
|
||||
Gids: toGids(gids),
|
||||
})
|
||||
return rpc.Auth{
|
||||
1, // = AUTH_SYS in RFC5531
|
||||
|
||||
@ -44,7 +44,7 @@ func (this NfsShare) Init(params map[string]string, app *App) (IBackend, error)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
auth := NewAuthUnix(params["machine_name"], uid, gid, gids)
|
||||
auth := NewAuthUnix(params["machine_name"], uid, gid, gids, params["gids"])
|
||||
v, err := mount.Mount(
|
||||
params["target"],
|
||||
auth,
|
||||
@ -52,7 +52,15 @@ func (this NfsShare) Init(params map[string]string, app *App) (IBackend, error)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NfsShare{mount, v, auth, app.Context, uid, gid, gids}, nil
|
||||
return NfsShare{mount, v, auth, app.Context, uid, gid, toGids(gids)}, nil
|
||||
}
|
||||
|
||||
func toGids(gids []groupLabel) []uint32 {
|
||||
g := make([]uint32, len(gids))
|
||||
for _, gid := range gids {
|
||||
g = append(g, gid.id)
|
||||
}
|
||||
return g
|
||||
}
|
||||
|
||||
func (this NfsShare) LoginForm() Form {
|
||||
|
||||
Reference in New Issue
Block a user