github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/go/util/oob_unix_conn.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  	"errors"
    22  	"net"
    23  	"os"
    24  	"sync"
    25  	"syscall"
    26  )
    27  
    28  // Error types for the protorpc package.
    29  var (
    30  	ErrOOBSendFailed  = errors.New("error sending out-of-band unix socket data")
    31  	ErrOOBParseFailed = errors.New("error parsing out-of-band unix socket data")
    32  )
    33  
    34  // Maximum amount of out-of-band data supported. This is enough to send
    35  // at least a set of credentials and 3 file descriptors.
    36  const OOBMaxLength = 100 // usually under 64 in practice
    37  
    38  // OOBUnixConn provides the same operations as net.UnixConn, plus the ability to
    39  // asynchronously make use of the out-of-band mechanism to share file descriptors
    40  // and credentials.
    41  type OOBUnixConn struct {
    42  	m         sync.Mutex // protects recvFiles, sendFDs, and peerCred
    43  	recvFiles []*os.File
    44  	sendFDs   []int
    45  	peerCred  *Ucred
    46  	*net.UnixConn
    47  }
    48  
    49  // Ucred holds credentials of a peer process.
    50  type Ucred struct {
    51  	Uid uint32
    52  	Gid uint32
    53  }
    54  
    55  // NewOOBUnixConn returns a new util.OOBUnixConn, which provides the same
    56  // operations as net.UnixConn but also allows sharing of file descriptors and
    57  // credentials.
    58  func NewOOBUnixConn(conn *net.UnixConn) *OOBUnixConn {
    59  	return &OOBUnixConn{UnixConn: conn}
    60  }
    61  
    62  // ShareFDs adds some file descriptors to the list of filescriptors to be
    63  // shared during the next Write.
    64  func (s *OOBUnixConn) ShareFDs(fd ...int) {
    65  	s.m.Lock()
    66  	s.sendFDs = append(s.sendFDs, fd...)
    67  	s.m.Unlock()
    68  }
    69  
    70  // SharedFiles retreives the open files shared during recent Read calls.
    71  func (s *OOBUnixConn) SharedFiles() []*os.File {
    72  	s.m.Lock()
    73  	fds := s.recvFiles
    74  	s.recvFiles = nil
    75  	s.m.Unlock()
    76  	return fds
    77  }
    78  
    79  func (s *OOBUnixConn) Write(buf []byte) (int, error) {
    80  	var oob []byte
    81  	s.m.Lock()
    82  	fds := s.sendFDs
    83  	s.sendFDs = nil
    84  	s.m.Unlock()
    85  	if len(fds) > 0 {
    86  		oob = syscall.UnixRights(fds...)
    87  	}
    88  	n, oobn, err := s.WriteMsgUnix(buf, oob, nil)
    89  	if err == nil && oobn != len(oob) {
    90  		err = ErrOOBSendFailed
    91  	}
    92  	return n, err
    93  }