feature (nfs): 16 group limit sorting

This commit is contained in:
MickaelK
2024-05-07 23:05:47 +10:00
parent 60f93f1cd8
commit 03603837a1
3 changed files with 50 additions and 16 deletions

View File

@ -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)

View File

@ -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

View File

@ -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 {