peercred_netbsd.go 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162
  1. //go:build netbsd
  2. package localapi
  3. import (
  4. "encoding/binary"
  5. "fmt"
  6. "net"
  7. "unsafe"
  8. "golang.org/x/sys/unix"
  9. )
  10. const peerCheckSupported = true
  11. // NetBSD reports the peer's identity through LOCAL_PEEREID at the SOL_LOCAL level,
  12. // filling a `struct unpcbid { pid_t unp_pid; uid_t unp_euid; gid_t unp_egid; }`.
  13. // golang.org/x/sys/unix has no typed wrapper for it, so the getsockopt goes out by hand
  14. // exactly the way that package's own generated wrappers do on this platform.
  15. const (
  16. solLocal = 0
  17. localPeerEID = 0x0003
  18. unpcbidSize = 12
  19. unpcbidEUIDOffs = 4
  20. )
  21. // peerUID returns the uid of the process on the other end of conn.
  22. //
  23. // Anything unexpected here is an error rather than a default, so a wrong constant or an
  24. // unsupported kernel refuses connections instead of silently admitting them.
  25. func peerUID(conn net.Conn) (uid uint32, err error) {
  26. err = withPeerFD(conn, func(fd int) error {
  27. var (
  28. buf [unpcbidSize]byte
  29. size = uint32(unpcbidSize)
  30. )
  31. _, _, errno := unix.Syscall6(
  32. unix.SYS_GETSOCKOPT,
  33. uintptr(fd),
  34. uintptr(solLocal),
  35. uintptr(localPeerEID),
  36. uintptr(unsafe.Pointer(&buf[0])),
  37. uintptr(unsafe.Pointer(&size)),
  38. 0,
  39. )
  40. if errno != 0 {
  41. return errno
  42. }
  43. if size != unpcbidSize {
  44. return fmt.Errorf("LOCAL_PEEREID returned %d bytes, expected %d", size, unpcbidSize)
  45. }
  46. // Read, not cast: the buffer is bytes, and a cast would fault on an
  47. // architecture that wants the uint32 aligned.
  48. uid = binary.NativeEndian.Uint32(buf[unpcbidEUIDOffs:])
  49. return nil
  50. })
  51. return uid, err
  52. }