blob: 80a8be431f7256ba509a03893daaba9e11644bcc [file] [log] [blame]
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001package ipc
2
3import (
Asim Shankarf4864f42014-11-25 18:53:05 -08004 "encoding/hex"
Jiri Simsa5293dcb2014-05-10 09:56:38 -07005 "errors"
6 "fmt"
7 "io"
Cosmos Nicolaoud6c3c9c2014-09-30 15:42:53 -07008 "net"
Cosmos Nicolaou9388ae42014-11-10 10:57:15 -08009 "path/filepath"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070010 "reflect"
Cosmos Nicolaou9388ae42014-11-10 10:57:15 -080011 "runtime"
Cosmos Nicolaou9fbe7d22015-01-25 22:13:13 -080012 "sort"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070013 "strings"
Bogdan Caprita27953142014-05-12 11:41:42 -070014 "sync"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070015 "testing"
16 "time"
17
Jiri Simsa6ac95222015-02-23 16:11:49 -080018 "v.io/v23/context"
19 "v.io/v23/ipc"
20 "v.io/v23/naming"
David Why Use Two When One Will Do Presottod424c212015-02-25 11:05:26 -080021 "v.io/v23/naming/ns"
Jiri Simsa6ac95222015-02-23 16:11:49 -080022 "v.io/v23/options"
23 "v.io/v23/security"
24 "v.io/v23/services/security/access"
25 "v.io/v23/uniqueid"
26 "v.io/v23/vdl"
27 "v.io/v23/verror"
Jiri Simsa6ac95222015-02-23 16:11:49 -080028 "v.io/v23/vtrace"
Jiri Simsa337af232015-02-27 14:36:46 -080029 "v.io/x/lib/vlog"
Matt Rosencrantzdbc1be22015-02-28 15:15:49 -080030 "v.io/x/ref/profiles/internal/ipc/stream"
Cosmos Nicolaouf889c732014-10-16 20:46:54 -070031
Jiri Simsaffceefa2015-02-28 11:03:34 -080032 "v.io/x/ref/lib/flags"
33 "v.io/x/ref/lib/netstate"
Matt Rosencrantzdbc1be22015-02-28 15:15:49 -080034 "v.io/x/ref/lib/publisher"
Jiri Simsaffceefa2015-02-28 11:03:34 -080035 "v.io/x/ref/lib/stats"
36 "v.io/x/ref/lib/testutil"
37 tsecurity "v.io/x/ref/lib/testutil/security"
Matt Rosencrantzdbc1be22015-02-28 15:15:49 -080038 _ "v.io/x/ref/profiles/internal/ipc/protocols/tcp"
39 imanager "v.io/x/ref/profiles/internal/ipc/stream/manager"
40 "v.io/x/ref/profiles/internal/ipc/stream/vc"
41 inaming "v.io/x/ref/profiles/internal/naming"
42 tnaming "v.io/x/ref/profiles/internal/testing/mocks/naming"
43 ivtrace "v.io/x/ref/profiles/internal/vtrace"
Jiri Simsa5293dcb2014-05-10 09:56:38 -070044)
45
Suharsh Sivakumard19c95d2015-02-19 14:44:50 -080046//go:generate v23 test generate
47
Jiri Simsa5293dcb2014-05-10 09:56:38 -070048var (
Jiri Simsa074bf362015-02-17 09:29:45 -080049 errMethod = verror.New(verror.ErrAborted, nil)
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -080050 clock = new(fakeClock)
51 listenAddrs = ipc.ListenAddrs{{"tcp", "127.0.0.1:0"}}
52 listenWSAddrs = ipc.ListenAddrs{{"ws", "127.0.0.1:0"}, {"tcp", "127.0.0.1:0"}}
53 listenSpec = ipc.ListenSpec{Addrs: listenAddrs}
54 listenWSSpec = ipc.ListenSpec{Addrs: listenWSAddrs}
Jiri Simsa5293dcb2014-05-10 09:56:38 -070055)
56
Andres Erbsenb7f95f32014-07-07 12:07:56 -070057type fakeClock struct {
58 sync.Mutex
59 time int
60}
61
62func (c *fakeClock) Now() int {
63 c.Lock()
64 defer c.Unlock()
65 return c.time
66}
67
68func (c *fakeClock) Advance(steps uint) {
69 c.Lock()
70 c.time += int(steps)
71 c.Unlock()
72}
73
Matt Rosencrantz4f8ac602014-12-29 14:42:48 -080074func testContextWithoutDeadline() *context.T {
Matt Rosencrantz1094d062015-01-30 06:43:12 -080075 ctx, _ := context.RootContext()
Matt Rosencrantzf7b00e22015-01-13 13:44:56 -080076 ctx, err := ivtrace.Init(ctx, flags.VtraceFlags{})
77 if err != nil {
78 panic(err)
79 }
Matt Rosencrantz5f98d942015-01-08 13:48:30 -080080 ctx, _ = vtrace.SetNewTrace(ctx)
Matt Rosencrantz4f8ac602014-12-29 14:42:48 -080081 return ctx
82}
83
David Why Use Two When One Will Do Presottod424c212015-02-25 11:05:26 -080084func testInternalNewServer(ctx *context.T, streamMgr stream.Manager, ns ns.Namespace, opts ...ipc.ServerOpt) (ipc.Server, error) {
Suharsh Sivakumaraf99c972015-01-28 15:28:49 -080085 client, err := InternalNewClient(streamMgr, ns)
86 if err != nil {
87 return nil, err
88 }
89 return InternalNewServer(ctx, streamMgr, ns, client, opts...)
90}
91
Jiri Simsa5293dcb2014-05-10 09:56:38 -070092type userType string
93
94type testServer struct{}
95
Matt Rosencrantz9dce9b22015-03-02 10:48:37 -080096func (*testServer) Closure(call ipc.ServerCall) error {
Todd Wange77f9952015-02-18 13:20:50 -080097 return nil
Jiri Simsa5293dcb2014-05-10 09:56:38 -070098}
99
Matt Rosencrantz9dce9b22015-03-02 10:48:37 -0800100func (*testServer) Error(call ipc.ServerCall) error {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700101 return errMethod
102}
103
Matt Rosencrantz9dce9b22015-03-02 10:48:37 -0800104func (*testServer) Echo(call ipc.ServerCall, arg string) (string, error) {
105 return fmt.Sprintf("method:%q,suffix:%q,arg:%q", call.Method(), call.Suffix(), arg), nil
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700106}
107
Matt Rosencrantz9dce9b22015-03-02 10:48:37 -0800108func (*testServer) EchoUser(call ipc.ServerCall, arg string, u userType) (string, userType, error) {
109 return fmt.Sprintf("method:%q,suffix:%q,arg:%q", call.Method(), call.Suffix(), arg), u, nil
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700110}
111
Matt Rosencrantz9dce9b22015-03-02 10:48:37 -0800112func (*testServer) EchoBlessings(call ipc.ServerCall) (server, client string, _ error) {
113 local, _ := call.LocalBlessings().ForCall(call)
114 remote, _ := call.RemoteBlessings().ForCall(call)
Todd Wange77f9952015-02-18 13:20:50 -0800115 return fmt.Sprintf("%v", local), fmt.Sprintf("%v", remote), nil
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700116}
117
Matt Rosencrantz9dce9b22015-03-02 10:48:37 -0800118func (*testServer) EchoGrantedBlessings(call ipc.ServerCall, arg string) (result, blessing string, _ error) {
119 return arg, fmt.Sprintf("%v", call.GrantedBlessings()), nil
Asim Shankarb54d7642014-06-05 13:08:04 -0700120}
121
Matt Rosencrantz9dce9b22015-03-02 10:48:37 -0800122func (*testServer) EchoAndError(call ipc.ServerCall, arg string) (string, error) {
123 result := fmt.Sprintf("method:%q,suffix:%q,arg:%q", call.Method(), call.Suffix(), arg)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700124 if arg == "error" {
125 return result, errMethod
126 }
127 return result, nil
128}
129
Matt Rosencrantz1dcd0a92015-02-27 11:05:59 -0800130func (*testServer) Stream(call ipc.StreamServerCall, arg string) (string, error) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700131 result := fmt.Sprintf("method:%q,suffix:%q,arg:%q", call.Method(), call.Suffix(), arg)
132 var u userType
133 var err error
134 for err = call.Recv(&u); err == nil; err = call.Recv(&u) {
135 result += " " + string(u)
136 if err := call.Send(u); err != nil {
137 return "", err
138 }
139 }
140 if err == io.EOF {
141 err = nil
142 }
143 return result, err
144}
145
Matt Rosencrantz1dcd0a92015-02-27 11:05:59 -0800146func (*testServer) Unauthorized(ipc.StreamServerCall) (string, error) {
Todd Wange77f9952015-02-18 13:20:50 -0800147 return "UnauthorizedResult", nil
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700148}
149
150type testServerAuthorizer struct{}
151
Matt Rosencrantz5c7ed212015-02-27 22:42:35 -0800152func (testServerAuthorizer) Authorize(c security.Call) error {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700153 if c.Method() != "Unauthorized" {
154 return nil
155 }
Asim Shankar8f05c222014-10-06 22:08:19 -0700156 return fmt.Errorf("testServerAuthorizer denied access")
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700157}
158
159type testServerDisp struct{ server interface{} }
160
Robin Thellenda02fe8f2014-11-19 09:58:29 -0800161func (t testServerDisp) Lookup(suffix string) (interface{}, security.Authorizer, error) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700162 // If suffix is "nilAuth" we use default authorization, if it is "aclAuth" we
163 // use an ACL based authorizer, and otherwise we use the custom testServerAuthorizer.
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700164 var authorizer security.Authorizer
165 switch suffix {
166 case "discharger":
Cosmos Nicolaou710daa22014-11-11 19:39:18 -0800167 return &dischargeServer{}, testServerAuthorizer{}, nil
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700168 case "nilAuth":
169 authorizer = nil
170 case "aclAuth":
Asim Shankar68885192014-11-26 12:48:35 -0800171 authorizer = &access.ACL{
Ankur78b8b2a2015-02-04 20:16:28 -0800172 In: []security.BlessingPattern{"client", "server"},
Asim Shankar68885192014-11-26 12:48:35 -0800173 }
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700174 default:
175 authorizer = testServerAuthorizer{}
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700176 }
Cosmos Nicolaou710daa22014-11-11 19:39:18 -0800177 return t.server, authorizer, nil
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700178}
179
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -0800180type dischargeServer struct {
181 mu sync.Mutex
182 called bool
183}
Ankure49a86a2014-11-11 18:52:43 -0800184
Asim Shankar08642822015-03-02 21:21:09 -0800185func (ds *dischargeServer) Discharge(call ipc.StreamServerCall, cav security.Caveat, _ security.DischargeImpetus) (security.Discharge, error) {
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -0800186 ds.mu.Lock()
187 ds.called = true
188 ds.mu.Unlock()
Asim Shankar19da8182015-02-06 01:41:16 -0800189 tp := cav.ThirdPartyDetails()
190 if tp == nil {
Asim Shankar08642822015-03-02 21:21:09 -0800191 return security.Discharge{}, fmt.Errorf("discharger: %v does not represent a third-party caveat", cav)
Ankure49a86a2014-11-11 18:52:43 -0800192 }
Matt Rosencrantz9dce9b22015-03-02 10:48:37 -0800193 if err := tp.Dischargeable(call); err != nil {
Asim Shankar08642822015-03-02 21:21:09 -0800194 return security.Discharge{}, fmt.Errorf("third-party caveat %v cannot be discharged for this context: %v", cav, err)
Ankure49a86a2014-11-11 18:52:43 -0800195 }
196 // Add a fakeTimeCaveat to be able to control discharge expiration via 'clock'.
Asim Shankar7283dd82015-02-03 19:35:58 -0800197 expiry, err := security.NewCaveat(fakeTimeCaveat, clock.Now())
198 if err != nil {
Asim Shankar08642822015-03-02 21:21:09 -0800199 return security.Discharge{}, fmt.Errorf("failed to create an expiration on the discharge: %v", err)
Asim Shankar7283dd82015-02-03 19:35:58 -0800200 }
Asim Shankar08642822015-03-02 21:21:09 -0800201 return call.LocalPrincipal().MintDischarge(cav, expiry)
Ankure49a86a2014-11-11 18:52:43 -0800202}
203
David Why Use Two When One Will Do Presottod424c212015-02-25 11:05:26 -0800204func startServer(t *testing.T, principal security.Principal, sm stream.Manager, ns ns.Namespace, name string, disp ipc.Dispatcher, opts ...ipc.ServerOpt) (naming.Endpoint, ipc.Server) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800205 return startServerWS(t, principal, sm, ns, name, disp, noWebsocket, opts...)
206}
207
Cosmos Nicolaou9fbe7d22015-01-25 22:13:13 -0800208func endpointsToStrings(eps []naming.Endpoint) []string {
209 r := make([]string, len(eps))
210 for i, e := range eps {
211 r[i] = e.String()
212 }
213 sort.Strings(r)
214 return r
215}
216
David Why Use Two When One Will Do Presottod424c212015-02-25 11:05:26 -0800217func startServerWS(t *testing.T, principal security.Principal, sm stream.Manager, ns ns.Namespace, name string, disp ipc.Dispatcher, shouldUseWebsocket websocketMode, opts ...ipc.ServerOpt) (naming.Endpoint, ipc.Server) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700218 vlog.VI(1).Info("InternalNewServer")
Ankure49a86a2014-11-11 18:52:43 -0800219 opts = append(opts, vc.LocalPrincipal{principal})
Matt Rosencrantzfa3082c2015-01-22 21:39:04 -0800220 ctx := testContext()
Suharsh Sivakumaraf99c972015-01-28 15:28:49 -0800221 server, err := testInternalNewServer(ctx, sm, ns, opts...)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700222 if err != nil {
223 t.Errorf("InternalNewServer failed: %v", err)
224 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700225 vlog.VI(1).Info("server.Listen")
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800226 spec := listenSpec
227 if shouldUseWebsocket {
228 spec = listenWSSpec
229 }
Cosmos Nicolaou9fbe7d22015-01-25 22:13:13 -0800230 eps, err := server.Listen(spec)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700231 if err != nil {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700232 t.Errorf("server.Listen failed: %v", err)
233 }
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700234 vlog.VI(1).Info("server.Serve")
Ankure49a86a2014-11-11 18:52:43 -0800235 if err := server.ServeDispatcher(name, disp); err != nil {
236 t.Errorf("server.ServeDispatcher failed: %v", err)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700237 }
Cosmos Nicolaou9fbe7d22015-01-25 22:13:13 -0800238
239 status := server.Status()
240 if got, want := endpointsToStrings(status.Endpoints), endpointsToStrings(eps); !reflect.DeepEqual(got, want) {
241 t.Fatalf("got %v, want %v", got, want)
242 }
243 names := status.Mounts.Names()
244 if len(names) != 1 || names[0] != name {
245 t.Fatalf("unexpected names: %v", names)
246 }
247 return eps[0], server
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700248}
249
Cosmos Nicolaou9388ae42014-11-10 10:57:15 -0800250func loc(d int) string {
251 _, file, line, _ := runtime.Caller(d + 1)
252 return fmt.Sprintf("%s:%d", filepath.Base(file), line)
253}
254
David Why Use Two When One Will Do Presottod424c212015-02-25 11:05:26 -0800255func verifyMount(t *testing.T, ns ns.Namespace, name string) []string {
David Why Use Two When One Will Do Presotto8de85852015-01-21 11:05:09 -0800256 me, err := ns.Resolve(testContext(), name)
Cosmos Nicolaou9388ae42014-11-10 10:57:15 -0800257 if err != nil {
258 t.Errorf("%s: %s not found in mounttable", loc(1), name)
259 return nil
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700260 }
Cosmos Nicolaou8bd8e102015-01-13 21:52:53 -0800261 return me.Names()
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700262}
263
David Why Use Two When One Will Do Presottod424c212015-02-25 11:05:26 -0800264func verifyMountMissing(t *testing.T, ns ns.Namespace, name string) {
David Why Use Two When One Will Do Presotto8de85852015-01-21 11:05:09 -0800265 if me, err := ns.Resolve(testContext(), name); err == nil {
Cosmos Nicolaou8bd8e102015-01-13 21:52:53 -0800266 names := me.Names()
Asim Shankarb547ea92015-02-17 18:49:45 -0800267 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 -0700268 }
269}
270
David Why Use Two When One Will Do Presottod424c212015-02-25 11:05:26 -0800271func stopServer(t *testing.T, server ipc.Server, ns ns.Namespace, name string) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700272 vlog.VI(1).Info("server.Stop")
Ankure49a86a2014-11-11 18:52:43 -0800273 new_name := "should_appear_in_mt/server"
274 verifyMount(t, ns, name)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700275
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700276 // publish a second name
Ankure49a86a2014-11-11 18:52:43 -0800277 if err := server.AddName(new_name); err != nil {
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700278 t.Errorf("server.Serve failed: %v", err)
279 }
Ankure49a86a2014-11-11 18:52:43 -0800280 verifyMount(t, ns, new_name)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700281
282 if err := server.Stop(); err != nil {
283 t.Errorf("server.Stop failed: %v", err)
284 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700285
Ankure49a86a2014-11-11 18:52:43 -0800286 verifyMountMissing(t, ns, name)
287 verifyMountMissing(t, ns, new_name)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700288
289 // Check that we can no longer serve after Stop.
Cosmos Nicolaou92dba582014-11-05 17:24:10 -0800290 err := server.AddName("name doesn't matter")
Jiri Simsa074bf362015-02-17 09:29:45 -0800291 if err == nil || !verror.Is(err, verror.ErrBadState.ID) {
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700292 t.Errorf("either no error, or a wrong error was returned: %v", err)
293 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700294 vlog.VI(1).Info("server.Stop DONE")
295}
296
Cosmos Nicolaou8bd8e102015-01-13 21:52:53 -0800297// fakeWSName creates a name containing a endpoint address that forces
298// the use of websockets. It does so by resolving the original name
299// and choosing the 'ws' endpoint from the set of endpoints returned.
300// It must return a name since it'll be passed to StartCall.
David Why Use Two When One Will Do Presottod424c212015-02-25 11:05:26 -0800301func fakeWSName(ns ns.Namespace, name string) (string, error) {
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800302 // Find the ws endpoint and use that.
David Why Use Two When One Will Do Presotto8de85852015-01-21 11:05:09 -0800303 me, err := ns.Resolve(testContext(), name)
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800304 if err != nil {
305 return "", err
306 }
Cosmos Nicolaou8bd8e102015-01-13 21:52:53 -0800307 names := me.Names()
308 for _, s := range names {
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800309 if strings.Index(s, "@ws@") != -1 {
310 return s, nil
311 }
312 }
Cosmos Nicolaou8bd8e102015-01-13 21:52:53 -0800313 return "", fmt.Errorf("No ws endpoint found %v", names)
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800314}
315
Bogdan Caprita27953142014-05-12 11:41:42 -0700316type bundle struct {
317 client ipc.Client
318 server ipc.Server
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700319 ep naming.Endpoint
David Why Use Two When One Will Do Presottod424c212015-02-25 11:05:26 -0800320 ns ns.Namespace
Bogdan Caprita27953142014-05-12 11:41:42 -0700321 sm stream.Manager
Ankure49a86a2014-11-11 18:52:43 -0800322 name string
Bogdan Caprita27953142014-05-12 11:41:42 -0700323}
324
325func (b bundle) cleanup(t *testing.T) {
Ankura3c97652014-07-17 20:01:21 -0700326 if b.server != nil {
Ankure49a86a2014-11-11 18:52:43 -0800327 stopServer(t, b.server, b.ns, b.name)
Ankura3c97652014-07-17 20:01:21 -0700328 }
329 if b.client != nil {
330 b.client.Close()
331 }
Bogdan Caprita27953142014-05-12 11:41:42 -0700332}
333
Asim Shankar8f05c222014-10-06 22:08:19 -0700334func createBundle(t *testing.T, client, server security.Principal, ts interface{}) (b bundle) {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800335 return createBundleWS(t, client, server, ts, noWebsocket)
336}
337
338func createBundleWS(t *testing.T, client, server security.Principal, ts interface{}, shouldUseWebsocket websocketMode) (b bundle) {
Bogdan Caprita27953142014-05-12 11:41:42 -0700339 b.sm = imanager.InternalNew(naming.FixedRoutingID(0x555555555))
Matt Rosencrantz9fe60822014-09-12 10:09:53 -0700340 b.ns = tnaming.NewSimpleNamespace()
Ankure49a86a2014-11-11 18:52:43 -0800341 b.name = "mountpoint/server"
Asim Shankar8f05c222014-10-06 22:08:19 -0700342 if server != nil {
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800343 b.ep, b.server = startServerWS(t, server, b.sm, b.ns, b.name, testServerDisp{ts}, shouldUseWebsocket)
Ankura3c97652014-07-17 20:01:21 -0700344 }
Asim Shankar8f05c222014-10-06 22:08:19 -0700345 if client != nil {
Ankura3c97652014-07-17 20:01:21 -0700346 var err error
Asim Shankar8f05c222014-10-06 22:08:19 -0700347 if b.client, err = InternalNewClient(b.sm, b.ns, vc.LocalPrincipal{client}); err != nil {
Ankura3c97652014-07-17 20:01:21 -0700348 t.Fatalf("InternalNewClient failed: %v", err)
349 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700350 }
Bogdan Caprita27953142014-05-12 11:41:42 -0700351 return
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700352}
353
Cosmos Nicolaou112bf1c2014-11-21 15:43:11 -0800354func matchesErrorPattern(err error, id verror.IDAction, pattern string) bool {
Asim Shankar558ea012015-01-28 12:49:36 -0800355 if len(pattern) > 0 && err != nil && strings.Index(err.Error(), pattern) < 0 {
356 return false
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700357 }
Cosmos Nicolaou1bce7d12015-01-05 17:42:06 -0800358 if err == nil && id.ID == "" {
359 return true
Cosmos Nicolaou112bf1c2014-11-21 15:43:11 -0800360 }
361 return verror.Is(err, id.ID)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700362}
363
Suharsh Sivakumar0902b7f2015-02-27 19:06:41 -0800364func runServer(t *testing.T, ns ns.Namespace, name string, obj interface{}, opts ...ipc.ServerOpt) stream.Manager {
365 rid, err := naming.NewRoutingID()
366 if err != nil {
367 t.Fatal(err)
368 }
369 sm := imanager.InternalNew(rid)
370 server, err := testInternalNewServer(testContext(), sm, ns, opts...)
371 if err != nil {
372 t.Fatal(err)
373 }
374 if _, err := server.Listen(listenSpec); err != nil {
375 t.Fatal(err)
376 }
377 if err := server.Serve(name, obj, acceptAllAuthorizer{}); err != nil {
378 t.Fatal(err)
379 }
380 return sm
381}
382
Cosmos Nicolaou92dba582014-11-05 17:24:10 -0800383func TestMultipleCallsToServeAndName(t *testing.T) {
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700384 sm := imanager.InternalNew(naming.FixedRoutingID(0x555555555))
Matt Rosencrantz9fe60822014-09-12 10:09:53 -0700385 ns := tnaming.NewSimpleNamespace()
Matt Rosencrantzfa3082c2015-01-22 21:39:04 -0800386 ctx := testContext()
Suharsh Sivakumaraf99c972015-01-28 15:28:49 -0800387 server, err := testInternalNewServer(ctx, sm, ns, vc.LocalPrincipal{tsecurity.NewPrincipal()})
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700388 if err != nil {
389 t.Errorf("InternalNewServer failed: %v", err)
390 }
Cosmos Nicolaouf8d4c2b2014-10-23 22:36:38 -0700391 _, err = server.Listen(listenSpec)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700392 if err != nil {
393 t.Errorf("server.Listen failed: %v", err)
394 }
395
396 disp := &testServerDisp{&testServer{}}
Cosmos Nicolaou92dba582014-11-05 17:24:10 -0800397 if err := server.ServeDispatcher("mountpoint/server", disp); err != nil {
398 t.Errorf("server.ServeDispatcher failed: %v", err)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700399 }
400
401 n1 := "mountpoint/server"
402 n2 := "should_appear_in_mt/server"
403 n3 := "should_appear_in_mt/server"
404 n4 := "should_not_appear_in_mt/server"
405
406 verifyMount(t, ns, n1)
407
Cosmos Nicolaou92dba582014-11-05 17:24:10 -0800408 if server.ServeDispatcher(n2, disp) == nil {
409 t.Errorf("server.ServeDispatcher should have failed")
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700410 }
Cosmos Nicolaou92dba582014-11-05 17:24:10 -0800411
412 if err := server.Serve(n2, &testServer{}, nil); err == nil {
413 t.Errorf("server.Serve should have failed")
414 }
415
416 if err := server.AddName(n3); err != nil {
417 t.Errorf("server.AddName failed: %v", err)
418 }
419
420 if err := server.AddName(n3); err != nil {
421 t.Errorf("server.AddName failed: %v", err)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700422 }
423 verifyMount(t, ns, n2)
424 verifyMount(t, ns, n3)
425
Cosmos Nicolaou9fbe7d22015-01-25 22:13:13 -0800426 server.RemoveName(n1)
Cosmos Nicolaou92dba582014-11-05 17:24:10 -0800427 verifyMountMissing(t, ns, n1)
428
Cosmos Nicolaou9fbe7d22015-01-25 22:13:13 -0800429 server.RemoveName("some randome name")
Cosmos Nicolaou92dba582014-11-05 17:24:10 -0800430
431 if err := server.ServeDispatcher(n4, &testServerDisp{&testServer{}}); err == nil {
432 t.Errorf("server.ServeDispatcher should have failed")
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -0700433 }
434 verifyMountMissing(t, ns, n4)
435
436 if err := server.Stop(); err != nil {
437 t.Errorf("server.Stop failed: %v", err)
438 }
439
440 verifyMountMissing(t, ns, n1)
441 verifyMountMissing(t, ns, n2)
442 verifyMountMissing(t, ns, n3)
443}
444
Ankure49a86a2014-11-11 18:52:43 -0800445func TestRPCServerAuthorization(t *testing.T) {
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700446 const (
Ankur50a5f392015-02-27 18:46:30 -0800447 publicKeyErr = "not matched by server key"
448 forPeerErr = "no blessings tagged for peer"
449 nameErr = "do not match pattern"
450 allowedErr = "do not match any allowed server patterns"
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700451 )
452 var (
Ankure49a86a2014-11-11 18:52:43 -0800453 pprovider, pclient, pserver = tsecurity.NewPrincipal("root"), tsecurity.NewPrincipal(), tsecurity.NewPrincipal()
454 pdischarger = pprovider
Asim Shankar558ea012015-01-28 12:49:36 -0800455 now = time.Now()
456 noErrID verror.IDAction
Ankure49a86a2014-11-11 18:52:43 -0800457
458 // Third-party caveats on blessings presented by server.
Asim Shankar558ea012015-01-28 12:49:36 -0800459 cavTPValid = mkThirdPartyCaveat(pdischarger.PublicKey(), "mountpoint/dischargeserver", mkCaveat(security.ExpiryCaveat(now.Add(24*time.Hour))))
460 cavTPExpired = mkThirdPartyCaveat(pdischarger.PublicKey(), "mountpoint/dischargeserver", mkCaveat(security.ExpiryCaveat(now.Add(-1*time.Second))))
Ankure49a86a2014-11-11 18:52:43 -0800461
462 // Server blessings.
463 bServer = bless(pprovider, pserver, "server")
464 bServerExpired = bless(pprovider, pserver, "server", mkCaveat(security.ExpiryCaveat(time.Now().Add(-1*time.Second))))
465 bServerTPValid = bless(pprovider, pserver, "serverWithTPCaveats", cavTPValid)
466 bServerTPExpired = bless(pprovider, pserver, "serverWithTPCaveats", cavTPExpired)
Asim Shankar558ea012015-01-28 12:49:36 -0800467 bTwoBlessings, _ = security.UnionOfBlessings(bServer, bServerTPValid)
Asim Shankar8f05c222014-10-06 22:08:19 -0700468
469 mgr = imanager.InternalNew(naming.FixedRoutingID(0x1111111))
470 ns = tnaming.NewSimpleNamespace()
471 tests = []struct {
Ankur50a5f392015-02-27 18:46:30 -0800472 server security.Blessings // blessings presented by the server to the client.
473 name string // name provided by the client to StartCall
474 opt ipc.CallOpt // option provided to StartCall.
475 errID verror.IDAction
476 err string
Asim Shankar8f05c222014-10-06 22:08:19 -0700477 }{
Asim Shankar558ea012015-01-28 12:49:36 -0800478 // Client accepts talking to the server only if the
479 // server's blessings match the provided pattern
Asim Shankarb547ea92015-02-17 18:49:45 -0800480 {bServer, "[...]mountpoint/server", nil, noErrID, ""},
Asim Shankar558ea012015-01-28 12:49:36 -0800481 {bServer, "[root/server]mountpoint/server", nil, noErrID, ""},
Jiri Simsa074bf362015-02-17 09:29:45 -0800482 {bServer, "[root/otherserver]mountpoint/server", nil, verror.ErrNotTrusted, nameErr},
483 {bServer, "[otherroot/server]mountpoint/server", nil, verror.ErrNotTrusted, nameErr},
Asim Shankar8f05c222014-10-06 22:08:19 -0700484
Asim Shankar558ea012015-01-28 12:49:36 -0800485 // and, if the server's blessing has third-party
486 // caveats then the server provides appropriate
487 // discharges.
Asim Shankarb547ea92015-02-17 18:49:45 -0800488 {bServerTPValid, "[...]mountpoint/server", nil, noErrID, ""},
Asim Shankar558ea012015-01-28 12:49:36 -0800489 {bServerTPValid, "[root/serverWithTPCaveats]mountpoint/server", nil, noErrID, ""},
Jiri Simsa074bf362015-02-17 09:29:45 -0800490 {bServerTPValid, "[root/otherserver]mountpoint/server", nil, verror.ErrNotTrusted, nameErr},
491 {bServerTPValid, "[otherroot/server]mountpoint/server", nil, verror.ErrNotTrusted, nameErr},
Ankure49a86a2014-11-11 18:52:43 -0800492
Asim Shankar558ea012015-01-28 12:49:36 -0800493 // Client does not talk to a server that presents
494 // expired blessings (because the blessing store is
Asim Shankarb547ea92015-02-17 18:49:45 -0800495 // configured to only talk to root).
Ankur50a5f392015-02-27 18:46:30 -0800496 {bServerExpired, "[...]mountpoint/server", nil, verror.ErrNotTrusted, forPeerErr},
Ankure49a86a2014-11-11 18:52:43 -0800497
Asim Shankar558ea012015-01-28 12:49:36 -0800498 // Client does not talk to a server that fails to
499 // provide discharges for third-party caveats on the
500 // blessings presented by it.
Ankur50a5f392015-02-27 18:46:30 -0800501 {bServerTPExpired, "[...]mountpoint/server", nil, verror.ErrNotTrusted, forPeerErr},
Asim Shankar558ea012015-01-28 12:49:36 -0800502
503 // Testing the AllowedServersPolicy option.
Asim Shankarb547ea92015-02-17 18:49:45 -0800504 {bServer, "[...]mountpoint/server", options.AllowedServersPolicy{"otherroot"}, verror.ErrNotTrusted, allowedErr},
Jiri Simsa074bf362015-02-17 09:29:45 -0800505 {bServer, "[root/server]mountpoint/server", options.AllowedServersPolicy{"otherroot"}, verror.ErrNotTrusted, allowedErr},
506 {bServer, "[otherroot/server]mountpoint/server", options.AllowedServersPolicy{"root/server"}, verror.ErrNotTrusted, nameErr},
Ankur78b8b2a2015-02-04 20:16:28 -0800507 {bServer, "[root/server]mountpoint/server", options.AllowedServersPolicy{"root"}, noErrID, ""},
Ankur50a5f392015-02-27 18:46:30 -0800508
509 // Test the ServerPublicKey option.
510 {bServer, "[...]mountpoint/server", options.ServerPublicKey{bServer.PublicKey()}, noErrID, ""},
511 {bServer, "[...]mountpoint/server", options.ServerPublicKey{tsecurity.NewPrincipal("irrelevant").PublicKey()}, verror.ErrNotTrusted, publicKeyErr},
Asim Shankar558ea012015-01-28 12:49:36 -0800512 // Server presents two blessings: One that satisfies
513 // the pattern provided to StartCall and one that
514 // satisfies the AllowedServersPolicy, so the server is
515 // authorized.
516 {bTwoBlessings, "[root/serverWithTPCaveats]mountpoint/server", options.AllowedServersPolicy{"root/server"}, noErrID, ""},
Asim Shankar8f05c222014-10-06 22:08:19 -0700517 }
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700518 )
Ankure49a86a2014-11-11 18:52:43 -0800519
Asim Shankar558ea012015-01-28 12:49:36 -0800520 _, server := startServer(t, pserver, mgr, ns, "mountpoint/server", testServerDisp{&testServer{}})
521 defer stopServer(t, server, ns, "mountpoint/server")
Ankure49a86a2014-11-11 18:52:43 -0800522
523 // Start the discharge server.
Asim Shankar558ea012015-01-28 12:49:36 -0800524 _, dischargeServer := startServer(t, pdischarger, mgr, ns, "mountpoint/dischargeserver", testutil.LeafDispatcher(&dischargeServer{}, &acceptAllAuthorizer{}))
525 defer stopServer(t, dischargeServer, ns, "mountpoint/dischargeserver")
Ankure49a86a2014-11-11 18:52:43 -0800526
Asim Shankar558ea012015-01-28 12:49:36 -0800527 // Make the client and server principals trust root certificates from
528 // pprovider
Asim Shankar8f05c222014-10-06 22:08:19 -0700529 pclient.AddToRoots(pprovider.BlessingStore().Default())
530 pserver.AddToRoots(pprovider.BlessingStore().Default())
Asim Shankar558ea012015-01-28 12:49:36 -0800531 // Set a blessing that the client is willing to share with servers with
532 // blessings from pprovider.
Ankur78b8b2a2015-02-04 20:16:28 -0800533 pclient.BlessingStore().Set(bless(pprovider, pclient, "client"), "root")
Asim Shankar558ea012015-01-28 12:49:36 -0800534
Cosmos Nicolaou112bf1c2014-11-21 15:43:11 -0800535 for i, test := range tests {
Ankur50a5f392015-02-27 18:46:30 -0800536 name := fmt.Sprintf("(#%d: Name:%q, Server:%q, opt:%v)", i, test.name, test.server, test.opt)
Ankure49a86a2014-11-11 18:52:43 -0800537 if err := pserver.BlessingStore().SetDefault(test.server); err != nil {
538 t.Fatalf("SetDefault failed on server's BlessingStore: %v", err)
539 }
Ankur78b8b2a2015-02-04 20:16:28 -0800540 if _, err := pserver.BlessingStore().Set(test.server, "root"); err != nil {
Ankure49a86a2014-11-11 18:52:43 -0800541 t.Fatalf("Set failed on server's BlessingStore: %v", err)
542 }
Asim Shankar8f05c222014-10-06 22:08:19 -0700543 // Recreate client in each test (so as to not re-use VCs to the server).
544 client, err := InternalNewClient(mgr, ns, vc.LocalPrincipal{pclient})
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700545 if err != nil {
Asim Shankara5b60b22014-11-06 15:37:07 -0800546 t.Errorf("%s: failed to create client: %v", name, err)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700547 continue
548 }
Asim Shankar558ea012015-01-28 12:49:36 -0800549 ctx, cancel := context.WithTimeout(testContextWithoutDeadline(), 10*time.Second)
Ankur50a5f392015-02-27 18:46:30 -0800550 call, err := client.StartCall(ctx, test.name, "Method", nil, test.opt)
Cosmos Nicolaou112bf1c2014-11-21 15:43:11 -0800551 if !matchesErrorPattern(err, test.errID, test.err) {
Asim Shankarb547ea92015-02-17 18:49:45 -0800552 t.Errorf(`%s: client.StartCall: got error "%v", want to match "%v"`, name, err, test.err)
Asim Shankar2d731a92014-09-29 17:46:38 -0700553 } else if call != nil {
Asim Shankar8f05c222014-10-06 22:08:19 -0700554 blessings, proof := call.RemoteBlessings()
Asim Shankar2bf7b1e2015-02-27 00:45:12 -0800555 if proof.IsZero() {
556 t.Errorf("%s: Returned zero value for remote blessings", name)
Asim Shankar8f05c222014-10-06 22:08:19 -0700557 }
Asim Shankar558ea012015-01-28 12:49:36 -0800558 // Currently all tests are configured so that the only
559 // blessings presented by the server that are
560 // recognized by the client match the pattern
Ankur78b8b2a2015-02-04 20:16:28 -0800561 // "root"
562 if len(blessings) < 1 || !security.BlessingPattern("root").MatchedBy(blessings...) {
563 t.Errorf("%s: Client sees server as %v, expected a single blessing matching root", name, blessings)
Asim Shankar2d731a92014-09-29 17:46:38 -0700564 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700565 }
Matt Rosencrantzcc922c12014-11-28 20:28:59 -0800566 cancel()
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700567 client.Close()
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700568 }
569}
570
Asim Shankarb547ea92015-02-17 18:49:45 -0800571func TestServerManInTheMiddleAttack(t *testing.T) {
572 // Test scenario: A server mounts itself, but then some other service
573 // somehow "takes over" the endpoint, thus trying to steal traffic.
574
575 // Start up the attacker's server.
576 attacker, err := testInternalNewServer(
577 testContext(),
578 imanager.InternalNew(naming.FixedRoutingID(0xaaaaaaaaaaaaaaaa)),
579 // (To prevent the attacker for legitimately mounting on the
580 // namespace that the client will use, provide it with a
581 // different namespace).
582 tnaming.NewSimpleNamespace(),
583 vc.LocalPrincipal{tsecurity.NewPrincipal("attacker")})
584 if err != nil {
585 t.Fatal(err)
586 }
587 if _, err := attacker.Listen(listenSpec); err != nil {
588 t.Fatal(err)
589 }
590 if err := attacker.ServeDispatcher("mountpoint/server", testServerDisp{&testServer{}}); err != nil {
591 t.Fatal(err)
592 }
593 var ep naming.Endpoint
594 if status := attacker.Status(); len(status.Endpoints) < 1 {
595 t.Fatalf("Attacker server does not have an endpoint: %+v", status)
596 } else {
597 ep = status.Endpoints[0]
598 }
599
600 // The legitimate server would have mounted the same endpoint on the
601 // namespace.
602 ns := tnaming.NewSimpleNamespace()
603 if err := ns.Mount(testContext(), "mountpoint/server", ep.Name(), time.Hour, naming.MountedServerBlessingsOpt{"server"}); err != nil {
604 t.Fatal(err)
605 }
606
607 // The RPC call should fail because the blessings presented by the
608 // (attacker's) server are not consistent with the ones registered in
609 // the mounttable trusted by the client.
610 client, err := InternalNewClient(
611 imanager.InternalNew(naming.FixedRoutingID(0xcccccccccccccccc)),
612 ns,
613 vc.LocalPrincipal{tsecurity.NewPrincipal("client")})
614 if err != nil {
615 t.Fatal(err)
616 }
617 defer client.Close()
618 if _, err := client.StartCall(testContext(), "mountpoint/server", "Closure", nil); !verror.Is(err, verror.ErrNotTrusted.ID) {
619 t.Errorf("Got error %v (errorid=%v), want errorid=%v", err, verror.ErrorID(err), verror.ErrNotTrusted.ID)
620 }
621 // But the RPC should succeed if the client explicitly
622 // decided to skip server authorization.
623 if _, err := client.StartCall(testContext(), "mountpoint/server", "Closure", nil, options.SkipResolveAuthorization{}); err != nil {
624 t.Errorf("Unexpected error(%v) when skipping server authorization", err)
625 }
626}
627
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800628type websocketMode bool
629type closeSendMode bool
630
631const (
632 useWebsocket websocketMode = true
633 noWebsocket websocketMode = false
634
635 closeSend closeSendMode = true
636 noCloseSend closeSendMode = false
637)
638
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700639func TestRPC(t *testing.T) {
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800640 testRPC(t, closeSend, noWebsocket)
641}
642
643func TestRPCWithWebsocket(t *testing.T) {
644 testRPC(t, closeSend, useWebsocket)
Tilak Sharma0c766112014-05-20 17:47:27 -0700645}
646
647// TestCloseSendOnFinish tests that Finish informs the server that no more
648// inputs will be sent by the client if CloseSend has not already done so.
649func TestRPCCloseSendOnFinish(t *testing.T) {
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800650 testRPC(t, noCloseSend, noWebsocket)
Tilak Sharma0c766112014-05-20 17:47:27 -0700651}
652
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800653func TestRPCCloseSendOnFinishWithWebsocket(t *testing.T) {
654 testRPC(t, noCloseSend, useWebsocket)
655}
656
657func testRPC(t *testing.T, shouldCloseSend closeSendMode, shouldUseWebsocket websocketMode) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700658 type v []interface{}
659 type testcase struct {
660 name string
661 method string
662 args v
663 streamArgs v
664 startErr error
665 results v
666 finishErr error
667 }
Asim Shankar8f05c222014-10-06 22:08:19 -0700668 var (
669 tests = []testcase{
670 {"mountpoint/server/suffix", "Closure", nil, nil, nil, nil, nil},
Todd Wange77f9952015-02-18 13:20:50 -0800671 {"mountpoint/server/suffix", "Error", nil, nil, nil, nil, errMethod},
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700672
Asim Shankar8f05c222014-10-06 22:08:19 -0700673 {"mountpoint/server/suffix", "Echo", v{"foo"}, nil, nil, v{`method:"Echo",suffix:"suffix",arg:"foo"`}, nil},
674 {"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 -0700675
Asim Shankar8f05c222014-10-06 22:08:19 -0700676 {"mountpoint/server/suffix", "EchoUser", v{"foo", userType("bar")}, nil, nil, v{`method:"EchoUser",suffix:"suffix",arg:"foo"`, userType("bar")}, nil},
677 {"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 -0800678 {"mountpoint/server/suffix", "Stream", v{"foo"}, v{userType("bar"), userType("baz")}, nil, v{`method:"Stream",suffix:"suffix",arg:"foo" bar baz`}, nil},
679 {"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 -0700680 {"mountpoint/server/suffix", "EchoBlessings", nil, nil, nil, v{"[server]", "[client]"}, nil},
Todd Wange77f9952015-02-18 13:20:50 -0800681 {"mountpoint/server/suffix", "EchoAndError", v{"bugs bunny"}, nil, nil, v{`method:"EchoAndError",suffix:"suffix",arg:"bugs bunny"`}, nil},
682 {"mountpoint/server/suffix", "EchoAndError", v{"error"}, nil, nil, nil, errMethod},
Asim Shankar8f05c222014-10-06 22:08:19 -0700683 }
684 name = func(t testcase) string {
685 return fmt.Sprintf("%s.%s(%v)", t.name, t.method, t.args)
686 }
687
Ankure49a86a2014-11-11 18:52:43 -0800688 pserver = tsecurity.NewPrincipal("server")
689 pclient = tsecurity.NewPrincipal("client")
Asim Shankar8f05c222014-10-06 22:08:19 -0700690
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -0800691 b = createBundleWS(t, pclient, pserver, &testServer{}, shouldUseWebsocket)
Asim Shankar8f05c222014-10-06 22:08:19 -0700692 )
Bogdan Caprita27953142014-05-12 11:41:42 -0700693 defer b.cleanup(t)
Asim Shankar8f05c222014-10-06 22:08:19 -0700694 // The server needs to recognize the client's root certificate.
695 pserver.AddToRoots(pclient.BlessingStore().Default())
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700696 for _, test := range tests {
697 vlog.VI(1).Infof("%s client.StartCall", name(test))
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800698 vname := test.name
699 if shouldUseWebsocket {
700 var err error
Cosmos Nicolaou8bd8e102015-01-13 21:52:53 -0800701 vname, err = fakeWSName(b.ns, vname)
Shyam Jayaramandbae76b2014-11-17 12:51:29 -0800702 if err != nil && err != test.startErr {
703 t.Errorf(`%s ns.Resolve got error "%v", want "%v"`, name(test), err, test.startErr)
704 continue
705 }
706 }
707 call, err := b.client.StartCall(testContext(), vname, test.method, test.args)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700708 if err != test.startErr {
709 t.Errorf(`%s client.StartCall got error "%v", want "%v"`, name(test), err, test.startErr)
710 continue
711 }
712 for _, sarg := range test.streamArgs {
713 vlog.VI(1).Infof("%s client.Send(%v)", name(test), sarg)
714 if err := call.Send(sarg); err != nil {
715 t.Errorf(`%s call.Send(%v) got unexpected error "%v"`, name(test), sarg, err)
716 }
717 var u userType
718 if err := call.Recv(&u); err != nil {
719 t.Errorf(`%s call.Recv(%v) got unexpected error "%v"`, name(test), sarg, err)
720 }
721 if !reflect.DeepEqual(u, sarg) {
722 t.Errorf("%s call.Recv got value %v, want %v", name(test), u, sarg)
723 }
724 }
Tilak Sharma0c766112014-05-20 17:47:27 -0700725 if shouldCloseSend {
726 vlog.VI(1).Infof("%s call.CloseSend", name(test))
Asim Shankar062d4222014-08-18 11:14:42 -0700727 // When the method does not involve streaming
728 // arguments, the server gets all the arguments in
729 // StartCall and then sends a response without
730 // (unnecessarily) waiting for a CloseSend message from
731 // the client. If the server responds before the
732 // CloseSend call is made at the client, the CloseSend
733 // call will fail. Thus, only check for errors on
734 // CloseSend if there are streaming arguments to begin
735 // with (i.e., only if the server is expected to wait
736 // for the CloseSend notification).
737 if err := call.CloseSend(); err != nil && len(test.streamArgs) > 0 {
Tilak Sharma0c766112014-05-20 17:47:27 -0700738 t.Errorf(`%s call.CloseSend got unexpected error "%v"`, name(test), err)
739 }
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700740 }
741 vlog.VI(1).Infof("%s client.Finish", name(test))
742 results := makeResultPtrs(test.results)
743 err = call.Finish(results...)
Todd Wange77f9952015-02-18 13:20:50 -0800744 if got, want := err, test.finishErr; (got == nil) != (want == nil) {
745 t.Errorf(`%s call.Finish got error "%v", want "%v'`, name(test), got, want)
746 } else if want != nil && !verror.Is(got, verror.ErrorID(want)) {
747 t.Errorf(`%s call.Finish got error "%v", want "%v"`, name(test), got, want)
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700748 }
749 checkResultPtrs(t, name(test), results, test.results)
750 }
751}
752
Ken Ashcraft2b8309a2014-09-09 10:44:43 -0700753func TestMultipleFinish(t *testing.T) {
754 type v []interface{}
Ankure49a86a2014-11-11 18:52:43 -0800755 b := createBundle(t, tsecurity.NewPrincipal("client"), tsecurity.NewPrincipal("server"), &testServer{})
Ken Ashcraft2b8309a2014-09-09 10:44:43 -0700756 defer b.cleanup(t)
757 call, err := b.client.StartCall(testContext(), "mountpoint/server/suffix", "Echo", v{"foo"})
758 if err != nil {
759 t.Fatalf(`client.StartCall got error "%v"`, err)
760 }
761 var results string
762 err = call.Finish(&results)
763 if err != nil {
764 t.Fatalf(`call.Finish got error "%v"`, err)
765 }
766 // Calling Finish a second time should result in a useful error.
Jiri Simsa074bf362015-02-17 09:29:45 -0800767 if err = call.Finish(&results); !matchesErrorPattern(err, verror.ErrBadState, "Finish has already been called") {
768 t.Fatalf(`got "%v", want "%v"`, err, verror.ErrBadState)
Ken Ashcraft2b8309a2014-09-09 10:44:43 -0700769 }
770}
771
Asim Shankar8f05c222014-10-06 22:08:19 -0700772// granter implements ipc.Granter, returning a fixed (security.Blessings, error) pair.
Asim Shankarb54d7642014-06-05 13:08:04 -0700773type granter struct {
774 ipc.CallOpt
Asim Shankar8f05c222014-10-06 22:08:19 -0700775 b security.Blessings
Asim Shankarb54d7642014-06-05 13:08:04 -0700776 err error
777}
778
Asim Shankar8f05c222014-10-06 22:08:19 -0700779func (g granter) Grant(id security.Blessings) (security.Blessings, error) { return g.b, g.err }
Asim Shankarb54d7642014-06-05 13:08:04 -0700780
Asim Shankar8f05c222014-10-06 22:08:19 -0700781func TestGranter(t *testing.T) {
782 var (
Ankure49a86a2014-11-11 18:52:43 -0800783 pclient = tsecurity.NewPrincipal("client")
784 pserver = tsecurity.NewPrincipal("server")
Asim Shankar8f05c222014-10-06 22:08:19 -0700785 b = createBundle(t, pclient, pserver, &testServer{})
786 )
Asim Shankarb54d7642014-06-05 13:08:04 -0700787 defer b.cleanup(t)
788
789 tests := []struct {
Asim Shankar8f05c222014-10-06 22:08:19 -0700790 granter ipc.Granter
Cosmos Nicolaou112bf1c2014-11-21 15:43:11 -0800791 startErrID, finishErrID verror.IDAction
Asim Shankarb54d7642014-06-05 13:08:04 -0700792 blessing, starterr, finisherr string
793 }{
Asim Shankar2bf7b1e2015-02-27 00:45:12 -0800794 {blessing: ""},
Asim Shankarb18a44f2014-10-21 20:25:07 -0700795 {granter: granter{b: bless(pclient, pserver, "blessed")}, blessing: "client/blessed"},
Jiri Simsa074bf362015-02-17 09:29:45 -0800796 {granter: granter{err: errors.New("hell no")}, startErrID: verror.ErrNotTrusted, starterr: "hell no"},
797 {granter: granter{b: pclient.BlessingStore().Default()}, finishErrID: verror.ErrNoAccess, finisherr: "blessing granted not bound to this server"},
Asim Shankarb54d7642014-06-05 13:08:04 -0700798 }
Cosmos Nicolaou112bf1c2014-11-21 15:43:11 -0800799 for i, test := range tests {
Asim Shankar8f05c222014-10-06 22:08:19 -0700800 call, err := b.client.StartCall(testContext(), "mountpoint/server/suffix", "EchoGrantedBlessings", []interface{}{"argument"}, test.granter)
Cosmos Nicolaou112bf1c2014-11-21 15:43:11 -0800801 if !matchesErrorPattern(err, test.startErrID, test.starterr) {
802 t.Errorf("%d: %+v: StartCall returned error %v", i, test, err)
Asim Shankarb54d7642014-06-05 13:08:04 -0700803 }
804 if err != nil {
805 continue
806 }
807 var result, blessing string
Cosmos Nicolaou112bf1c2014-11-21 15:43:11 -0800808 if err = call.Finish(&result, &blessing); !matchesErrorPattern(err, test.finishErrID, test.finisherr) {
Asim Shankarb54d7642014-06-05 13:08:04 -0700809 t.Errorf("%+v: Finish returned error %v", test, err)
810 }
811 if err != nil {
812 continue
813 }
814 if result != "argument" || blessing != test.blessing {
815 t.Errorf("%+v: Got (%q, %q)", test, result, blessing)
816 }
817 }
818}
819
Asim Shankar8f05c222014-10-06 22:08:19 -0700820func mkThirdPartyCaveat(discharger security.PublicKey, location string, c security.Caveat) security.Caveat {
821 tpc, err := security.NewPublicKeyCaveat(discharger, location, security.ThirdPartyRequirements{}, c)
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700822 if err != nil {
823 panic(err)
824 }
Asim Shankar7283dd82015-02-03 19:35:58 -0800825 return tpc
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700826}
827
Asim Shankarf4864f42014-11-25 18:53:05 -0800828// dischargeTestServer implements the discharge service. Always fails to
829// issue a discharge, but records the impetus and traceid of the RPC call.
830type dischargeTestServer struct {
831 p security.Principal
832 impetus []security.DischargeImpetus
Benjamin Prosnitzc97fe192015-02-03 10:33:25 -0800833 traceid []uniqueid.Id
Asim Shankara94e5072014-08-19 18:18:36 -0700834}
835
Asim Shankar08642822015-03-02 21:21:09 -0800836func (s *dischargeTestServer) Discharge(call ipc.ServerCall, cav security.Caveat, impetus security.DischargeImpetus) (security.Discharge, error) {
Asim Shankarc8cfcf12014-11-20 12:26:58 -0800837 s.impetus = append(s.impetus, impetus)
Matt Rosencrantz9dce9b22015-03-02 10:48:37 -0800838 s.traceid = append(s.traceid, vtrace.GetSpan(call.Context()).Trace())
Asim Shankar08642822015-03-02 21:21:09 -0800839 return security.Discharge{}, fmt.Errorf("discharges not issued")
Asim Shankara94e5072014-08-19 18:18:36 -0700840}
841
Benjamin Prosnitzc97fe192015-02-03 10:33:25 -0800842func (s *dischargeTestServer) Release() ([]security.DischargeImpetus, []uniqueid.Id) {
Asim Shankarf4864f42014-11-25 18:53:05 -0800843 impetus, traceid := s.impetus, s.traceid
844 s.impetus, s.traceid = nil, nil
845 return impetus, traceid
Asim Shankarc8cfcf12014-11-20 12:26:58 -0800846}
847
Asim Shankarf4864f42014-11-25 18:53:05 -0800848func TestDischargeImpetusAndContextPropagation(t *testing.T) {
Asim Shankara94e5072014-08-19 18:18:36 -0700849 var (
Ankure49a86a2014-11-11 18:52:43 -0800850 pserver = tsecurity.NewPrincipal("server")
Asim Shankarf4864f42014-11-25 18:53:05 -0800851 pdischarger = tsecurity.NewPrincipal("discharger")
852 pclient = tsecurity.NewPrincipal("client")
Asim Shankar8f05c222014-10-06 22:08:19 -0700853 sm = imanager.InternalNew(naming.FixedRoutingID(0x555555555))
854 ns = tnaming.NewSimpleNamespace()
Asim Shankara94e5072014-08-19 18:18:36 -0700855
Asim Shankar8f05c222014-10-06 22:08:19 -0700856 mkClient = func(req security.ThirdPartyRequirements) vc.LocalPrincipal {
Asim Shankarf4864f42014-11-25 18:53:05 -0800857 // Setup the client so that it shares a blessing with a third-party caveat with the server.
Asim Shankar7283dd82015-02-03 19:35:58 -0800858 cav, err := security.NewPublicKeyCaveat(pdischarger.PublicKey(), "mountpoint/discharger", req, security.UnconstrainedUse())
Asim Shankara94e5072014-08-19 18:18:36 -0700859 if err != nil {
Asim Shankar8f05c222014-10-06 22:08:19 -0700860 t.Fatalf("Failed to create ThirdPartyCaveat(%+v): %v", req, err)
Asim Shankara94e5072014-08-19 18:18:36 -0700861 }
Asim Shankarf4864f42014-11-25 18:53:05 -0800862 b, err := pclient.BlessSelf("client_for_server", cav)
Asim Shankar8f05c222014-10-06 22:08:19 -0700863 if err != nil {
864 t.Fatalf("BlessSelf failed: %v", err)
865 }
Asim Shankar8f05c222014-10-06 22:08:19 -0700866 pclient.BlessingStore().Set(b, "server")
867 return vc.LocalPrincipal{pclient}
Asim Shankara94e5072014-08-19 18:18:36 -0700868 }
869 )
Asim Shankarf4864f42014-11-25 18:53:05 -0800870 // Initialize the client principal.
871 // It trusts both the application server and the discharger.
872 pclient.AddToRoots(pserver.BlessingStore().Default())
873 pclient.AddToRoots(pdischarger.BlessingStore().Default())
874 // Share a blessing without any third-party caveats with the discharger.
875 // It could share the same blessing as generated by setupClientBlessing, but
876 // that will lead to possibly debugging confusion (since it will try to fetch
877 // a discharge to talk to the discharge service).
878 if b, err := pclient.BlessSelf("client_for_discharger"); err != nil {
879 t.Fatalf("BlessSelf failed: %v", err)
880 } else {
881 pclient.BlessingStore().Set(b, "discharger")
882 }
883
884 // Setup the discharge server.
885 var tester dischargeTestServer
Matt Rosencrantzfa3082c2015-01-22 21:39:04 -0800886 ctx := testContext()
Suharsh Sivakumaraf99c972015-01-28 15:28:49 -0800887 dischargeServer, err := testInternalNewServer(ctx, sm, ns, vc.LocalPrincipal{pdischarger})
Asim Shankara94e5072014-08-19 18:18:36 -0700888 if err != nil {
889 t.Fatal(err)
890 }
Asim Shankarf4864f42014-11-25 18:53:05 -0800891 defer dischargeServer.Stop()
892 if _, err := dischargeServer.Listen(listenSpec); err != nil {
893 t.Fatal(err)
894 }
895 if err := dischargeServer.Serve("mountpoint/discharger", &tester, &testServerAuthorizer{}); err != nil {
Asim Shankara94e5072014-08-19 18:18:36 -0700896 t.Fatal(err)
897 }
898
Asim Shankarf4864f42014-11-25 18:53:05 -0800899 // Setup the application server.
Suharsh Sivakumaraf99c972015-01-28 15:28:49 -0800900 appServer, err := testInternalNewServer(ctx, sm, ns, vc.LocalPrincipal{pserver})
Asim Shankarf4864f42014-11-25 18:53:05 -0800901 if err != nil {
902 t.Fatal(err)
903 }
904 defer appServer.Stop()
Cosmos Nicolaou28dabfc2014-12-15 22:51:07 -0800905 eps, err := appServer.Listen(listenSpec)
Asim Shankarf4864f42014-11-25 18:53:05 -0800906 if err != nil {
907 t.Fatal(err)
908 }
909 // TODO(bjornick,cnicolaou,ashankar): This is a hack to workaround the
910 // fact that a single Listen on the "tcp" protocol followed by a call
911 // to Serve(<name>, ...) transparently creates two endpoints (one for
912 // tcp, one for websockets) and maps both to <name> via a mount.
913 // Because all endpoints to a name are tried in a parallel, this
914 // transparency makes this test hard to follow (many discharge fetch
915 // attempts are made - one for VIF authentication, one for VC
916 // authentication and one for the actual RPC - and having them be made
917 // to two different endpoints in parallel leads to a lot of
918 // non-determinism). The last plan of record known by the author of
919 // this comment was to stop this sly creation of two endpoints and
920 // require that they be done explicitly. When that happens, this hack
921 // can go away, but till then, this workaround allows the test to be
922 // more predictable by ensuring there is only one VIF/VC/Flow to the
923 // server.
Cosmos Nicolaou28dabfc2014-12-15 22:51:07 -0800924 object := naming.JoinAddressName(eps[0].String(), "object") // instead of "mountpoint/object"
Asim Shankarf4864f42014-11-25 18:53:05 -0800925 if err := appServer.Serve("mountpoint/object", &testServer{}, &testServerAuthorizer{}); err != nil {
926 t.Fatal(err)
927 }
Asim Shankara94e5072014-08-19 18:18:36 -0700928 tests := []struct {
929 Requirements security.ThirdPartyRequirements
930 Impetus security.DischargeImpetus
931 }{
932 { // No requirements, no impetus
933 Requirements: security.ThirdPartyRequirements{},
934 Impetus: security.DischargeImpetus{},
935 },
936 { // Require everything
937 Requirements: security.ThirdPartyRequirements{ReportServer: true, ReportMethod: true, ReportArguments: true},
Todd Wangb31da592015-02-20 12:50:39 -0800938 Impetus: security.DischargeImpetus{Server: []security.BlessingPattern{"server"}, Method: "Method", Arguments: []*vdl.Value{vdl.StringValue("argument")}},
Asim Shankara94e5072014-08-19 18:18:36 -0700939 },
940 { // Require only the method name
941 Requirements: security.ThirdPartyRequirements{ReportMethod: true},
942 Impetus: security.DischargeImpetus{Method: "Method"},
943 },
944 }
945
Ankur50a5f392015-02-27 18:46:30 -0800946 for _, test := range tests {
Ankure49a86a2014-11-11 18:52:43 -0800947 pclient := mkClient(test.Requirements)
Suharsh Sivakumar1b6683e2014-12-30 13:00:38 -0800948 client, err := InternalNewClient(sm, ns, pclient)
Asim Shankara94e5072014-08-19 18:18:36 -0700949 if err != nil {
950 t.Fatalf("InternalNewClient(%+v) failed: %v", test.Requirements, err)
951 }
952 defer client.Close()
Asim Shankarf4864f42014-11-25 18:53:05 -0800953 ctx := testContext()
Matt Rosencrantz5f98d942015-01-08 13:48:30 -0800954 tid := vtrace.GetSpan(ctx).Trace()
Asim Shankara94e5072014-08-19 18:18:36 -0700955 // 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 -0800956 if _, err := client.StartCall(ctx, object, "Method", []interface{}{"argument"}); err != nil {
Asim Shankara94e5072014-08-19 18:18:36 -0700957 t.Errorf("StartCall(%+v) failed: %v", test.Requirements, err)
958 continue
959 }
Asim Shankarf4864f42014-11-25 18:53:05 -0800960 impetus, traceid := tester.Release()
Ankur50a5f392015-02-27 18:46:30 -0800961 // There should have been exactly 1 attempt to fetch discharges when making
962 // the RPC to the remote object.
963 if len(impetus) != 1 || len(traceid) != 1 {
964 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 -0800965 continue
966 }
967 // VC creation does not have any "impetus", it is established without
968 // knowledge of the context of the RPC. So ignore that.
969 //
970 // TODO(ashankar): Should the impetus of the RPC that initiated the
971 // VIF/VC creation be propagated?
972 if got, want := impetus[len(impetus)-1], test.Impetus; !reflect.DeepEqual(got, want) {
973 t.Errorf("Test %+v: Got impetus %v, want %v", test.Requirements, got, want)
974 }
975 // But the context used for all of this should be the same
976 // (thereby allowing debug traces to link VIF/VC creation with
977 // the RPC that initiated them).
978 for idx, got := range traceid {
979 if !reflect.DeepEqual(got, tid) {
980 t.Errorf("Test %+v: %d - Got trace id %q, want %q", test.Requirements, idx, hex.EncodeToString(got[:]), hex.EncodeToString(tid[:]))
981 }
Asim Shankara94e5072014-08-19 18:18:36 -0700982 }
983 }
984}
985
Ankure49a86a2014-11-11 18:52:43 -0800986func TestRPCClientAuthorization(t *testing.T) {
987 type v []interface{}
Andres Erbsenb7f95f32014-07-07 12:07:56 -0700988 var (
Asim Shankar8f05c222014-10-06 22:08:19 -0700989 // Principals
Ankure49a86a2014-11-11 18:52:43 -0800990 pclient, pserver = tsecurity.NewPrincipal("client"), tsecurity.NewPrincipal("server")
991 pdischarger = pserver
Jiri Simsa5293dcb2014-05-10 09:56:38 -0700992
Asim Shankar8f05c222014-10-06 22:08:19 -0700993 now = time.Now()
994
Ankure49a86a2014-11-11 18:52:43 -0800995 serverName = "mountpoint/server"
996 dischargeServerName = "mountpoint/dischargeserver"
997
Asim Shankar8f05c222014-10-06 22:08:19 -0700998 // Caveats on blessings to the client: First-party caveats
999 cavOnlyEcho = mkCaveat(security.MethodCaveat("Echo"))
1000 cavExpired = mkCaveat(security.ExpiryCaveat(now.Add(-1 * time.Second)))
1001 // Caveats on blessings to the client: Third-party caveats
1002 cavTPValid = mkThirdPartyCaveat(pdischarger.PublicKey(), "mountpoint/server/discharger", mkCaveat(security.ExpiryCaveat(now.Add(24*time.Hour))))
1003 cavTPExpired = mkThirdPartyCaveat(pdischarger.PublicKey(), "mountpoint/server/discharger", mkCaveat(security.ExpiryCaveat(now.Add(-1*time.Second))))
1004
1005 // Client blessings that will be tested.
1006 bServerClientOnlyEcho = bless(pserver, pclient, "onlyecho", cavOnlyEcho)
1007 bServerClientExpired = bless(pserver, pclient, "expired", cavExpired)
1008 bServerClientTPValid = bless(pserver, pclient, "dischargeable_third_party_caveat", cavTPValid)
1009 bServerClientTPExpired = bless(pserver, pclient, "expired_third_party_caveat", cavTPExpired)
1010 bClient = pclient.BlessingStore().Default()
1011 bRandom, _ = pclient.BlessSelf("random")
Ankure49a86a2014-11-11 18:52:43 -08001012
1013 mgr = imanager.InternalNew(naming.FixedRoutingID(0x1111111))
1014 ns = tnaming.NewSimpleNamespace()
1015 tests = []struct {
1016 blessings security.Blessings // Blessings used by the client
1017 name string // object name on which the method is invoked
1018 method string
1019 args v
1020 results v
1021 authorized bool // Whether or not the RPC should be authorized by the server.
1022 }{
1023 // There are three different authorization policies (security.Authorizer implementations)
1024 // used by the server, depending on the suffix (see testServerDisp.Lookup):
1025 // - nilAuth suffix: the default authorization policy (only delegates of or delegators of the server can call RPCs)
Ankur78b8b2a2015-02-04 20:16:28 -08001026 // - aclAuth suffix: the ACL only allows blessings matching the patterns "server" or "client"
Ankure49a86a2014-11-11 18:52:43 -08001027 // - other suffixes: testServerAuthorizer allows any principal to call any method except "Unauthorized"
1028
1029 // Expired blessings should fail nilAuth and aclAuth (which care about names), but should succeed on
1030 // other suffixes (which allow all blessings), unless calling the Unauthorized method.
1031 {bServerClientExpired, "mountpoint/server/nilAuth", "Echo", v{"foo"}, v{""}, false},
1032 {bServerClientExpired, "mountpoint/server/aclAuth", "Echo", v{"foo"}, v{""}, false},
1033 {bServerClientExpired, "mountpoint/server/suffix", "Echo", v{"foo"}, v{""}, true},
1034 {bServerClientExpired, "mountpoint/server/suffix", "Unauthorized", nil, v{""}, false},
1035
1036 // Same for blessings that should fail to obtain a discharge for the third party caveat.
1037 {bServerClientTPExpired, "mountpoint/server/nilAuth", "Echo", v{"foo"}, v{""}, false},
1038 {bServerClientTPExpired, "mountpoint/server/aclAuth", "Echo", v{"foo"}, v{""}, false},
1039 {bServerClientTPExpired, "mountpoint/server/suffix", "Echo", v{"foo"}, v{""}, true},
1040 {bServerClientTPExpired, "mountpoint/server/suffix", "Unauthorized", nil, v{""}, false},
1041
1042 // The "server/client" blessing (with MethodCaveat("Echo")) should satisfy all authorization policies
1043 // when "Echo" is called.
1044 {bServerClientOnlyEcho, "mountpoint/server/nilAuth", "Echo", v{"foo"}, v{""}, true},
1045 {bServerClientOnlyEcho, "mountpoint/server/aclAuth", "Echo", v{"foo"}, v{""}, true},
1046 {bServerClientOnlyEcho, "mountpoint/server/suffix", "Echo", v{"foo"}, v{""}, true},
1047
1048 // The "server/client" blessing (with MethodCaveat("Echo")) should satisfy no authorization policy
1049 // when any other method is invoked, except for the testServerAuthorizer policy (which will
1050 // not recognize the blessing "server/onlyecho", but it would authorize anyone anyway).
1051 {bServerClientOnlyEcho, "mountpoint/server/nilAuth", "Closure", nil, nil, false},
1052 {bServerClientOnlyEcho, "mountpoint/server/aclAuth", "Closure", nil, nil, false},
1053 {bServerClientOnlyEcho, "mountpoint/server/suffix", "Closure", nil, nil, true},
1054
1055 // The "client" blessing doesn't satisfy the default authorization policy, but does satisfy
1056 // the ACL and the testServerAuthorizer policy.
1057 {bClient, "mountpoint/server/nilAuth", "Echo", v{"foo"}, v{""}, false},
1058 {bClient, "mountpoint/server/aclAuth", "Echo", v{"foo"}, v{""}, true},
1059 {bClient, "mountpoint/server/suffix", "Echo", v{"foo"}, v{""}, true},
1060 {bClient, "mountpoint/server/suffix", "Unauthorized", nil, v{""}, false},
1061
1062 // The "random" blessing does not satisfy either the default policy or the ACL, but does
1063 // satisfy testServerAuthorizer.
1064 {bRandom, "mountpoint/server/nilAuth", "Echo", v{"foo"}, v{""}, false},
1065 {bRandom, "mountpoint/server/aclAuth", "Echo", v{"foo"}, v{""}, false},
1066 {bRandom, "mountpoint/server/suffix", "Echo", v{"foo"}, v{""}, true},
1067 {bRandom, "mountpoint/server/suffix", "Unauthorized", nil, v{""}, false},
1068
1069 // The "server/dischargeable_third_party_caveat" blessing satisfies all policies.
1070 // (the discharges should be fetched).
1071 {bServerClientTPValid, "mountpoint/server/nilAuth", "Echo", v{"foo"}, v{""}, true},
1072 {bServerClientTPValid, "mountpoint/server/aclAuth", "Echo", v{"foo"}, v{""}, true},
1073 {bServerClientTPValid, "mountpoint/server/suffix", "Echo", v{"foo"}, v{""}, true},
1074 {bServerClientTPValid, "mountpoint/server/suffix", "Unauthorized", nil, v{""}, false},
1075 }
Andres Erbsenb7f95f32014-07-07 12:07:56 -07001076 )
Ankure49a86a2014-11-11 18:52:43 -08001077 // Start the main server.
1078 _, server := startServer(t, pserver, mgr, ns, serverName, testServerDisp{&testServer{}})
1079 defer stopServer(t, server, ns, serverName)
1080
1081 // Start the discharge server.
Bogdan Caprita7590a6d2015-01-08 13:43:40 -08001082 _, dischargeServer := startServer(t, pdischarger, mgr, ns, dischargeServerName, testutil.LeafDispatcher(&dischargeServer{}, &acceptAllAuthorizer{}))
Ankure49a86a2014-11-11 18:52:43 -08001083 defer stopServer(t, dischargeServer, ns, dischargeServerName)
1084
Ankur78b8b2a2015-02-04 20:16:28 -08001085 // The server should recognize the client principal as an authority on "client" and "random" blessings.
Asim Shankar8f05c222014-10-06 22:08:19 -07001086 pserver.AddToRoots(bClient)
1087 pserver.AddToRoots(bRandom)
Ankure49a86a2014-11-11 18:52:43 -08001088 // And the client needs to recognize the server's and discharger's blessings to decide which of its
1089 // own blessings to share.
Asim Shankar8f05c222014-10-06 22:08:19 -07001090 pclient.AddToRoots(pserver.BlessingStore().Default())
Ankure49a86a2014-11-11 18:52:43 -08001091 // tsecurity.NewPrincipal sets up a principal that shares blessings with all servers, undo that.
Asim Shankar2bf7b1e2015-02-27 00:45:12 -08001092 pclient.BlessingStore().Set(security.Blessings{}, security.AllPrincipals)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001093
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001094 for _, test := range tests {
Asim Shankar8f05c222014-10-06 22:08:19 -07001095 name := fmt.Sprintf("%q.%s(%v) by %v", test.name, test.method, test.args, test.blessings)
Suharsh Sivakumar1b6683e2014-12-30 13:00:38 -08001096 client, err := InternalNewClient(mgr, ns, vc.LocalPrincipal{pclient})
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001097 if err != nil {
1098 t.Fatalf("InternalNewClient failed: %v", err)
1099 }
1100 defer client.Close()
Ankure49a86a2014-11-11 18:52:43 -08001101
Asim Shankar8f05c222014-10-06 22:08:19 -07001102 pclient.BlessingStore().Set(test.blessings, "server")
Matt Rosencrantzbf85d542014-08-22 13:31:14 -07001103 call, err := client.StartCall(testContext(), test.name, test.method, test.args)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001104 if err != nil {
Asim Shankar8f05c222014-10-06 22:08:19 -07001105 t.Errorf(`%s client.StartCall got unexpected error: "%v"`, name, err)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001106 continue
1107 }
Ankure49a86a2014-11-11 18:52:43 -08001108
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001109 results := makeResultPtrs(test.results)
1110 err = call.Finish(results...)
Asim Shankar8f05c222014-10-06 22:08:19 -07001111 if err != nil && test.authorized {
1112 t.Errorf(`%s call.Finish got error: "%v", wanted the RPC to succeed`, name, err)
1113 } else if err == nil && !test.authorized {
1114 t.Errorf("%s call.Finish succeeded, expected authorization failure", name)
Jiri Simsa074bf362015-02-17 09:29:45 -08001115 } else if !test.authorized && !verror.Is(err, verror.ErrNoAccess.ID) {
1116 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 -07001117 }
1118 }
1119}
1120
Andres Erbsenb7f95f32014-07-07 12:07:56 -07001121func TestDischargePurgeFromCache(t *testing.T) {
1122 var (
Ankure49a86a2014-11-11 18:52:43 -08001123 pserver = tsecurity.NewPrincipal("server")
Asim Shankar8f05c222014-10-06 22:08:19 -07001124 pdischarger = pserver // In general, the discharger can be a separate principal. In this test, it happens to be the server.
Ankure49a86a2014-11-11 18:52:43 -08001125 pclient = tsecurity.NewPrincipal("client")
Asim Shankar8f05c222014-10-06 22:08:19 -07001126 // Client is blessed with a third-party caveat. The discharger service issues discharges with a fakeTimeCaveat.
1127 // This blessing is presented to "server".
1128 bclient = bless(pserver, pclient, "client", mkThirdPartyCaveat(pdischarger.PublicKey(), "mountpoint/server/discharger", security.UnconstrainedUse()))
Andres Erbsenb7f95f32014-07-07 12:07:56 -07001129 )
Asim Shankar8f05c222014-10-06 22:08:19 -07001130 // Setup the client to recognize the server's blessing and present bclient to it.
1131 pclient.AddToRoots(pserver.BlessingStore().Default())
1132 pclient.BlessingStore().Set(bclient, "server")
1133
Ankure49a86a2014-11-11 18:52:43 -08001134 b := createBundle(t, nil, pserver, &testServer{})
Andres Erbsenb7f95f32014-07-07 12:07:56 -07001135 defer b.cleanup(t)
1136
Suharsh Sivakumar1b6683e2014-12-30 13:00:38 -08001137 var err error
1138 if b.client, err = InternalNewClient(b.sm, b.ns, vc.LocalPrincipal{pclient}); err != nil {
Ankure49a86a2014-11-11 18:52:43 -08001139 t.Fatalf("InternalNewClient failed: %v", err)
1140 }
Mike Burrowsdc6b3602015-02-05 15:52:12 -08001141 call := func() error {
Asim Shankar8f05c222014-10-06 22:08:19 -07001142 call, err := b.client.StartCall(testContext(), "mountpoint/server/aclAuth", "Echo", []interface{}{"batman"})
Andres Erbsenb7f95f32014-07-07 12:07:56 -07001143 if err != nil {
Mike Burrows2a548352015-02-06 18:24:02 -08001144 return err //fmt.Errorf("client.StartCall failed: %v", err)
Andres Erbsenb7f95f32014-07-07 12:07:56 -07001145 }
1146 var got string
1147 if err := call.Finish(&got); err != nil {
Mike Burrows2a548352015-02-06 18:24:02 -08001148 return err //fmt.Errorf("client.Finish failed: %v", err)
Andres Erbsenb7f95f32014-07-07 12:07:56 -07001149 }
Asim Shankar8f05c222014-10-06 22:08:19 -07001150 if want := `method:"Echo",suffix:"aclAuth",arg:"batman"`; got != want {
Jiri Simsa074bf362015-02-17 09:29:45 -08001151 return verror.Convert(verror.ErrBadArg, nil, fmt.Errorf("Got [%v] want [%v]", got, want))
Andres Erbsenb7f95f32014-07-07 12:07:56 -07001152 }
1153 return nil
1154 }
1155
1156 // First call should succeed
1157 if err := call(); err != nil {
1158 t.Fatal(err)
1159 }
1160 // Advance virtual clock, which will invalidate the discharge
1161 clock.Advance(1)
Jiri Simsa074bf362015-02-17 09:29:45 -08001162 if err, want := call(), "not authorized"; !matchesErrorPattern(err, verror.ErrNoAccess, want) {
Asim Shankar8f05c222014-10-06 22:08:19 -07001163 t.Errorf("Got error [%v] wanted to match pattern %q", err, want)
Andres Erbsenb7f95f32014-07-07 12:07:56 -07001164 }
1165 // But retrying will succeed since the discharge should be purged from cache and refreshed
1166 if err := call(); err != nil {
1167 t.Fatal(err)
1168 }
1169}
1170
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001171type cancelTestServer struct {
1172 started chan struct{}
1173 cancelled chan struct{}
Matt Rosencrantzbae08212014-10-03 08:04:17 -07001174 t *testing.T
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001175}
1176
Matt Rosencrantzbae08212014-10-03 08:04:17 -07001177func newCancelTestServer(t *testing.T) *cancelTestServer {
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001178 return &cancelTestServer{
1179 started: make(chan struct{}),
1180 cancelled: make(chan struct{}),
Matt Rosencrantzbae08212014-10-03 08:04:17 -07001181 t: t,
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001182 }
1183}
1184
Matt Rosencrantz1dcd0a92015-02-27 11:05:59 -08001185func (s *cancelTestServer) CancelStreamReader(call ipc.StreamServerCall) error {
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001186 close(s.started)
Matt Rosencrantzbae08212014-10-03 08:04:17 -07001187 var b []byte
1188 if err := call.Recv(&b); err != io.EOF {
1189 s.t.Errorf("Got error %v, want io.EOF", err)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001190 }
Matt Rosencrantz8f9fca12014-12-19 14:02:31 -08001191 <-call.Context().Done()
Matt Rosencrantzbae08212014-10-03 08:04:17 -07001192 close(s.cancelled)
1193 return nil
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001194}
1195
1196// CancelStreamIgnorer doesn't read from it's input stream so all it's
Matt Rosencrantz137b8d22014-08-18 09:56:15 -07001197// buffers fill. The intention is to show that call.Done() is closed
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001198// even when the stream is stalled.
Matt Rosencrantz1dcd0a92015-02-27 11:05:59 -08001199func (s *cancelTestServer) CancelStreamIgnorer(call ipc.StreamServerCall) error {
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001200 close(s.started)
Matt Rosencrantz8f9fca12014-12-19 14:02:31 -08001201 <-call.Context().Done()
Matt Rosencrantzbae08212014-10-03 08:04:17 -07001202 close(s.cancelled)
1203 return nil
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001204}
1205
Matt Rosencrantz9346b412014-12-18 15:59:19 -08001206func waitForCancel(t *testing.T, ts *cancelTestServer, cancel context.CancelFunc) {
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001207 <-ts.started
Matt Rosencrantz9346b412014-12-18 15:59:19 -08001208 cancel()
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001209 <-ts.cancelled
1210}
1211
1212// TestCancel tests cancellation while the server is reading from a stream.
1213func TestCancel(t *testing.T) {
Matt Rosencrantzbae08212014-10-03 08:04:17 -07001214 ts := newCancelTestServer(t)
Ankure49a86a2014-11-11 18:52:43 -08001215 b := createBundle(t, tsecurity.NewPrincipal("client"), tsecurity.NewPrincipal("server"), ts)
Bogdan Caprita27953142014-05-12 11:41:42 -07001216 defer b.cleanup(t)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001217
Matt Rosencrantz89445a42015-01-05 13:32:37 -08001218 ctx, cancel := context.WithCancel(testContext())
Matt Rosencrantz9346b412014-12-18 15:59:19 -08001219 _, err := b.client.StartCall(ctx, "mountpoint/server/suffix", "CancelStreamReader", []interface{}{})
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001220 if err != nil {
1221 t.Fatalf("Start call failed: %v", err)
1222 }
Matt Rosencrantz9346b412014-12-18 15:59:19 -08001223 waitForCancel(t, ts, cancel)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001224}
1225
1226// TestCancelWithFullBuffers tests that even if the writer has filled the buffers and
1227// the server is not reading that the cancel message gets through.
1228func TestCancelWithFullBuffers(t *testing.T) {
Matt Rosencrantzbae08212014-10-03 08:04:17 -07001229 ts := newCancelTestServer(t)
Ankure49a86a2014-11-11 18:52:43 -08001230 b := createBundle(t, tsecurity.NewPrincipal("client"), tsecurity.NewPrincipal("server"), ts)
Bogdan Caprita27953142014-05-12 11:41:42 -07001231 defer b.cleanup(t)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001232
Matt Rosencrantz89445a42015-01-05 13:32:37 -08001233 ctx, cancel := context.WithCancel(testContext())
Matt Rosencrantz9346b412014-12-18 15:59:19 -08001234 call, err := b.client.StartCall(ctx, "mountpoint/server/suffix", "CancelStreamIgnorer", []interface{}{})
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001235 if err != nil {
1236 t.Fatalf("Start call failed: %v", err)
1237 }
1238 // Fill up all the write buffers to ensure that cancelling works even when the stream
1239 // is blocked.
1240 call.Send(make([]byte, vc.MaxSharedBytes))
1241 call.Send(make([]byte, vc.DefaultBytesBufferedPerFlow))
1242
Matt Rosencrantz9346b412014-12-18 15:59:19 -08001243 waitForCancel(t, ts, cancel)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001244}
1245
1246type streamRecvInGoroutineServer struct{ c chan error }
1247
Matt Rosencrantz1dcd0a92015-02-27 11:05:59 -08001248func (s *streamRecvInGoroutineServer) RecvInGoroutine(call ipc.StreamServerCall) error {
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001249 // Spawn a goroutine to read streaming data from the client.
1250 go func() {
1251 var i interface{}
1252 for {
1253 err := call.Recv(&i)
1254 if err != nil {
1255 s.c <- err
1256 return
1257 }
1258 }
1259 }()
1260 // Imagine the server did some processing here and now that it is done,
1261 // it does not care to see what else the client has to say.
1262 return nil
1263}
1264
1265func TestStreamReadTerminatedByServer(t *testing.T) {
1266 s := &streamRecvInGoroutineServer{c: make(chan error, 1)}
Ankure49a86a2014-11-11 18:52:43 -08001267 b := createBundle(t, tsecurity.NewPrincipal("client"), tsecurity.NewPrincipal("server"), s)
Bogdan Caprita27953142014-05-12 11:41:42 -07001268 defer b.cleanup(t)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001269
Matt Rosencrantzbf85d542014-08-22 13:31:14 -07001270 call, err := b.client.StartCall(testContext(), "mountpoint/server/suffix", "RecvInGoroutine", []interface{}{})
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001271 if err != nil {
1272 t.Fatalf("StartCall failed: %v", err)
1273 }
1274
1275 c := make(chan error, 1)
1276 go func() {
1277 for i := 0; true; i++ {
1278 if err := call.Send(i); err != nil {
1279 c <- err
1280 return
1281 }
1282 }
1283 }()
1284
1285 // The goroutine at the server executing "Recv" should have terminated
1286 // with EOF.
1287 if err := <-s.c; err != io.EOF {
1288 t.Errorf("Got %v at server, want io.EOF", err)
1289 }
1290 // The client Send should have failed since the RPC has been
1291 // terminated.
1292 if err := <-c; err == nil {
1293 t.Errorf("Client Send should fail as the server should have closed the flow")
1294 }
1295}
1296
1297// TestConnectWithIncompatibleServers tests that clients ignore incompatible endpoints.
1298func TestConnectWithIncompatibleServers(t *testing.T) {
Ankure49a86a2014-11-11 18:52:43 -08001299 b := createBundle(t, tsecurity.NewPrincipal("client"), tsecurity.NewPrincipal("server"), &testServer{})
Bogdan Caprita27953142014-05-12 11:41:42 -07001300 defer b.cleanup(t)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001301
1302 // Publish some incompatible endpoints.
Matt Rosencrantzbf85d542014-08-22 13:31:14 -07001303 publisher := publisher.New(testContext(), b.ns, publishPeriod)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001304 defer publisher.WaitForStop()
1305 defer publisher.Stop()
1306 publisher.AddName("incompatible")
David Why Use Two When One Will Do Presotto3da1c792014-10-03 11:15:53 -07001307 publisher.AddServer("/@2@tcp@localhost:10000@@1000000@2000000@@", false)
1308 publisher.AddServer("/@2@tcp@localhost:10001@@2000000@3000000@@", false)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001309
Matt Rosencrantz89445a42015-01-05 13:32:37 -08001310 ctx, _ := context.WithTimeout(testContext(), 100*time.Millisecond)
Cosmos Nicolaou5a8a1252014-12-01 14:14:25 -08001311
1312 _, err := b.client.StartCall(ctx, "incompatible/suffix", "Echo", []interface{}{"foo"})
Jiri Simsa074bf362015-02-17 09:29:45 -08001313 if !verror.Is(err, verror.ErrNoServers.ID) {
1314 t.Errorf("Expected error %s, found: %v", verror.ErrNoServers, err)
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001315 }
1316
1317 // Now add a server with a compatible endpoint and try again.
David Why Use Two When One Will Do Presotto3da1c792014-10-03 11:15:53 -07001318 publisher.AddServer("/"+b.ep.String(), false)
Cosmos Nicolaoufdc838b2014-06-30 21:44:27 -07001319 publisher.AddName("incompatible")
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001320
Matt Rosencrantzbf85d542014-08-22 13:31:14 -07001321 call, err := b.client.StartCall(testContext(), "incompatible/suffix", "Echo", []interface{}{"foo"})
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001322 if err != nil {
Asim Shankar3a8a7e22014-05-12 18:01:44 -07001323 t.Fatal(err)
1324 }
1325 var result string
1326 if err = call.Finish(&result); err != nil {
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001327 t.Errorf("Unexpected error finishing call %v", err)
1328 }
Asim Shankar3a8a7e22014-05-12 18:01:44 -07001329 expected := `method:"Echo",suffix:"suffix",arg:"foo"`
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001330 if result != expected {
1331 t.Errorf("Wrong result returned. Got %s, wanted %s", result, expected)
1332 }
1333}
1334
Cosmos Nicolaoubae615a2014-08-27 23:32:31 -07001335func TestPreferredAddress(t *testing.T) {
1336 sm := imanager.InternalNew(naming.FixedRoutingID(0x555555555))
1337 defer sm.Shutdown()
Matt Rosencrantz9fe60822014-09-12 10:09:53 -07001338 ns := tnaming.NewSimpleNamespace()
Cosmos Nicolaou66bc1202014-09-30 20:42:43 -07001339 pa := func(string, []ipc.Address) ([]ipc.Address, error) {
Cosmos Nicolaoubae615a2014-08-27 23:32:31 -07001340 a := &net.IPAddr{}
1341 a.IP = net.ParseIP("1.1.1.1")
Cosmos Nicolaou66bc1202014-09-30 20:42:43 -07001342 return []ipc.Address{&netstate.AddrIfc{Addr: a}}, nil
Cosmos Nicolaoubae615a2014-08-27 23:32:31 -07001343 }
Matt Rosencrantzfa3082c2015-01-22 21:39:04 -08001344 ctx := testContext()
Suharsh Sivakumaraf99c972015-01-28 15:28:49 -08001345 server, err := testInternalNewServer(ctx, sm, ns, vc.LocalPrincipal{tsecurity.NewPrincipal("server")})
Cosmos Nicolaoubae615a2014-08-27 23:32:31 -07001346 if err != nil {
1347 t.Errorf("InternalNewServer failed: %v", err)
1348 }
1349 defer server.Stop()
Cosmos Nicolaou28dabfc2014-12-15 22:51:07 -08001350
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -08001351 spec := ipc.ListenSpec{
1352 Addrs: ipc.ListenAddrs{{"tcp", ":0"}},
1353 AddressChooser: pa,
1354 }
Cosmos Nicolaou28dabfc2014-12-15 22:51:07 -08001355 eps, err := server.Listen(spec)
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -08001356 if err != nil {
1357 t.Errorf("unexpected error: %s", err)
1358 }
Cosmos Nicolaou28dabfc2014-12-15 22:51:07 -08001359 iep := eps[0].(*inaming.Endpoint)
Cosmos Nicolaoubae615a2014-08-27 23:32:31 -07001360 host, _, err := net.SplitHostPort(iep.Address)
1361 if err != nil {
1362 t.Errorf("unexpected error: %s", err)
1363 }
1364 if got, want := host, "1.1.1.1"; got != want {
1365 t.Errorf("got %q, want %q", got, want)
1366 }
1367 // Won't override the specified address.
Cosmos Nicolaou28dabfc2014-12-15 22:51:07 -08001368 eps, err = server.Listen(listenSpec)
1369 iep = eps[0].(*inaming.Endpoint)
Cosmos Nicolaoubae615a2014-08-27 23:32:31 -07001370 host, _, err = net.SplitHostPort(iep.Address)
1371 if err != nil {
1372 t.Errorf("unexpected error: %s", err)
1373 }
1374 if got, want := host, "127.0.0.1"; got != want {
1375 t.Errorf("got %q, want %q", got, want)
1376 }
1377}
1378
1379func TestPreferredAddressErrors(t *testing.T) {
1380 sm := imanager.InternalNew(naming.FixedRoutingID(0x555555555))
1381 defer sm.Shutdown()
Matt Rosencrantz9fe60822014-09-12 10:09:53 -07001382 ns := tnaming.NewSimpleNamespace()
Cosmos Nicolaou66bc1202014-09-30 20:42:43 -07001383 paerr := func(_ string, a []ipc.Address) ([]ipc.Address, error) {
Cosmos Nicolaoubae615a2014-08-27 23:32:31 -07001384 return nil, fmt.Errorf("oops")
1385 }
Matt Rosencrantzfa3082c2015-01-22 21:39:04 -08001386 ctx := testContext()
Suharsh Sivakumaraf99c972015-01-28 15:28:49 -08001387 server, err := testInternalNewServer(ctx, sm, ns, vc.LocalPrincipal{tsecurity.NewPrincipal("server")})
Cosmos Nicolaoubae615a2014-08-27 23:32:31 -07001388 if err != nil {
1389 t.Errorf("InternalNewServer failed: %v", err)
1390 }
1391 defer server.Stop()
Cosmos Nicolaouae8dd212014-12-13 23:43:08 -08001392 spec := ipc.ListenSpec{
1393 Addrs: ipc.ListenAddrs{{"tcp", ":0"}},
1394 AddressChooser: paerr,
1395 }
Cosmos Nicolaou28dabfc2014-12-15 22:51:07 -08001396 eps, err := server.Listen(spec)
1397 iep := eps[0].(*inaming.Endpoint)
Cosmos Nicolaoubae615a2014-08-27 23:32:31 -07001398 host, _, err := net.SplitHostPort(iep.Address)
1399 if err != nil {
1400 t.Errorf("unexpected error: %s", err)
1401 }
Cosmos Nicolaoud6c3c9c2014-09-30 15:42:53 -07001402 ip := net.ParseIP(host)
1403 if ip == nil {
1404 t.Fatalf("failed to parse IP address: %q", host)
1405 }
1406 if !ip.IsUnspecified() {
1407 t.Errorf("IP: %q is not unspecified", ip)
Cosmos Nicolaoubae615a2014-08-27 23:32:31 -07001408 }
1409}
1410
Suharsh Sivakumarcd743f72014-10-27 10:03:42 -07001411func TestSecurityNone(t *testing.T) {
1412 sm := imanager.InternalNew(naming.FixedRoutingID(0x66666666))
1413 defer sm.Shutdown()
1414 ns := tnaming.NewSimpleNamespace()
Matt Rosencrantzfa3082c2015-01-22 21:39:04 -08001415 ctx := testContext()
Suharsh Sivakumaraf99c972015-01-28 15:28:49 -08001416 server, err := testInternalNewServer(ctx, sm, ns, options.VCSecurityNone)
Suharsh Sivakumarcd743f72014-10-27 10:03:42 -07001417 if err != nil {
1418 t.Fatalf("InternalNewServer failed: %v", err)
1419 }
1420 if _, err = server.Listen(listenSpec); err != nil {
1421 t.Fatalf("server.Listen failed: %v", err)
1422 }
1423 disp := &testServerDisp{&testServer{}}
Cosmos Nicolaou92dba582014-11-05 17:24:10 -08001424 if err := server.ServeDispatcher("mp/server", disp); err != nil {
Suharsh Sivakumarcd743f72014-10-27 10:03:42 -07001425 t.Fatalf("server.Serve failed: %v", err)
1426 }
Suharsh Sivakumarae774a52015-01-09 14:26:32 -08001427 client, err := InternalNewClient(sm, ns)
Suharsh Sivakumarcd743f72014-10-27 10:03:42 -07001428 if err != nil {
1429 t.Fatalf("InternalNewClient failed: %v", err)
1430 }
1431 // When using VCSecurityNone, all authorization checks should be skipped, so
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001432 // unauthorized methods should be callable.
Matt Rosencrantzfa3082c2015-01-22 21:39:04 -08001433 call, err := client.StartCall(ctx, "mp/server", "Unauthorized", nil, options.VCSecurityNone)
Suharsh Sivakumarcd743f72014-10-27 10:03:42 -07001434 if err != nil {
1435 t.Fatalf("client.StartCall failed: %v", err)
1436 }
1437 var got string
Todd Wange77f9952015-02-18 13:20:50 -08001438 if err := call.Finish(&got); err != nil {
Suharsh Sivakumarcd743f72014-10-27 10:03:42 -07001439 t.Errorf("call.Finish failed: %v", err)
1440 }
1441 if want := "UnauthorizedResult"; got != want {
1442 t.Errorf("got (%v), want (%v)", got, want)
1443 }
1444}
1445
Matt Rosencrantz321a51d2014-10-30 10:37:56 -07001446func TestCallWithNilContext(t *testing.T) {
1447 sm := imanager.InternalNew(naming.FixedRoutingID(0x66666666))
1448 defer sm.Shutdown()
1449 ns := tnaming.NewSimpleNamespace()
Suharsh Sivakumarae774a52015-01-09 14:26:32 -08001450 client, err := InternalNewClient(sm, ns)
Matt Rosencrantz321a51d2014-10-30 10:37:56 -07001451 if err != nil {
1452 t.Fatalf("InternalNewClient failed: %v", err)
1453 }
Suharsh Sivakumarae774a52015-01-09 14:26:32 -08001454 call, err := client.StartCall(nil, "foo", "bar", []interface{}{}, options.VCSecurityNone)
Matt Rosencrantz321a51d2014-10-30 10:37:56 -07001455 if call != nil {
1456 t.Errorf("Expected nil interface got: %#v", call)
1457 }
Jiri Simsa074bf362015-02-17 09:29:45 -08001458 if !verror.Is(err, verror.ErrBadArg.ID) {
Cosmos Nicolaou112bf1c2014-11-21 15:43:11 -08001459 t.Errorf("Expected an BadArg error, got: %s", err.Error())
Matt Rosencrantz321a51d2014-10-30 10:37:56 -07001460 }
1461}
1462
Asim Shankara5b60b22014-11-06 15:37:07 -08001463func TestServerBlessingsOpt(t *testing.T) {
1464 var (
Ankure49a86a2014-11-11 18:52:43 -08001465 pserver = tsecurity.NewPrincipal("server")
1466 pclient = tsecurity.NewPrincipal("client")
Asim Shankara5b60b22014-11-06 15:37:07 -08001467 batman, _ = pserver.BlessSelf("batman")
1468 )
1469 // Make the client recognize all server blessings
1470 if err := pclient.AddToRoots(batman); err != nil {
1471 t.Fatal(err)
1472 }
1473 if err := pclient.AddToRoots(pserver.BlessingStore().Default()); err != nil {
1474 t.Fatal(err)
1475 }
1476 // Start a server that uses the ServerBlessings option to configure itself
1477 // to act as batman (as opposed to using the default blessing).
1478 ns := tnaming.NewSimpleNamespace()
Asim Shankara5b60b22014-11-06 15:37:07 -08001479
Suharsh Sivakumar0902b7f2015-02-27 19:06:41 -08001480 popt := vc.LocalPrincipal{pserver}
1481 defer runServer(t, ns, "mountpoint/batman", &testServer{}, popt, options.ServerBlessings{batman}).Shutdown()
1482 defer runServer(t, ns, "mountpoint/default", &testServer{}, popt).Shutdown()
Asim Shankara5b60b22014-11-06 15:37:07 -08001483
Asim Shankarb547ea92015-02-17 18:49:45 -08001484 // And finally, make an RPC and see that the client sees "batman"
Asim Shankara5b60b22014-11-06 15:37:07 -08001485 runClient := func(server string) ([]string, error) {
1486 smc := imanager.InternalNew(naming.FixedRoutingID(0xc))
1487 defer smc.Shutdown()
1488 client, err := InternalNewClient(
1489 smc,
1490 ns,
1491 vc.LocalPrincipal{pclient})
1492 if err != nil {
1493 return nil, err
1494 }
1495 defer client.Close()
1496 call, err := client.StartCall(testContext(), server, "Closure", nil)
1497 if err != nil {
1498 return nil, err
1499 }
1500 blessings, _ := call.RemoteBlessings()
1501 return blessings, nil
1502 }
1503
1504 // When talking to mountpoint/batman, should see "batman"
1505 // When talking to mountpoint/default, should see "server"
1506 if got, err := runClient("mountpoint/batman"); err != nil || len(got) != 1 || got[0] != "batman" {
1507 t.Errorf("Got (%v, %v) wanted 'batman'", got, err)
1508 }
1509 if got, err := runClient("mountpoint/default"); err != nil || len(got) != 1 || got[0] != "server" {
1510 t.Errorf("Got (%v, %v) wanted 'server'", got, err)
1511 }
1512}
1513
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001514func TestNoDischargesOpt(t *testing.T) {
1515 var (
1516 pdischarger = tsecurity.NewPrincipal("discharger")
1517 pserver = tsecurity.NewPrincipal("server")
1518 pclient = tsecurity.NewPrincipal("client")
1519 )
1520 // Make the client recognize all server blessings
1521 if err := pclient.AddToRoots(pserver.BlessingStore().Default()); err != nil {
1522 t.Fatal(err)
1523 }
1524 if err := pclient.AddToRoots(pdischarger.BlessingStore().Default()); err != nil {
1525 t.Fatal(err)
1526 }
1527
1528 // Bless the client with a ThirdPartyCaveat.
1529 tpcav := mkThirdPartyCaveat(pdischarger.PublicKey(), "mountpoint/discharger", mkCaveat(security.ExpiryCaveat(time.Now().Add(time.Hour))))
1530 blessings, err := pserver.Bless(pclient.PublicKey(), pserver.BlessingStore().Default(), "tpcav", tpcav)
1531 if err != nil {
1532 t.Fatalf("failed to create Blessings: %v", err)
1533 }
1534 if _, err = pclient.BlessingStore().Set(blessings, "server"); err != nil {
1535 t.Fatalf("failed to set blessings: %v", err)
1536 }
1537
1538 ns := tnaming.NewSimpleNamespace()
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001539
1540 // Setup the disharger and test server.
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08001541 discharger := &dischargeServer{}
Suharsh Sivakumar0902b7f2015-02-27 19:06:41 -08001542 defer runServer(t, ns, "mountpoint/discharger", discharger, vc.LocalPrincipal{pdischarger}).Shutdown()
1543 defer runServer(t, ns, "mountpoint/testServer", &testServer{}, vc.LocalPrincipal{pserver}).Shutdown()
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001544
1545 runClient := func(noDischarges bool) {
1546 rid, err := naming.NewRoutingID()
1547 if err != nil {
1548 t.Fatal(err)
1549 }
1550 smc := imanager.InternalNew(rid)
1551 defer smc.Shutdown()
Suharsh Sivakumar1b6683e2014-12-30 13:00:38 -08001552 client, err := InternalNewClient(smc, ns, vc.LocalPrincipal{pclient})
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001553 if err != nil {
1554 t.Fatalf("failed to create client: %v", err)
1555 }
1556 defer client.Close()
1557 var opts []ipc.CallOpt
1558 if noDischarges {
Ankur50a5f392015-02-27 18:46:30 -08001559 opts = append(opts, NoDischarges{})
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001560 }
1561 if _, err = client.StartCall(testContext(), "mountpoint/testServer", "Closure", nil, opts...); err != nil {
1562 t.Fatalf("failed to StartCall: %v", err)
1563 }
1564 }
1565
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08001566 // Test that when the NoDischarges option is set, dischargeServer does not get called.
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001567 if runClient(true); discharger.called {
1568 t.Errorf("did not expect discharger to be called")
1569 }
1570 discharger.called = false
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08001571 // Test that when the Nodischarges option is not set, dischargeServer does get called.
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001572 if runClient(false); !discharger.called {
1573 t.Errorf("expected discharger to be called")
1574 }
1575}
1576
1577func TestNoImplicitDischargeFetching(t *testing.T) {
1578 // This test ensures that discharge clients only fetch discharges for the specified tp caveats and not its own.
1579 var (
1580 pdischarger1 = tsecurity.NewPrincipal("discharger1")
1581 pdischarger2 = tsecurity.NewPrincipal("discharger2")
1582 pdischargeClient = tsecurity.NewPrincipal("dischargeClient")
1583 )
1584
1585 // Bless the client with a ThirdPartyCaveat from discharger1.
1586 tpcav1 := mkThirdPartyCaveat(pdischarger1.PublicKey(), "mountpoint/discharger1", mkCaveat(security.ExpiryCaveat(time.Now().Add(time.Hour))))
1587 blessings, err := pdischarger1.Bless(pdischargeClient.PublicKey(), pdischarger1.BlessingStore().Default(), "tpcav1", tpcav1)
1588 if err != nil {
1589 t.Fatalf("failed to create Blessings: %v", err)
1590 }
1591 if err = pdischargeClient.BlessingStore().SetDefault(blessings); err != nil {
1592 t.Fatalf("failed to set blessings: %v", err)
1593 }
1594
1595 ns := tnaming.NewSimpleNamespace()
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001596
1597 // Setup the disharger and test server.
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08001598 discharger1 := &dischargeServer{}
1599 discharger2 := &dischargeServer{}
Suharsh Sivakumar0902b7f2015-02-27 19:06:41 -08001600 defer runServer(t, ns, "mountpoint/discharger1", discharger1, vc.LocalPrincipal{pdischarger1}).Shutdown()
1601 defer runServer(t, ns, "mountpoint/discharger2", discharger2, vc.LocalPrincipal{pdischarger2}).Shutdown()
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001602
1603 rid, err := naming.NewRoutingID()
1604 if err != nil {
1605 t.Fatal(err)
1606 }
1607 sm := imanager.InternalNew(rid)
Suharsh Sivakumar1b6683e2014-12-30 13:00:38 -08001608
1609 c, err := InternalNewClient(sm, ns, vc.LocalPrincipal{pdischargeClient})
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001610 if err != nil {
Suharsh Sivakumar1b6683e2014-12-30 13:00:38 -08001611 t.Fatalf("failed to create client: %v", err)
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001612 }
Suharsh Sivakumar1b6683e2014-12-30 13:00:38 -08001613 dc := c.(*client).dc
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001614 tpcav2, err := security.NewPublicKeyCaveat(pdischarger2.PublicKey(), "mountpoint/discharger2", security.ThirdPartyRequirements{}, mkCaveat(security.ExpiryCaveat(time.Now().Add(time.Hour))))
1615 if err != nil {
1616 t.Error(err)
1617 }
Asim Shankar19da8182015-02-06 01:41:16 -08001618 dc.PrepareDischarges(testContext(), []security.Caveat{tpcav2}, security.DischargeImpetus{})
Suharsh Sivakumar11316872014-11-25 15:57:00 -08001619
1620 // Ensure that discharger1 was not called and discharger2 was called.
1621 if discharger1.called {
1622 t.Errorf("discharge for caveat on discharge client should not have been fetched.")
1623 }
1624 if !discharger2.called {
1625 t.Errorf("discharge for caveat passed to PrepareDischarges should have been fetched.")
1626 }
1627}
1628
Suharsh Sivakumar720b7042014-12-22 17:33:23 -08001629// TestBlessingsCache tests that the VCCache is used to sucessfully used to cache duplicate
1630// calls blessings.
1631func TestBlessingsCache(t *testing.T) {
1632 var (
1633 pserver = tsecurity.NewPrincipal("server")
1634 pclient = tsecurity.NewPrincipal("client")
1635 )
1636 // Make the client recognize all server blessings
1637 if err := pclient.AddToRoots(pserver.BlessingStore().Default()); err != nil {
1638 t.Fatal(err)
1639 }
1640
1641 ns := tnaming.NewSimpleNamespace()
Suharsh Sivakumar720b7042014-12-22 17:33:23 -08001642
Suharsh Sivakumar0902b7f2015-02-27 19:06:41 -08001643 serverSM := runServer(t, ns, "mountpoint/testServer", &testServer{}, vc.LocalPrincipal{pserver})
Suharsh Sivakumar720b7042014-12-22 17:33:23 -08001644 defer serverSM.Shutdown()
Suharsh Sivakumar0902b7f2015-02-27 19:06:41 -08001645 rid := serverSM.RoutingID()
Suharsh Sivakumar720b7042014-12-22 17:33:23 -08001646
1647 newClient := func() ipc.Client {
1648 rid, err := naming.NewRoutingID()
1649 if err != nil {
1650 t.Fatal(err)
1651 }
1652 smc := imanager.InternalNew(rid)
1653 defer smc.Shutdown()
1654 client, err := InternalNewClient(smc, ns, vc.LocalPrincipal{pclient})
1655 if err != nil {
1656 t.Fatalf("failed to create client: %v", err)
1657 }
1658 return client
1659 }
1660
1661 runClient := func(client ipc.Client) {
Suharsh Sivakumar0902b7f2015-02-27 19:06:41 -08001662 if call, err := client.StartCall(testContext(), "mountpoint/testServer", "Closure", nil); err != nil {
Suharsh Sivakumar720b7042014-12-22 17:33:23 -08001663 t.Fatalf("failed to StartCall: %v", err)
Suharsh Sivakumar0902b7f2015-02-27 19:06:41 -08001664 } else if err := call.Finish(); err != nil {
Suharsh Sivakumar720b7042014-12-22 17:33:23 -08001665 t.Fatal(err)
1666 }
1667 }
1668
1669 cachePrefix := naming.Join("ipc", "server", "routing-id", rid.String(), "security", "blessings", "cache")
1670 cacheHits, err := stats.GetStatsObject(naming.Join(cachePrefix, "hits"))
1671 if err != nil {
1672 t.Fatal(err)
1673 }
1674 cacheAttempts, err := stats.GetStatsObject(naming.Join(cachePrefix, "attempts"))
1675 if err != nil {
1676 t.Fatal(err)
1677 }
1678
1679 // Check that the blessings cache is not used on the first call.
1680 clientA := newClient()
1681 runClient(clientA)
1682 if gotAttempts, gotHits := cacheAttempts.Value().(int64), cacheHits.Value().(int64); gotAttempts != 1 || gotHits != 0 {
1683 t.Errorf("got cacheAttempts(%v), cacheHits(%v), expected cacheAttempts(1), cacheHits(0)", gotAttempts, gotHits)
1684 }
1685 // Check that the cache is hit on the second call with the same blessings.
1686 runClient(clientA)
1687 if gotAttempts, gotHits := cacheAttempts.Value().(int64), cacheHits.Value().(int64); gotAttempts != 2 || gotHits != 1 {
1688 t.Errorf("got cacheAttempts(%v), cacheHits(%v), expected cacheAttempts(2), cacheHits(1)", gotAttempts, gotHits)
1689 }
1690 clientA.Close()
1691 // Check that the cache is not used with a different client.
1692 clientB := newClient()
1693 runClient(clientB)
1694 if gotAttempts, gotHits := cacheAttempts.Value().(int64), cacheHits.Value().(int64); gotAttempts != 3 || gotHits != 1 {
1695 t.Errorf("got cacheAttempts(%v), cacheHits(%v), expected cacheAttempts(3), cacheHits(1)", gotAttempts, gotHits)
1696 }
1697 // clientB changes its blessings, the cache should not be used.
1698 blessings, err := pserver.Bless(pclient.PublicKey(), pserver.BlessingStore().Default(), "cav", mkCaveat(security.ExpiryCaveat(time.Now().Add(time.Hour))))
1699 if err != nil {
1700 t.Fatalf("failed to create Blessings: %v", err)
1701 }
1702 if _, err = pclient.BlessingStore().Set(blessings, "server"); err != nil {
1703 t.Fatalf("failed to set blessings: %v", err)
1704 }
1705 runClient(clientB)
1706 if gotAttempts, gotHits := cacheAttempts.Value().(int64), cacheHits.Value().(int64); gotAttempts != 4 || gotHits != 1 {
1707 t.Errorf("got cacheAttempts(%v), cacheHits(%v), expected cacheAttempts(4), cacheHits(1)", gotAttempts, gotHits)
1708 }
1709 clientB.Close()
1710}
1711
Asim Shankar7283dd82015-02-03 19:35:58 -08001712var fakeTimeCaveat = security.CaveatDescriptor{
1713 Id: uniqueid.Id{0x18, 0xba, 0x6f, 0x84, 0xd5, 0xec, 0xdb, 0x9b, 0xf2, 0x32, 0x19, 0x5b, 0x53, 0x92, 0x80, 0x0},
1714 ParamType: vdl.TypeOf(int64(0)),
Jiri Simsa5293dcb2014-05-10 09:56:38 -07001715}
Suharsh Sivakumar9d17e4a2015-02-02 22:42:16 -08001716
Suharsh Sivakumara8633b02015-02-14 17:08:07 -08001717func TestServerPublicKeyOpt(t *testing.T) {
1718 var (
1719 pserver = tsecurity.NewPrincipal("server")
1720 pother = tsecurity.NewPrincipal("other")
1721 pclient = tsecurity.NewPrincipal("client")
1722 )
1723
1724 ns := tnaming.NewSimpleNamespace()
Suharsh Sivakumara8633b02015-02-14 17:08:07 -08001725 mountName := "mountpoint/default"
Suharsh Sivakumara8633b02015-02-14 17:08:07 -08001726
1727 // Start a server with pserver.
Suharsh Sivakumar0902b7f2015-02-27 19:06:41 -08001728 defer runServer(t, ns, mountName, &testServer{}, vc.LocalPrincipal{pserver}).Shutdown()
Suharsh Sivakumara8633b02015-02-14 17:08:07 -08001729
1730 smc := imanager.InternalNew(naming.FixedRoutingID(0xc))
1731 client, err := InternalNewClient(
1732 smc,
1733 ns,
1734 vc.LocalPrincipal{pclient})
1735 if err != nil {
1736 t.Fatal(err)
1737 }
1738 defer smc.Shutdown()
1739 defer client.Close()
1740
1741 // The call should succeed when the server presents the same public as the opt...
1742 if _, err = client.StartCall(testContext(), mountName, "Closure", nil, options.ServerPublicKey{pserver.PublicKey()}); err != nil {
1743 t.Errorf("Expected call to succeed but got %v", err)
1744 }
1745 // ...but fail if they differ.
Jiri Simsa074bf362015-02-17 09:29:45 -08001746 if _, err = client.StartCall(testContext(), mountName, "Closure", nil, options.ServerPublicKey{pother.PublicKey()}); !verror.Is(err, verror.ErrNotTrusted.ID) {
1747 t.Errorf("got %v, want %v", verror.ErrorID(err), verror.ErrNotTrusted.ID)
Suharsh Sivakumara8633b02015-02-14 17:08:07 -08001748 }
1749}
1750
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08001751type expiryDischarger struct {
1752 called bool
1753}
1754
Asim Shankar08642822015-03-02 21:21:09 -08001755func (ed *expiryDischarger) Discharge(call ipc.StreamServerCall, cav security.Caveat, _ security.DischargeImpetus) (security.Discharge, error) {
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08001756 tp := cav.ThirdPartyDetails()
1757 if tp == nil {
Asim Shankar08642822015-03-02 21:21:09 -08001758 return security.Discharge{}, fmt.Errorf("discharger: %v does not represent a third-party caveat", cav)
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08001759 }
Matt Rosencrantz9dce9b22015-03-02 10:48:37 -08001760 if err := tp.Dischargeable(call); err != nil {
Asim Shankar08642822015-03-02 21:21:09 -08001761 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 -08001762 }
1763 expDur := 10 * time.Millisecond
1764 if ed.called {
1765 expDur = time.Second
1766 }
1767 expiry, err := security.ExpiryCaveat(time.Now().Add(expDur))
1768 if err != nil {
Asim Shankar08642822015-03-02 21:21:09 -08001769 return security.Discharge{}, fmt.Errorf("failed to create an expiration on the discharge: %v", err)
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08001770 }
Matt Rosencrantz9dce9b22015-03-02 10:48:37 -08001771 d, err := call.LocalPrincipal().MintDischarge(cav, expiry)
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08001772 if err != nil {
Asim Shankar08642822015-03-02 21:21:09 -08001773 return security.Discharge{}, err
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08001774 }
1775 ed.called = true
Asim Shankar08642822015-03-02 21:21:09 -08001776 return d, nil
Suharsh Sivakumarcd07e252015-02-28 01:04:26 -08001777}
1778
1779func TestDischargeClientFetchExpiredDischarges(t *testing.T) {
1780 var (
1781 pdischarger = tsecurity.NewPrincipal("discharger")
1782 )
1783
1784 // Bless the client with a ThirdPartyCaveat.
1785 tpcav := mkThirdPartyCaveat(pdischarger.PublicKey(), "mountpoint/discharger", mkCaveat(security.ExpiryCaveat(time.Now().Add(time.Hour))))
1786
1787 ns := tnaming.NewSimpleNamespace()
1788 ctx := testContext()
1789
1790 // Setup the disharge server.
1791 discharger := &expiryDischarger{}
1792 defer runServer(t, ns, "mountpoint/discharger", discharger, vc.LocalPrincipal{pdischarger}).Shutdown()
1793
1794 // Create a discharge client.
1795 rid, err := naming.NewRoutingID()
1796 if err != nil {
1797 t.Fatal(err)
1798 }
1799 smc := imanager.InternalNew(rid)
1800 defer smc.Shutdown()
1801 client, err := InternalNewClient(smc, ns)
1802 if err != nil {
1803 t.Fatalf("failed to create client: %v", err)
1804 }
1805 defer client.Close()
1806 dc := InternalNewDischargeClient(ctx, client)
1807
1808 // Fetch discharges for tpcav.
1809 dis := dc.PrepareDischarges(nil, []security.Caveat{tpcav}, security.DischargeImpetus{})[0]
1810 // Check that the discharges is not yet expired, but is expired after 100 milliseconds.
1811 expiry := dis.Expiry()
1812 // The discharge should expire.
1813 select {
1814 case <-time.After(time.Now().Sub(expiry)):
1815 break
1816 case <-time.After(time.Second):
1817 t.Fatalf("discharge didn't expire within a second")
1818 }
1819 // Preparing Discharges again to get fresh discharges.
1820 now := time.Now()
1821 dis = dc.PrepareDischarges(nil, []security.Caveat{tpcav}, security.DischargeImpetus{})[0]
1822 if expiry = dis.Expiry(); expiry.Before(now) {
1823 t.Fatalf("discharge has expired %v, but should be fresh", dis)
1824 }
1825}
1826
Suharsh Sivakumard19c95d2015-02-19 14:44:50 -08001827func init() {
Matt Rosencrantz5c7ed212015-02-27 22:42:35 -08001828 security.RegisterCaveatValidator(fakeTimeCaveat, func(_ security.Call, t int64) error {
Asim Shankar7283dd82015-02-03 19:35:58 -08001829 if now := clock.Now(); now > int(t) {
1830 return fmt.Errorf("fakeTimeCaveat expired: now=%d > then=%d", now, t)
1831 }
1832 return nil
1833 })
Suharsh Sivakumar9d17e4a2015-02-02 22:42:16 -08001834}