enforce permissions on all paths, use system user/group
- fileOwnerGroup: session internals owned by agent/agent,
everything else by current system user and primary group
- checkPerm: always enforce, remove no-enforcement bypass
- Directory modes: /s/{sid}=755, /s/{sid}/t=500, /s=755,
/u,/x=555, /p=664, /a=744, /sk=754, /tmp=777, /tr=766
- File modes: /p/=664, /sk/=664, /s/{sid}/t/*=500
- Session store: sh=550, b/bfg/bbg=555
This commit is contained in:
parent
629a841cf5
commit
000ad64673
47
server.go
47
server.go
|
|
@ -9,6 +9,7 @@ import (
|
|||
"io"
|
||||
"net"
|
||||
"os"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
|
@ -331,32 +332,32 @@ func (s *Server) InGroup(group, user string) bool {
|
|||
}
|
||||
|
||||
// fileOwnerGroup returns the uid and gid for a given path.
|
||||
// Session files are owned by the session's principal with group "agent".
|
||||
// Prompt library (/p/) is owned by "ollie" with group "user".
|
||||
// Everything else is owned by "ollie" with group "ollie".
|
||||
// Session namespace (/s/{sid}/**) is owned by the agent principal with group "agent".
|
||||
// Everything else is owned by the current system user and their primary group.
|
||||
func (s *Server) fileOwnerGroup(path string) (uid, gid string) {
|
||||
if strings.HasPrefix(path, "/s/") {
|
||||
parts := strings.SplitN(strings.TrimPrefix(path, "/s/"), "/", 2)
|
||||
if len(parts) >= 1 && parts[0] != "new" {
|
||||
if len(parts) >= 1 && parts[0] != "new" && !isSessionStoreFile(path) {
|
||||
if sess := s.sessionStore.Session(parts[0]); sess != nil {
|
||||
return sess.Uname(), "agent"
|
||||
}
|
||||
}
|
||||
}
|
||||
if path == "/p" || strings.HasPrefix(path, "/p/") {
|
||||
return "ollie", "user"
|
||||
if u, err := user.Current(); err == nil {
|
||||
gid := u.Gid
|
||||
if g, err := user.LookupGroupId(u.Gid); err == nil {
|
||||
gid = g.Name
|
||||
}
|
||||
return u.Username, gid
|
||||
}
|
||||
return "ollie", "ollie"
|
||||
}
|
||||
|
||||
// checkPerm verifies that uname has the requested access (mode) to path.
|
||||
// mode is the 9P open mode: OREAD=0, OWRITE=1, ORDWR=2, OEXEC=3.
|
||||
// Enforced on session files and group-restricted paths (e.g. /p/).
|
||||
// Enforced on all paths.
|
||||
func (s *Server) checkPerm(uname, path string, mode uint8) error {
|
||||
uid, gid := s.fileOwnerGroup(path)
|
||||
if uid == "ollie" && gid == "ollie" {
|
||||
return nil // no enforcement
|
||||
}
|
||||
dir := s.makeStat(path)
|
||||
perm := uint32(dir.Mode) & 0777
|
||||
|
||||
|
|
@ -1641,14 +1642,26 @@ func (s *Server) makeStat(path string) plan9.Dir {
|
|||
if strings.HasPrefix(path, "/s/") {
|
||||
parts := strings.SplitN(strings.TrimPrefix(path, "/s/"), "/", 3)
|
||||
if (len(parts) == 2 && parts[1] == "t") || (len(parts) == 3 && parts[1] == "t") {
|
||||
mode = plan9.DMDIR | 0700
|
||||
mode = plan9.DMDIR | 0500 // rx owner only
|
||||
} else {
|
||||
mode = plan9.DMDIR | 0555
|
||||
mode = plan9.DMDIR | 0755
|
||||
}
|
||||
} else if path == "/a" || path == "/m" || path == "/tmp" || path == "/u" {
|
||||
} else if path == "/s" {
|
||||
mode = plan9.DMDIR | 0755
|
||||
} else {
|
||||
} else if path == "/u" || path == "/x" {
|
||||
mode = plan9.DMDIR | 0555
|
||||
} else if path == "/p" {
|
||||
mode = plan9.DMDIR | 0664
|
||||
} else if path == "/a" {
|
||||
mode = plan9.DMDIR | 0744
|
||||
} else if path == "/sk" {
|
||||
mode = plan9.DMDIR | 0754
|
||||
} else if path == "/tmp" {
|
||||
mode = plan9.DMDIR | 0777
|
||||
} else if path == "/tr" {
|
||||
mode = plan9.DMDIR | 0766
|
||||
} else {
|
||||
mode = plan9.DMDIR | 0755
|
||||
}
|
||||
} else {
|
||||
switch base {
|
||||
|
|
@ -1671,19 +1684,19 @@ func (s *Server) makeStat(path string) plan9.Dir {
|
|||
} else if strings.HasPrefix(path, "/a/") {
|
||||
mode = 0666
|
||||
} else if strings.HasPrefix(path, "/p/") {
|
||||
mode = 0640
|
||||
mode = 0664
|
||||
} else if strings.HasPrefix(path, "/m/") {
|
||||
mode = 0666
|
||||
} else if path == "/sk/idx" {
|
||||
mode = 0444
|
||||
} else if strings.HasPrefix(path, "/sk/") {
|
||||
mode = 0666
|
||||
mode = 0664
|
||||
} else if strings.HasPrefix(path, "/s/") {
|
||||
parts := strings.SplitN(strings.TrimPrefix(path, "/s/"), "/", 3)
|
||||
if len(parts) == 3 && parts[1] == "t" && parts[2] == "idx" {
|
||||
mode = 0400
|
||||
} else if len(parts) == 3 && parts[1] == "t" {
|
||||
mode = 0700
|
||||
mode = 0500
|
||||
} else {
|
||||
mode = 0444
|
||||
}
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ var sessionStoreFiles = map[string]os.FileMode{
|
|||
"idx": 0444,
|
||||
"ls": 0555,
|
||||
"kill": 0555,
|
||||
"sh": 0555,
|
||||
"sh": 0550,
|
||||
"b": 0555,
|
||||
"bfg": 0555,
|
||||
"bbg": 0555,
|
||||
|
|
|
|||
Reference in New Issue