56 lines
1.3 KiB
Go
56 lines
1.3 KiB
Go
//go:build linux
|
|
|
|
package localcontrol
|
|
|
|
import (
|
|
"fmt"
|
|
"net"
|
|
"os"
|
|
"syscall"
|
|
|
|
"golang.org/x/sys/unix"
|
|
)
|
|
|
|
func (kernelPeerCredentialSource) Supported() bool {
|
|
return true
|
|
}
|
|
|
|
// UID obtains the peer identity from the kernel SO_PEERCRED record.
|
|
func (kernelPeerCredentialSource) UID(conn net.Conn) (uint32, error) {
|
|
syscallConn, ok := conn.(syscall.Conn)
|
|
if !ok {
|
|
return 0, fmt.Errorf("localcontrol: connection does not expose a syscall handle")
|
|
}
|
|
raw, err := syscallConn.SyscallConn()
|
|
if err != nil {
|
|
return 0, fmt.Errorf("localcontrol: obtain peer syscall handle: %w", err)
|
|
}
|
|
var (
|
|
credential *unix.Ucred
|
|
socketErr error
|
|
)
|
|
if err := raw.Control(func(fileDescriptor uintptr) {
|
|
credential, socketErr = unix.GetsockoptUcred(
|
|
int(fileDescriptor),
|
|
unix.SOL_SOCKET,
|
|
unix.SO_PEERCRED,
|
|
)
|
|
}); err != nil {
|
|
return 0, fmt.Errorf("localcontrol: inspect peer credentials: %w", err)
|
|
}
|
|
if socketErr != nil {
|
|
return 0, fmt.Errorf("localcontrol: inspect SO_PEERCRED: %w", socketErr)
|
|
}
|
|
if credential == nil {
|
|
return 0, fmt.Errorf("localcontrol: SO_PEERCRED returned no identity")
|
|
}
|
|
return credential.Uid, nil
|
|
}
|
|
|
|
func fileOwnerUID(info os.FileInfo) (uint32, error) {
|
|
stat, ok := info.Sys().(*syscall.Stat_t)
|
|
if !ok {
|
|
return 0, fmt.Errorf("localcontrol: filesystem owner is unavailable")
|
|
}
|
|
return stat.Uid, nil
|
|
}
|