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 fds
, err
:= syscall
.Socketpair(syscall
.AF_LOCAL
, syscall
.SOCK_STREAM
, 0)
24 t
.Fatalf("Socketpair: %v", err
)
26 defer syscall
.Close(fds
[0])
27 defer syscall
.Close(fds
[1])
29 err
= syscall
.SetsockoptInt(fds
[0], syscall
.SOL_SOCKET
, syscall
.SO_PASSCRED
, 1)
31 t
.Fatalf("SetsockoptInt: %v", err
)
34 srvFile
:= os
.NewFile(uintptr(fds
[0]), "server")
36 srv
, err
:= net
.FileConn(srvFile
)
38 t
.Errorf("FileConn: %v", err
)
43 cliFile
:= os
.NewFile(uintptr(fds
[1]), "client")
45 cli
, err
:= net
.FileConn(cliFile
)
47 t
.Errorf("FileConn: %v", err
)
52 var ucred syscall
.Ucred
54 ucred
.Pid
= int32(os
.Getpid())
57 oob
:= syscall
.UnixCredentials(&ucred
)
58 _
, _
, err
:= cli
.(*net
.UnixConn
).WriteMsgUnix(nil, oob
, nil)
59 if op
, ok
:= err
.(*net
.OpError
); ok
{
62 if sys
, ok
:= err
.(*os
.SyscallError
); ok
{
65 if err
!= syscall
.EPERM
{
66 t
.Fatalf("WriteMsgUnix failed with %v, want EPERM", err
)
70 ucred
.Pid
= int32(os
.Getpid())
71 ucred
.Uid
= uint32(os
.Getuid())
72 ucred
.Gid
= uint32(os
.Getgid())
73 oob
:= syscall
.UnixCredentials(&ucred
)
75 // this is going to send a dummy byte
76 n
, oobn
, err
:= cli
.(*net
.UnixConn
).WriteMsgUnix(nil, oob
, nil)
78 t
.Fatalf("WriteMsgUnix: %v", err
)
81 t
.Fatalf("WriteMsgUnix n = %d, want 0", n
)
84 t
.Fatalf("WriteMsgUnix oobn = %d, want %d", oobn
, len(oob
))
87 oob2
:= make([]byte, 10*len(oob
))
88 n
, oobn2
, flags
, _
, err
:= srv
.(*net
.UnixConn
).ReadMsgUnix(nil, oob2
)
90 t
.Fatalf("ReadMsgUnix: %v", err
)
93 t
.Fatalf("ReadMsgUnix flags = 0x%x, want 0", flags
)
96 t
.Fatalf("ReadMsgUnix n = %d, want 1 (dummy byte)", n
)
99 // without SO_PASSCRED set on the socket, ReadMsgUnix will
100 // return zero oob bytes
101 t
.Fatalf("ReadMsgUnix oobn = %d, want %d", oobn2
, oobn
)
104 if !bytes
.Equal(oob
, oob2
) {
105 t
.Fatal("ReadMsgUnix oob bytes don't match")
108 scm
, err
:= syscall
.ParseSocketControlMessage(oob2
)
110 t
.Fatalf("ParseSocketControlMessage: %v", err
)
112 newUcred
, err
:= syscall
.ParseUnixCredentials(&scm
[0])
114 t
.Fatalf("ParseUnixCredentials: %v", err
)
116 if *newUcred
!= ucred
{
117 t
.Fatalf("ParseUnixCredentials = %+v, want %+v", newUcred
, ucred
)