github.com/jlmucb/cloudproxy@v0.0.0-20170830161738-b5aa0b619bc4/go/tao/linux_host_admin_rpc.go (about)

     1  // Copyright (c) 2014, Google Inc.  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 tao
    16  
    17  // This provides client and server stubs for LinuxHost's admin RPC interface.
    18  // This code is extremely dull and, ideally, would be generated automatically.
    19  
    20  import (
    21  	"net"
    22  	"net/rpc"
    23  	"os"
    24  
    25  	"github.com/golang/protobuf/proto"
    26  	"github.com/jlmucb/cloudproxy/go/tao/auth"
    27  	"github.com/jlmucb/cloudproxy/go/util"
    28  	"github.com/jlmucb/cloudproxy/go/util/protorpc"
    29  )
    30  
    31  // LinuxHostAdminClient is a client stub for LinuxHost's admin RPC interface.
    32  type LinuxHostAdminClient struct {
    33  	oob *util.OOBUnixConn
    34  	*rpc.Client
    35  }
    36  
    37  // NewLinuxHostAdminClient returns a new client stub for LinuxHost's admin RPC
    38  // interface.
    39  func NewLinuxHostAdminClient(conn *net.UnixConn) LinuxHostAdminClient {
    40  	oob := util.NewOOBUnixConn(conn)
    41  	c := rpc.NewClientWithCodec(protorpc.NewClientCodec(oob))
    42  	return LinuxHostAdminClient{oob, c}
    43  }
    44  
    45  // StartHostedProgram is the client stub for LinuxHost.StartHostedProgram.
    46  func (client LinuxHostAdminClient) StartHostedProgram(spec *HostedProgramSpec) (auth.SubPrin, int, error) {
    47  	req := &LinuxHostAdminRPCRequest{
    48  		Path:          proto.String(spec.Path),
    49  		Dir:           proto.String(spec.Dir),
    50  		ContainerArgs: spec.ContainerArgs,
    51  		Args:          spec.Args,
    52  		// TODO: pass uid and gid?
    53  	}
    54  	var fds []int
    55  	if spec.Stdin != nil {
    56  		req.Stdin = proto.Int32(int32(len(fds)))
    57  		fds = append(fds, int(spec.Stdin.Fd()))
    58  	}
    59  	if spec.Stdin != nil {
    60  		req.Stdout = proto.Int32(int32(len(fds)))
    61  		fds = append(fds, int(spec.Stdout.Fd()))
    62  	}
    63  	if spec.Stdin != nil {
    64  		req.Stderr = proto.Int32(int32(len(fds)))
    65  		fds = append(fds, int(spec.Stderr.Fd()))
    66  	}
    67  	resp := new(LinuxHostAdminRPCResponse)
    68  	client.oob.ShareFDs(fds...)
    69  	err := client.Call("LinuxHost.StartHostedProgram", req, resp)
    70  	if err != nil {
    71  		return auth.SubPrin{}, 0, err
    72  	}
    73  	if len(resp.Child) != 1 {
    74  		return auth.SubPrin{}, 0, newError("invalid response")
    75  	}
    76  	subprin, err := auth.UnmarshalSubPrin(resp.Child[0].Subprin)
    77  	return subprin, int(*resp.Child[0].Pid), err
    78  }
    79  
    80  // StopHostedProgram is the client stub for LinuxHost.StopHostedProgram.
    81  func (client LinuxHostAdminClient) StopHostedProgram(subprin auth.SubPrin) error {
    82  	req := &LinuxHostAdminRPCRequest{
    83  		Subprin: auth.Marshal(subprin),
    84  	}
    85  	resp := new(LinuxHostAdminRPCResponse)
    86  	err := client.Call("LinuxHost.StopHostedProgram", req, resp)
    87  	if err != nil {
    88  		return err
    89  	}
    90  	return nil
    91  }
    92  
    93  // ListHostedPrograms is the client stub for LinuxHost.ListHostedPrograms.
    94  func (client LinuxHostAdminClient) ListHostedPrograms() (name []auth.SubPrin, pid []int, err error) {
    95  	req := &LinuxHostAdminRPCRequest{}
    96  	resp := new(LinuxHostAdminRPCResponse)
    97  	err = client.Call("LinuxHost.ListHostedPrograms", req, resp)
    98  	if err != nil {
    99  		return nil, nil, err
   100  	}
   101  	name = make([]auth.SubPrin, len(resp.Child))
   102  	pid = make([]int, len(resp.Child))
   103  	for i, child := range resp.Child {
   104  		pid[i] = int(*child.Pid)
   105  		name[i], err = auth.UnmarshalSubPrin(child.Subprin)
   106  		if err != nil {
   107  			return nil, nil, err
   108  		}
   109  	}
   110  	return name, pid, nil
   111  }
   112  
   113  // WaitHostedProgram is the client stub for LinuxHost.WaitHostedProgram.
   114  func (client LinuxHostAdminClient) WaitHostedProgram(pid int, subprin auth.SubPrin) (int, error) {
   115  	req := &LinuxHostAdminRPCRequest{
   116  		Pid:     proto.Int32(int32(pid)),
   117  		Subprin: auth.Marshal(subprin),
   118  	}
   119  	resp := new(LinuxHostAdminRPCResponse)
   120  	err := client.Call("LinuxHost.WaitHostedProgram", req, resp)
   121  	if err != nil {
   122  		return -1, err
   123  	}
   124  	return int(*resp.Status), nil
   125  }
   126  
   127  // KillHostedProgram is the client stub for LinuxHost.KillHostedProgram.
   128  func (client LinuxHostAdminClient) KillHostedProgram(subprin auth.SubPrin) error {
   129  	req := &LinuxHostAdminRPCRequest{
   130  		Subprin: auth.Marshal(subprin),
   131  	}
   132  	resp := new(LinuxHostAdminRPCResponse)
   133  	err := client.Call("LinuxHost.KillHostedProgram", req, resp)
   134  	if err != nil {
   135  		return err
   136  	}
   137  	return nil
   138  }
   139  
   140  // HostName is the client stub for LinuxHost.HostName.
   141  func (client LinuxHostAdminClient) HostName() (auth.Prin, error) {
   142  	req := &LinuxHostAdminRPCRequest{}
   143  	resp := new(LinuxHostAdminRPCResponse)
   144  	err := client.Call("LinuxHost.HostName", req, resp)
   145  	if err != nil {
   146  		return auth.Prin{}, err
   147  	}
   148  	return auth.UnmarshalPrin(resp.Prin)
   149  }
   150  
   151  // Shutdown is the client stub for LinuxHost.Shutdown.
   152  func (client LinuxHostAdminClient) Shutdown() error {
   153  	req := &LinuxHostAdminRPCRequest{}
   154  	resp := new(LinuxHostAdminRPCResponse)
   155  	return client.Call("LinuxHost.Shutdown", req, resp)
   156  }
   157  
   158  // LinuxHostAdminServer is a server stub for LinuxHost's admin RPC interface.
   159  type LinuxHostAdminServer struct {
   160  	lh   *LinuxHost
   161  	Done chan bool
   162  }
   163  
   164  type linuxHostAdminServerStub struct {
   165  	oob  *util.OOBUnixConn
   166  	lh   *LinuxHost
   167  	Done chan bool
   168  }
   169  
   170  // NewLinuxHostAdminServer returns a new server stub for LinuxHost's admin RPC
   171  // interface.
   172  func NewLinuxHostAdminServer(host *LinuxHost) LinuxHostAdminServer {
   173  	return LinuxHostAdminServer{host, make(chan bool, 1)}
   174  }
   175  
   176  // StartHostedProgram is the server stub for LinuxHost.StartHostedProgram.
   177  func (server linuxHostAdminServerStub) StartHostedProgram(r *LinuxHostAdminRPCRequest, s *LinuxHostAdminRPCResponse) error {
   178  	files := server.oob.SharedFiles()
   179  	defer func() {
   180  		for _, f := range files {
   181  			f.Close()
   182  		}
   183  	}()
   184  	ucred := server.oob.PeerCred()
   185  	if r.Path == nil {
   186  		return newError("missing path")
   187  	}
   188  	spec := HostedProgramSpec{
   189  		Path:          *r.Path,
   190  		Args:          r.Args,
   191  		ContainerArgs: r.ContainerArgs,
   192  		Dir:           *r.Dir,
   193  		Uid:           int(ucred.Uid),
   194  		Gid:           int(ucred.Gid),
   195  	}
   196  	// We do allow superuser here, since we trust the oob credentials
   197  	spec.Superuser = (ucred.Uid == 0 || ucred.Gid == 0)
   198  	if r.Stdin != nil {
   199  		if int(*r.Stdin) >= len(files) {
   200  			return newError("missing stdin")
   201  		}
   202  		spec.Stdin = files[*r.Stdin]
   203  	}
   204  	if r.Stdout != nil {
   205  		if int(*r.Stdout) >= len(files) {
   206  			return newError("missing stdout")
   207  		}
   208  		spec.Stdout = files[*r.Stdout]
   209  	}
   210  	if r.Stderr != nil {
   211  		if int(*r.Stderr) >= len(files) {
   212  			return newError("missing stderr")
   213  		}
   214  		spec.Stderr = files[*r.Stderr]
   215  	}
   216  	subprin, pid, err := server.lh.StartHostedProgram(spec)
   217  	if err != nil {
   218  		return err
   219  	}
   220  	s.Child = make([]*LinuxHostAdminRPCHostedProgram, 1)
   221  	s.Child[0] = &LinuxHostAdminRPCHostedProgram{
   222  		Subprin: auth.Marshal(subprin),
   223  		Pid:     proto.Int32(int32(pid)),
   224  	}
   225  	return nil
   226  }
   227  
   228  // StopHostedProgram is the server stub for LinuxHost.StopHostedProgram.
   229  func (server linuxHostAdminServerStub) StopHostedProgram(r *LinuxHostAdminRPCRequest, s *LinuxHostAdminRPCResponse) error {
   230  	ucred := server.oob.PeerCred()
   231  	// TODO(kwalsh): also authorize owner of child
   232  	if ucred.Uid != 0 && int(ucred.Uid) != os.Geteuid() {
   233  		return newError("unauthorized: only root or owner can stop hosted programs")
   234  	}
   235  	subprin, err := auth.UnmarshalSubPrin(r.Subprin)
   236  	if err != nil {
   237  		return err
   238  	}
   239  	return server.lh.StopHostedProgram(subprin)
   240  }
   241  
   242  // ListHostedPrograms is the server stub for LinuxHost.ListHostedPrograms.
   243  func (server linuxHostAdminServerStub) ListHostedPrograms(r *LinuxHostAdminRPCRequest, s *LinuxHostAdminRPCResponse) error {
   244  	names, pids, err := server.lh.ListHostedPrograms()
   245  	if err != nil {
   246  		return err
   247  	}
   248  	if len(names) != len(pids) {
   249  		return newError("invalid response")
   250  	}
   251  	s.Child = make([]*LinuxHostAdminRPCHostedProgram, len(names))
   252  	for i := range names {
   253  		s.Child[i] = &LinuxHostAdminRPCHostedProgram{
   254  			Subprin: auth.Marshal(names[i]),
   255  			Pid:     proto.Int32(int32(pids[i])),
   256  		}
   257  	}
   258  	return nil
   259  }
   260  
   261  // WaitHostedProgram is the server stub for LinuxHost.WaitHostedProgram.
   262  func (server linuxHostAdminServerStub) WaitHostedProgram(r *LinuxHostAdminRPCRequest, s *LinuxHostAdminRPCResponse) error {
   263  	// ucred := server.oob.PeerCred()
   264  	// TODO(kwalsh): also authorize owner of child
   265  	// if ucred.Uid != 0 && int(ucred.Uid) != os.Geteuid() {
   266  	// 	return newError("unauthorized: only root or owner can wait for hosted programs")
   267  	// }
   268  	if r.Pid == nil {
   269  		return newError("required pid is nil")
   270  	}
   271  	pid := int(*r.Pid)
   272  	subprin, err := auth.UnmarshalSubPrin(r.Subprin)
   273  	if err != nil {
   274  		return err
   275  	}
   276  	status, err := server.lh.WaitHostedProgram(pid, subprin)
   277  	if err != nil {
   278  		return err
   279  	}
   280  	s.Status = proto.Int32(int32(status))
   281  	return nil
   282  }
   283  
   284  // KillHostedProgram is the server stub for LinuxHost.KillHostedProgram.
   285  func (server linuxHostAdminServerStub) KillHostedProgram(r *LinuxHostAdminRPCRequest, s *LinuxHostAdminRPCResponse) error {
   286  	ucred := server.oob.PeerCred()
   287  	// TODO(kwalsh): also authorize owner of child
   288  	if ucred.Uid != 0 && int(ucred.Uid) != os.Geteuid() {
   289  		return newError("unauthorized: only root or owner can kill hosted programs")
   290  	}
   291  	subprin, err := auth.UnmarshalSubPrin(r.Subprin)
   292  	if err != nil {
   293  		return err
   294  	}
   295  	return server.lh.KillHostedProgram(subprin)
   296  }
   297  
   298  // HostName is the server stub for LinuxHost.HostName.
   299  func (server linuxHostAdminServerStub) HostName(r *LinuxHostAdminRPCRequest, s *LinuxHostAdminRPCResponse) error {
   300  	prin := server.lh.HostName()
   301  	s.Prin = auth.Marshal(prin)
   302  	return nil
   303  }
   304  
   305  // Shutdown is the server stub for LinuxHost.Shutdown.
   306  func (server linuxHostAdminServerStub) Shutdown(r *LinuxHostAdminRPCRequest, s *LinuxHostAdminRPCResponse) error {
   307  	ucred := server.oob.PeerCred()
   308  	// TODO(kwalsh): also authorize owner of child
   309  	if ucred.Uid != 0 && int(ucred.Uid) != os.Geteuid() {
   310  		return newError("unauthorized: only root or owner can shut down linux_host")
   311  	}
   312  	err := server.lh.Shutdown()
   313  	server.Done <- true
   314  	close(server.Done)
   315  	return err
   316  }
   317  
   318  // Serve listens on sock for new connections and services them.
   319  func (server LinuxHostAdminServer) Serve(sock *net.UnixListener) error {
   320  	// Set the socket to allow peer credentials to be passed
   321  	err := NewAuthenticatedFileSocket(sock);
   322  	if err != nil {
   323  		return err
   324  	}
   325  
   326  	connections := make(chan *net.UnixConn, 1)
   327  	errors := make(chan error, 1)
   328  	go func() {
   329  		for {
   330  			conn, err := sock.AcceptUnix()
   331  			if err != nil {
   332  				errors <- err
   333  				break
   334  			}
   335  			connections <- conn
   336  		}
   337  	}()
   338  
   339  	for {
   340  		var conn *net.UnixConn
   341  		select {
   342  		case conn = <-connections:
   343  			break
   344  		case err = <-errors:
   345  			return err
   346  		case <-server.Done:
   347  			return nil
   348  		}
   349  		s := rpc.NewServer()
   350  		oob := util.NewOOBUnixConn(conn)
   351  		err = s.RegisterName("LinuxHost", linuxHostAdminServerStub{oob, server.lh, server.Done})
   352  		if err != nil {
   353  			return err
   354  		}
   355  		go s.ServeCodec(protorpc.NewServerCodec(oob))
   356  	}
   357  }