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
49
server.go
49
server.go
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
|
"os/user"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
@ -331,32 +332,32 @@ func (s *Server) InGroup(group, user string) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
// fileOwnerGroup returns the uid and gid for a given path.
|
// fileOwnerGroup returns the uid and gid for a given path.
|
||||||
// Session files are owned by the session's principal with group "agent".
|
// Session namespace (/s/{sid}/**) is owned by the agent principal with group "agent".
|
||||||
// Prompt library (/p/) is owned by "ollie" with group "user".
|
// Everything else is owned by the current system user and their primary group.
|
||||||
// Everything else is owned by "ollie" with group "ollie".
|
|
||||||
func (s *Server) fileOwnerGroup(path string) (uid, gid string) {
|
func (s *Server) fileOwnerGroup(path string) (uid, gid string) {
|
||||||
if strings.HasPrefix(path, "/s/") {
|
if strings.HasPrefix(path, "/s/") {
|
||||||
parts := strings.SplitN(strings.TrimPrefix(path, "/s/"), "/", 2)
|
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 {
|
if sess := s.sessionStore.Session(parts[0]); sess != nil {
|
||||||
return sess.Uname(), "agent"
|
return sess.Uname(), "agent"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if path == "/p" || strings.HasPrefix(path, "/p/") {
|
if u, err := user.Current(); err == nil {
|
||||||
return "ollie", "user"
|
gid := u.Gid
|
||||||
|
if g, err := user.LookupGroupId(u.Gid); err == nil {
|
||||||
|
gid = g.Name
|
||||||
|
}
|
||||||
|
return u.Username, gid
|
||||||
}
|
}
|
||||||
return "ollie", "ollie"
|
return "ollie", "ollie"
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkPerm verifies that uname has the requested access (mode) to path.
|
// 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.
|
// 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 {
|
func (s *Server) checkPerm(uname, path string, mode uint8) error {
|
||||||
uid, gid := s.fileOwnerGroup(path)
|
uid, gid := s.fileOwnerGroup(path)
|
||||||
if uid == "ollie" && gid == "ollie" {
|
|
||||||
return nil // no enforcement
|
|
||||||
}
|
|
||||||
dir := s.makeStat(path)
|
dir := s.makeStat(path)
|
||||||
perm := uint32(dir.Mode) & 0777
|
perm := uint32(dir.Mode) & 0777
|
||||||
|
|
||||||
|
|
@ -1641,14 +1642,26 @@ func (s *Server) makeStat(path string) plan9.Dir {
|
||||||
if strings.HasPrefix(path, "/s/") {
|
if strings.HasPrefix(path, "/s/") {
|
||||||
parts := strings.SplitN(strings.TrimPrefix(path, "/s/"), "/", 3)
|
parts := strings.SplitN(strings.TrimPrefix(path, "/s/"), "/", 3)
|
||||||
if (len(parts) == 2 && parts[1] == "t") || (len(parts) == 3 && parts[1] == "t") {
|
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 {
|
} else {
|
||||||
mode = plan9.DMDIR | 0555
|
|
||||||
}
|
|
||||||
} else if path == "/a" || path == "/m" || path == "/tmp" || path == "/u" {
|
|
||||||
mode = plan9.DMDIR | 0755
|
mode = plan9.DMDIR | 0755
|
||||||
} else {
|
}
|
||||||
|
} else if path == "/s" {
|
||||||
|
mode = plan9.DMDIR | 0755
|
||||||
|
} else if path == "/u" || path == "/x" {
|
||||||
mode = plan9.DMDIR | 0555
|
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 {
|
} else {
|
||||||
switch base {
|
switch base {
|
||||||
|
|
@ -1671,19 +1684,19 @@ func (s *Server) makeStat(path string) plan9.Dir {
|
||||||
} else if strings.HasPrefix(path, "/a/") {
|
} else if strings.HasPrefix(path, "/a/") {
|
||||||
mode = 0666
|
mode = 0666
|
||||||
} else if strings.HasPrefix(path, "/p/") {
|
} else if strings.HasPrefix(path, "/p/") {
|
||||||
mode = 0640
|
mode = 0664
|
||||||
} else if strings.HasPrefix(path, "/m/") {
|
} else if strings.HasPrefix(path, "/m/") {
|
||||||
mode = 0666
|
mode = 0666
|
||||||
} else if path == "/sk/idx" {
|
} else if path == "/sk/idx" {
|
||||||
mode = 0444
|
mode = 0444
|
||||||
} else if strings.HasPrefix(path, "/sk/") {
|
} else if strings.HasPrefix(path, "/sk/") {
|
||||||
mode = 0666
|
mode = 0664
|
||||||
} else if strings.HasPrefix(path, "/s/") {
|
} else if strings.HasPrefix(path, "/s/") {
|
||||||
parts := strings.SplitN(strings.TrimPrefix(path, "/s/"), "/", 3)
|
parts := strings.SplitN(strings.TrimPrefix(path, "/s/"), "/", 3)
|
||||||
if len(parts) == 3 && parts[1] == "t" && parts[2] == "idx" {
|
if len(parts) == 3 && parts[1] == "t" && parts[2] == "idx" {
|
||||||
mode = 0400
|
mode = 0400
|
||||||
} else if len(parts) == 3 && parts[1] == "t" {
|
} else if len(parts) == 3 && parts[1] == "t" {
|
||||||
mode = 0700
|
mode = 0500
|
||||||
} else {
|
} else {
|
||||||
mode = 0444
|
mode = 0444
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -83,7 +83,7 @@ var sessionStoreFiles = map[string]os.FileMode{
|
||||||
"idx": 0444,
|
"idx": 0444,
|
||||||
"ls": 0555,
|
"ls": 0555,
|
||||||
"kill": 0555,
|
"kill": 0555,
|
||||||
"sh": 0555,
|
"sh": 0550,
|
||||||
"b": 0555,
|
"b": 0555,
|
||||||
"bfg": 0555,
|
"bfg": 0555,
|
||||||
"bbg": 0555,
|
"bbg": 0555,
|
||||||
|
|
|
||||||
Reference in New Issue