"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) {