github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/go/util/peercred_darwin.go (about) 1 // Copyright (c) 2015, Kevin Walsh. All rights reserved. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package util 16 17 // This provides a version of UnixConn that can inject and collect out-of-band 18 // data, specifically, credentials and file descriptors. 19 20 import ( 21 "syscall" 22 "unsafe" 23 ) 24 25 // PeerCred retreives the most recently passed peer credential, or nil if no 26 // credentials have been received yet. 27 func (s *OOBUnixConn) PeerCred() *Ucred { 28 s.m.Lock() 29 defer s.m.Unlock() 30 if s.peerCred == nil { 31 f, err := s.File() 32 if err != nil { 33 return nil 34 } 35 defer f.Close() 36 s.peerCred = getpeereid(f.Fd()) 37 } 38 return s.peerCred 39 } 40 41 func getpeereid(fd uintptr) *Ucred { 42 var lvl uintptr = 0 43 var name uintptr = 1 44 var buf [19]uint32 // cmsgcred is larger, but actual getpeereid usex 0x4c buf size 45 var n int32 = 19 * 4 46 var bufptr uintptr = uintptr(unsafe.Pointer(&buf[0])) 47 var nptr uintptr = uintptr(unsafe.Pointer(&n)) 48 a, _, err := syscall.RawSyscall6(syscall.SYS_GETSOCKOPT, fd, lvl, name, bufptr, nptr, 0) 49 if a != 0 || err != 0 { 50 return nil 51 } 52 return &Ucred{Uid: buf[1], Gid: buf[3]} 53 } 54 55 func (s *OOBUnixConn) Read(p []byte) (n int, err error) { 56 var oob [OOBMaxLength]byte 57 n, oobn, _, _, err := s.ReadMsgUnix(p, oob[:]) 58 if err == nil && n > 0 && oobn > 0 { 59 scm, err := syscall.ParseSocketControlMessage(oob[0:oobn]) 60 if err != nil { 61 return n, err 62 } 63 s.m.Lock() 64 for _, m := range scm { 65 if m.Header.Level != syscall.SOL_SOCKET { 66 continue 67 } 68 switch m.Header.Type { 69 case syscall.SCM_RIGHTS: 70 if fds, err := syscall.ParseUnixRights(&m); err == nil { 71 for _, fd := range fds { 72 // Note: We wrap the raw FDs inside an os.File just 73 // once, early, to prevent double-free or leaking FDs. 74 f := NewFile(fd) 75 s.recvFiles = append(s.recvFiles, f) 76 } 77 } 78 } 79 } 80 s.m.Unlock() 81 } 82 return n, err 83 }