mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-14 20:48:17 +08:00
46 lines
1.3 KiB
Go
46 lines
1.3 KiB
Go
//go:build linux
|
|
|
|
package control
|
|
|
|
import (
|
|
"net"
|
|
"syscall"
|
|
|
|
"github.com/matthewlu070111/smart-srun/core/internal/domain"
|
|
)
|
|
|
|
// peerUID reads the caller's uid from the kernel.
|
|
//
|
|
// SO_PEERCRED, not anything the caller sends. The credentials are recorded by
|
|
// the kernel at connect time and cannot be chosen by the process on the other
|
|
// end, which is the whole reason this is worth checking: a uid a client claimed
|
|
// would be a uid a client picked.
|
|
func peerUID(conn net.Conn) (uint32, error) {
|
|
unixConn, ok := conn.(*net.UnixConn)
|
|
if !ok {
|
|
return 0, domain.Errorf(domain.CodeInvalidArgument,
|
|
"控制连接不是 Unix 套接字,无法确认调用者身份")
|
|
}
|
|
raw, err := unixConn.SyscallConn()
|
|
if err != nil {
|
|
return 0, domain.Errorf(domain.CodeServiceStopped,
|
|
"无法读取控制连接").Wrap(err)
|
|
}
|
|
|
|
var credentials *syscall.Ucred
|
|
var sockErr error
|
|
controlErr := raw.Control(func(fd uintptr) {
|
|
credentials, sockErr = syscall.GetsockoptUcred(
|
|
int(fd), syscall.SOL_SOCKET, syscall.SO_PEERCRED)
|
|
})
|
|
if controlErr != nil {
|
|
return 0, domain.Errorf(domain.CodeServiceStopped,
|
|
"无法读取控制连接").Wrap(controlErr)
|
|
}
|
|
if sockErr != nil {
|
|
return 0, domain.Errorf(domain.CodeInvalidArgument,
|
|
"无法确认调用者身份").Wrap(sockErr)
|
|
}
|
|
return credentials.Uid, nil
|
|
}
|