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