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