Use ipcauth.Principal for the socket restriction instead of a second principal type

This commit is contained in:
Viktor Liu
2026-09-16 11:20:11 +02:00
parent 031ed560b2
commit ca70e5389f
7 changed files with 143 additions and 94 deletions
+16 -1
View File
@@ -164,6 +164,7 @@ type PrincipalKind string
const (
KindUID PrincipalKind = "uid" // Unix user ID
KindGID PrincipalKind = "gid" // Unix group ID
KindSID PrincipalKind = "sid" // Windows user or group SID
)
@@ -181,7 +182,7 @@ func ParsePrincipal(s string) (Principal, bool) {
return Principal{}, false
}
switch PrincipalKind(kind) {
case KindUID, KindSID:
case KindUID, KindGID, KindSID:
return Principal{Kind: PrincipalKind(kind), Value: value}, true
default:
return Principal{}, false
@@ -193,6 +194,11 @@ func UIDPrincipal(uid uint32) string {
return string(KindUID) + ":" + strconv.FormatUint(uint64(uid), 10)
}
// GIDPrincipal builds the principal string for a Unix group ID.
func GIDPrincipal(gid uint32) string {
return string(KindGID) + ":" + strconv.FormatUint(uint64(gid), 10)
}
// SIDPrincipal builds the owner string for a Windows SID.
func SIDPrincipal(sid string) string { return string(KindSID) + ":" + sid }
@@ -227,6 +233,15 @@ func (p Principal) Matches(id Identity) bool {
}
// Only the user SID. Group ownership is not supported yet.
return id.SID == p.Value
case KindGID:
// A group principal never confers ownership. It exists for the daemon
// socket restriction, which the kernel enforces at connect() from the
// caller's full group set; the identity here carries only the primary
// GID, so matching on it would grant ownership to members of a group
// and deny it to others in the same group, depending on which one
// happens to be primary. Deciding this properly is the group-ownership
// work that is still ahead.
return false
default:
return false
}
@@ -74,6 +74,21 @@ func TestPrincipalDoesNotMatchGroupSID(t *testing.T) {
assert.False(t, group.Matches(member), "a group SID owner must not match a group member")
}
// A GID principal is parseable because the daemon socket restriction stores one,
// but it confers no ownership: an owner field holding one must match nobody
// rather than admit everyone whose primary group happens to be it.
func TestGIDPrincipalNeverMatches(t *testing.T) {
group, ok := ParsePrincipal(GIDPrincipal(1000))
require.True(t, ok, "a gid principal must parse, the socket restriction stores it")
assert.Equal(t, KindGID, group.Kind)
assert.Equal(t, "gid:1000", group.String())
assert.False(t, group.Matches(KnownForTest(Identity{UID: 1000, GID: 1000})),
"a gid owner must not match a caller whose primary group it is")
assert.False(t, group.Matches(KnownForTest(Identity{UID: 0, GID: 0})))
assert.False(t, group.Matches(Identity{}))
}
func TestPrincipalMatchingIsPlatformScoped(t *testing.T) {
unix, ok := ParsePrincipal("uid:1000")
require.True(t, ok)