"x/ref": Update w.r.t to CL #9371

See: https://vanadium-review.googlesource.com/#/c/9371/

MultiPart: 2/2

Change-Id: Idb7270b1f1cee70ae3a9e162af472931115469d8
diff --git a/cmd/principal/main.go b/cmd/principal/main.go
index 67fb4e1..0f18ad2 100644
--- a/cmd/principal/main.go
+++ b/cmd/principal/main.go
@@ -262,7 +262,7 @@
 			// Send blessings to a "server" started by a "recvblessings" command, either
 			// with the --remote-arg-file flag, or with --remote-key and --remote-token flags.
 			if len(remoteKey) > 0 {
-				granter := &granter{p, with, extension, caveats, remoteKey}
+				granter := &granter{with, extension, caveats, remoteKey}
 				return blessOverNetwork(ctx, tobless, granter, remoteToken)
 			}
 
@@ -1017,14 +1017,16 @@
 func (allowAnyone) Authorize(*context.T) error { return nil }
 
 type granter struct {
-	p         security.Principal
 	with      security.Blessings
 	extension string
 	caveats   []security.Caveat
 	serverKey string
 }
 
-func (g *granter) Grant(server security.Blessings) (security.Blessings, error) {
+func (g *granter) Grant(ctx *context.T) (security.Blessings, error) {
+	call := security.GetCall(ctx)
+	server := call.RemoteBlessings()
+	p := call.LocalPrincipal()
 	if got := fmt.Sprintf("%v", server.PublicKey()); got != g.serverKey {
 		// If the granter returns an error, the RPC framework should
 		// abort the RPC before sending the request to the server.
@@ -1032,7 +1034,7 @@
 		// imposter server.
 		return security.Blessings{}, fmt.Errorf("key mismatch: Remote end has public key %v, want %v", got, g.serverKey)
 	}
-	return g.p.Bless(server.PublicKey(), g.with, g.extension, g.caveats[0], g.caveats[1:]...)
+	return p.Bless(server.PublicKey(), g.with, g.extension, g.caveats[0], g.caveats[1:]...)
 }
 func (*granter) RPCCallOpt() {}
 
diff --git a/profiles/internal/rpc/client.go b/profiles/internal/rpc/client.go
index 26b7244..200c33b 100644
--- a/profiles/internal/rpc/client.go
+++ b/profiles/internal/rpc/client.go
@@ -492,7 +492,7 @@
 				return nil, verror.NoRetry, err
 			}
 
