transport_unixcred_dragonfly.go 2.7 KB

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