blob: 8d1ee86b62524f4ae0507492ff3b25a5f73d630f [file] [log] [blame]
Jiri Simsad7616c92015-03-24 23:44:30 -07001// Copyright 2015 The Vanadium 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.
4
Matt Rosencrantz94502cf2015-03-18 09:43:44 -07005package rpc
Jiri Simsa5293dcb2014-05-10 09:56:38 -07006
7import (
Asim Shankarf4864f42014-11-25 18:53:05 -08008 "encoding/hex"
Jiri Simsa5293dcb2014-05-10 09:56:38 -07009 "errors"
10 "fmt"
11 "io"
Cosmos Nicolaoud6c3c9c2014-09-30 15:42:53 -070012 "net"
Cosmos Nicolaou9388ae42014-11-10 10:57:15 -080013 "path/filepath"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070014 "reflect"
Cosmos Nicolaou9388ae42014-11-10 10:57:15 -080015 "runtime"
Cosmos Nicolaou9fbe7d22015-01-25 22:13:13 -080016 "sort"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070017 "strings"
Bogdan Caprita27953142014-05-12 11:41:42 -070018 "sync"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070019 "testing"
20 "time"
21
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -070022 "v.io/v23"
Jiri Simsa6ac95222015-02-23 16:11:49 -080023 "v.io/v23/context"
Todd Wang5082a552015-04-02 10:56:11 -070024 "v.io/v23/namespace"
Jiri Simsa6ac95222015-02-23 16:11:49 -080025 "v.io/v23/naming"
26 "v.io/v23/options"
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070027 "v.io/v23/rpc"
Jiri Simsa6ac95222015-02-23 16:11:49 -080028 "v.io/v23/security"
Todd Wang387d8a42015-03-30 17:09:05 -070029 "v.io/v23/security/access"
Jiri Simsa6ac95222015-02-23 16:11:49 -080030 "v.io/v23/uniqueid"
31 "v.io/v23/vdl"
32 "v.io/v23/verror"
Jiri Simsa6ac95222015-02-23 16:11:49 -080033 "v.io/v23/vtrace"
Jiri Simsa337af232015-02-27 14:36:46 -080034 "v.io/x/lib/vlog"
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070035 "v.io/x/ref/profiles/internal/rpc/stream"
Cosmos Nicolaouf889c732014-10-16 20:46:54 -070036
Matt Rosencrantz9d3278a2015-03-11 14:58:34 -070037 "v.io/x/lib/netstate"
Jiri Simsaffceefa2015-02-28 11:03:34 -080038 "v.io/x/ref/lib/stats"
Matt Rosencrantz86ba1a12015-03-09 13:19:02 -070039 "v.io/x/ref/profiles/internal/lib/publisher"
Suharsh Sivakumarcbfe4742015-03-11 14:54:22 -070040 "v.io/x/ref/profiles/internal/lib/websocket"
Matt Rosencrantzdbc1be22015-02-28 15:15:49 -080041 inaming "v.io/x/ref/profiles/internal/naming"
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070042 _ "v.io/x/ref/profiles/internal/rpc/protocols/tcp"
43 _ "v.io/x/ref/profiles/internal/rpc/protocols/ws"
44 _ "v.io/x/ref/profiles/internal/rpc/protocols/wsh"
45 imanager "v.io/x/ref/profiles/internal/rpc/stream/manager"
46 "v.io/x/ref/profiles/internal/rpc/stream/vc"
Matt Rosencrantzdbc1be22015-02-28 15:15:49 -080047 tnaming "v.io/x/ref/profiles/internal/testing/mocks/naming"
Cosmos Nicolaou1381f8a2015-03-13 09:40:34 -070048 "v.io/x/ref/test/testutil"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070049)
50
Suharsh Sivakumard19c95d2015-02-19 14:44:50 -080051//go:generate v23 test generate
52
Jiri Simsa5293dcb2014-05-10 09:56:38 -070053var (
Jiri Simsa074bf362015-02-17 09:29:45 -080054 errMethod = verror.New(verror.ErrAborted, nil)
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -080055 clock = new(fakeClock)
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070056 listenAddrs = rpc.ListenAddrs{{"tcp", "127.0.0.1:0"}}
57 listenWSAddrs = rpc.ListenAddrs{{"ws", "127.0.0.1:0"}, {"tcp", "127.0.0.1:0"}}
58 listenSpec = rpc.ListenSpec{Addrs: listenAddrs}
59 listenWSSpec = rpc.ListenSpec{Addrs: listenWSAddrs}
Jiri Simsa5293dcb2014-05-10 09:56:38 -070060)
61
Andres Erbsenb7f95f32014-07-07 12:07:56 -070062type fakeClock struct {
63 sync.Mutex
Suharsh Sivakumar8a0adbb2015-03-06 13:16:34 -080064 time int64
Andres Erbsenb7f95f32014-07-07 12:07:56 -070065}
66
Suharsh Sivakumar8a0adbb2015-03-06 13:16:34 -080067func (c *fakeClock) Now() int64 {
Andres Erbsenb7f95f32014-07-07 12:07:56 -070068 c.Lock()
69 defer c.Unlock()
70 return c.time
71}
72
73func (c *fakeClock) Advance(steps uint) {
74 c.Lock()
Suharsh Sivakumar8a0adbb2015-03-06 13:16:34 -080075 c.time += int64(steps)
Andres Erbsenb7f95f32014-07-07 12:07:56 -070076 c.Unlock()
77}
78
Todd Wang5082a552015-04-02 10:56:11 -070079func testInternalNewServer(ctx *context.T, streamMgr stream.Manager, ns namespace.T, principal security.Principal, opts ...rpc.ServerOpt) (rpc.Server, error) {
Suharsh Sivakumaraf99c972015-01-28 15:28:49 -080080 client, err := InternalNewClient(streamMgr, ns)
81 if err != nil {
82 return nil, err
83 }
Suharsh Sivakumar59c423c2015-03-11 14:06:03 -070084 return InternalNewServer(ctx, streamMgr, ns, client, principal, opts...)
Suharsh Sivakumaraf99c972015-01-28 15:28:49 -080085}
86
Jiri Simsa5293dcb2014-05-10 09:56:38 -070087type userType string
88
89type testServer struct{}
90
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070091func (*testServer) Closure(call rpc.ServerCall) error {
Todd Wange77f9952015-02-18 13:20:50 -080092 return nil
Jiri Simsa5293dcb2014-05-10 09:56:38 -070093}
94
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070095func (*testServer) Error(call rpc.ServerCall) error {
Jiri Simsa5293dcb2014-05-10 09:56:38 -070096 return errMethod
97}
98
Matt Rosencrantz94502cf2015-03-18 09:43:44 -070099func (*testServer) Echo(call rpc.ServerCall, arg string) (string, error) {
Matt Rosencrantz311378b2015-03-25 15:26:12 -0700100 return fmt.Sprintf("method:%q,suffix:%q,arg:%q", "Echo", call.Suffix(), arg), nil
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700101}
102
Matt Rosencrantz94502cf2015-03-18 09:43:44 -0700103func (*testServer) EchoUser(call rpc.ServerCall, arg string, u userType) (string, userType, error) {
Matt Rosencrantz311378b2015-03-25 15:26:12 -0700104 return fmt.Sprintf("method:%q,suffix:%q,arg:%q", "EchoUser", call.Suffix(), arg), u, nil
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700105}
106
Matt Rosencrantz94502cf2015-03-18 09:43:44 -0700107func (*testServer) EchoBlessings(call rpc.ServerCall) (server, client string, _ error) {
Ankur9e75e7f2015-03-18 18:48:41 -0700108 local := security.LocalBlessingNames(call.Context())
109 remote, _ := security.RemoteBlessingNames(call.Context())
Todd Wange77f9952015-02-18 13:20:50 -0800110 return fmt.Sprintf("%v", local), fmt.Sprintf("%v", remote), nil
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700111}
112
Matt Rosencrantz94502cf2015-03-18 09:43:44 -0700113func (*testServer) EchoGrantedBlessings(call rpc.ServerCall, arg string) (result, blessing string, _ error) {
Matt Rosencrantz9dce9b22015-03-02 10:48:37 -0800114 return arg, fmt.Sprintf("%v", call.GrantedBlessings()), nil
Asim Shankarb54d7642014-06-05 13:08:04 -0700115}
116
Matt Rosencrantz94502cf2015-03-18 09:43:44 -0700117func (*testServer) EchoAndError(call rpc.ServerCall, arg string) (string, error) {
Matt Rosencrantz311378b2015-03-25 15:26:12 -0700118 result := fmt.Sprintf("method:%q,suffix:%q,arg:%q", "EchoAndError", call.Suffix(), arg)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700119 if arg == "error" {
120 return result, errMethod
121 }
122 return result, nil
123}
124
Matt Rosencrantz94502cf2015-03-18 09:43:44 -0700125func (*testServer) Stream(call rpc.StreamServerCall, arg string) (string, error) {
Matt Rosencrantz311378b2015-03-25 15:26:12 -0700126 result := fmt.Sprintf("method:%q,suffix:%q,arg:%q", "Stream", call.Suffix(), arg)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700127 var u userType
128 var err error
129 for err = call.Recv(&u); err == nil; err = call.Recv(&u) {
130 result += " " + string(u)
131 if err := call.Send(u); err != nil {
132 return "", err
133 }
134 }
135 if err == io.EOF {
136 err = nil
137 }
138 return result, err
139}
140
Matt Rosencrantz94502cf2015-03-18 09:43:44 -0700141func (*testServer) Unauthorized(rpc.StreamServerCall) (string, error) {
Todd Wange77f9952015-02-18 13:20:50 -0800142 return "UnauthorizedResult", nil
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700143}
144
145type testServerAuthorizer struct{}
146
Matt Rosencrantz250558f2015-03-17 11:37:31 -0700147func (testServerAuthorizer) Authorize(ctx *context.T) error {
148 c := security.GetCall(ctx)
Ankuredd74ee2015-03-04 16:38:45 -0800149 // Verify that the Call object seen by the authorizer
150 // has the necessary fields.
151 lb := c.LocalBlessings()
152 if lb.IsZero() {
153 return fmt.Errorf("testServerAuthorzer: Call object %v has no LocalBlessings", c)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700154 }
Ankuredd74ee2015-03-04 16:38:45 -0800155 if tpcavs := lb.ThirdPartyCaveats(); len(tpcavs) > 0 && c.LocalDischarges() == nil {
156 return fmt.Errorf("testServerAuthorzer: Call object %v has no LocalDischarges even when LocalBlessings have third-party caveats", c)
157
158 }
159 if c.LocalPrincipal() == nil {
160 return fmt.Errorf("testServerAuthorzer: Call object %v has no LocalPrincipal", c)
161 }
162 if c.Method() == "" {
163 return fmt.Errorf("testServerAuthorzer: Call object %v has no Method", c)
164 }
165 if c.LocalEndpoint() == nil {
166 return fmt.Errorf("testServerAuthorzer: Call object %v has no LocalEndpoint", c)
167 }
168 if c.RemoteEndpoint() == nil {
169 return fmt.Errorf("testServerAuthorzer: Call object %v has no RemoteEndpoint", c)
170 }
171
172 // Do not authorize the method "Unauthorized".
173 if c.Method() == "Unauthorized" {
174 return fmt.Errorf("testServerAuthorizer denied access")
175 }
176 return nil
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700177}
178
179type testServerDisp struct{ server interface{} }
180
Robin Thellenda02fe8f2014-11-19 09:58:29 -0800181func (t testServerDisp) Lookup(suffix string) (interface{}, security.Authorizer, error) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700182 // If suffix is "nilAuth" we use default authorization, if it is "aclAuth" we
Benjamin Prosnitzb60efb92015-03-11 17:47:43 -0700183 // use an AccessList based authorizer, and otherwise we use the custom testServerAuthorizer.
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700184 var authorizer security.Authorizer
185 switch suffix {
186 case "discharger":
Cosmos Nicolaou710daa22014-11-11 19:39:18 -0800187 return &dischargeServer{}, testServerAuthorizer{}, nil
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700188 case "nilAuth":
189 authorizer = nil
190 case "aclAuth":
Benjamin Prosnitzb60efb92015-03-11 17:47:43 -0700191 authorizer = &access.AccessList{
Ankur78b8b2a2015-02-04 20:16:28 -0800192 In: []security.BlessingPattern{"client", "server"},
Asim Shankar68885192014-11-26 12:48:35 -0800193 }
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700194 default:
195 authorizer = testServerAuthorizer{}
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700196 }
Cosmos Nicolaou710daa22014-11-11 19:39:18 -0800197 return t.server, authorizer, nil
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700198}
199
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -0800200type dischargeServer struct {
201 mu sync.Mutex
202 called bool
203}
Ankure49a86a2014-11-11 18:52:43 -0800204
Matt Rosencrantz94502cf2015-03-18 09:43:44 -0700205func (ds *dischargeServer) Discharge(call rpc.StreamServerCall, cav security.Caveat, _ security.DischargeImpetus) (security.Discharge, error) {
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -0800206 ds.mu.Lock()
207 ds.called = true
208 ds.mu.Unlock()
Asim Shankar19da8182015-02-06 01:41:16 -0800209 tp := cav.ThirdPartyDetails()
210 if tp == nil {
Asim Shankar08642822015-03-02 21:21:09 -0800211 return security.Discharge{}, fmt.Errorf("discharger: %v does not represent a third-party caveat", cav)
Ankure49a86a2014-11-11 18:52:43 -0800212 }
Matt Rosencrantz317b0c52015-03-24 20:47:01 -0700213 if err := tp.Dischargeable(call.Context()); err != nil {
Asim Shankar08642822015-03-02 21:21:09 -0800214 return security.Discharge{}, fmt.Errorf("third-party caveat %v cannot be discharged for this context: %v", cav, err)
Ankure49a86a2014-11-11 18:52:43 -0800215 }
216 // Add a fakeTimeCaveat to be able to control discharge expiration via 'clock'.
Asim Shankar7283dd82015-02-03 19:35:58 -0800217 expiry, err := security.NewCaveat(fakeTimeCaveat, clock.Now())
218 if err != nil {
Asim Shankar08642822015-03-02 21:21:09 -0800219 return security.Discharge{}, fmt.Errorf("failed to create an expiration on the discharge: %v", err)
Asim Shankar7283dd82015-02-03 19:35:58 -0800220 }
Matt Rosencrantz311378b2015-03-25 15:26:12 -0700221 return security.GetCall(call.Context()).LocalPrincipal().MintDischarge(cav, expiry)
Ankure49a86a2014-11-11 18:52:43 -0800222}
223
Todd Wang5082a552015-04-02 10:56:11 -0700224func startServer(t *testing.T, ctx *context.T, principal security.Principal, sm stream.Manager, ns namespace.T, name string, disp rpc.Dispatcher, opts ...rpc.ServerOpt) (naming.Endpoint, rpc.Server) {
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700225 return startServerWS(t, ctx, principal, sm, ns, name, disp, noWebsocket, opts...)
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800226}
227
Cosmos Nicolaou9fbe7d22015-01-25 22:13:13 -0800228func endpointsToStrings(eps []naming.Endpoint) []string {
229 r := make([]string, len(eps))
230 for i, e := range eps {
231 r[i] = e.String()
232 }
233 sort.Strings(r)
234 return r
235}
236
Todd Wang5082a552015-04-02 10:56:11 -0700237func startServerWS(t *testing.T, ctx *context.T, principal security.Principal, sm stream.Manager, ns namespace.T, name string, disp rpc.Dispatcher, shouldUseWebsocket websocketMode, opts ...rpc.ServerOpt) (naming.Endpoint, rpc.Server) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700238 vlog.VI(1).Info("InternalNewServer")
Asim Shankar263c73b2015-03-19 18:31:26 -0700239 ctx, _ = v23.SetPrincipal(ctx, principal)
Suharsh Sivakumar59c423c2015-03-11 14:06:03 -0700240 server, err := testInternalNewServer(ctx, sm, ns, principal, opts...)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700241 if err != nil {
242 t.Errorf("InternalNewServer failed: %v", err)
243 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700244 vlog.VI(1).Info("server.Listen")
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800245 spec := listenSpec
246 if shouldUseWebsocket {
247 spec = listenWSSpec
248 }
Cosmos Nicolaou9fbe7d22015-01-25 22:13:13 -0800249 eps, err := server.Listen(spec)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700250 if err != nil {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700251 t.Errorf("server.Listen failed: %v", err)
252 }
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700253 vlog.VI(1).Info("server.Serve")
Ankure49a86a2014-11-11 18:52:43 -0800254 if err := server.ServeDispatcher(name, disp); err != nil {
255 t.Errorf("server.ServeDispatcher failed: %v", err)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700256 }
Cosmos Nicolaou9fbe7d22015-01-25 22:13:13 -0800257
258 status := server.Status()
259 if got, want := endpointsToStrings(status.Endpoints), endpointsToStrings(eps); !reflect.DeepEqual(got, want) {
260 t.Fatalf("got %v, want %v", got, want)
261 }
262 names := status.Mounts.Names()
263 if len(names) != 1 || names[0] != name {
264 t.Fatalf("unexpected names: %v", names)
265 }
266 return eps[0], server
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700267}
268
Cosmos Nicolaou9388ae42014-11-10 10:57:15 -0800269func loc(d int) string {
270 _, file, line, _ := runtime.Caller(d + 1)
271 return fmt.Sprintf("%s:%d", filepath.Base(file), line)
272}
273
Todd Wang5082a552015-04-02 10:56:11 -0700274func verifyMount(t *testing.T, ctx *context.T, ns namespace.T, name string) []string {
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700275 me, err := ns.Resolve(ctx, name)
Cosmos Nicolaou9388ae42014-11-10 10:57:15 -0800276 if err != nil {
277 t.Errorf("%s: %s not found in mounttable", loc(1), name)
278 return nil
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700279 }
Cosmos Nicolaou8bd8e102015-01-13 21:52:53 -0800280 return me.Names()
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700281}
282
Todd Wang5082a552015-04-02 10:56:11 -0700283func verifyMountMissing(t *testing.T, ctx *context.T, ns namespace.T, name string) {
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700284 if me, err := ns.Resolve(ctx, name); err == nil {
Cosmos Nicolaou8bd8e102015-01-13 21:52:53 -0800285 names := me.Names()
Asim Shankarb547ea92015-02-17 18:49:45 -0800286 t.Errorf("%s: %s not supposed to be found in mounttable; got %d servers instead: %v (%+v)", loc(1), name, len(names), names, me)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700287 }
288}
289
Todd Wang5082a552015-04-02 10:56:11 -0700290func stopServer(t *testing.T, ctx *context.T, server rpc.Server, ns namespace.T, name string) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700291 vlog.VI(1).Info("server.Stop")
Ankure49a86a2014-11-11 18:52:43 -0800292 new_name := "should_appear_in_mt/server"
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700293 verifyMount(t, ctx, ns, name)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700294
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700295 // publish a second name
Ankure49a86a2014-11-11 18:52:43 -0800296 if err := server.AddName(new_name); err != nil {
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700297 t.Errorf("server.Serve failed: %v", err)
298 }
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700299 verifyMount(t, ctx, ns, new_name)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700300
301 if err := server.Stop(); err != nil {
302 t.Errorf("server.Stop failed: %v", err)
303 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700304
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700305 verifyMountMissing(t, ctx, ns, name)
306 verifyMountMissing(t, ctx, ns, new_name)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700307
308 // Check that we can no longer serve after Stop.
Cosmos Nicolaou92dba582014-11-05 17:24:10 -0800309 err := server.AddName("name doesn't matter")
Todd Wang8fa38762015-03-25 14:04:59 -0700310 if err == nil || verror.ErrorID(err) != verror.ErrBadState.ID {
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700311 t.Errorf("either no error, or a wrong error was returned: %v", err)
312 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700313 vlog.VI(1).Info("server.Stop DONE")
314}
315
Cosmos Nicolaou8bd8e102015-01-13 21:52:53 -0800316// fakeWSName creates a name containing a endpoint address that forces
317// the use of websockets. It does so by resolving the original name
318// and choosing the 'ws' endpoint from the set of endpoints returned.
319// It must return a name since it'll be passed to StartCall.
Todd Wang5082a552015-04-02 10:56:11 -0700320func fakeWSName(ctx *context.T, ns namespace.T, name string) (string, error) {
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800321 // Find the ws endpoint and use that.
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700322 me, err := ns.Resolve(ctx, name)
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800323 if err != nil {
324 return "", err
325 }
Cosmos Nicolaou8bd8e102015-01-13 21:52:53 -0800326 names := me.Names()
327 for _, s := range names {
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800328 if strings.Index(s, "@ws@") != -1 {
329 return s, nil
330 }
331 }
Cosmos Nicolaou8bd8e102015-01-13 21:52:53 -0800332 return "", fmt.Errorf("No ws endpoint found %v", names)
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800333}
334
Bogdan Caprita27953142014-05-12 11:41:42 -0700335type bundle struct {
Matt Rosencrantz94502cf2015-03-18 09:43:44 -0700336 client rpc.Client
337 server rpc.Server
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700338 ep naming.Endpoint
Todd Wang5082a552015-04-02 10:56:11 -0700339 ns namespace.T
Bogdan Caprita27953142014-05-12 11:41:42 -0700340 sm stream.Manager
Ankure49a86a2014-11-11 18:52:43 -0800341 name string
Bogdan Caprita27953142014-05-12 11:41:42 -0700342}
343
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700344func (b bundle) cleanup(t *testing.T, ctx *context.T) {
Ankura3c97652014-07-17 20:01:21 -0700345 if b.server != nil {
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700346 stopServer(t, ctx, b.server, b.ns, b.name)
Ankura3c97652014-07-17 20:01:21 -0700347 }
348 if b.client != nil {
349 b.client.Close()
350 }
Bogdan Caprita27953142014-05-12 11:41:42 -0700351}
352
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700353func createBundle(t *testing.T, ctx *context.T, server security.Principal, ts interface{}) (b bundle) {
354 return createBundleWS(t, ctx, server, ts, noWebsocket)
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800355}
356
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700357func createBundleWS(t *testing.T, ctx *context.T, server security.Principal, ts interface{}, shouldUseWebsocket websocketMode) (b bundle) {
Bogdan Caprita27953142014-05-12 11:41:42 -0700358 b.sm = imanager.InternalNew(naming.FixedRoutingID(0x555555555))
Matt Rosencrantz9fe60822014-09-12 10:09:53 -0700359 b.ns = tnaming.NewSimpleNamespace()
Ankure49a86a2014-11-11 18:52:43 -0800360 b.name = "mountpoint/server"
Asim Shankar8f05c222014-10-06 22:08:19 -0700361 if server != nil {
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700362 b.ep, b.server = startServerWS(t, ctx, server, b.sm, b.ns, b.name, testServerDisp{ts}, shouldUseWebsocket)
Ankura3c97652014-07-17 20:01:21 -0700363 }
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700364 var err error
365 if b.client, err = InternalNewClient(b.sm, b.ns); err != nil {
366 t.Fatalf("InternalNewClient failed: %v", err)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700367 }
Bogdan Caprita27953142014-05-12 11:41:42 -0700368 return
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700369}
370
Cosmos Nicolaou112bf1c2014-11-21 15:43:11 -0800371func matchesErrorPattern(err error, id verror.IDAction, pattern string) bool {
Asim Shankar558ea012015-01-28 12:49:36 -0800372 if len(pattern) > 0 && err != nil && strings.Index(err.Error(), pattern) < 0 {
373 return false
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700374 }
Cosmos Nicolaou1bce7d12015-01-05 17:42:06 -0800375 if err == nil && id.ID == "" {
376 return true
Cosmos Nicolaou112bf1c2014-11-21 15:43:11 -0800377 }
Todd Wang8fa38762015-03-25 14:04:59 -0700378 return verror.ErrorID(err) == id.ID
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700379}
380
Todd Wang5082a552015-04-02 10:56:11 -0700381func runServer(t *testing.T, ctx *context.T, ns namespace.T, principal security.Principal, name string, obj interface{}, opts ...rpc.ServerOpt) stream.Manager {
Suharsh Sivakumar0902b7f2015-02-27 19:06:41 -0800382 rid, err := naming.NewRoutingID()
383 if err != nil {
384 t.Fatal(err)
385 }
386 sm := imanager.InternalNew(rid)
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700387 server, err := testInternalNewServer(ctx, sm, ns, principal, opts...)
Suharsh Sivakumar0902b7f2015-02-27 19:06:41 -0800388 if err != nil {
389 t.Fatal(err)
390 }
391 if _, err := server.Listen(listenSpec); err != nil {
392 t.Fatal(err)
393 }
394 if err := server.Serve(name, obj, acceptAllAuthorizer{}); err != nil {
395 t.Fatal(err)
396 }
397 return sm
398}
399
Cosmos Nicolaou92dba582014-11-05 17:24:10 -0800400func TestMultipleCallsToServeAndName(t *testing.T) {
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700401 sm := imanager.InternalNew(naming.FixedRoutingID(0x555555555))
Matt Rosencrantz9fe60822014-09-12 10:09:53 -0700402 ns := tnaming.NewSimpleNamespace()
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700403 ctx, shutdown := initForTest()
404 defer shutdown()
Asim Shankar4a698282015-03-21 21:59:18 -0700405 server, err := testInternalNewServer(ctx, sm, ns, testutil.NewPrincipal("server"))
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700406 if err != nil {
407 t.Errorf("InternalNewServer failed: %v", err)
408 }
Cosmos Nicolaouf8d4c2b2014-10-23 22:36:38 -0700409 _, err = server.Listen(listenSpec)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700410 if err != nil {
411 t.Errorf("server.Listen failed: %v", err)
412 }
413
414 disp := &testServerDisp{&testServer{}}
Cosmos Nicolaou92dba582014-11-05 17:24:10 -0800415 if err := server.ServeDispatcher("mountpoint/server", disp); err != nil {
416 t.Errorf("server.ServeDispatcher failed: %v", err)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700417 }
418
419 n1 := "mountpoint/server"
420 n2 := "should_appear_in_mt/server"
421 n3 := "should_appear_in_mt/server"
422 n4 := "should_not_appear_in_mt/server"
423
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700424 verifyMount(t, ctx, ns, n1)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700425
Cosmos Nicolaou92dba582014-11-05 17:24:10 -0800426 if server.ServeDispatcher(n2, disp) == nil {
427 t.Errorf("server.ServeDispatcher should have failed")
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700428 }
Cosmos Nicolaou92dba582014-11-05 17:24:10 -0800429
430 if err := server.Serve(n2, &testServer{}, nil); err == nil {
431 t.Errorf("server.Serve should have failed")
432 }
433
434 if err := server.AddName(n3); err != nil {
435 t.Errorf("server.AddName failed: %v", err)
436 }
437
438 if err := server.AddName(n3); err != nil {
439 t.Errorf("server.AddName failed: %v", err)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700440 }
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700441 verifyMount(t, ctx, ns, n2)
442 verifyMount(t, ctx, ns, n3)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700443
Cosmos Nicolaou9fbe7d22015-01-25 22:13:13 -0800444 server.RemoveName(n1)
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700445 verifyMountMissing(t, ctx, ns, n1)
Cosmos Nicolaou92dba582014-11-05 17:24:10 -0800446
Cosmos Nicolaou9fbe7d22015-01-25 22:13:13 -0800447 server.RemoveName("some randome name")
Cosmos Nicolaou92dba582014-11-05 17:24:10 -0800448
449 if err := server.ServeDispatcher(n4, &testServerDisp{&testServer{}}); err == nil {
450 t.Errorf("server.ServeDispatcher should have failed")
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700451 }
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700452 verifyMountMissing(t, ctx, ns, n4)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700453
454 if err := server.Stop(); err != nil {
455 t.Errorf("server.Stop failed: %v", err)
456 }
457
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700458 verifyMountMissing(t, ctx, ns, n1)
459 verifyMountMissing(t, ctx, ns, n2)
460 verifyMountMissing(t, ctx, ns, n3)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700461}
462
Ankure49a86a2014-11-11 18:52:43 -0800463func TestRPCServerAuthorization(t *testing.T) {
Asim Shankar263c73b2015-03-19 18:31:26 -0700464 ctx, shutdown := initForTest()
465 defer shutdown()
466
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700467 const (
Asim Shankar263c73b2015-03-19 18:31:26 -0700468 publicKeyErr = "not matched by server key"
469 missingDischargeErr = "missing discharge"
470 expiryErr = "is after expiry"
471 allowedErr = "do not match any allowed server patterns"
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700472 )
Asim Shankar263c73b2015-03-19 18:31:26 -0700473 type O []rpc.CallOpt // shorthand
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700474 var (
Asim Shankar4a698282015-03-21 21:59:18 -0700475 pprovider, pclient, pserver = testutil.NewPrincipal("root"), testutil.NewPrincipal(), testutil.NewPrincipal()
Ankure49a86a2014-11-11 18:52:43 -0800476 pdischarger = pprovider
Asim Shankar558ea012015-01-28 12:49:36 -0800477 now = time.Now()
478 noErrID verror.IDAction
Ankure49a86a2014-11-11 18:52:43 -0800479
480 // Third-party caveats on blessings presented by server.
Asim Shankar558ea012015-01-28 12:49:36 -0800481 cavTPValid = mkThirdPartyCaveat(pdischarger.PublicKey(), "mountpoint/dischargeserver", mkCaveat(security.ExpiryCaveat(now.Add(24*time.Hour))))
482 cavTPExpired = mkThirdPartyCaveat(pdischarger.PublicKey(), "mountpoint/dischargeserver", mkCaveat(security.ExpiryCaveat(now.Add(-1*time.Second))))
Ankure49a86a2014-11-11 18:52:43 -0800483
484 // Server blessings.
485 bServer = bless(pprovider, pserver, "server")
Asim Shankar263c73b2015-03-19 18:31:26 -0700486 bServerExpired = bless(pprovider, pserver, "expiredserver", mkCaveat(security.ExpiryCaveat(time.Now().Add(-1*time.Second))))
Ankure49a86a2014-11-11 18:52:43 -0800487 bServerTPValid = bless(pprovider, pserver, "serverWithTPCaveats", cavTPValid)
Asim Shankar263c73b2015-03-19 18:31:26 -0700488 bServerTPExpired = bless(pprovider, pserver, "serverWithExpiredTPCaveats", cavTPExpired)
489 bOther = bless(pprovider, pserver, "other")
490 bTwoBlessings, _ = security.UnionOfBlessings(bServer, bOther)
Asim Shankar8f05c222014-10-06 22:08:19 -0700491
492 mgr = imanager.InternalNew(naming.FixedRoutingID(0x1111111))
493 ns = tnaming.NewSimpleNamespace()
494 tests = []struct {
Ankur50a5f392015-02-27 18:46:30 -0800495 server security.Blessings // blessings presented by the server to the client.
496 name string // name provided by the client to StartCall
Asim Shankar263c73b2015-03-19 18:31:26 -0700497 opts O // options provided to StartCall.
Ankur50a5f392015-02-27 18:46:30 -0800498 errID verror.IDAction
499 err string
Asim Shankar8f05c222014-10-06 22:08:19 -0700500 }{
Asim Shankar558ea012015-01-28 12:49:36 -0800501 // Client accepts talking to the server only if the
Asim Shankar263c73b2015-03-19 18:31:26 -0700502 // server presents valid blessings (and discharges)
503 // consistent with the ones published in the endpoint.
504 {bServer, "mountpoint/server", nil, noErrID, ""},
505 {bServerTPValid, "mountpoint/server", nil, noErrID, ""},
Asim Shankar8f05c222014-10-06 22:08:19 -0700506
Asim Shankar263c73b2015-03-19 18:31:26 -0700507 // Client will not talk to a server that presents
508 // expired blessings or is missing discharges.
509 {bServerExpired, "mountpoint/server", nil, verror.ErrNotTrusted, expiryErr},
510 {bServerTPExpired, "mountpoint/server", nil, verror.ErrNotTrusted, missingDischargeErr},
Asim Shankar558ea012015-01-28 12:49:36 -0800511
512 // Testing the AllowedServersPolicy option.
Asim Shankar263c73b2015-03-19 18:31:26 -0700513 {bServer, "mountpoint/server", O{options.AllowedServersPolicy{"otherroot"}}, verror.ErrNotTrusted, allowedErr},
514 {bServer, "mountpoint/server", O{options.AllowedServersPolicy{"root"}}, noErrID, ""},
515 {bTwoBlessings, "mountpoint/server", O{options.AllowedServersPolicy{"root/other"}}, noErrID, ""},
Ankur50a5f392015-02-27 18:46:30 -0800516
517 // Test the ServerPublicKey option.
Asim Shankar263c73b2015-03-19 18:31:26 -0700518 {bOther, "mountpoint/server", O{options.SkipServerEndpointAuthorization{}, options.ServerPublicKey{bOther.PublicKey()}}, noErrID, ""},
Asim Shankar4a698282015-03-21 21:59:18 -0700519 {bOther, "mountpoint/server", O{options.SkipServerEndpointAuthorization{}, options.ServerPublicKey{testutil.NewPrincipal("irrelevant").PublicKey()}}, verror.ErrNotTrusted, publicKeyErr},
Asim Shankar263c73b2015-03-19 18:31:26 -0700520
521 // Test the "paranoid" names, where the pattern is provided in the name.
522 {bServer, "__(root/server)/mountpoint/server", nil, noErrID, ""},
523 {bServer, "__(root/other)/mountpoint/server", nil, verror.ErrNotTrusted, allowedErr},
524 {bTwoBlessings, "__(root/server)/mountpoint/server", O{options.AllowedServersPolicy{"root/other"}}, noErrID, ""},
Asim Shankar8f05c222014-10-06 22:08:19 -0700525 }
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700526 )
Ankure49a86a2014-11-11 18:52:43 -0800527 // Start the discharge server.
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700528 _, dischargeServer := startServer(t, ctx, pdischarger, mgr, ns, "mountpoint/dischargeserver", testutil.LeafDispatcher(&dischargeServer{}, &acceptAllAuthorizer{}))
529 defer stopServer(t, ctx, dischargeServer, ns, "mountpoint/dischargeserver")
Ankure49a86a2014-11-11 18:52:43 -0800530
Asim Shankar558ea012015-01-28 12:49:36 -0800531 // Make the client and server principals trust root certificates from
532 // pprovider
Asim Shankar8f05c222014-10-06 22:08:19 -0700533 pclient.AddToRoots(pprovider.BlessingStore().Default())
534 pserver.AddToRoots(pprovider.BlessingStore().Default())
Asim Shankar263c73b2015-03-19 18:31:26 -0700535 // Set a blessing that the client is willing to share with servers
536 // (that are blessed by pprovider).
Ankur78b8b2a2015-02-04 20:16:28 -0800537 pclient.BlessingStore().Set(bless(pprovider, pclient, "client"), "root")
Asim Shankar558ea012015-01-28 12:49:36 -0800538
Asim Shankar263c73b2015-03-19 18:31:26 -0700539 clientCtx, _ := v23.SetPrincipal(ctx, pclient)
540 client, err := InternalNewClient(mgr, ns)
541 if err != nil {
542 t.Fatal(err)
543 }
544 defer client.Close()
545
546 var server rpc.Server
547 stop := func() {
548 if server != nil {
549 stopServer(t, ctx, server, ns, "mountpoint/server")
550 }
551 }
552 defer stop()
Cosmos Nicolaou112bf1c2014-11-21 15:43:11 -0800553 for i, test := range tests {
Asim Shankar263c73b2015-03-19 18:31:26 -0700554 stop() // Stop any server started in the previous test.
555 name := fmt.Sprintf("(#%d: Name:%q, Server:%q, opts:%v)", i, test.name, test.server, test.opts)
Ankure49a86a2014-11-11 18:52:43 -0800556 if err := pserver.BlessingStore().SetDefault(test.server); err != nil {
557 t.Fatalf("SetDefault failed on server's BlessingStore: %v", err)
558 }
Ankur78b8b2a2015-02-04 20:16:28 -0800559 if _, err := pserver.BlessingStore().Set(test.server, "root"); err != nil {
Ankure49a86a2014-11-11 18:52:43 -0800560 t.Fatalf("Set failed on server's BlessingStore: %v", err)
561 }
Asim Shankar263c73b2015-03-19 18:31:26 -0700562 _, server = startServer(t, ctx, pserver, mgr, ns, "mountpoint/server", testServerDisp{&testServer{}})
563 clientCtx, cancel := context.WithCancel(clientCtx)
564 call, err := client.StartCall(clientCtx, test.name, "Method", nil, test.opts...)
Cosmos Nicolaou112bf1c2014-11-21 15:43:11 -0800565 if !matchesErrorPattern(err, test.errID, test.err) {
Asim Shankarb547ea92015-02-17 18:49:45 -0800566 t.Errorf(`%s: client.StartCall: got error "%v", want to match "%v"`, name, err, test.err)
Asim Shankar2d731a92014-09-29 17:46:38 -0700567 } else if call != nil {
Asim Shankar8f05c222014-10-06 22:08:19 -0700568 blessings, proof := call.RemoteBlessings()
Asim Shankar2bf7b1e2015-02-27 00:45:12 -0800569 if proof.IsZero() {
570 t.Errorf("%s: Returned zero value for remote blessings", name)
Asim Shankar8f05c222014-10-06 22:08:19 -0700571 }
Asim Shankar558ea012015-01-28 12:49:36 -0800572 // Currently all tests are configured so that the only
573 // blessings presented by the server that are
574 // recognized by the client match the pattern
Ankur78b8b2a2015-02-04 20:16:28 -0800575 // "root"
576 if len(blessings) < 1 || !security.BlessingPattern("root").MatchedBy(blessings...) {
577 t.Errorf("%s: Client sees server as %v, expected a single blessing matching root", name, blessings)
Asim Shankar2d731a92014-09-29 17:46:38 -0700578 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700579 }
Matt Rosencrantzcc922c12014-11-28 20:28:59 -0800580 cancel()
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700581 }
582}
583
Asim Shankarb547ea92015-02-17 18:49:45 -0800584func TestServerManInTheMiddleAttack(t *testing.T) {
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700585 ctx, shutdown := initForTest()
586 defer shutdown()
Asim Shankar263c73b2015-03-19 18:31:26 -0700587 // Test scenario: A server mounts itself, but then some other service
588 // somehow "takes over" the network endpoint (a naughty router
589 // perhaps), thus trying to steal traffic.
590 var (
Asim Shankar4a698282015-03-21 21:59:18 -0700591 pclient = testutil.NewPrincipal("client")
592 pserver = testutil.NewPrincipal("server")
593 pattacker = testutil.NewPrincipal("attacker")
Asim Shankar263c73b2015-03-19 18:31:26 -0700594 )
595 // Client recognizes both the server and the attacker's blessings.
596 // (Though, it doesn't need to do the latter for the purposes of this
597 // test).
598 pclient.AddToRoots(pserver.BlessingStore().Default())
599 pclient.AddToRoots(pattacker.BlessingStore().Default())
Asim Shankarb547ea92015-02-17 18:49:45 -0800600
601 // Start up the attacker's server.
602 attacker, err := testInternalNewServer(
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700603 ctx,
Asim Shankarb547ea92015-02-17 18:49:45 -0800604 imanager.InternalNew(naming.FixedRoutingID(0xaaaaaaaaaaaaaaaa)),
605 // (To prevent the attacker for legitimately mounting on the
606 // namespace that the client will use, provide it with a
607 // different namespace).
608 tnaming.NewSimpleNamespace(),
Asim Shankar263c73b2015-03-19 18:31:26 -0700609 pattacker)
Asim Shankarb547ea92015-02-17 18:49:45 -0800610 if err != nil {
611 t.Fatal(err)
612 }
613 if _, err := attacker.Listen(listenSpec); err != nil {
614 t.Fatal(err)
615 }
616 if err := attacker.ServeDispatcher("mountpoint/server", testServerDisp{&testServer{}}); err != nil {
617 t.Fatal(err)
618 }
619 var ep naming.Endpoint
620 if status := attacker.Status(); len(status.Endpoints) < 1 {
621 t.Fatalf("Attacker server does not have an endpoint: %+v", status)
622 } else {
623 ep = status.Endpoints[0]
624 }
625
626 // The legitimate server would have mounted the same endpoint on the
Asim Shankar263c73b2015-03-19 18:31:26 -0700627 // namespace, but with different blessings.
Asim Shankarb547ea92015-02-17 18:49:45 -0800628 ns := tnaming.NewSimpleNamespace()
Asim Shankar263c73b2015-03-19 18:31:26 -0700629 ep.(*inaming.Endpoint).Blessings = []string{"server"}
630 if err := ns.Mount(ctx, "mountpoint/server", ep.Name(), time.Hour); err != nil {
Asim Shankarb547ea92015-02-17 18:49:45 -0800631 t.Fatal(err)
632 }
633
634 // The RPC call should fail because the blessings presented by the
635 // (attacker's) server are not consistent with the ones registered in
636 // the mounttable trusted by the client.
637 client, err := InternalNewClient(
638 imanager.InternalNew(naming.FixedRoutingID(0xcccccccccccccccc)),
Asim Shankar263c73b2015-03-19 18:31:26 -0700639 ns)
Asim Shankarb547ea92015-02-17 18:49:45 -0800640 if err != nil {
641 t.Fatal(err)
642 }
643 defer client.Close()
Asim Shankar263c73b2015-03-19 18:31:26 -0700644 ctx, _ = v23.SetPrincipal(ctx, pclient)
Todd Wang8fa38762015-03-25 14:04:59 -0700645 if _, err := client.StartCall(ctx, "mountpoint/server", "Closure", nil); verror.ErrorID(err) != verror.ErrNotTrusted.ID {
Asim Shankarb547ea92015-02-17 18:49:45 -0800646 t.Errorf("Got error %v (errorid=%v), want errorid=%v", err, verror.ErrorID(err), verror.ErrNotTrusted.ID)
647 }
648 // But the RPC should succeed if the client explicitly
649 // decided to skip server authorization.
Asim Shankar263c73b2015-03-19 18:31:26 -0700650 if _, err := client.StartCall(ctx, "mountpoint/server", "Closure", nil, options.SkipServerEndpointAuthorization{}); err != nil {
Asim Shankarb547ea92015-02-17 18:49:45 -0800651 t.Errorf("Unexpected error(%v) when skipping server authorization", err)
652 }
653}
654
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800655type websocketMode bool
656type closeSendMode bool
657
658const (
659 useWebsocket websocketMode = true
660 noWebsocket websocketMode = false
661
662 closeSend closeSendMode = true
663 noCloseSend closeSendMode = false
664)
665
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700666func TestRPC(t *testing.T) {
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800667 testRPC(t, closeSend, noWebsocket)
668}
669
670func TestRPCWithWebsocket(t *testing.T) {
671 testRPC(t, closeSend, useWebsocket)
Tilak Sharma0c766112014-05-20 17:47:27 -0700672}
673
674// TestCloseSendOnFinish tests that Finish informs the server that no more
675// inputs will be sent by the client if CloseSend has not already done so.
676func TestRPCCloseSendOnFinish(t *testing.T) {
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800677 testRPC(t, noCloseSend, noWebsocket)
Tilak Sharma0c766112014-05-20 17:47:27 -0700678}
679
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800680func TestRPCCloseSendOnFinishWithWebsocket(t *testing.T) {
681 testRPC(t, noCloseSend, useWebsocket)
682}
683
684func testRPC(t *testing.T, shouldCloseSend closeSendMode, shouldUseWebsocket websocketMode) {
Asim Shankar263c73b2015-03-19 18:31:26 -0700685 ctx, shutdown := initForTest()
686 defer shutdown()
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700687 type v []interface{}
688 type testcase struct {
689 name string
690 method string
691 args v
692 streamArgs v
693 startErr error
694 results v
695 finishErr error
696 }
Asim Shankar8f05c222014-10-06 22:08:19 -0700697 var (
698 tests = []testcase{
699 {"mountpoint/server/suffix", "Closure", nil, nil, nil, nil, nil},
Todd Wange77f9952015-02-18 13:20:50 -0800700 {"mountpoint/server/suffix", "Error", nil, nil, nil, nil, errMethod},
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700701
Asim Shankar8f05c222014-10-06 22:08:19 -0700702 {"mountpoint/server/suffix", "Echo", v{"foo"}, nil, nil, v{`method:"Echo",suffix:"suffix",arg:"foo"`}, nil},
703 {"mountpoint/server/suffix/abc", "Echo", v{"bar"}, nil, nil, v{`method:"Echo",suffix:"suffix/abc",arg:"bar"`}, nil},
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700704
Asim Shankar8f05c222014-10-06 22:08:19 -0700705 {"mountpoint/server/suffix", "EchoUser", v{"foo", userType("bar")}, nil, nil, v{`method:"EchoUser",suffix:"suffix",arg:"foo"`, userType("bar")}, nil},
706 {"mountpoint/server/suffix/abc", "EchoUser", v{"baz", userType("bla")}, nil, nil, v{`method:"EchoUser",suffix:"suffix/abc",arg:"baz"`, userType("bla")}, nil},
Todd Wange77f9952015-02-18 13:20:50 -0800707 {"mountpoint/server/suffix", "Stream", v{"foo"}, v{userType("bar"), userType("baz")}, nil, v{`method:"Stream",suffix:"suffix",arg:"foo" bar baz`}, nil},
708 {"mountpoint/server/suffix/abc", "Stream", v{"123"}, v{userType("456"), userType("789")}, nil, v{`method:"Stream",suffix:"suffix/abc",arg:"123" 456 789`}, nil},
Asim Shankar8f05c222014-10-06 22:08:19 -0700709 {"mountpoint/server/suffix", "EchoBlessings", nil, nil, nil, v{"[server]", "[client]"}, nil},
Todd Wange77f9952015-02-18 13:20:50 -0800710 {"mountpoint/server/suffix", "EchoAndError", v{"bugs bunny"}, nil, nil, v{`method:"EchoAndError",suffix:"suffix",arg:"bugs bunny"`}, nil},
711 {"mountpoint/server/suffix", "EchoAndError", v{"error"}, nil, nil, nil, errMethod},
Asim Shankar8f05c222014-10-06 22:08:19 -0700712 }
713 name = func(t testcase) string {
714 return fmt.Sprintf("%s.%s(%v)", t.name, t.method, t.args)
715 }
716
Asim Shankar263c73b2015-03-19 18:31:26 -0700717 pclient, pserver = newClientServerPrincipals()
718 b = createBundleWS(t, ctx, pserver, &testServer{}, shouldUseWebsocket)
Asim Shankar8f05c222014-10-06 22:08:19 -0700719 )
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700720 defer b.cleanup(t, ctx)
721 ctx, _ = v23.SetPrincipal(ctx, pclient)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700722 for _, test := range tests {
723 vlog.VI(1).Infof("%s client.StartCall", name(test))
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800724 vname := test.name
725 if shouldUseWebsocket {
726 var err error
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700727 vname, err = fakeWSName(ctx, b.ns, vname)
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800728 if err != nil && err != test.startErr {
729 t.Errorf(`%s ns.Resolve got error "%v", want "%v"`, name(test), err, test.startErr)
730 continue
731 }
732 }
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700733 call, err := b.client.StartCall(ctx, vname, test.method, test.args)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700734 if err != test.startErr {
735 t.Errorf(`%s client.StartCall got error "%v", want "%v"`, name(test), err, test.startErr)
736 continue
737 }
738 for _, sarg := range test.streamArgs {
739 vlog.VI(1).Infof("%s client.Send(%v)", name(test), sarg)
740 if err := call.Send(sarg); err != nil {
741 t.Errorf(`%s call.Send(%v) got unexpected error "%v"`, name(test), sarg, err)
742 }
743 var u userType
744 if err := call.Recv(&u); err != nil {
745 t.Errorf(`%s call.Recv(%v) got unexpected error "%v"`, name(test), sarg, err)
746 }
747 if !reflect.DeepEqual(u, sarg) {
748 t.Errorf("%s call.Recv got value %v, want %v", name(test), u, sarg)
749 }
750 }
Tilak Sharma0c766112014-05-20 17:47:27 -0700751 if shouldCloseSend {
752 vlog.VI(1).Infof("%s call.CloseSend", name(test))
Asim Shankar062d4222014-08-18 11:14:42 -0700753 // When the method does not involve streaming
754 // arguments, the server gets all the arguments in
755 // StartCall and then sends a response without
756 // (unnecessarily) waiting for a CloseSend message from
757 // the client. If the server responds before the
758 // CloseSend call is made at the client, the CloseSend
759 // call will fail. Thus, only check for errors on
760 // CloseSend if there are streaming arguments to begin
761 // with (i.e., only if the server is expected to wait
762 // for the CloseSend notification).
763 if err := call.CloseSend(); err != nil && len(test.streamArgs) > 0 {
Tilak Sharma0c766112014-05-20 17:47:27 -0700764 t.Errorf(`%s call.CloseSend got unexpected error "%v"`, name(test), err)
765 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700766 }
767 vlog.VI(1).Infof("%s client.Finish", name(test))
768 results := makeResultPtrs(test.results)
769 err = call.Finish(results...)
Todd Wange77f9952015-02-18 13:20:50 -0800770 if got, want := err, test.finishErr; (got == nil) != (want == nil) {
771 t.Errorf(`%s call.Finish got error "%v", want "%v'`, name(test), got, want)
Todd Wang8fa38762015-03-25 14:04:59 -0700772 } else if want != nil && verror.ErrorID(got) != verror.ErrorID(want) {
Todd Wange77f9952015-02-18 13:20:50 -0800773 t.Errorf(`%s call.Finish got error "%v", want "%v"`, name(test), got, want)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700774 }
775 checkResultPtrs(t, name(test), results, test.results)
776 }
777}
778
Ken Ashcraft2b8309a2014-09-09 10:44:43 -0700779func TestMultipleFinish(t *testing.T) {
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700780 ctx, shutdown := initForTest()
781 defer shutdown()
Ken Ashcraft2b8309a2014-09-09 10:44:43 -0700782 type v []interface{}
Asim Shankar263c73b2015-03-19 18:31:26 -0700783 var (
784 pclient, pserver = newClientServerPrincipals()
785 b = createBundle(t, ctx, pserver, &testServer{})
786 )
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700787 defer b.cleanup(t, ctx)
Asim Shankar263c73b2015-03-19 18:31:26 -0700788 ctx, _ = v23.SetPrincipal(ctx, pclient)
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700789 call, err := b.client.StartCall(ctx, "mountpoint/server/suffix", "Echo", v{"foo"})
Ken Ashcraft2b8309a2014-09-09 10:44:43 -0700790 if err != nil {
791 t.Fatalf(`client.StartCall got error "%v"`, err)
792 }
793 var results string
794 err = call.Finish(&results)
795 if err != nil {
796 t.Fatalf(`call.Finish got error "%v"`, err)
797 }
798 // Calling Finish a second time should result in a useful error.
Jiri Simsa074bf362015-02-17 09:29:45 -0800799 if err = call.Finish(&results); !matchesErrorPattern(err, verror.ErrBadState, "Finish has already been called") {
800 t.Fatalf(`got "%v", want "%v"`, err, verror.ErrBadState)
Ken Ashcraft2b8309a2014-09-09 10:44:43 -0700801 }
802}
803
Ankurdda16492015-04-07 12:35:42 -0700804// granter implements rpc.Granter.
805//
806// It returns the specified (security.Blessings, error) pair if either the
807// blessing or the error is specified. Otherwise it returns a blessing
808// derived from the local blessings of the current call.
Asim Shankarb54d7642014-06-05 13:08:04 -0700809type granter struct {
Matt Rosencrantz94502cf2015-03-18 09:43:44 -0700810 rpc.CallOpt
Asim Shankar8f05c222014-10-06 22:08:19 -0700811 b security.Blessings
Asim Shankarb54d7642014-06-05 13:08:04 -0700812 err error
813}
814
Ankurdda16492015-04-07 12:35:42 -0700815func (g granter) Grant(ctx *context.T) (security.Blessings, error) {
816 if !g.b.IsZero() || g.err != nil {
817 return g.b, g.err
818 }
819 call := security.GetCall(ctx)
820 return call.LocalPrincipal().Bless(call.RemoteBlessings().PublicKey(), call.LocalBlessings(), "blessed", security.UnconstrainedUse())
821}
Asim Shankarb54d7642014-06-05 13:08:04 -0700822
Asim Shankar8f05c222014-10-06 22:08:19 -0700823func TestGranter(t *testing.T) {
824 var (
Asim Shankar263c73b2015-03-19 18:31:26 -0700825 pclient, pserver = newClientServerPrincipals()
826 ctx, shutdown = initForTest()
827 b = createBundle(t, ctx, pserver, &testServer{})
Asim Shankar8f05c222014-10-06 22:08:19 -0700828 )
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700829 defer shutdown()
830 defer b.cleanup(t, ctx)
831
832 ctx, _ = v23.SetPrincipal(ctx, pclient)
Asim Shankarb54d7642014-06-05 13:08:04 -0700833 tests := []struct {
Matt Rosencrantz94502cf2015-03-18 09:43:44 -0700834 granter rpc.Granter
Cosmos Nicolaou112bf1c2014-11-21 15:43:11 -0800835 startErrID, finishErrID verror.IDAction
Asim Shankarb54d7642014-06-05 13:08:04 -0700836 blessing, starterr, finisherr string
837 }{
Asim Shankar2bf7b1e2015-02-27 00:45:12 -0800838 {blessing: ""},
Asim Shankarb18a44f2014-10-21 20:25:07 -0700839 {granter: granter{b: bless(pclient, pserver, "blessed")}, blessing: "client/blessed"},
Jiri Simsa074bf362015-02-17 09:29:45 -0800840 {granter: granter{err: errors.New("hell no")}, startErrID: verror.ErrNotTrusted, starterr: "hell no"},
Ankurdda16492015-04-07 12:35:42 -0700841 {granter: granter{}, blessing: "client/blessed"},
Jiri Simsa074bf362015-02-17 09:29:45 -0800842 {granter: granter{b: pclient.BlessingStore().Default()}, finishErrID: verror.ErrNoAccess, finisherr: "blessing granted not bound to this server"},
Asim Shankarb54d7642014-06-05 13:08:04 -0700843 }
Cosmos Nicolaou112bf1c2014-11-21 15:43:11 -0800844 for i, test := range tests {
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700845 call, err := b.client.StartCall(ctx, "mountpoint/server/suffix", "EchoGrantedBlessings", []interface{}{"argument"}, test.granter)
Cosmos Nicolaou112bf1c2014-11-21 15:43:11 -0800846 if !matchesErrorPattern(err, test.startErrID, test.starterr) {
847 t.Errorf("%d: %+v: StartCall returned error %v", i, test, err)
Asim Shankarb54d7642014-06-05 13:08:04 -0700848 }
849 if err != nil {
850 continue
851 }
852 var result, blessing string
Cosmos Nicolaou112bf1c2014-11-21 15:43:11 -0800853 if err = call.Finish(&result, &blessing); !matchesErrorPattern(err, test.finishErrID, test.finisherr) {
Asim Shankarb54d7642014-06-05 13:08:04 -0700854 t.Errorf("%+v: Finish returned error %v", test, err)
855 }
856 if err != nil {
857 continue
858 }
859 if result != "argument" || blessing != test.blessing {
860 t.Errorf("%+v: Got (%q, %q)", test, result, blessing)
861 }
862 }
863}
864
Asim Shankarf4864f42014-11-25 18:53:05 -0800865// dischargeTestServer implements the discharge service. Always fails to
866// issue a discharge, but records the impetus and traceid of the RPC call.
867type dischargeTestServer struct {
868 p security.Principal
869 impetus []security.DischargeImpetus
Benjamin Prosnitzc97fe192015-02-03 10:33:25 -0800870 traceid []uniqueid.Id
Asim Shankara94e5072014-08-19 18:18:36 -0700871}
872
Matt Rosencrantz94502cf2015-03-18 09:43:44 -0700873func (s *dischargeTestServer) Discharge(call rpc.ServerCall, cav security.Caveat, impetus security.DischargeImpetus) (security.Discharge, error) {
Asim Shankarc8cfcf12014-11-20 12:26:58 -0800874 s.impetus = append(s.impetus, impetus)
Matt Rosencrantz9dce9b22015-03-02 10:48:37 -0800875 s.traceid = append(s.traceid, vtrace.GetSpan(call.Context()).Trace())
Asim Shankar08642822015-03-02 21:21:09 -0800876 return security.Discharge{}, fmt.Errorf("discharges not issued")
Asim Shankara94e5072014-08-19 18:18:36 -0700877}
878
Benjamin Prosnitzc97fe192015-02-03 10:33:25 -0800879func (s *dischargeTestServer) Release() ([]security.DischargeImpetus, []uniqueid.Id) {
Asim Shankarf4864f42014-11-25 18:53:05 -0800880 impetus, traceid := s.impetus, s.traceid
881 s.impetus, s.traceid = nil, nil
882 return impetus, traceid
Asim Shankarc8cfcf12014-11-20 12:26:58 -0800883}
884
Asim Shankarf4864f42014-11-25 18:53:05 -0800885func TestDischargeImpetusAndContextPropagation(t *testing.T) {
Asim Shankar263c73b2015-03-19 18:31:26 -0700886 ctx, shutdown := initForTest()
887 defer shutdown()
Asim Shankara94e5072014-08-19 18:18:36 -0700888 var (
Asim Shankar4a698282015-03-21 21:59:18 -0700889 pserver = testutil.NewPrincipal("server")
890 pdischarger = testutil.NewPrincipal("discharger")
891 pclient = testutil.NewPrincipal("client")
Asim Shankar8f05c222014-10-06 22:08:19 -0700892 sm = imanager.InternalNew(naming.FixedRoutingID(0x555555555))
893 ns = tnaming.NewSimpleNamespace()
Asim Shankara94e5072014-08-19 18:18:36 -0700894
Asim Shankar263c73b2015-03-19 18:31:26 -0700895 // Setup the client so that it shares a blessing with a third-party caveat with the server.
896 setClientBlessings = func(req security.ThirdPartyRequirements) security.Principal {
Asim Shankar7283dd82015-02-03 19:35:58 -0800897 cav, err := security.NewPublicKeyCaveat(pdischarger.PublicKey(), "mountpoint/discharger", req, security.UnconstrainedUse())
Asim Shankara94e5072014-08-19 18:18:36 -0700898 if err != nil {
Asim Shankar8f05c222014-10-06 22:08:19 -0700899 t.Fatalf("Failed to create ThirdPartyCaveat(%+v): %v", req, err)
Asim Shankara94e5072014-08-19 18:18:36 -0700900 }
Asim Shankarf4864f42014-11-25 18:53:05 -0800901 b, err := pclient.BlessSelf("client_for_server", cav)
Asim Shankar8f05c222014-10-06 22:08:19 -0700902 if err != nil {
903 t.Fatalf("BlessSelf failed: %v", err)
904 }
Asim Shankar8f05c222014-10-06 22:08:19 -0700905 pclient.BlessingStore().Set(b, "server")
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700906 return pclient
Asim Shankara94e5072014-08-19 18:18:36 -0700907 }
908 )
Asim Shankarf4864f42014-11-25 18:53:05 -0800909 // Initialize the client principal.
910 // It trusts both the application server and the discharger.
911 pclient.AddToRoots(pserver.BlessingStore().Default())
912 pclient.AddToRoots(pdischarger.BlessingStore().Default())
Asim Shankarf4864f42014-11-25 18:53:05 -0800913
914 // Setup the discharge server.
915 var tester dischargeTestServer
Suharsh Sivakumar59c423c2015-03-11 14:06:03 -0700916 dischargeServer, err := testInternalNewServer(ctx, sm, ns, pdischarger)
Asim Shankara94e5072014-08-19 18:18:36 -0700917 if err != nil {
918 t.Fatal(err)
919 }
Asim Shankarf4864f42014-11-25 18:53:05 -0800920 defer dischargeServer.Stop()
921 if _, err := dischargeServer.Listen(listenSpec); err != nil {
922 t.Fatal(err)
923 }
924 if err := dischargeServer.Serve("mountpoint/discharger", &tester, &testServerAuthorizer{}); err != nil {
Asim Shankara94e5072014-08-19 18:18:36 -0700925 t.Fatal(err)
926 }
927
Asim Shankarf4864f42014-11-25 18:53:05 -0800928 // Setup the application server.
Suharsh Sivakumar59c423c2015-03-11 14:06:03 -0700929 appServer, err := testInternalNewServer(ctx, sm, ns, pserver)
Asim Shankarf4864f42014-11-25 18:53:05 -0800930 if err != nil {
931 t.Fatal(err)
932 }
933 defer appServer.Stop()
Cosmos Nicolaou28dabfc2014-12-15 22:51:07 -0800934 eps, err := appServer.Listen(listenSpec)
Asim Shankarf4864f42014-11-25 18:53:05 -0800935 if err != nil {
936 t.Fatal(err)
937 }
938 // TODO(bjornick,cnicolaou,ashankar): This is a hack to workaround the
939 // fact that a single Listen on the "tcp" protocol followed by a call
940 // to Serve(<name>, ...) transparently creates two endpoints (one for
941 // tcp, one for websockets) and maps both to <name> via a mount.
942 // Because all endpoints to a name are tried in a parallel, this
943 // transparency makes this test hard to follow (many discharge fetch
944 // attempts are made - one for VIF authentication, one for VC
945 // authentication and one for the actual RPC - and having them be made
946 // to two different endpoints in parallel leads to a lot of
947 // non-determinism). The last plan of record known by the author of
948 // this comment was to stop this sly creation of two endpoints and
949 // require that they be done explicitly. When that happens, this hack
950 // can go away, but till then, this workaround allows the test to be
951 // more predictable by ensuring there is only one VIF/VC/Flow to the
952 // server.
Cosmos Nicolaou28dabfc2014-12-15 22:51:07 -0800953 object := naming.JoinAddressName(eps[0].String(), "object") // instead of "mountpoint/object"
Asim Shankarf4864f42014-11-25 18:53:05 -0800954 if err := appServer.Serve("mountpoint/object", &testServer{}, &testServerAuthorizer{}); err != nil {
955 t.Fatal(err)
956 }
Asim Shankara94e5072014-08-19 18:18:36 -0700957 tests := []struct {
958 Requirements security.ThirdPartyRequirements
959 Impetus security.DischargeImpetus
960 }{
961 { // No requirements, no impetus
962 Requirements: security.ThirdPartyRequirements{},
963 Impetus: security.DischargeImpetus{},
964 },
965 { // Require everything
966 Requirements: security.ThirdPartyRequirements{ReportServer: true, ReportMethod: true, ReportArguments: true},
Todd Wangb31da592015-02-20 12:50:39 -0800967 Impetus: security.DischargeImpetus{Server: []security.BlessingPattern{"server"}, Method: "Method", Arguments: []*vdl.Value{vdl.StringValue("argument")}},
Asim Shankara94e5072014-08-19 18:18:36 -0700968 },
969 { // Require only the method name
970 Requirements: security.ThirdPartyRequirements{ReportMethod: true},
971 Impetus: security.DischargeImpetus{Method: "Method"},
972 },
973 }
974
Ankur50a5f392015-02-27 18:46:30 -0800975 for _, test := range tests {
Asim Shankar263c73b2015-03-19 18:31:26 -0700976 pclient := setClientBlessings(test.Requirements)
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -0700977 ctx, _ = v23.SetPrincipal(ctx, pclient)
978 client, err := InternalNewClient(sm, ns)
Asim Shankara94e5072014-08-19 18:18:36 -0700979 if err != nil {
980 t.Fatalf("InternalNewClient(%+v) failed: %v", test.Requirements, err)
981 }
982 defer client.Close()
Matt Rosencrantz5f98d942015-01-08 13:48:30 -0800983 tid := vtrace.GetSpan(ctx).Trace()
Asim Shankara94e5072014-08-19 18:18:36 -0700984 // StartCall should fetch the discharge, do not worry about finishing the RPC - do not care about that for this test.
Asim Shankarf4864f42014-11-25 18:53:05 -0800985 if _, err := client.StartCall(ctx, object, "Method", []interface{}{"argument"}); err != nil {
Asim Shankara94e5072014-08-19 18:18:36 -0700986 t.Errorf("StartCall(%+v) failed: %v", test.Requirements, err)
987 continue
988 }
Asim Shankarf4864f42014-11-25 18:53:05 -0800989 impetus, traceid := tester.Release()
Ankur50a5f392015-02-27 18:46:30 -0800990 // There should have been exactly 1 attempt to fetch discharges when making
991 // the RPC to the remote object.
992 if len(impetus) != 1 || len(traceid) != 1 {
993 t.Errorf("Test %+v: Got (%d, %d) (#impetus, #traceid), wanted exactly one", test.Requirements, len(impetus), len(traceid))
Asim Shankarf4864f42014-11-25 18:53:05 -0800994 continue
995 }
996 // VC creation does not have any "impetus", it is established without
997 // knowledge of the context of the RPC. So ignore that.
998 //
999 // TODO(ashankar): Should the impetus of the RPC that initiated the
1000 // VIF/VC creation be propagated?
1001 if got, want := impetus[len(impetus)-1], test.Impetus; !reflect.DeepEqual(got, want) {
1002 t.Errorf("Test %+v: Got impetus %v, want %v", test.Requirements, got, want)
1003 }
1004 // But the context used for all of this should be the same
1005 // (thereby allowing debug traces to link VIF/VC creation with
1006 // the RPC that initiated them).
1007 for idx, got := range traceid {
1008 if !reflect.DeepEqual(got, tid) {
1009 t.Errorf("Test %+v: %d - Got trace id %q, want %q", test.Requirements, idx, hex.EncodeToString(got[:]), hex.EncodeToString(tid[:]))
1010 }
Asim Shankara94e5072014-08-19 18:18:36 -07001011 }
1012 }
1013}
1014
Ankure49a86a2014-11-11 18:52:43 -08001015func TestRPCClientAuthorization(t *testing.T) {
1016 type v []interface{}
Andres Erbsenb7f95f32014-07-07 12:07:56 -07001017 var (
Asim Shankar8f05c222014-10-06 22:08:19 -07001018 // Principals
Asim Shankar4a698282015-03-21 21:59:18 -07001019 pclient, pserver = testutil.NewPrincipal("client"), testutil.NewPrincipal("server")
1020 pdischarger = testutil.NewPrincipal("discharger")
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001021
Asim Shankar8f05c222014-10-06 22:08:19 -07001022 now = time.Now()
1023
Ankure49a86a2014-11-11 18:52:43 -08001024 serverName = "mountpoint/server"
1025 dischargeServerName = "mountpoint/dischargeserver"
1026
Asim Shankar8f05c222014-10-06 22:08:19 -07001027 // Caveats on blessings to the client: First-party caveats
1028 cavOnlyEcho = mkCaveat(security.MethodCaveat("Echo"))
1029 cavExpired = mkCaveat(security.ExpiryCaveat(now.Add(-1 * time.Second)))
1030 // Caveats on blessings to the client: Third-party caveats
Ankuredd74ee2015-03-04 16:38:45 -08001031 cavTPValid = mkThirdPartyCaveat(pdischarger.PublicKey(), dischargeServerName, mkCaveat(security.ExpiryCaveat(now.Add(24*time.Hour))))
1032 cavTPExpired = mkThirdPartyCaveat(pdischarger.PublicKey(), dischargeServerName, mkCaveat(security.ExpiryCaveat(now.Add(-1*time.Second))))
Asim Shankar8f05c222014-10-06 22:08:19 -07001033
1034 // Client blessings that will be tested.
1035 bServerClientOnlyEcho = bless(pserver, pclient, "onlyecho", cavOnlyEcho)
1036 bServerClientExpired = bless(pserver, pclient, "expired", cavExpired)
1037 bServerClientTPValid = bless(pserver, pclient, "dischargeable_third_party_caveat", cavTPValid)
1038 bServerClientTPExpired = bless(pserver, pclient, "expired_third_party_caveat", cavTPExpired)
1039 bClient = pclient.BlessingStore().Default()
1040 bRandom, _ = pclient.BlessSelf("random")
Ankure49a86a2014-11-11 18:52:43 -08001041
1042 mgr = imanager.InternalNew(naming.FixedRoutingID(0x1111111))
1043 ns = tnaming.NewSimpleNamespace()
1044 tests = []struct {
1045 blessings security.Blessings // Blessings used by the client
1046 name string // object name on which the method is invoked
1047 method string
1048 args v
1049 results v
1050 authorized bool // Whether or not the RPC should be authorized by the server.
1051 }{
1052 // There are three different authorization policies (security.Authorizer implementations)
1053 // used by the server, depending on the suffix (see testServerDisp.Lookup):
1054 // - nilAuth suffix: the default authorization policy (only delegates of or delegators of the server can call RPCs)
Benjamin Prosnitzb60efb92015-03-11 17:47:43 -07001055 // - aclAuth suffix: the AccessList only allows blessings matching the patterns "server" or "client"
Ankure49a86a2014-11-11 18:52:43 -08001056 // - other suffixes: testServerAuthorizer allows any principal to call any method except "Unauthorized"
1057
1058 // Expired blessings should fail nilAuth and aclAuth (which care about names), but should succeed on
1059 // other suffixes (which allow all blessings), unless calling the Unauthorized method.
1060 {bServerClientExpired, "mountpoint/server/nilAuth", "Echo", v{"foo"}, v{""}, false},
1061 {bServerClientExpired, "mountpoint/server/aclAuth", "Echo", v{"foo"}, v{""}, false},
1062 {bServerClientExpired, "mountpoint/server/suffix", "Echo", v{"foo"}, v{""}, true},
1063 {bServerClientExpired, "mountpoint/server/suffix", "Unauthorized", nil, v{""}, false},
1064
1065 // Same for blessings that should fail to obtain a discharge for the third party caveat.
1066 {bServerClientTPExpired, "mountpoint/server/nilAuth", "Echo", v{"foo"}, v{""}, false},
1067 {bServerClientTPExpired, "mountpoint/server/aclAuth", "Echo", v{"foo"}, v{""}, false},
1068 {bServerClientTPExpired, "mountpoint/server/suffix", "Echo", v{"foo"}, v{""}, true},
1069 {bServerClientTPExpired, "mountpoint/server/suffix", "Unauthorized", nil, v{""}, false},
1070
1071 // The "server/client" blessing (with MethodCaveat("Echo")) should satisfy all authorization policies
1072 // when "Echo" is called.
1073 {bServerClientOnlyEcho, "mountpoint/server/nilAuth", "Echo", v{"foo"}, v{""}, true},
1074 {bServerClientOnlyEcho, "mountpoint/server/aclAuth", "Echo", v{"foo"}, v{""}, true},
1075 {bServerClientOnlyEcho, "mountpoint/server/suffix", "Echo", v{"foo"}, v{""}, true},
1076
1077 // The "server/client" blessing (with MethodCaveat("Echo")) should satisfy no authorization policy
1078 // when any other method is invoked, except for the testServerAuthorizer policy (which will
1079 // not recognize the blessing "server/onlyecho", but it would authorize anyone anyway).
1080 {bServerClientOnlyEcho, "mountpoint/server/nilAuth", "Closure", nil, nil, false},
1081 {bServerClientOnlyEcho, "mountpoint/server/aclAuth", "Closure", nil, nil, false},
1082 {bServerClientOnlyEcho, "mountpoint/server/suffix", "Closure", nil, nil, true},
1083
1084 // The "client" blessing doesn't satisfy the default authorization policy, but does satisfy
Benjamin Prosnitzb60efb92015-03-11 17:47:43 -07001085 // the AccessList and the testServerAuthorizer policy.
Ankure49a86a2014-11-11 18:52:43 -08001086 {bClient, "mountpoint/server/nilAuth", "Echo", v{"foo"}, v{""}, false},
1087 {bClient, "mountpoint/server/aclAuth", "Echo", v{"foo"}, v{""}, true},
1088 {bClient, "mountpoint/server/suffix", "Echo", v{"foo"}, v{""}, true},
1089 {bClient, "mountpoint/server/suffix", "Unauthorized", nil, v{""}, false},
1090
Benjamin Prosnitzb60efb92015-03-11 17:47:43 -07001091 // The "random" blessing does not satisfy either the default policy or the AccessList, but does
Ankure49a86a2014-11-11 18:52:43 -08001092 // satisfy testServerAuthorizer.
1093 {bRandom, "mountpoint/server/nilAuth", "Echo", v{"foo"}, v{""}, false},
1094 {bRandom, "mountpoint/server/aclAuth", "Echo", v{"foo"}, v{""}, false},
1095 {bRandom, "mountpoint/server/suffix", "Echo", v{"foo"}, v{""}, true},
1096 {bRandom, "mountpoint/server/suffix", "Unauthorized", nil, v{""}, false},
1097
1098 // The "server/dischargeable_third_party_caveat" blessing satisfies all policies.
1099 // (the discharges should be fetched).
1100 {bServerClientTPValid, "mountpoint/server/nilAuth", "Echo", v{"foo"}, v{""}, true},
1101 {bServerClientTPValid, "mountpoint/server/aclAuth", "Echo", v{"foo"}, v{""}, true},
1102 {bServerClientTPValid, "mountpoint/server/suffix", "Echo", v{"foo"}, v{""}, true},
1103 {bServerClientTPValid, "mountpoint/server/suffix", "Unauthorized", nil, v{""}, false},
1104 }
Andres Erbsenb7f95f32014-07-07 12:07:56 -07001105 )
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001106
1107 ctx, shutdown := initForTest()
1108 defer shutdown()
Ankure49a86a2014-11-11 18:52:43 -08001109 // Start the main server.
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001110 _, server := startServer(t, ctx, pserver, mgr, ns, serverName, testServerDisp{&testServer{}})
1111 defer stopServer(t, ctx, server, ns, serverName)
Ankure49a86a2014-11-11 18:52:43 -08001112
1113 // Start the discharge server.
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001114 _, dischargeServer := startServer(t, ctx, pdischarger, mgr, ns, dischargeServerName, testutil.LeafDispatcher(&dischargeServer{}, &acceptAllAuthorizer{}))
1115 defer stopServer(t, ctx, dischargeServer, ns, dischargeServerName)
Ankure49a86a2014-11-11 18:52:43 -08001116
Ankur78b8b2a2015-02-04 20:16:28 -08001117 // The server should recognize the client principal as an authority on "client" and "random" blessings.
Asim Shankar8f05c222014-10-06 22:08:19 -07001118 pserver.AddToRoots(bClient)
1119 pserver.AddToRoots(bRandom)
Ankure49a86a2014-11-11 18:52:43 -08001120 // And the client needs to recognize the server's and discharger's blessings to decide which of its
1121 // own blessings to share.
Asim Shankar8f05c222014-10-06 22:08:19 -07001122 pclient.AddToRoots(pserver.BlessingStore().Default())
Ankuredd74ee2015-03-04 16:38:45 -08001123 pclient.AddToRoots(pdischarger.BlessingStore().Default())
1124 // Set a blessing on the client's blessing store to be presented to the discharge server.
1125 pclient.BlessingStore().Set(pclient.BlessingStore().Default(), "discharger")
Asim Shankar4a698282015-03-21 21:59:18 -07001126 // testutil.NewPrincipal sets up a principal that shares blessings with all servers, undo that.
Asim Shankar2bf7b1e2015-02-27 00:45:12 -08001127 pclient.BlessingStore().Set(security.Blessings{}, security.AllPrincipals)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001128
Ankuredd74ee2015-03-04 16:38:45 -08001129 for i, test := range tests {
1130 name := fmt.Sprintf("#%d: %q.%s(%v) by %v", i, test.name, test.method, test.args, test.blessings)
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001131 client, err := InternalNewClient(mgr, ns)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001132 if err != nil {
1133 t.Fatalf("InternalNewClient failed: %v", err)
1134 }
1135 defer client.Close()
Ankure49a86a2014-11-11 18:52:43 -08001136
Asim Shankar8f05c222014-10-06 22:08:19 -07001137 pclient.BlessingStore().Set(test.blessings, "server")
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001138 ctx, _ := v23.SetPrincipal(ctx, pclient)
Suharsh Sivakumar1abd5a82015-04-10 00:24:14 -07001139 err = client.Call(ctx, test.name, test.method, test.args, makeResultPtrs(test.results))
Asim Shankar8f05c222014-10-06 22:08:19 -07001140 if err != nil && test.authorized {
Suharsh Sivakumar1abd5a82015-04-10 00:24:14 -07001141 t.Errorf(`%s client.Call got error: "%v", wanted the RPC to succeed`, name, err)
Asim Shankar8f05c222014-10-06 22:08:19 -07001142 } else if err == nil && !test.authorized {
1143 t.Errorf("%s call.Finish succeeded, expected authorization failure", name)
Todd Wang8fa38762015-03-25 14:04:59 -07001144 } else if !test.authorized && verror.ErrorID(err) != verror.ErrNoAccess.ID {
Jiri Simsa074bf362015-02-17 09:29:45 -08001145 t.Errorf("%s. call.Finish returned error %v(%v), wanted %v", name, verror.ErrorID(verror.Convert(verror.ErrNoAccess, nil, err)), err, verror.ErrNoAccess)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001146 }
1147 }
1148}
1149
Asim Shankar263c73b2015-03-19 18:31:26 -07001150// singleBlessingStore implements security.BlessingStore. It is a
Ankurb905dae2015-03-04 12:38:20 -08001151// BlessingStore that marks the last blessing that was set on it as
1152// shareable with any peer. It does not care about the public key that
1153// blessing being set is bound to.
Asim Shankar263c73b2015-03-19 18:31:26 -07001154type singleBlessingStore struct {
Ankurb905dae2015-03-04 12:38:20 -08001155 b security.Blessings
1156}
1157
Asim Shankar263c73b2015-03-19 18:31:26 -07001158func (s *singleBlessingStore) Set(b security.Blessings, _ security.BlessingPattern) (security.Blessings, error) {
Ankurb905dae2015-03-04 12:38:20 -08001159 s.b = b
1160 return security.Blessings{}, nil
1161}
Asim Shankar263c73b2015-03-19 18:31:26 -07001162func (s *singleBlessingStore) ForPeer(...string) security.Blessings {
Ankurb905dae2015-03-04 12:38:20 -08001163 return s.b
1164}
Asim Shankar263c73b2015-03-19 18:31:26 -07001165func (*singleBlessingStore) SetDefault(b security.Blessings) error {
Ankurb905dae2015-03-04 12:38:20 -08001166 return nil
1167}
Asim Shankar263c73b2015-03-19 18:31:26 -07001168func (*singleBlessingStore) Default() security.Blessings {
Ankurb905dae2015-03-04 12:38:20 -08001169 return security.Blessings{}
1170}
Asim Shankar263c73b2015-03-19 18:31:26 -07001171func (*singleBlessingStore) PublicKey() security.PublicKey {
Ankurb905dae2015-03-04 12:38:20 -08001172 return nil
1173}
Asim Shankar263c73b2015-03-19 18:31:26 -07001174func (*singleBlessingStore) DebugString() string {
Ankurb905dae2015-03-04 12:38:20 -08001175 return ""
1176}
Asim Shankar263c73b2015-03-19 18:31:26 -07001177func (*singleBlessingStore) PeerBlessings() map[security.BlessingPattern]security.Blessings {
Ankurb905dae2015-03-04 12:38:20 -08001178 return nil
1179}
1180
Asim Shankar263c73b2015-03-19 18:31:26 -07001181// singleBlessingPrincipal implements security.Principal. It is a wrapper over
Ankurb905dae2015-03-04 12:38:20 -08001182// a security.Principal that intercepts all invocations on the
Asim Shankar263c73b2015-03-19 18:31:26 -07001183// principal's BlessingStore and serves them via a singleBlessingStore.
1184type singleBlessingPrincipal struct {
Ankurb905dae2015-03-04 12:38:20 -08001185 security.Principal
Asim Shankar263c73b2015-03-19 18:31:26 -07001186 b singleBlessingStore
Ankurb905dae2015-03-04 12:38:20 -08001187}
1188
Asim Shankar263c73b2015-03-19 18:31:26 -07001189func (p *singleBlessingPrincipal) BlessingStore() security.BlessingStore {
Ankurb905dae2015-03-04 12:38:20 -08001190 return &p.b
1191}
1192
1193func TestRPCClientBlessingsPublicKey(t *testing.T) {
Asim Shankar263c73b2015-03-19 18:31:26 -07001194 ctx, shutdown := initForTest()
1195 defer shutdown()
Ankurb905dae2015-03-04 12:38:20 -08001196 var (
Asim Shankar4a698282015-03-21 21:59:18 -07001197 pprovider, pserver = testutil.NewPrincipal("root"), testutil.NewPrincipal("server")
1198 pclient = &singleBlessingPrincipal{Principal: testutil.NewPrincipal("client")}
Ankurb905dae2015-03-04 12:38:20 -08001199
1200 bserver = bless(pprovider, pserver, "server")
1201 bclient = bless(pprovider, pclient, "client")
Asim Shankar4a698282015-03-21 21:59:18 -07001202 bvictim = bless(pprovider, testutil.NewPrincipal("victim"), "victim")
Ankurb905dae2015-03-04 12:38:20 -08001203 )
Ankurb905dae2015-03-04 12:38:20 -08001204 // Make the client and server trust blessings from pprovider.
1205 pclient.AddToRoots(pprovider.BlessingStore().Default())
1206 pserver.AddToRoots(pprovider.BlessingStore().Default())
1207
Asim Shankar263c73b2015-03-19 18:31:26 -07001208 // Make the server present bserver to all clients and start the server.
Ankurb905dae2015-03-04 12:38:20 -08001209 pserver.BlessingStore().SetDefault(bserver)
Asim Shankar263c73b2015-03-19 18:31:26 -07001210 b := createBundle(t, ctx, pserver, &testServer{})
1211 defer b.cleanup(t, ctx)
1212
1213 ctx, _ = v23.SetPrincipal(ctx, pclient)
Ankurb905dae2015-03-04 12:38:20 -08001214 tests := []struct {
1215 blessings security.Blessings
1216 errID verror.IDAction
1217 err string
1218 }{
1219 {blessings: bclient},
1220 // server disallows clients from authenticating with blessings not bound to
1221 // the client principal's public key
1222 {blessings: bvictim, errID: verror.ErrNoAccess, err: "bound to a different public key"},
Ankurb905dae2015-03-04 12:38:20 -08001223 {blessings: bserver, errID: verror.ErrNoAccess, err: "bound to a different public key"},
1224 }
1225 for i, test := range tests {
1226 name := fmt.Sprintf("%d: Client RPCing with blessings %v", i, test.blessings)
Ankurb905dae2015-03-04 12:38:20 -08001227 pclient.BlessingStore().Set(test.blessings, "root")
Suharsh Sivakumar1abd5a82015-04-10 00:24:14 -07001228 if err := b.client.Call(ctx, "mountpoint/server/suffix", "Closure", nil, nil); !matchesErrorPattern(err, test.errID, test.err) {
1229 t.Errorf("%v: client.Call returned error %v", name, err)
Ankurb905dae2015-03-04 12:38:20 -08001230 continue
1231 }
1232 }
1233}
1234
Ankuredd74ee2015-03-04 16:38:45 -08001235func TestServerLocalBlessings(t *testing.T) {
Asim Shankar263c73b2015-03-19 18:31:26 -07001236 ctx, shutdown := initForTest()
1237 defer shutdown()
Ankuredd74ee2015-03-04 16:38:45 -08001238 var (
Asim Shankar4a698282015-03-21 21:59:18 -07001239 pprovider, pclient, pserver = testutil.NewPrincipal("root"), testutil.NewPrincipal("client"), testutil.NewPrincipal("server")
Ankuredd74ee2015-03-04 16:38:45 -08001240 pdischarger = pprovider
1241
1242 mgr = imanager.InternalNew(naming.FixedRoutingID(0x1111111))
1243 ns = tnaming.NewSimpleNamespace()
1244
1245 tpCav = mkThirdPartyCaveat(pdischarger.PublicKey(), "mountpoint/dischargeserver", mkCaveat(security.ExpiryCaveat(time.Now().Add(time.Hour))))
1246
1247 bserver = bless(pprovider, pserver, "server", tpCav)
1248 bclient = bless(pprovider, pclient, "client")
1249 )
Ankuredd74ee2015-03-04 16:38:45 -08001250 // Make the client and server principals trust root certificates from
1251 // pprovider.
1252 pclient.AddToRoots(pprovider.BlessingStore().Default())
1253 pserver.AddToRoots(pprovider.BlessingStore().Default())
1254
1255 // Make the server present bserver to all clients.
1256 pserver.BlessingStore().SetDefault(bserver)
1257
Asim Shankar7171a252015-03-07 14:41:40 -08001258 // Start the server and the discharger.
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001259 _, server := startServer(t, ctx, pserver, mgr, ns, "mountpoint/server", testServerDisp{&testServer{}})
1260 defer stopServer(t, ctx, server, ns, "mountpoint/server")
Asim Shankar7171a252015-03-07 14:41:40 -08001261
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001262 _, dischargeServer := startServer(t, ctx, pdischarger, mgr, ns, "mountpoint/dischargeserver", testutil.LeafDispatcher(&dischargeServer{}, &acceptAllAuthorizer{}))
1263 defer stopServer(t, ctx, dischargeServer, ns, "mountpoint/dischargeserver")
Asim Shankar7171a252015-03-07 14:41:40 -08001264
Ankuredd74ee2015-03-04 16:38:45 -08001265 // Make the client present bclient to all servers that are blessed
1266 // by pprovider.
1267 pclient.BlessingStore().Set(bclient, "root")
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001268 client, err := InternalNewClient(mgr, ns)
Ankuredd74ee2015-03-04 16:38:45 -08001269 if err != nil {
1270 t.Fatalf("InternalNewClient failed: %v", err)
1271 }
1272 defer client.Close()
1273
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001274 ctx, _ = v23.SetPrincipal(ctx, pclient)
Ankuredd74ee2015-03-04 16:38:45 -08001275 var gotServer, gotClient string
Suharsh Sivakumar1abd5a82015-04-10 00:24:14 -07001276 if err := client.Call(ctx, "mountpoint/server/suffix", "EchoBlessings", nil, []interface{}{&gotServer, &gotClient}); err != nil {
Ankuredd74ee2015-03-04 16:38:45 -08001277 t.Fatalf("Finish failed: %v", err)
1278 }
1279 if wantServer, wantClient := "[root/server]", "[root/client]"; gotServer != wantServer || gotClient != wantClient {
1280 t.Fatalf("EchoBlessings: got %v, %v want %v, %v", gotServer, gotClient, wantServer, wantClient)
1281 }
1282}
1283
Andres Erbsenb7f95f32014-07-07 12:07:56 -07001284func TestDischargePurgeFromCache(t *testing.T) {
Asim Shankar263c73b2015-03-19 18:31:26 -07001285 ctx, shutdown := initForTest()
1286 defer shutdown()
1287
Andres Erbsenb7f95f32014-07-07 12:07:56 -07001288 var (
Asim Shankar4a698282015-03-21 21:59:18 -07001289 pserver = testutil.NewPrincipal("server")
Asim Shankar8f05c222014-10-06 22:08:19 -07001290 pdischarger = pserver // In general, the discharger can be a separate principal. In this test, it happens to be the server.
Asim Shankar4a698282015-03-21 21:59:18 -07001291 pclient = testutil.NewPrincipal("client")
Asim Shankar8f05c222014-10-06 22:08:19 -07001292 // Client is blessed with a third-party caveat. The discharger service issues discharges with a fakeTimeCaveat.
1293 // This blessing is presented to "server".
1294 bclient = bless(pserver, pclient, "client", mkThirdPartyCaveat(pdischarger.PublicKey(), "mountpoint/server/discharger", security.UnconstrainedUse()))
Asim Shankar263c73b2015-03-19 18:31:26 -07001295
1296 b = createBundle(t, ctx, pserver, &testServer{})
Andres Erbsenb7f95f32014-07-07 12:07:56 -07001297 )
Asim Shankar263c73b2015-03-19 18:31:26 -07001298 defer b.cleanup(t, ctx)
Asim Shankar8f05c222014-10-06 22:08:19 -07001299 // Setup the client to recognize the server's blessing and present bclient to it.
1300 pclient.AddToRoots(pserver.BlessingStore().Default())
1301 pclient.BlessingStore().Set(bclient, "server")
1302
Suharsh Sivakumar1b6683e2014-12-30 13:00:38 -08001303 var err error
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001304 if b.client, err = InternalNewClient(b.sm, b.ns); err != nil {
Ankure49a86a2014-11-11 18:52:43 -08001305 t.Fatalf("InternalNewClient failed: %v", err)
1306 }
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001307 ctx, _ = v23.SetPrincipal(ctx, pclient)
Mike Burrowsdc6b3602015-02-05 15:52:12 -08001308 call := func() error {
Andres Erbsenb7f95f32014-07-07 12:07:56 -07001309 var got string
Suharsh Sivakumar1abd5a82015-04-10 00:24:14 -07001310 if err := b.client.Call(ctx, "mountpoint/server/aclAuth", "Echo", []interface{}{"batman"}, []interface{}{&got}); err != nil {
Asim Shankar263c73b2015-03-19 18:31:26 -07001311 return err
Andres Erbsenb7f95f32014-07-07 12:07:56 -07001312 }
Asim Shankar8f05c222014-10-06 22:08:19 -07001313 if want := `method:"Echo",suffix:"aclAuth",arg:"batman"`; got != want {
Jiri Simsa074bf362015-02-17 09:29:45 -08001314 return verror.Convert(verror.ErrBadArg, nil, fmt.Errorf("Got [%v] want [%v]", got, want))
Andres Erbsenb7f95f32014-07-07 12:07:56 -07001315 }
1316 return nil
1317 }
1318
1319 // First call should succeed
1320 if err := call(); err != nil {
1321 t.Fatal(err)
1322 }
1323 // Advance virtual clock, which will invalidate the discharge
1324 clock.Advance(1)
Jiri Simsa074bf362015-02-17 09:29:45 -08001325 if err, want := call(), "not authorized"; !matchesErrorPattern(err, verror.ErrNoAccess, want) {
Asim Shankar8f05c222014-10-06 22:08:19 -07001326 t.Errorf("Got error [%v] wanted to match pattern %q", err, want)
Andres Erbsenb7f95f32014-07-07 12:07:56 -07001327 }
1328 // But retrying will succeed since the discharge should be purged from cache and refreshed
1329 if err := call(); err != nil {
1330 t.Fatal(err)
1331 }
1332}
1333
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001334type cancelTestServer struct {
1335 started chan struct{}
1336 cancelled chan struct{}
Matt Rosencrantzbae08212014-10-03 08:04:17 -07001337 t *testing.T
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001338}
1339
Matt Rosencrantzbae08212014-10-03 08:04:17 -07001340func newCancelTestServer(t *testing.T) *cancelTestServer {
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001341 return &cancelTestServer{
1342 started: make(chan struct{}),
1343 cancelled: make(chan struct{}),
Matt Rosencrantzbae08212014-10-03 08:04:17 -07001344 t: t,
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001345 }
1346}
1347
Matt Rosencrantz94502cf2015-03-18 09:43:44 -07001348func (s *cancelTestServer) CancelStreamReader(call rpc.StreamServerCall) error {
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001349 close(s.started)
Matt Rosencrantzbae08212014-10-03 08:04:17 -07001350 var b []byte
1351 if err := call.Recv(&b); err != io.EOF {
1352 s.t.Errorf("Got error %v, want io.EOF", err)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001353 }
Matt Rosencrantz8f9fca12014-12-19 14:02:31 -08001354 <-call.Context().Done()
Matt Rosencrantzbae08212014-10-03 08:04:17 -07001355 close(s.cancelled)
1356 return nil
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001357}
1358
1359// CancelStreamIgnorer doesn't read from it's input stream so all it's
Matt Rosencrantz137b8d22014-08-18 09:56:15 -07001360// buffers fill. The intention is to show that call.Done() is closed
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001361// even when the stream is stalled.
Matt Rosencrantz94502cf2015-03-18 09:43:44 -07001362func (s *cancelTestServer) CancelStreamIgnorer(call rpc.StreamServerCall) error {
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001363 close(s.started)
Matt Rosencrantz8f9fca12014-12-19 14:02:31 -08001364 <-call.Context().Done()
Matt Rosencrantzbae08212014-10-03 08:04:17 -07001365 close(s.cancelled)
1366 return nil
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001367}
1368
Matt Rosencrantz9346b412014-12-18 15:59:19 -08001369func waitForCancel(t *testing.T, ts *cancelTestServer, cancel context.CancelFunc) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001370 <-ts.started
Matt Rosencrantz9346b412014-12-18 15:59:19 -08001371 cancel()
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001372 <-ts.cancelled
1373}
1374
1375// TestCancel tests cancellation while the server is reading from a stream.
1376func TestCancel(t *testing.T) {
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001377 ctx, shutdown := initForTest()
1378 defer shutdown()
Asim Shankar263c73b2015-03-19 18:31:26 -07001379 var (
1380 ts = newCancelTestServer(t)
1381 pclient, pserver = newClientServerPrincipals()
1382 b = createBundle(t, ctx, pserver, ts)
1383 )
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001384 defer b.cleanup(t, ctx)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001385
Asim Shankar263c73b2015-03-19 18:31:26 -07001386 ctx, _ = v23.SetPrincipal(ctx, pclient)
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001387 ctx, cancel := context.WithCancel(ctx)
Matt Rosencrantz9346b412014-12-18 15:59:19 -08001388 _, err := b.client.StartCall(ctx, "mountpoint/server/suffix", "CancelStreamReader", []interface{}{})
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001389 if err != nil {
1390 t.Fatalf("Start call failed: %v", err)
1391 }
Matt Rosencrantz9346b412014-12-18 15:59:19 -08001392 waitForCancel(t, ts, cancel)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001393}
1394
1395// TestCancelWithFullBuffers tests that even if the writer has filled the buffers and
1396// the server is not reading that the cancel message gets through.
1397func TestCancelWithFullBuffers(t *testing.T) {
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001398 ctx, shutdown := initForTest()
1399 defer shutdown()
Asim Shankar263c73b2015-03-19 18:31:26 -07001400 var (
1401 ts = newCancelTestServer(t)
1402 pclient, pserver = newClientServerPrincipals()
1403 b = createBundle(t, ctx, pserver, ts)
1404 )
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001405 defer b.cleanup(t, ctx)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001406
Asim Shankar263c73b2015-03-19 18:31:26 -07001407 ctx, _ = v23.SetPrincipal(ctx, pclient)
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001408 ctx, cancel := context.WithCancel(ctx)
Matt Rosencrantz9346b412014-12-18 15:59:19 -08001409 call, err := b.client.StartCall(ctx, "mountpoint/server/suffix", "CancelStreamIgnorer", []interface{}{})
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001410 if err != nil {
1411 t.Fatalf("Start call failed: %v", err)
1412 }
1413 // Fill up all the write buffers to ensure that cancelling works even when the stream
1414 // is blocked.
1415 call.Send(make([]byte, vc.MaxSharedBytes))
1416 call.Send(make([]byte, vc.DefaultBytesBufferedPerFlow))
1417
Matt Rosencrantz9346b412014-12-18 15:59:19 -08001418 waitForCancel(t, ts, cancel)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001419}
1420
1421type streamRecvInGoroutineServer struct{ c chan error }
1422
Matt Rosencrantz94502cf2015-03-18 09:43:44 -07001423func (s *streamRecvInGoroutineServer) RecvInGoroutine(call rpc.StreamServerCall) error {
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001424 // Spawn a goroutine to read streaming data from the client.
1425 go func() {
1426 var i interface{}
1427 for {
1428 err := call.Recv(&i)
1429 if err != nil {
1430 s.c <- err
1431 return
1432 }
1433 }
1434 }()
1435 // Imagine the server did some processing here and now that it is done,
1436 // it does not care to see what else the client has to say.
1437 return nil
1438}
1439
1440func TestStreamReadTerminatedByServer(t *testing.T) {
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001441 ctx, shutdown := initForTest()
1442 defer shutdown()
Asim Shankar263c73b2015-03-19 18:31:26 -07001443 var (
1444 pclient, pserver = newClientServerPrincipals()
1445 s = &streamRecvInGoroutineServer{c: make(chan error, 1)}
1446 b = createBundle(t, ctx, pserver, s)
1447 )
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001448 defer b.cleanup(t, ctx)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001449
Asim Shankar263c73b2015-03-19 18:31:26 -07001450 ctx, _ = v23.SetPrincipal(ctx, pclient)
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001451 call, err := b.client.StartCall(ctx, "mountpoint/server/suffix", "RecvInGoroutine", []interface{}{})
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001452 if err != nil {
1453 t.Fatalf("StartCall failed: %v", err)
1454 }
1455
1456 c := make(chan error, 1)
1457 go func() {
1458 for i := 0; true; i++ {
1459 if err := call.Send(i); err != nil {
1460 c <- err
1461 return
1462 }
1463 }
1464 }()
1465
1466 // The goroutine at the server executing "Recv" should have terminated
1467 // with EOF.
1468 if err := <-s.c; err != io.EOF {
1469 t.Errorf("Got %v at server, want io.EOF", err)
1470 }
1471 // The client Send should have failed since the RPC has been
1472 // terminated.
1473 if err := <-c; err == nil {
1474 t.Errorf("Client Send should fail as the server should have closed the flow")
1475 }
1476}
1477
1478// TestConnectWithIncompatibleServers tests that clients ignore incompatible endpoints.
1479func TestConnectWithIncompatibleServers(t *testing.T) {
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001480 ctx, shutdown := initForTest()
1481 defer shutdown()
Asim Shankar263c73b2015-03-19 18:31:26 -07001482 var (
1483 pclient, pserver = newClientServerPrincipals()
1484 b = createBundle(t, ctx, pserver, &testServer{})
1485 )
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001486 defer b.cleanup(t, ctx)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001487
1488 // Publish some incompatible endpoints.
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001489 publisher := publisher.New(ctx, b.ns, publishPeriod)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001490 defer publisher.WaitForStop()
1491 defer publisher.Stop()
Robin Thellend89e95232015-03-24 13:48:48 -07001492 publisher.AddName("incompatible", false, false)
1493 publisher.AddServer("/@2@tcp@localhost:10000@@1000000@2000000@@")
1494 publisher.AddServer("/@2@tcp@localhost:10001@@2000000@3000000@@")
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001495
Asim Shankar263c73b2015-03-19 18:31:26 -07001496 ctx, _ = v23.SetPrincipal(ctx, pclient)
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001497 _, err := b.client.StartCall(ctx, "incompatible/suffix", "Echo", []interface{}{"foo"}, options.NoRetry{})
Todd Wang8fa38762015-03-25 14:04:59 -07001498 if verror.ErrorID(err) != verror.ErrNoServers.ID {
Jiri Simsa074bf362015-02-17 09:29:45 -08001499 t.Errorf("Expected error %s, found: %v", verror.ErrNoServers, err)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001500 }
1501
1502 // Now add a server with a compatible endpoint and try again.
Robin Thellend89e95232015-03-24 13:48:48 -07001503 publisher.AddServer("/" + b.ep.String())
1504 publisher.AddName("incompatible", false, false)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001505
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001506 call, err := b.client.StartCall(ctx, "incompatible/suffix", "Echo", []interface{}{"foo"})
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001507 if err != nil {
Asim Shankar3a8a7e22014-05-12 18:01:44 -07001508 t.Fatal(err)
1509 }
1510 var result string
1511 if err = call.Finish(&result); err != nil {
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001512 t.Errorf("Unexpected error finishing call %v", err)
1513 }
Asim Shankar3a8a7e22014-05-12 18:01:44 -07001514 expected := `method:"Echo",suffix:"suffix",arg:"foo"`
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001515 if result != expected {
1516 t.Errorf("Wrong result returned. Got %s, wanted %s", result, expected)
1517 }
1518}
1519
Cosmos Nicolaoubae615a2014-08-27 23:32:31 -07001520func TestPreferredAddress(t *testing.T) {
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001521 ctx, shutdown := initForTest()
1522 defer shutdown()
Cosmos Nicolaoubae615a2014-08-27 23:32:31 -07001523 sm := imanager.InternalNew(naming.FixedRoutingID(0x555555555))
1524 defer sm.Shutdown()
Matt Rosencrantz9fe60822014-09-12 10:09:53 -07001525 ns := tnaming.NewSimpleNamespace()
Matt Rosencrantz94502cf2015-03-18 09:43:44 -07001526 pa := func(string, []rpc.Address) ([]rpc.Address, error) {
Cosmos Nicolaoubae615a2014-08-27 23:32:31 -07001527 a := &net.IPAddr{}
1528 a.IP = net.ParseIP("1.1.1.1")
Matt Rosencrantz94502cf2015-03-18 09:43:44 -07001529 return []rpc.Address{&netstate.AddrIfc{Addr: a}}, nil
Cosmos Nicolaoubae615a2014-08-27 23:32:31 -07001530 }
Asim Shankar4a698282015-03-21 21:59:18 -07001531 server, err := testInternalNewServer(ctx, sm, ns, testutil.NewPrincipal("server"))
Cosmos Nicolaoubae615a2014-08-27 23:32:31 -07001532 if err != nil {
1533 t.Errorf("InternalNewServer failed: %v", err)
1534 }
1535 defer server.Stop()
Cosmos Nicolaou28dabfc2014-12-15 22:51:07 -08001536
Matt Rosencrantz94502cf2015-03-18 09:43:44 -07001537 spec := rpc.ListenSpec{
1538 Addrs: rpc.ListenAddrs{{"tcp", ":0"}},
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -08001539 AddressChooser: pa,
1540 }
Cosmos Nicolaou28dabfc2014-12-15 22:51:07 -08001541 eps, err := server.Listen(spec)
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -08001542 if err != nil {
1543 t.Errorf("unexpected error: %s", err)
1544 }
Cosmos Nicolaou28dabfc2014-12-15 22:51:07 -08001545 iep := eps[0].(*inaming.Endpoint)
Cosmos Nicolaoubae615a2014-08-27 23:32:31 -07001546 host, _, err := net.SplitHostPort(iep.Address)
1547 if err != nil {
1548 t.Errorf("unexpected error: %s", err)
1549 }
1550 if got, want := host, "1.1.1.1"; got != want {
1551 t.Errorf("got %q, want %q", got, want)
1552 }
1553 // Won't override the specified address.
Cosmos Nicolaou28dabfc2014-12-15 22:51:07 -08001554 eps, err = server.Listen(listenSpec)
1555 iep = eps[0].(*inaming.Endpoint)
Cosmos Nicolaoubae615a2014-08-27 23:32:31 -07001556 host, _, err = net.SplitHostPort(iep.Address)
1557 if err != nil {
1558 t.Errorf("unexpected error: %s", err)
1559 }
1560 if got, want := host, "127.0.0.1"; got != want {
1561 t.Errorf("got %q, want %q", got, want)
1562 }
1563}
1564
1565func TestPreferredAddressErrors(t *testing.T) {
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001566 ctx, shutdown := initForTest()
1567 defer shutdown()
Cosmos Nicolaoubae615a2014-08-27 23:32:31 -07001568 sm := imanager.InternalNew(naming.FixedRoutingID(0x555555555))
1569 defer sm.Shutdown()
Matt Rosencrantz9fe60822014-09-12 10:09:53 -07001570 ns := tnaming.NewSimpleNamespace()
Matt Rosencrantz94502cf2015-03-18 09:43:44 -07001571 paerr := func(_ string, a []rpc.Address) ([]rpc.Address, error) {
Cosmos Nicolaoubae615a2014-08-27 23:32:31 -07001572 return nil, fmt.Errorf("oops")
1573 }
Asim Shankar4a698282015-03-21 21:59:18 -07001574 server, err := testInternalNewServer(ctx, sm, ns, testutil.NewPrincipal("server"))
Cosmos Nicolaoubae615a2014-08-27 23:32:31 -07001575 if err != nil {
1576 t.Errorf("InternalNewServer failed: %v", err)
1577 }
1578 defer server.Stop()
Matt Rosencrantz94502cf2015-03-18 09:43:44 -07001579 spec := rpc.ListenSpec{
1580 Addrs: rpc.ListenAddrs{{"tcp", ":0"}},
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -08001581 AddressChooser: paerr,
1582 }
Cosmos Nicolaou28dabfc2014-12-15 22:51:07 -08001583 eps, err := server.Listen(spec)
1584 iep := eps[0].(*inaming.Endpoint)
Cosmos Nicolaoubae615a2014-08-27 23:32:31 -07001585 host, _, err := net.SplitHostPort(iep.Address)
1586 if err != nil {
1587 t.Errorf("unexpected error: %s", err)
1588 }
Cosmos Nicolaoud6c3c9c2014-09-30 15:42:53 -07001589 ip := net.ParseIP(host)
1590 if ip == nil {
1591 t.Fatalf("failed to parse IP address: %q", host)
1592 }
1593 if !ip.IsUnspecified() {
1594 t.Errorf("IP: %q is not unspecified", ip)
Cosmos Nicolaoubae615a2014-08-27 23:32:31 -07001595 }
1596}
1597
Suharsh Sivakumarcd743f72014-10-27 10:03:42 -07001598func TestSecurityNone(t *testing.T) {
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001599 ctx, shutdown := initForTest()
1600 defer shutdown()
Suharsh Sivakumarcd743f72014-10-27 10:03:42 -07001601 sm := imanager.InternalNew(naming.FixedRoutingID(0x66666666))
1602 defer sm.Shutdown()
1603 ns := tnaming.NewSimpleNamespace()
Suharsh Sivakumar2c5d8102015-03-23 08:49:12 -07001604 server, err := testInternalNewServer(ctx, sm, ns, nil, options.SecurityNone)
Suharsh Sivakumarcd743f72014-10-27 10:03:42 -07001605 if err != nil {
1606 t.Fatalf("InternalNewServer failed: %v", err)
1607 }
1608 if _, err = server.Listen(listenSpec); err != nil {
1609 t.Fatalf("server.Listen failed: %v", err)
1610 }
1611 disp := &testServerDisp{&testServer{}}
Cosmos Nicolaou92dba582014-11-05 17:24:10 -08001612 if err := server.ServeDispatcher("mp/server", disp); err != nil {
Suharsh Sivakumarcd743f72014-10-27 10:03:42 -07001613 t.Fatalf("server.Serve failed: %v", err)
1614 }
Suharsh Sivakumarae774a52015-01-09 14:26:32 -08001615 client, err := InternalNewClient(sm, ns)
Suharsh Sivakumarcd743f72014-10-27 10:03:42 -07001616 if err != nil {
1617 t.Fatalf("InternalNewClient failed: %v", err)
1618 }
Suharsh Sivakumar2c5d8102015-03-23 08:49:12 -07001619 // When using SecurityNone, all authorization checks should be skipped, so
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001620 // unauthorized methods should be callable.
Suharsh Sivakumarcd743f72014-10-27 10:03:42 -07001621 var got string
Suharsh Sivakumar1abd5a82015-04-10 00:24:14 -07001622 if err := client.Call(ctx, "mp/server", "Unauthorized", nil, []interface{}{&got}, options.SecurityNone); err != nil {
1623 t.Fatalf("client.Call failed: %v", err)
Suharsh Sivakumarcd743f72014-10-27 10:03:42 -07001624 }
1625 if want := "UnauthorizedResult"; got != want {
1626 t.Errorf("got (%v), want (%v)", got, want)
1627 }
1628}
1629
Suharsh Sivakumar0ed10c22015-04-06 12:55:55 -07001630func TestNoPrincipal(t *testing.T) {
1631 ctx, shutdown := initForTest()
1632 defer shutdown()
1633 sm := imanager.InternalNew(naming.FixedRoutingID(0x66666666))
1634 defer sm.Shutdown()
1635 ns := tnaming.NewSimpleNamespace()
1636 server, err := testInternalNewServer(ctx, sm, ns, testutil.NewPrincipal("server"))
1637 if err != nil {
1638 t.Fatalf("InternalNewServer failed: %v", err)
1639 }
1640 if _, err = server.Listen(listenSpec); err != nil {
1641 t.Fatalf("server.Listen failed: %v", err)
1642 }
1643 disp := &testServerDisp{&testServer{}}
1644 if err := server.ServeDispatcher("mp/server", disp); err != nil {
1645 t.Fatalf("server.Serve failed: %v", err)
1646 }
1647 client, err := InternalNewClient(sm, ns)
1648 if err != nil {
1649 t.Fatalf("InternalNewClient failed: %v", err)
1650 }
1651
1652 // A call should fail if the principal in the ctx is nil and SecurityNone is not specified.
1653 ctx, err = v23.SetPrincipal(ctx, nil)
1654 if err != nil {
1655 t.Fatalf("failed to set principal: %v", err)
1656 }
1657 _, err = client.StartCall(ctx, "mp/server", "Echo", []interface{}{"foo"})
1658 if err == nil || verror.ErrorID(err) != errNoPrincipal.ID {
1659 t.Fatalf("Expected errNoPrincipal, got %v", err)
1660 }
1661}
1662
Matt Rosencrantz321a51d2014-10-30 10:37:56 -07001663func TestCallWithNilContext(t *testing.T) {
1664 sm := imanager.InternalNew(naming.FixedRoutingID(0x66666666))
1665 defer sm.Shutdown()
1666 ns := tnaming.NewSimpleNamespace()
Suharsh Sivakumarae774a52015-01-09 14:26:32 -08001667 client, err := InternalNewClient(sm, ns)
Matt Rosencrantz321a51d2014-10-30 10:37:56 -07001668 if err != nil {
1669 t.Fatalf("InternalNewClient failed: %v", err)
1670 }
Suharsh Sivakumar2c5d8102015-03-23 08:49:12 -07001671 call, err := client.StartCall(nil, "foo", "bar", []interface{}{}, options.SecurityNone)
Matt Rosencrantz321a51d2014-10-30 10:37:56 -07001672 if call != nil {
1673 t.Errorf("Expected nil interface got: %#v", call)
1674 }
Todd Wang8fa38762015-03-25 14:04:59 -07001675 if verror.ErrorID(err) != verror.ErrBadArg.ID {
Suharsh Sivakumar0ed10c22015-04-06 12:55:55 -07001676 t.Errorf("Expected a BadArg error, got: %s", err.Error())
Matt Rosencrantz321a51d2014-10-30 10:37:56 -07001677 }
1678}
1679
Asim Shankara5b60b22014-11-06 15:37:07 -08001680func TestServerBlessingsOpt(t *testing.T) {
1681 var (
Asim Shankar4a698282015-03-21 21:59:18 -07001682 pserver = testutil.NewPrincipal("server")
1683 pclient = testutil.NewPrincipal("client")
Asim Shankara5b60b22014-11-06 15:37:07 -08001684 batman, _ = pserver.BlessSelf("batman")
1685 )
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001686 ctx, shutdown := initForTest()
1687 defer shutdown()
Asim Shankar7171a252015-03-07 14:41:40 -08001688 // Client and server recognize the servers blessings
1689 for _, p := range []security.Principal{pserver, pclient} {
1690 if err := p.AddToRoots(pserver.BlessingStore().Default()); err != nil {
1691 t.Fatal(err)
1692 }
1693 if err := p.AddToRoots(batman); err != nil {
1694 t.Fatal(err)
1695 }
Asim Shankara5b60b22014-11-06 15:37:07 -08001696 }
1697 // Start a server that uses the ServerBlessings option to configure itself
1698 // to act as batman (as opposed to using the default blessing).
1699 ns := tnaming.NewSimpleNamespace()
Asim Shankara5b60b22014-11-06 15:37:07 -08001700
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001701 defer runServer(t, ctx, ns, pserver, "mountpoint/batman", &testServer{}, options.ServerBlessings{batman}).Shutdown()
1702 defer runServer(t, ctx, ns, pserver, "mountpoint/default", &testServer{}).Shutdown()
Asim Shankara5b60b22014-11-06 15:37:07 -08001703
Asim Shankarb547ea92015-02-17 18:49:45 -08001704 // And finally, make an RPC and see that the client sees "batman"
Asim Shankara5b60b22014-11-06 15:37:07 -08001705 runClient := func(server string) ([]string, error) {
1706 smc := imanager.InternalNew(naming.FixedRoutingID(0xc))
1707 defer smc.Shutdown()
1708 client, err := InternalNewClient(
1709 smc,
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001710 ns)
Asim Shankara5b60b22014-11-06 15:37:07 -08001711 if err != nil {
1712 return nil, err
1713 }
1714 defer client.Close()
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001715 ctx, _ = v23.SetPrincipal(ctx, pclient)
1716 call, err := client.StartCall(ctx, server, "Closure", nil)
Asim Shankara5b60b22014-11-06 15:37:07 -08001717 if err != nil {
1718 return nil, err
1719 }
1720 blessings, _ := call.RemoteBlessings()
1721 return blessings, nil
1722 }
1723
1724 // When talking to mountpoint/batman, should see "batman"
1725 // When talking to mountpoint/default, should see "server"
1726 if got, err := runClient("mountpoint/batman"); err != nil || len(got) != 1 || got[0] != "batman" {
1727 t.Errorf("Got (%v, %v) wanted 'batman'", got, err)
1728 }
1729 if got, err := runClient("mountpoint/default"); err != nil || len(got) != 1 || got[0] != "server" {
1730 t.Errorf("Got (%v, %v) wanted 'server'", got, err)
1731 }
1732}
1733
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001734func TestNoDischargesOpt(t *testing.T) {
1735 var (
Asim Shankar4a698282015-03-21 21:59:18 -07001736 pdischarger = testutil.NewPrincipal("discharger")
1737 pserver = testutil.NewPrincipal("server")
1738 pclient = testutil.NewPrincipal("client")
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001739 )
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001740 ctx, shutdown := initForTest()
1741 defer shutdown()
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001742 // Make the client recognize all server blessings
1743 if err := pclient.AddToRoots(pserver.BlessingStore().Default()); err != nil {
1744 t.Fatal(err)
1745 }
1746 if err := pclient.AddToRoots(pdischarger.BlessingStore().Default()); err != nil {
1747 t.Fatal(err)
1748 }
1749
1750 // Bless the client with a ThirdPartyCaveat.
1751 tpcav := mkThirdPartyCaveat(pdischarger.PublicKey(), "mountpoint/discharger", mkCaveat(security.ExpiryCaveat(time.Now().Add(time.Hour))))
1752 blessings, err := pserver.Bless(pclient.PublicKey(), pserver.BlessingStore().Default(), "tpcav", tpcav)
1753 if err != nil {
1754 t.Fatalf("failed to create Blessings: %v", err)
1755 }
1756 if _, err = pclient.BlessingStore().Set(blessings, "server"); err != nil {
1757 t.Fatalf("failed to set blessings: %v", err)
1758 }
1759
1760 ns := tnaming.NewSimpleNamespace()
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001761
1762 // Setup the disharger and test server.
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08001763 discharger := &dischargeServer{}
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001764 defer runServer(t, ctx, ns, pdischarger, "mountpoint/discharger", discharger).Shutdown()
1765 defer runServer(t, ctx, ns, pserver, "mountpoint/testServer", &testServer{}).Shutdown()
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001766
1767 runClient := func(noDischarges bool) {
1768 rid, err := naming.NewRoutingID()
1769 if err != nil {
1770 t.Fatal(err)
1771 }
1772 smc := imanager.InternalNew(rid)
1773 defer smc.Shutdown()
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001774 client, err := InternalNewClient(smc, ns)
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001775 if err != nil {
1776 t.Fatalf("failed to create client: %v", err)
1777 }
1778 defer client.Close()
Matt Rosencrantz94502cf2015-03-18 09:43:44 -07001779 var opts []rpc.CallOpt
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001780 if noDischarges {
Ankur50a5f392015-02-27 18:46:30 -08001781 opts = append(opts, NoDischarges{})
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001782 }
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001783 ctx, _ = v23.SetPrincipal(ctx, pclient)
1784 if _, err = client.StartCall(ctx, "mountpoint/testServer", "Closure", nil, opts...); err != nil {
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001785 t.Fatalf("failed to StartCall: %v", err)
1786 }
1787 }
1788
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08001789 // Test that when the NoDischarges option is set, dischargeServer does not get called.
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001790 if runClient(true); discharger.called {
1791 t.Errorf("did not expect discharger to be called")
1792 }
1793 discharger.called = false
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08001794 // Test that when the Nodischarges option is not set, dischargeServer does get called.
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001795 if runClient(false); !discharger.called {
1796 t.Errorf("expected discharger to be called")
1797 }
1798}
1799
1800func TestNoImplicitDischargeFetching(t *testing.T) {
1801 // This test ensures that discharge clients only fetch discharges for the specified tp caveats and not its own.
1802 var (
Asim Shankar4a698282015-03-21 21:59:18 -07001803 pdischarger1 = testutil.NewPrincipal("discharger1")
1804 pdischarger2 = testutil.NewPrincipal("discharger2")
1805 pdischargeClient = testutil.NewPrincipal("dischargeClient")
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001806 )
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001807 ctx, shutdown := initForTest()
1808 defer shutdown()
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001809 // Bless the client with a ThirdPartyCaveat from discharger1.
1810 tpcav1 := mkThirdPartyCaveat(pdischarger1.PublicKey(), "mountpoint/discharger1", mkCaveat(security.ExpiryCaveat(time.Now().Add(time.Hour))))
1811 blessings, err := pdischarger1.Bless(pdischargeClient.PublicKey(), pdischarger1.BlessingStore().Default(), "tpcav1", tpcav1)
1812 if err != nil {
1813 t.Fatalf("failed to create Blessings: %v", err)
1814 }
1815 if err = pdischargeClient.BlessingStore().SetDefault(blessings); err != nil {
1816 t.Fatalf("failed to set blessings: %v", err)
1817 }
Asim Shankar263c73b2015-03-19 18:31:26 -07001818 // The client will only talk to the discharge services if it recognizes them.
1819 pdischargeClient.AddToRoots(pdischarger1.BlessingStore().Default())
1820 pdischargeClient.AddToRoots(pdischarger2.BlessingStore().Default())
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001821
1822 ns := tnaming.NewSimpleNamespace()
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001823
1824 // Setup the disharger and test server.
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08001825 discharger1 := &dischargeServer{}
1826 discharger2 := &dischargeServer{}
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001827 defer runServer(t, ctx, ns, pdischarger1, "mountpoint/discharger1", discharger1).Shutdown()
1828 defer runServer(t, ctx, ns, pdischarger2, "mountpoint/discharger2", discharger2).Shutdown()
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001829
1830 rid, err := naming.NewRoutingID()
1831 if err != nil {
1832 t.Fatal(err)
1833 }
1834 sm := imanager.InternalNew(rid)
Suharsh Sivakumar1b6683e2014-12-30 13:00:38 -08001835
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001836 c, err := InternalNewClient(sm, ns)
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001837 if err != nil {
Suharsh Sivakumar1b6683e2014-12-30 13:00:38 -08001838 t.Fatalf("failed to create client: %v", err)
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001839 }
Suharsh Sivakumar1b6683e2014-12-30 13:00:38 -08001840 dc := c.(*client).dc
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001841 tpcav2, err := security.NewPublicKeyCaveat(pdischarger2.PublicKey(), "mountpoint/discharger2", security.ThirdPartyRequirements{}, mkCaveat(security.ExpiryCaveat(time.Now().Add(time.Hour))))
1842 if err != nil {
1843 t.Error(err)
1844 }
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001845 ctx, _ = v23.SetPrincipal(ctx, pdischargeClient)
1846 dc.PrepareDischarges(ctx, []security.Caveat{tpcav2}, security.DischargeImpetus{})
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001847
1848 // Ensure that discharger1 was not called and discharger2 was called.
1849 if discharger1.called {
1850 t.Errorf("discharge for caveat on discharge client should not have been fetched.")
1851 }
1852 if !discharger2.called {
1853 t.Errorf("discharge for caveat passed to PrepareDischarges should have been fetched.")
1854 }
1855}
1856
Suharsh Sivakumar720b7042014-12-22 17:33:23 -08001857// TestBlessingsCache tests that the VCCache is used to sucessfully used to cache duplicate
1858// calls blessings.
1859func TestBlessingsCache(t *testing.T) {
1860 var (
Asim Shankar4a698282015-03-21 21:59:18 -07001861 pserver = testutil.NewPrincipal("server")
1862 pclient = testutil.NewPrincipal("client")
Suharsh Sivakumar720b7042014-12-22 17:33:23 -08001863 )
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001864 ctx, shutdown := initForTest()
1865 defer shutdown()
Suharsh Sivakumar720b7042014-12-22 17:33:23 -08001866 // Make the client recognize all server blessings
1867 if err := pclient.AddToRoots(pserver.BlessingStore().Default()); err != nil {
1868 t.Fatal(err)
1869 }
1870
1871 ns := tnaming.NewSimpleNamespace()
Suharsh Sivakumar720b7042014-12-22 17:33:23 -08001872
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001873 serverSM := runServer(t, ctx, ns, pserver, "mountpoint/testServer", &testServer{})
Suharsh Sivakumar720b7042014-12-22 17:33:23 -08001874 defer serverSM.Shutdown()
Suharsh Sivakumar0902b7f2015-02-27 19:06:41 -08001875 rid := serverSM.RoutingID()
Suharsh Sivakumar720b7042014-12-22 17:33:23 -08001876
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001877 ctx, _ = v23.SetPrincipal(ctx, pclient)
1878
Matt Rosencrantz94502cf2015-03-18 09:43:44 -07001879 newClient := func() rpc.Client {
Suharsh Sivakumar720b7042014-12-22 17:33:23 -08001880 rid, err := naming.NewRoutingID()
1881 if err != nil {
1882 t.Fatal(err)
1883 }
1884 smc := imanager.InternalNew(rid)
1885 defer smc.Shutdown()
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001886 client, err := InternalNewClient(smc, ns)
Suharsh Sivakumar720b7042014-12-22 17:33:23 -08001887 if err != nil {
1888 t.Fatalf("failed to create client: %v", err)
1889 }
1890 return client
1891 }
1892
Matt Rosencrantz94502cf2015-03-18 09:43:44 -07001893 runClient := func(client rpc.Client) {
Suharsh Sivakumar1abd5a82015-04-10 00:24:14 -07001894 if err := client.Call(ctx, "mountpoint/testServer", "Closure", nil, nil); err != nil {
1895 t.Fatalf("failed to Call: %v", err)
Suharsh Sivakumar720b7042014-12-22 17:33:23 -08001896 }
1897 }
1898
Matt Rosencrantz94502cf2015-03-18 09:43:44 -07001899 cachePrefix := naming.Join("rpc", "server", "routing-id", rid.String(), "security", "blessings", "cache")
Suharsh Sivakumar720b7042014-12-22 17:33:23 -08001900 cacheHits, err := stats.GetStatsObject(naming.Join(cachePrefix, "hits"))
1901 if err != nil {
1902 t.Fatal(err)
1903 }
1904 cacheAttempts, err := stats.GetStatsObject(naming.Join(cachePrefix, "attempts"))
1905 if err != nil {
1906 t.Fatal(err)
1907 }
1908
1909 // Check that the blessings cache is not used on the first call.
1910 clientA := newClient()
1911 runClient(clientA)
1912 if gotAttempts, gotHits := cacheAttempts.Value().(int64), cacheHits.Value().(int64); gotAttempts != 1 || gotHits != 0 {
1913 t.Errorf("got cacheAttempts(%v), cacheHits(%v), expected cacheAttempts(1), cacheHits(0)", gotAttempts, gotHits)
1914 }
1915 // Check that the cache is hit on the second call with the same blessings.
1916 runClient(clientA)
1917 if gotAttempts, gotHits := cacheAttempts.Value().(int64), cacheHits.Value().(int64); gotAttempts != 2 || gotHits != 1 {
1918 t.Errorf("got cacheAttempts(%v), cacheHits(%v), expected cacheAttempts(2), cacheHits(1)", gotAttempts, gotHits)
1919 }
1920 clientA.Close()
1921 // Check that the cache is not used with a different client.
1922 clientB := newClient()
1923 runClient(clientB)
1924 if gotAttempts, gotHits := cacheAttempts.Value().(int64), cacheHits.Value().(int64); gotAttempts != 3 || gotHits != 1 {
1925 t.Errorf("got cacheAttempts(%v), cacheHits(%v), expected cacheAttempts(3), cacheHits(1)", gotAttempts, gotHits)
1926 }
1927 // clientB changes its blessings, the cache should not be used.
1928 blessings, err := pserver.Bless(pclient.PublicKey(), pserver.BlessingStore().Default(), "cav", mkCaveat(security.ExpiryCaveat(time.Now().Add(time.Hour))))
1929 if err != nil {
1930 t.Fatalf("failed to create Blessings: %v", err)
1931 }
1932 if _, err = pclient.BlessingStore().Set(blessings, "server"); err != nil {
1933 t.Fatalf("failed to set blessings: %v", err)
1934 }
1935 runClient(clientB)
1936 if gotAttempts, gotHits := cacheAttempts.Value().(int64), cacheHits.Value().(int64); gotAttempts != 4 || gotHits != 1 {
1937 t.Errorf("got cacheAttempts(%v), cacheHits(%v), expected cacheAttempts(4), cacheHits(1)", gotAttempts, gotHits)
1938 }
1939 clientB.Close()
1940}
1941
Asim Shankar7283dd82015-02-03 19:35:58 -08001942var fakeTimeCaveat = security.CaveatDescriptor{
1943 Id: uniqueid.Id{0x18, 0xba, 0x6f, 0x84, 0xd5, 0xec, 0xdb, 0x9b, 0xf2, 0x32, 0x19, 0x5b, 0x53, 0x92, 0x80, 0x0},
1944 ParamType: vdl.TypeOf(int64(0)),
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001945}
Suharsh Sivakumar9d17e4a2015-02-02 22:42:16 -08001946
Suharsh Sivakumara8633b02015-02-14 17:08:07 -08001947func TestServerPublicKeyOpt(t *testing.T) {
1948 var (
Asim Shankar4a698282015-03-21 21:59:18 -07001949 pserver = testutil.NewPrincipal("server")
1950 pother = testutil.NewPrincipal("other")
1951 pclient = testutil.NewPrincipal("client")
Suharsh Sivakumara8633b02015-02-14 17:08:07 -08001952 )
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001953 ctx, shutdown := initForTest()
1954 defer shutdown()
Suharsh Sivakumara8633b02015-02-14 17:08:07 -08001955 ns := tnaming.NewSimpleNamespace()
Suharsh Sivakumara8633b02015-02-14 17:08:07 -08001956 mountName := "mountpoint/default"
Suharsh Sivakumara8633b02015-02-14 17:08:07 -08001957
1958 // Start a server with pserver.
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001959 defer runServer(t, ctx, ns, pserver, mountName, &testServer{}).Shutdown()
Suharsh Sivakumara8633b02015-02-14 17:08:07 -08001960
1961 smc := imanager.InternalNew(naming.FixedRoutingID(0xc))
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001962 client, err := InternalNewClient(smc, ns)
Suharsh Sivakumara8633b02015-02-14 17:08:07 -08001963 if err != nil {
1964 t.Fatal(err)
1965 }
1966 defer smc.Shutdown()
1967 defer client.Close()
1968
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07001969 ctx, _ = v23.SetPrincipal(ctx, pclient)
Suharsh Sivakumara8633b02015-02-14 17:08:07 -08001970 // The call should succeed when the server presents the same public as the opt...
Asim Shankar263c73b2015-03-19 18:31:26 -07001971 if _, err = client.StartCall(ctx, mountName, "Closure", nil, options.SkipServerEndpointAuthorization{}, options.ServerPublicKey{pserver.PublicKey()}); err != nil {
Suharsh Sivakumara8633b02015-02-14 17:08:07 -08001972 t.Errorf("Expected call to succeed but got %v", err)
1973 }
1974 // ...but fail if they differ.
Todd Wang8fa38762015-03-25 14:04:59 -07001975 if _, err = client.StartCall(ctx, mountName, "Closure", nil, options.SkipServerEndpointAuthorization{}, options.ServerPublicKey{pother.PublicKey()}); verror.ErrorID(err) != verror.ErrNotTrusted.ID {
Jiri Simsa074bf362015-02-17 09:29:45 -08001976 t.Errorf("got %v, want %v", verror.ErrorID(err), verror.ErrNotTrusted.ID)
Suharsh Sivakumara8633b02015-02-14 17:08:07 -08001977 }
1978}
1979
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08001980type expiryDischarger struct {
1981 called bool
1982}
1983
Matt Rosencrantz94502cf2015-03-18 09:43:44 -07001984func (ed *expiryDischarger) Discharge(call rpc.StreamServerCall, cav security.Caveat, _ security.DischargeImpetus) (security.Discharge, error) {
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08001985 tp := cav.ThirdPartyDetails()
1986 if tp == nil {
Asim Shankar08642822015-03-02 21:21:09 -08001987 return security.Discharge{}, fmt.Errorf("discharger: %v does not represent a third-party caveat", cav)
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08001988 }
Matt Rosencrantz317b0c52015-03-24 20:47:01 -07001989 if err := tp.Dischargeable(call.Context()); err != nil {
Asim Shankar08642822015-03-02 21:21:09 -08001990 return security.Discharge{}, fmt.Errorf("third-party caveat %v cannot be discharged for this context: %v", cav, err)
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08001991 }
1992 expDur := 10 * time.Millisecond
1993 if ed.called {
1994 expDur = time.Second
1995 }
1996 expiry, err := security.ExpiryCaveat(time.Now().Add(expDur))
1997 if err != nil {
Asim Shankar08642822015-03-02 21:21:09 -08001998 return security.Discharge{}, fmt.Errorf("failed to create an expiration on the discharge: %v", err)
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08001999 }
Matt Rosencrantz311378b2015-03-25 15:26:12 -07002000 d, err := security.GetCall(call.Context()).LocalPrincipal().MintDischarge(cav, expiry)
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08002001 if err != nil {
Asim Shankar08642822015-03-02 21:21:09 -08002002 return security.Discharge{}, err
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08002003 }
2004 ed.called = true
Asim Shankar08642822015-03-02 21:21:09 -08002005 return d, nil
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08002006}
2007
2008func TestDischargeClientFetchExpiredDischarges(t *testing.T) {
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07002009 ctx, shutdown := initForTest()
2010 defer shutdown()
Asim Shankar263c73b2015-03-19 18:31:26 -07002011 var (
2012 pclient, pdischarger = newClientServerPrincipals()
2013 tpcav = mkThirdPartyCaveat(pdischarger.PublicKey(), "mountpoint/discharger", mkCaveat(security.ExpiryCaveat(time.Now().Add(time.Hour))))
2014 ns = tnaming.NewSimpleNamespace()
2015 discharger = &expiryDischarger{}
2016 )
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08002017
2018 // Setup the disharge server.
Suharsh Sivakumar2ad4e102015-03-17 21:23:37 -07002019 defer runServer(t, ctx, ns, pdischarger, "mountpoint/discharger", discharger).Shutdown()
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08002020
2021 // Create a discharge client.
2022 rid, err := naming.NewRoutingID()
2023 if err != nil {
2024 t.Fatal(err)
2025 }
2026 smc := imanager.InternalNew(rid)
2027 defer smc.Shutdown()
2028 client, err := InternalNewClient(smc, ns)
2029 if err != nil {
2030 t.Fatalf("failed to create client: %v", err)
2031 }
2032 defer client.Close()
Asim Shankar263c73b2015-03-19 18:31:26 -07002033 ctx, _ = v23.SetPrincipal(ctx, pclient)
Suharsh Sivakumar08918582015-03-03 15:16:36 -08002034 dc := InternalNewDischargeClient(ctx, client, 0)
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08002035
2036 // Fetch discharges for tpcav.
Asim Shankar263c73b2015-03-19 18:31:26 -07002037 dis := dc.PrepareDischarges(ctx, []security.Caveat{tpcav}, security.DischargeImpetus{})[0]
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08002038 // Check that the discharges is not yet expired, but is expired after 100 milliseconds.
2039 expiry := dis.Expiry()
2040 // The discharge should expire.
2041 select {
2042 case <-time.After(time.Now().Sub(expiry)):
2043 break
2044 case <-time.After(time.Second):
2045 t.Fatalf("discharge didn't expire within a second")
2046 }
2047 // Preparing Discharges again to get fresh discharges.
2048 now := time.Now()
Asim Shankar263c73b2015-03-19 18:31:26 -07002049 dis = dc.PrepareDischarges(ctx, []security.Caveat{tpcav}, security.DischargeImpetus{})[0]
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08002050 if expiry = dis.Expiry(); expiry.Before(now) {
2051 t.Fatalf("discharge has expired %v, but should be fresh", dis)
2052 }
2053}
2054
Asim Shankar263c73b2015-03-19 18:31:26 -07002055// newClientServerPrincipals creates a pair of principals and sets them up to
2056// recognize each others default blessings.
2057//
2058// If the client does not recognize the blessings presented by the server,
2059// then it will not even send it the request.
2060//
2061// If the server does not recognize the blessings presented by the client,
2062// it is likely to deny access (unless the server authorizes all principals).
2063func newClientServerPrincipals() (client, server security.Principal) {
Asim Shankar4a698282015-03-21 21:59:18 -07002064 client = testutil.NewPrincipal("client")
2065 server = testutil.NewPrincipal("server")
Asim Shankar263c73b2015-03-19 18:31:26 -07002066 client.AddToRoots(server.BlessingStore().Default())
2067 server.AddToRoots(client.BlessingStore().Default())
2068 return
2069}
2070
Suharsh Sivakumard19c95d2015-02-19 14:44:50 -08002071func init() {
Matt Rosencrantz94502cf2015-03-18 09:43:44 -07002072 rpc.RegisterUnknownProtocol("wsh", websocket.HybridDial, websocket.HybridListener)
Matt Rosencrantz317b0c52015-03-24 20:47:01 -07002073 security.RegisterCaveatValidator(fakeTimeCaveat, func(_ *context.T, t int64) error {
Suharsh Sivakumar8a0adbb2015-03-06 13:16:34 -08002074 if now := clock.Now(); now > t {
Asim Shankar7283dd82015-02-03 19:35:58 -08002075 return fmt.Errorf("fakeTimeCaveat expired: now=%d > then=%d", now, t)
2076 }
2077 return nil
2078 })
Suharsh Sivakumar9d17e4a2015-02-02 22:42:16 -08002079}