transport_unixcred_freebsd.go 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. // The UnixCredentials system call is currently only implemented on Linux
  2. // http://golang.org/src/pkg/syscall/sockcmsg_linux.go
  3. // https://golang.org/s/go1.4-syscall
  4. // http://code.google.com/p/go/source/browse/unix/sockcmsg_linux.go?repo=sys
  5. // Local implementation of the UnixCredentials system call for FreeBSD
  6. package dbus
  7. /*
  8. const int sizeofPtr = sizeof(void*);
  9. #define _WANT_UCRED
  10. #include <sys/ucred.h>
  11. */
  12. import "C"
  13. import (
  14. "io"
  15. "os"
  16. "syscall"
  17. "unsafe"
  18. )
  19. // http://golang.org/src/pkg/syscall/ztypes_linux_amd64.go
  20. // https://golang.org/src/syscall/ztypes_freebsd_amd64.go
  21. type Ucred struct {
  22. Pid int32
  23. Uid uint32
  24. Gid uint32
  25. }
  26. // http://golang.org/src/pkg/syscall/types_linux.go
  27. // https://golang.org/src/syscall/types_freebsd.go
  28. // https://github.com/freebsd/freebsd/blob/master/sys/sys/ucred.h
  29. const (
  30. SizeofUcred = C.sizeof_struct_ucred
  31. )
  32. // http://golang.org/src/pkg/syscall/sockcmsg_unix.go
  33. func cmsgAlignOf(salen int) int {
  34. salign := C.sizeofPtr
  35. return (salen + salign - 1) & ^(salign - 1)
  36. }
  37. // http://golang.org/src/pkg/syscall/sockcmsg_unix.go
  38. func cmsgData(h *syscall.Cmsghdr) unsafe.Pointer {
  39. return unsafe.Pointer(uintptr(unsafe.Pointer(h)) + uintptr(cmsgAlignOf(syscall.SizeofCmsghdr)))
  40. }
  41. // http://golang.org/src/pkg/syscall/sockcmsg_linux.go
  42. // UnixCredentials encodes credentials into a socket control message
  43. // for sending to another process. This can be used for
  44. // authentication.
  45. func UnixCredentials(ucred *Ucred) []byte {
  46. b := make([]byte, syscall.CmsgSpace(SizeofUcred))
  47. h := (*syscall.Cmsghdr)(unsafe.Pointer(&b[0]))
  48. h.Level = syscall.SOL_SOCKET
  49. h.Type = syscall.SCM_CREDS
  50. h.SetLen(syscall.CmsgLen(SizeofUcred))
  51. *((*Ucred)(cmsgData(h))) = *ucred
  52. return b
  53. }
  54. // http://golang.org/src/pkg/syscall/sockcmsg_linux.go
  55. // ParseUnixCredentials decodes a socket control message that contains
  56. // credentials in a Ucred structure. To receive such a message, the
  57. // SO_PASSCRED option must be enabled on the socket.
  58. func ParseUnixCredentials(m *syscall.SocketControlMessage) (*Ucred, error) {
  59. if m.Header.Level != syscall.SOL_SOCKET {
  60. return nil, syscall.EINVAL
  61. }
  62. if m.Header.Type != syscall.SCM_CREDS {
  63. return nil, syscall.EINVAL
  64. }
  65. ucred := *(*Ucred)(unsafe.Pointer(&m.Data[0]))
  66. return &ucred, nil
  67. }
  68. func (t *unixTransport) SendNullByte() error {
  69. ucred := &Ucred{Pid: int32(os.Getpid()), Uid: uint32(os.Getuid()), Gid: uint32(os.Getgid())}
  70. b := UnixCredentials(ucred)
  71. _, oobn, err := t.UnixConn.WriteMsgUnix([]byte{0}, b, nil)
  72. if err != nil {
  73. return err
  74. }
  75. if oobn != len(b) {
  76. return io.ErrShortWrite
  77. }
  78. return nil
  79. }