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 }