-			if err := fc.prepareBlessingsAndDischarges(method, args, r.rejectedBlessings, opts); err != nil {
+			if err := fc.prepareBlessingsAndDischarges(ctx, method, r.suffix, args, r.rejectedBlessings, opts); err != nil {
 				r.err = verror.New(verror.ErrNotTrusted, ctx, name, r.flow.RemoteBlessings(), err)
 				vlog.VI(2).Infof("rpc: err: %s", r.err)
 				r.flow.Close()
@@ -609,19 +609,13 @@
 // server, (2) preparing blessings that the client authenticates with,
 // and, (3) preparing any discharges for third-party caveats on the client's
 // blessings.
-func (fc *flowClient) prepareBlessingsAndDischarges(method string, args []interface{}, rejectedServerBlessings []security.RejectedBlessing, opts []rpc.CallOpt) error {
+func (fc *flowClient) prepareBlessingsAndDischarges(ctx *context.T, method, suffix string, args []interface{}, rejectedServerBlessings []security.RejectedBlessing, opts []rpc.CallOpt) error {
 	// LocalPrincipal is nil which means we are operating under
 	// SecurityNone.
 	if fc.flow.LocalPrincipal() == nil {
 		return nil
 	}
 
-	// Prepare blessings that must be granted to the server (using any
-	// rpc.Granter implementation in 'opts').
-	if err := fc.prepareGrantedBlessings(opts); err != nil {
-		return err
-	}
-
 	// Fetch blessings from the client's blessing store that are to be
 	// shared with the server.
 	if fc.blessings = fc.flow.LocalPrincipal().BlessingStore().ForPeer(fc.server...); fc.blessings.IsZero() {
@@ -639,14 +633,44 @@
 		}
 		fc.discharges = fc.dc.PrepareDischarges(fc.ctx, fc.blessings.ThirdPartyCaveats(), impetus)
 	}
+
+	// Prepare blessings that must be granted to the server (using any
+	// rpc.Granter implementation in 'opts').
+	//
+	// NOTE(ataly, suharshs): Before invoking the granter, we set the parameters of
+	// the current call on the context. The context would now have two principals
+	// set on it -- one available via v23.GetPrincipal(ctx) and the other available
+	// via security.GetCall(ctx).LocalPrincipal(). While in theory the two principals
+	// can be different, the flow.LocalPrincipal == nil check at the beginning
+	// of this method ensures that the two are the same and non-nil at this point
+	// in the code.
+	ldischargeMap := make(map[string]security.Discharge)
+	for _, d := range fc.discharges {
+		ldischargeMap[d.ID()] = d
+	}
+	seccall := security.NewCall(&security.CallParams{
+		LocalPrincipal:   fc.flow.LocalPrincipal(),
+		LocalBlessings:   fc.blessings,
+		RemoteBlessings:  fc.flow.RemoteBlessings(),
+		LocalEndpoint:    fc.flow.LocalEndpoint(),
+		RemoteEndpoint:   fc.flow.RemoteEndpoint(),
+		LocalDischarges:  ldischargeMap,
+		RemoteDischarges: fc.flow.RemoteDischarges(),
+		Method:           method,
+		Suffix:           suffix,
+	})
+	ctx = security.SetCall(ctx, seccall)
+	if err := fc.prepareGrantedBlessings(ctx, opts); err != nil {
+		return err
+	}
 	return nil
 }
 
-func (fc *flowClient) prepareGrantedBlessings(opts []rpc.CallOpt) error {
+func (fc *flowClient) prepareGrantedBlessings(ctx *context.T, opts []rpc.CallOpt) error {
 	for _, o := range opts {
 		switch v := o.(type) {
 		case rpc.Granter:
-			if b, err := v.Grant(fc.flow.RemoteBlessings()); err != nil {
+			if b, err := v.Grant(ctx); err != nil {
 				return verror.New(errBlessingGrant, fc.ctx, fc.server, err)
 			} else if fc.grantedBlessings, err = security.UnionOfBlessings(fc.grantedBlessings, b); err != nil {
 				return verror.New(errBlessingAdd, fc.ctx, fc.server, err)
diff --git a/profiles/internal/rpc/full_test.go b/profiles/internal/rpc/full_test.go
index 8f0383c..b6916ce 100644
--- a/profiles/internal/rpc/full_test.go
+++ b/profiles/internal/rpc/full_test.go
@@ -801,14 +801,24 @@
 	}
 }
 
-// granter implements rpc.Granter, returning a fixed (security.Blessings, error) pair.
+// granter implements rpc.Granter.
+//
+// It returns the specified (security.Blessings, error) pair if either the
+// blessing or the error is specified. Otherwise it returns a blessing
+// derived from the local blessings of the current call.
 type granter struct {
 	rpc.CallOpt
 	b   security.Blessings
 	err error
 }
 
-func (g granter) Grant(id security.Blessings) (security.Blessings, error) { return g.b, g.err }
+func (g granter) Grant(ctx *context.T) (security.Blessings, error) {
+	if !g.b.IsZero() || g.err != nil {
+		return g.b, g.err
+	}
+	call := security.GetCall(ctx)
+	return call.LocalPrincipal().Bless(call.RemoteBlessings().PublicKey(), call.LocalBlessings(), "blessed", security.UnconstrainedUse())
+}
 
 func TestGranter(t *testing.T) {
 	var (
@@ -828,6 +838,7 @@
 		{blessing: ""},
 		{granter: granter{b: bless(pclient, pserver, "blessed")}, blessing: "client/blessed"},
 		{granter: granter{err: errors.New("hell no")}, startErrID: verror.ErrNotTrusted, starterr: "hell no"},
+		{granter: granter{}, blessing: "client/blessed"},
 		{granter: granter{b: pclient.BlessingStore().Default()}, finishErrID: verror.ErrNoAccess, finisherr: "blessing granted not bound to this server"},
 	}
 	for i, test := range tests {
diff --git a/services/device/device/impl.go b/services/device/device/impl.go
index bfd28cb..cf45c9e 100644
--- a/services/device/device/impl.go
+++ b/services/device/device/impl.go
@@ -126,12 +126,13 @@
 
 type granter struct {
 	rpc.CallOpt
-	p         security.Principal
 	extension string
 }
 
-func (g *granter) Grant(other security.Blessings) (security.Blessings, error) {
-	return g.p.Bless(other.PublicKey(), g.p.BlessingStore().Default(), g.extension, security.UnconstrainedUse())
+func (g *granter) Grant(ctx *context.T) (security.Blessings, error) {
+	call := security.GetCall(ctx)
+	p := call.LocalPrincipal()
+	return p.Bless(call.RemoteBlessings().PublicKey(), p.BlessingStore().Default(), g.extension, security.UnconstrainedUse())
 }
 
 func runStart(cmd *cmdline.Command, args []string) error {
@@ -226,7 +227,7 @@
 	}
 	// Skip server endpoint authorization since an unclaimed device might have
 	// roots that will not be recognized by the claimer.
-	if err := device.ClaimableClient(deviceName).Claim(gctx, pairingToken, &granter{p: v23.GetPrincipal(gctx), extension: grant}, serverKeyOpts, options.SkipServerEndpointAuthorization{}); err != nil {
+	if err := device.ClaimableClient(deviceName).Claim(gctx, pairingToken, &granter{extension: grant}, serverKeyOpts, options.SkipServerEndpointAuthorization{}); err != nil {
 		return err
 	}
 	fmt.Fprintln(cmd.Stdout(), "Successfully claimed.")
diff --git a/services/device/internal/impl/util_test.go b/services/device/internal/impl/util_test.go
index 4d66f34..25719b0 100644
--- a/services/device/internal/impl/util_test.go
+++ b/services/device/internal/impl/util_test.go
@@ -96,7 +96,7 @@
 
 func claimDevice(t *testing.T, ctx *context.T, name, extension, pairingToken string) {
 	// Setup blessings to be granted to the claimed device
-	g := &granter{p: v23.GetPrincipal(ctx), extension: extension}
+	g := &granter{extension: extension}
 	s := options.SkipServerEndpointAuthorization{}
 	// Call the Claim RPC: Skip server authorization because the unclaimed
 	// device presents nothing that can be used to recognize it.
@@ -122,7 +122,7 @@
 
 func claimDeviceExpectError(t *testing.T, ctx *context.T, name, extension, pairingToken string, errID verror.ID) {
 	// Setup blessings to be granted to the claimed device
-	g := &granter{p: v23.GetPrincipal(ctx), extension: extension}
+	g := &granter{extension: extension}
 	s := options.SkipServerEndpointAuthorization{}
 	// Call the Claim RPC
 	if err := device.ClaimableClient(name).Claim(ctx, pairingToken, g, s); verror.ErrorID(err) != errID {
@@ -218,8 +218,10 @@
 	extension string
 }
 
-func (g *granter) Grant(other security.Blessings) (security.Blessings, error) {
-	return g.p.Bless(other.PublicKey(), g.p.BlessingStore().Default(), g.extension, security.UnconstrainedUse())
+func (g *granter) Grant(ctx *context.T) (security.Blessings, error) {
+	call := security.GetCall(ctx)
+	p := call.LocalPrincipal()
+	return p.Bless(call.RemoteBlessings().PublicKey(), p.BlessingStore().Default(), g.extension, security.UnconstrainedUse())
 }
 
 func startAppImpl(t *testing.T, ctx *context.T, appID, grant string) (string, error) {