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