1 // Copyright 2012 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
17 // TestSCMCredentials tests the sending and receiving of credentials
18 // (PID, UID, GID) in an ancillary message between two UNIX
19 // sockets. The SO_PASSCRED socket option is enabled on the sending
20 // socket for this to work.
21 func TestSCMCredentials(t
*testing
.T
) {
22 socketTypeTests
:= []struct {
35 for _
, tt
:= range socketTypeTests
{
36 fds
, err
:= syscall
.Socketpair(syscall
.AF_LOCAL
, tt
.socketType
, 0)
38 t
.Fatalf("Socketpair: %v", err
)
40 defer syscall
.Close(fds
[0])
41 defer syscall
.Close(fds
[1])
43 err
= syscall
.SetsockoptInt(fds
[0], syscall
.SOL_SOCKET
, syscall
.SO_PASSCRED
, 1)
45 t
.Fatalf("SetsockoptInt: %v", err
)
48 srvFile
:= os
.NewFile(uintptr(fds
[0]), "server")
50 srv
, err
:= net
.FileConn(srvFile
)
52 t
.Errorf("FileConn: %v", err
)
57 cliFile
:= os
.NewFile(uintptr(fds
[1]), "client")
59 cli
, err
:= net
.FileConn(cliFile
)
61 t
.Errorf("FileConn: %v", err
)
66 var ucred syscall
.Ucred
68 ucred
.Pid
= int32(os
.Getpid())
71 oob
:= syscall
.UnixCredentials(&ucred
)
72 _
, _
, err
:= cli
.(*net
.UnixConn
).WriteMsgUnix(nil, oob
, nil)
73 if op
, ok
:= err
.(*net
.OpError
); ok
{
76 if sys
, ok
:= err
.(*os
.SyscallError
); ok
{
79 if err
!= syscall
.EPERM
{
80 t
.Fatalf("WriteMsgUnix failed with %v, want EPERM", err
)
84 ucred
.Pid
= int32(os
.Getpid())
85 ucred
.Uid
= uint32(os
.Getuid())
86 ucred
.Gid
= uint32(os
.Getgid())
87 oob
:= syscall
.UnixCredentials(&ucred
)
89 // On SOCK_STREAM, this is internally going to send a dummy byte
90 n
, oobn
, err
:= cli
.(*net
.UnixConn
).WriteMsgUnix(nil, oob
, nil)
92 t
.Fatalf("WriteMsgUnix: %v", err
)
95 t
.Fatalf("WriteMsgUnix n = %d, want 0", n
)
98 t
.Fatalf("WriteMsgUnix oobn = %d, want %d", oobn
, len(oob
))
101 oob2
:= make([]byte, 10*len(oob
))
102 n
, oobn2
, flags
, _
, err
:= srv
.(*net
.UnixConn
).ReadMsgUnix(nil, oob2
)
104 t
.Fatalf("ReadMsgUnix: %v", err
)
107 t
.Fatalf("ReadMsgUnix flags = 0x%x, want 0", flags
)
110 t
.Fatalf("ReadMsgUnix n = %d, want %d", n
, tt
.dataLen
)
113 // without SO_PASSCRED set on the socket, ReadMsgUnix will
114 // return zero oob bytes
115 t
.Fatalf("ReadMsgUnix oobn = %d, want %d", oobn2
, oobn
)
118 if !bytes
.Equal(oob
, oob2
) {
119 t
.Fatal("ReadMsgUnix oob bytes don't match")
122 scm
, err
:= syscall
.ParseSocketControlMessage(oob2
)
124 t
.Fatalf("ParseSocketControlMessage: %v", err
)
126 newUcred
, err
:= syscall
.ParseUnixCredentials(&scm
[0])
128 t
.Fatalf("ParseUnixCredentials: %v", err
)
130 if *newUcred
!= ucred
{
131 t
.Fatalf("ParseUnixCredentials = %+v, want %+v", newUcred
, ucred
)