mirror of
https://github.com/netbirdio/netbird.git
synced 2026-08-07 02:28:53 -04:00
85 lines
1.9 KiB
Go
85 lines
1.9 KiB
Go
package ipcauth
|
|
|
|
import (
|
|
"slices"
|
|
"strconv"
|
|
)
|
|
|
|
// Ownership is a profile's access policy: the typed owner principals plus the
|
|
// opt-in shared flag.
|
|
type Ownership struct {
|
|
Owners []string
|
|
Shared bool
|
|
}
|
|
|
|
// GroupResolver resolves a Unix caller's effective group IDs and owner group
|
|
// names to GIDs. A nil resolver disables group matching.
|
|
type GroupResolver interface {
|
|
// CallerGIDs returns the set of group IDs the caller belongs to.
|
|
CallerGIDs(id Identity) map[uint32]struct{}
|
|
// GroupNameGID resolves a group name to its GID.
|
|
GroupNameGID(name string) (uint32, bool)
|
|
}
|
|
|
|
// Authorize reports whether the identity may control a profile with the given
|
|
// ownership. Privileged callers and shared profiles are always allowed.
|
|
func Authorize(o Ownership, id Identity, r GroupResolver) bool {
|
|
if id.IsPrivileged() {
|
|
return true
|
|
}
|
|
if o.Shared {
|
|
return true
|
|
}
|
|
for _, raw := range o.Owners {
|
|
p, ok := ParsePrincipal(raw)
|
|
if !ok {
|
|
continue
|
|
}
|
|
if principalMatches(p, id, r) {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
func principalMatches(p Principal, id Identity, r GroupResolver) bool {
|
|
switch p.Kind {
|
|
case KindUID:
|
|
if id.IsWindows() {
|
|
return false
|
|
}
|
|
uid, err := strconv.ParseUint(p.Value, 10, 32)
|
|
return err == nil && uint32(uid) == id.UID
|
|
case KindGID:
|
|
if id.IsWindows() {
|
|
return false
|
|
}
|
|
gid, err := strconv.ParseUint(p.Value, 10, 32)
|
|
return err == nil && callerHasGID(uint32(gid), id, r)
|
|
case KindGroup:
|
|
if id.IsWindows() || r == nil {
|
|
return false
|
|
}
|
|
gid, ok := r.GroupNameGID(p.Value)
|
|
return ok && callerHasGID(gid, id, r)
|
|
case KindSID:
|
|
if !id.IsWindows() {
|
|
return false
|
|
}
|
|
return id.SID == p.Value || slices.Contains(id.Groups, p.Value)
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
func callerHasGID(gid uint32, id Identity, r GroupResolver) bool {
|
|
if id.GID == gid {
|
|
return true
|
|
}
|
|
if r == nil {
|
|
return false
|
|
}
|
|
_, ok := r.CallerGIDs(id)[gid]
|
|
return ok
|
|
}
|