Merge "ref: Change TypeBuilder.Build() to return nothing."
diff --git a/cmd/principal/main.go b/cmd/principal/main.go
index a894f30..cbed2dd 100644
--- a/cmd/principal/main.go
+++ b/cmd/principal/main.go
@@ -1034,7 +1034,7 @@
}
var s []string
for _, cav := range cavs {
- if cav.Id == security.PublicKeyThirdPartyCaveatX.Id {
+ if cav.Id == security.PublicKeyThirdPartyCaveat.Id {
c := cav.ThirdPartyDetails()
s = append(s, fmt.Sprintf("ThirdPartyCaveat: Requires discharge from %v (ID=%q)", c.Location(), c.ID()))
continue
@@ -1050,9 +1050,9 @@
if !param.(bool) {
s = append(s, fmt.Sprintf("Never validates"))
}
- case security.ExpiryCaveatX.Id:
+ case security.ExpiryCaveat.Id:
s = append(s, fmt.Sprintf("Expires at %v", param))
- case security.MethodCaveatX.Id:
+ case security.MethodCaveat.Id:
s = append(s, fmt.Sprintf("Restricted to methods %v", param))
case security.PeerBlessingsCaveat.Id:
s = append(s, fmt.Sprintf("Restricted to peers with blessings %v", param))
@@ -1252,7 +1252,7 @@
return nil, fmt.Errorf("failed to parse caveats: %v", err)
}
if expiry > 0 {
- ecav, err := security.ExpiryCaveat(time.Now().Add(expiry))
+ ecav, err := security.NewExpiryCaveat(time.Now().Add(expiry))
if err != nil {
return nil, fmt.Errorf("failed to create expiration caveat: %v", err)
}
diff --git a/cmd/principal/principal_v23_test.go b/cmd/principal/principal_v23_test.go
index 07ea2a0..e6c59dd 100644
--- a/cmd/principal/principal_v23_test.go
+++ b/cmd/principal/principal_v23_test.go
@@ -422,7 +422,7 @@
bin = bin.WithEnv(credEnv(aliceDir))
args := []string{
"blessself",
- "--caveat=\"v.io/v23/security\".MethodCaveatX={\"method\"}",
+ "--caveat=\"v.io/v23/security\".MethodCaveat={\"method\"}",
"--caveat={{0x54,0xa6,0x76,0x39,0x81,0x37,0x18,0x7e,0xcd,0xb2,0x6d,0x2d,0x69,0xba,0x0,0x3},typeobject([]string)}={\"method\"}",
"alicereborn",
}
diff --git a/cmd/vrun/vrun.go b/cmd/vrun/vrun.go
index 92f707f..390d0f1 100644
--- a/cmd/vrun/vrun.go
+++ b/cmd/vrun/vrun.go
@@ -92,7 +92,7 @@
}
func bless(ctx *context.T, p security.Principal, name string) error {
- caveat, err := security.ExpiryCaveat(time.Now().Add(durationFlag))
+ caveat, err := security.NewExpiryCaveat(time.Now().Add(durationFlag))
if err != nil {
vlog.Errorf("Couldn't create caveat")
return err
diff --git a/lib/security/audit/principal_test.go b/lib/security/audit/principal_test.go
index cc5a81b..ac0eecd 100644
--- a/lib/security/audit/principal_test.go
+++ b/lib/security/audit/principal_test.go
@@ -283,7 +283,7 @@
func newThirdPartyCaveatAndDischarge(t *testing.T) (security.Caveat, security.Discharge) {
p := newPrincipal(t)
- c, err := security.NewPublicKeyCaveat(p.PublicKey(), "location", security.ThirdPartyRequirements{}, newCaveat(security.MethodCaveat("method")))
+ c, err := security.NewPublicKeyCaveat(p.PublicKey(), "location", security.ThirdPartyRequirements{}, newCaveat(security.NewMethodCaveat("method")))
if err != nil {
t.Fatal(err)
}
diff --git a/profiles/chrome/chromeinit.go b/profiles/chrome/chromeinit.go
index 6445080..ccbfc83 100644
--- a/profiles/chrome/chromeinit.go
+++ b/profiles/chrome/chromeinit.go
@@ -37,7 +37,7 @@
protocols := []string{"wsh", "ws"}
listenSpec := rpc.ListenSpec{Addrs: rpc.ListenAddrs{{Protocol: "ws", Address: ""}}}
- runtime, ctx, shutdown, err := grt.Init(ctx, nil, protocols, &listenSpec, commonFlags.RuntimeFlags(), nil)
+ runtime, ctx, shutdown, err := grt.Init(ctx, nil, protocols, &listenSpec, nil, "", commonFlags.RuntimeFlags(), nil)
if err != nil {
return nil, nil, shutdown, err
}
diff --git a/profiles/gce/init.go b/profiles/gce/init.go
index 73a675f..d71409d 100644
--- a/profiles/gce/init.go
+++ b/profiles/gce/init.go
@@ -63,7 +63,7 @@
}
}
- runtime, ctx, shutdown, err := grt.Init(ctx, ac, nil, &listenSpec, commonFlags.RuntimeFlags(), nil)
+ runtime, ctx, shutdown, err := grt.Init(ctx, ac, nil, &listenSpec, nil, "", commonFlags.RuntimeFlags(), nil)
if err != nil {
return nil, nil, shutdown, err
}
diff --git a/profiles/genericinit.go b/profiles/genericinit.go
index b04189e..484f621 100644
--- a/profiles/genericinit.go
+++ b/profiles/genericinit.go
@@ -49,6 +49,8 @@
ac,
nil,
&listenSpec,
+ nil,
+ "",
commonFlags.RuntimeFlags(),
nil)
if err != nil {
diff --git a/profiles/internal/rpc/discharges_test.go b/profiles/internal/rpc/discharges_test.go
index 7072a69..7b67b1b 100644
--- a/profiles/internal/rpc/discharges_test.go
+++ b/profiles/internal/rpc/discharges_test.go
@@ -26,7 +26,7 @@
methodCav = mkCaveat(security.NewPublicKeyCaveat(discharger.PublicKey(), "moline", security.ThirdPartyRequirements{}, security.UnconstrainedUse()))
serverCav = mkCaveat(security.NewPublicKeyCaveat(discharger.PublicKey(), "moline", security.ThirdPartyRequirements{}, security.UnconstrainedUse()))
- dExpired = mkDischarge(discharger.MintDischarge(expiredCav, mkCaveat(security.ExpiryCaveat(time.Now().Add(-1*time.Minute)))))
+ dExpired = mkDischarge(discharger.MintDischarge(expiredCav, mkCaveat(security.NewExpiryCaveat(time.Now().Add(-1*time.Minute)))))
dArgs = mkDischarge(discharger.MintDischarge(argsCav, security.UnconstrainedUse()))
dMethod = mkDischarge(discharger.MintDischarge(methodCav, security.UnconstrainedUse()))
dServer = mkDischarge(discharger.MintDischarge(serverCav, security.UnconstrainedUse()))
diff --git a/profiles/internal/rpc/full_test.go b/profiles/internal/rpc/full_test.go
index e2e3abf..ad89931 100644
--- a/profiles/internal/rpc/full_test.go
+++ b/profiles/internal/rpc/full_test.go
@@ -19,6 +19,10 @@
"testing"
"time"
+ "v.io/x/lib/netstate"
+ "v.io/x/lib/pubsub"
+ "v.io/x/lib/vlog"
+
"v.io/v23"
"v.io/v23/context"
"v.io/v23/namespace"
@@ -31,8 +35,7 @@
"v.io/v23/vdl"
"v.io/v23/verror"
"v.io/v23/vtrace"
- "v.io/x/lib/netstate"
- "v.io/x/lib/vlog"
+
"v.io/x/ref/lib/stats"
"v.io/x/ref/profiles/internal/lib/publisher"
"v.io/x/ref/profiles/internal/lib/websocket"
@@ -75,12 +78,16 @@
c.Unlock()
}
-func testInternalNewServer(ctx *context.T, streamMgr stream.Manager, ns namespace.T, principal security.Principal, opts ...rpc.ServerOpt) (rpc.Server, error) {
+func testInternalNewServerWithPubsub(ctx *context.T, streamMgr stream.Manager, ns namespace.T, settingsPublisher *pubsub.Publisher, settingsStreamName string, principal security.Principal, opts ...rpc.ServerOpt) (rpc.Server, error) {
client, err := InternalNewClient(streamMgr, ns)
if err != nil {
return nil, err
}
- return InternalNewServer(ctx, streamMgr, ns, client, principal, opts...)
+ return InternalNewServer(ctx, streamMgr, ns, settingsPublisher, settingsStreamName, client, principal, opts...)
+}
+
+func testInternalNewServer(ctx *context.T, streamMgr stream.Manager, ns namespace.T, principal security.Principal, opts ...rpc.ServerOpt) (rpc.Server, error) {
+ return testInternalNewServerWithPubsub(ctx, streamMgr, ns, nil, "", principal, opts...)
}
type userType string
@@ -476,12 +483,12 @@
noErrID verror.IDAction
// Third-party caveats on blessings presented by server.
- cavTPValid = mkThirdPartyCaveat(pdischarger.PublicKey(), "mountpoint/dischargeserver", mkCaveat(security.ExpiryCaveat(now.Add(24*time.Hour))))
- cavTPExpired = mkThirdPartyCaveat(pdischarger.PublicKey(), "mountpoint/dischargeserver", mkCaveat(security.ExpiryCaveat(now.Add(-1*time.Second))))
+ cavTPValid = mkThirdPartyCaveat(pdischarger.PublicKey(), "mountpoint/dischargeserver", mkCaveat(security.NewExpiryCaveat(now.Add(24*time.Hour))))
+ cavTPExpired = mkThirdPartyCaveat(pdischarger.PublicKey(), "mountpoint/dischargeserver", mkCaveat(security.NewExpiryCaveat(now.Add(-1*time.Second))))
// Server blessings.
bServer = bless(pprovider, pserver, "server")
- bServerExpired = bless(pprovider, pserver, "expiredserver", mkCaveat(security.ExpiryCaveat(time.Now().Add(-1*time.Second))))
+ bServerExpired = bless(pprovider, pserver, "expiredserver", mkCaveat(security.NewExpiryCaveat(time.Now().Add(-1*time.Second))))
bServerTPValid = bless(pprovider, pserver, "serverWithTPCaveats", cavTPValid)
bServerTPExpired = bless(pprovider, pserver, "serverWithExpiredTPCaveats", cavTPExpired)
bOther = bless(pprovider, pserver, "other")
@@ -1022,11 +1029,11 @@
dischargeServerName = "mountpoint/dischargeserver"
// Caveats on blessings to the client: First-party caveats
- cavOnlyEcho = mkCaveat(security.MethodCaveat("Echo"))
- cavExpired = mkCaveat(security.ExpiryCaveat(now.Add(-1 * time.Second)))
+ cavOnlyEcho = mkCaveat(security.NewMethodCaveat("Echo"))
+ cavExpired = mkCaveat(security.NewExpiryCaveat(now.Add(-1 * time.Second)))
// Caveats on blessings to the client: Third-party caveats
- cavTPValid = mkThirdPartyCaveat(pdischarger.PublicKey(), dischargeServerName, mkCaveat(security.ExpiryCaveat(now.Add(24*time.Hour))))
- cavTPExpired = mkThirdPartyCaveat(pdischarger.PublicKey(), dischargeServerName, mkCaveat(security.ExpiryCaveat(now.Add(-1*time.Second))))
+ cavTPValid = mkThirdPartyCaveat(pdischarger.PublicKey(), dischargeServerName, mkCaveat(security.NewExpiryCaveat(now.Add(24*time.Hour))))
+ cavTPExpired = mkThirdPartyCaveat(pdischarger.PublicKey(), dischargeServerName, mkCaveat(security.NewExpiryCaveat(now.Add(-1*time.Second))))
// Client blessings that will be tested.
bServerClientOnlyEcho = bless(pserver, pclient, "onlyecho", cavOnlyEcho)
@@ -1239,7 +1246,7 @@
mgr = imanager.InternalNew(naming.FixedRoutingID(0x1111111))
ns = tnaming.NewSimpleNamespace()
- tpCav = mkThirdPartyCaveat(pdischarger.PublicKey(), "mountpoint/dischargeserver", mkCaveat(security.ExpiryCaveat(time.Now().Add(time.Hour))))
+ tpCav = mkThirdPartyCaveat(pdischarger.PublicKey(), "mountpoint/dischargeserver", mkCaveat(security.NewExpiryCaveat(time.Now().Add(time.Hour))))
bserver = bless(pprovider, pserver, "server", tpCav)
bclient = bless(pprovider, pclient, "client")
@@ -1742,7 +1749,7 @@
}
// Bless the client with a ThirdPartyCaveat.
- tpcav := mkThirdPartyCaveat(pdischarger.PublicKey(), "mountpoint/discharger", mkCaveat(security.ExpiryCaveat(time.Now().Add(time.Hour))))
+ tpcav := mkThirdPartyCaveat(pdischarger.PublicKey(), "mountpoint/discharger", mkCaveat(security.NewExpiryCaveat(time.Now().Add(time.Hour))))
blessings, err := pserver.Bless(pclient.PublicKey(), pserver.BlessingStore().Default(), "tpcav", tpcav)
if err != nil {
t.Fatalf("failed to create Blessings: %v", err)
@@ -1801,7 +1808,7 @@
ctx, shutdown := initForTest()
defer shutdown()
// Bless the client with a ThirdPartyCaveat from discharger1.
- tpcav1 := mkThirdPartyCaveat(pdischarger1.PublicKey(), "mountpoint/discharger1", mkCaveat(security.ExpiryCaveat(time.Now().Add(time.Hour))))
+ tpcav1 := mkThirdPartyCaveat(pdischarger1.PublicKey(), "mountpoint/discharger1", mkCaveat(security.NewExpiryCaveat(time.Now().Add(time.Hour))))
blessings, err := pdischarger1.Bless(pdischargeClient.PublicKey(), pdischarger1.BlessingStore().Default(), "tpcav1", tpcav1)
if err != nil {
t.Fatalf("failed to create Blessings: %v", err)
@@ -1832,7 +1839,7 @@
t.Fatalf("failed to create client: %v", err)
}
dc := c.(*client).dc
- tpcav2, err := security.NewPublicKeyCaveat(pdischarger2.PublicKey(), "mountpoint/discharger2", security.ThirdPartyRequirements{}, mkCaveat(security.ExpiryCaveat(time.Now().Add(time.Hour))))
+ tpcav2, err := security.NewPublicKeyCaveat(pdischarger2.PublicKey(), "mountpoint/discharger2", security.ThirdPartyRequirements{}, mkCaveat(security.NewExpiryCaveat(time.Now().Add(time.Hour))))
if err != nil {
t.Error(err)
}
@@ -1919,7 +1926,7 @@
t.Errorf("got cacheAttempts(%v), cacheHits(%v), expected cacheAttempts(3), cacheHits(1)", gotAttempts, gotHits)
}
// clientB changes its blessings, the cache should not be used.
- blessings, err := pserver.Bless(pclient.PublicKey(), pserver.BlessingStore().Default(), "cav", mkCaveat(security.ExpiryCaveat(time.Now().Add(time.Hour))))
+ blessings, err := pserver.Bless(pclient.PublicKey(), pserver.BlessingStore().Default(), "cav", mkCaveat(security.NewExpiryCaveat(time.Now().Add(time.Hour))))
if err != nil {
t.Fatalf("failed to create Blessings: %v", err)
}
@@ -1987,7 +1994,7 @@
if ed.called {
expDur = time.Second
}
- expiry, err := security.ExpiryCaveat(time.Now().Add(expDur))
+ expiry, err := security.NewExpiryCaveat(time.Now().Add(expDur))
if err != nil {
return security.Discharge{}, fmt.Errorf("failed to create an expiration on the discharge: %v", err)
}
@@ -2004,7 +2011,7 @@
defer shutdown()
var (
pclient, pdischarger = newClientServerPrincipals()
- tpcav = mkThirdPartyCaveat(pdischarger.PublicKey(), "mountpoint/discharger", mkCaveat(security.ExpiryCaveat(time.Now().Add(time.Hour))))
+ tpcav = mkThirdPartyCaveat(pdischarger.PublicKey(), "mountpoint/discharger", mkCaveat(security.NewExpiryCaveat(time.Now().Add(time.Hour))))
ns = tnaming.NewSimpleNamespace()
discharger = &expiryDischarger{}
)
diff --git a/profiles/internal/rpc/protocols/tcp/init.go b/profiles/internal/rpc/protocols/tcp/init.go
index 08f95e6..a6067b9 100644
--- a/profiles/internal/rpc/protocols/tcp/init.go
+++ b/profiles/internal/rpc/protocols/tcp/init.go
@@ -22,7 +22,6 @@
}
func tcpDial(network, address string, timeout time.Duration) (net.Conn, error) {
- vlog.Infof("tcp.Dial %v", address)
conn, err := net.DialTimeout(network, address, timeout)
if err != nil {
return nil, err
diff --git a/profiles/internal/rpc/pubsub.go b/profiles/internal/rpc/pubsub.go
new file mode 100644
index 0000000..7bfe46c
--- /dev/null
+++ b/profiles/internal/rpc/pubsub.go
@@ -0,0 +1,30 @@
+// Copyright 2015 The Vanadium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package rpc
+
+import (
+ "net"
+
+ "v.io/x/lib/pubsub"
+)
+
+// NewAddAddrsSetting creates the Setting to be sent to Listen to inform
+// it of new addresses that have become available since the last change.
+func NewAddAddrsSetting(a []net.Addr) pubsub.Setting {
+ return pubsub.NewAny(NewAddrsSetting, NewAddrsSettingDesc, a)
+}
+
+// NewRmAddrsSetting creates the Setting to be sent to Listen to inform
+// it of addresses that are no longer available.
+func NewRmAddrsSetting(a []net.Addr) pubsub.Setting {
+ return pubsub.NewAny(RmAddrsSetting, RmAddrsSettingDesc, a)
+}
+
+const (
+ NewAddrsSetting = "NewAddrs"
+ NewAddrsSettingDesc = "New Addresses discovered since last change"
+ RmAddrsSetting = "RmAddrs"
+ RmAddrsSettingDesc = "Addresses that have been removed since last change"
+)
diff --git a/profiles/internal/rpc/resolve_test.go b/profiles/internal/rpc/resolve_test.go
index 20bf957..e0f6878 100644
--- a/profiles/internal/rpc/resolve_test.go
+++ b/profiles/internal/rpc/resolve_test.go
@@ -50,6 +50,8 @@
ac,
nil,
&listenSpec,
+ nil,
+ "",
commonFlags.RuntimeFlags(),
nil)
if err != nil {
diff --git a/profiles/internal/rpc/server.go b/profiles/internal/rpc/server.go
index 657b3ba..102f82a 100644
--- a/profiles/internal/rpc/server.go
+++ b/profiles/internal/rpc/server.go
@@ -15,9 +15,9 @@
"time"
"v.io/x/lib/netstate"
+ "v.io/x/lib/pubsub"
"v.io/x/lib/vlog"
- "v.io/v23/config"
"v.io/v23/context"
"v.io/v23/namespace"
"v.io/v23/naming"
@@ -73,9 +73,9 @@
type dhcpState struct {
name string
- publisher *config.Publisher
- stream *config.Stream
- ch chan config.Setting // channel to receive dhcp settings over
+ publisher *pubsub.Publisher
+ stream *pubsub.Stream
+ ch chan pubsub.Setting // channel to receive dhcp settings over
err error // error status.
watchers map[chan<- rpc.NetworkChange]struct{}
}
@@ -83,15 +83,17 @@
type server struct {
sync.Mutex
// context used by the server to make internal RPCs, error messages etc.
- ctx *context.T
- cancel context.CancelFunc // function to cancel the above context.
- state serverState // track state of the server.
- streamMgr stream.Manager // stream manager to listen for new flows.
- publisher publisher.Publisher // publisher to publish mounttable mounts.
- listenerOpts []stream.ListenerOpt // listener opts for Listen.
- dhcpState *dhcpState // dhcpState, nil if not using dhcp
- principal security.Principal
- blessings security.Blessings
+ ctx *context.T
+ cancel context.CancelFunc // function to cancel the above context.
+ state serverState // track state of the server.
+ streamMgr stream.Manager // stream manager to listen for new flows.
+ publisher publisher.Publisher // publisher to publish mounttable mounts.
+ listenerOpts []stream.ListenerOpt // listener opts for Listen.
+ settingsPublisher *pubsub.Publisher // pubsub publisher for dhcp
+ settingsName string // pubwsub stream name for dhcp
+ dhcpState *dhcpState // dhcpState, nil if not using dhcp
+ principal security.Principal
+ blessings security.Blessings
// maps that contain state on listeners.
listenState map[*listenState]struct{}
@@ -173,6 +175,8 @@
ctx *context.T,
streamMgr stream.Manager,
ns namespace.T,
+ settingsPublisher *pubsub.Publisher,
+ settingsName string,
client rpc.Client,
principal security.Principal,
opts ...rpc.ServerOpt) (rpc.Server, error) {
@@ -180,18 +184,20 @@
ctx, _ = vtrace.WithNewSpan(ctx, "NewServer")
statsPrefix := naming.Join("rpc", "server", "routing-id", streamMgr.RoutingID().String())
s := &server{
- ctx: ctx,
- cancel: cancel,
- streamMgr: streamMgr,
- principal: principal,
- publisher: publisher.New(ctx, ns, publishPeriod),
- listenState: make(map[*listenState]struct{}),
- listeners: make(map[stream.Listener]struct{}),
- proxies: make(map[string]proxyState),
- stoppedChan: make(chan struct{}),
- ipNets: ipNetworks(),
- ns: ns,
- stats: newRPCStats(statsPrefix),
+ ctx: ctx,
+ cancel: cancel,
+ streamMgr: streamMgr,
+ principal: principal,
+ publisher: publisher.New(ctx, ns, publishPeriod),
+ listenState: make(map[*listenState]struct{}),
+ listeners: make(map[stream.Listener]struct{}),
+ proxies: make(map[string]proxyState),
+ stoppedChan: make(chan struct{}),
+ ipNets: ipNetworks(),
+ ns: ns,
+ stats: newRPCStats(statsPrefix),
+ settingsPublisher: settingsPublisher,
+ settingsName: settingsName,
}
var (
dischargeExpiryBuffer = vc.DefaultServerDischargeExpiryBuffer
@@ -412,15 +418,15 @@
return nil, verror.New(verror.ErrBadArg, s.ctx, "failed to create any listeners")
}
- if roaming && s.dhcpState == nil && listenSpec.StreamPublisher != nil {
+ if roaming && s.dhcpState == nil && s.settingsPublisher != nil {
// Create a dhcp listener if we haven't already done so.
dhcp := &dhcpState{
- name: listenSpec.StreamName,
- publisher: listenSpec.StreamPublisher,
+ name: s.settingsName,
+ publisher: s.settingsPublisher,
watchers: make(map[chan<- rpc.NetworkChange]struct{}),
}
s.dhcpState = dhcp
- dhcp.ch = make(chan config.Setting, 10)
+ dhcp.ch = make(chan pubsub.Setting, 10)
dhcp.stream, dhcp.err = dhcp.publisher.ForkStream(dhcp.name, dhcp.ch)
if dhcp.err == nil {
// We have a goroutine to listen for dhcp changes.
@@ -610,7 +616,7 @@
}
}
-func (s *server) dhcpLoop(ch chan config.Setting) {
+func (s *server) dhcpLoop(ch chan pubsub.Setting) {
defer vlog.VI(1).Infof("rpc: Stopped listen for dhcp changes")
vlog.VI(2).Infof("rpc: dhcp loop")
for setting := range ch {
@@ -624,20 +630,17 @@
s.Unlock()
return
}
- var err error
- var changed []naming.Endpoint
- switch setting.Name() {
- case rpc.NewAddrsSetting:
- changed = s.addAddresses(v)
- case rpc.RmAddrsSetting:
- changed, err = s.removeAddresses(v)
- }
change := rpc.NetworkChange{
- Time: time.Now(),
- State: externalStates[s.state],
- Setting: setting,
- Changed: changed,
- Error: err,
+ Time: time.Now(),
+ State: externalStates[s.state],
+ }
+ switch setting.Name() {
+ case NewAddrsSetting:
+ change.Changed = s.addAddresses(v)
+ change.AddedAddrs = v
+ case RmAddrsSetting:
+ change.Changed, change.Error = s.removeAddresses(v)
+ change.RemovedAddrs = v
}
vlog.VI(2).Infof("rpc: dhcp: change %v", change)
for ch, _ := range s.dhcpState.watchers {
@@ -703,14 +706,11 @@
// to ensure that those addresses are externally reachable.
func (s *server) addAddresses(addrs []net.Addr) []naming.Endpoint {
var added []naming.Endpoint
- vlog.Infof("HERE WITH %v -> %v", addrs, netstate.ConvertToAddresses(addrs))
for _, address := range netstate.ConvertToAddresses(addrs) {
if !netstate.IsAccessibleIP(address) {
- vlog.Infof("RETURN A %v", added)
return added
}
host := getHost(address)
- vlog.Infof("LISTEN ST: %v", s.listenState)
for ls, _ := range s.listenState {
if ls != nil && ls.roaming {
niep := ls.protoIEP
@@ -724,7 +724,6 @@
}
}
}
- vlog.Infof("RETURN B %v", added)
return added
}
@@ -854,7 +853,7 @@
}(ln)
}
- drain := func(ch chan config.Setting) {
+ drain := func(ch chan pubsub.Setting) {
for {
select {
case v := <-ch:
@@ -957,26 +956,26 @@
discharges: make(map[string]security.Discharge),
}
var err error
- typedec := flow.VCDataCache().Get(vc.TypeDecoderKey{})
- if typedec == nil {
- if fs.dec, err = vom.NewDecoder(flow); err != nil {
- flow.Close()
- return nil, err
- }
+ typeenc := flow.VCDataCache().Get(vc.TypeEncoderKey{})
+ if typeenc == nil {
if fs.enc, err = vom.NewEncoder(flow); err != nil {
flow.Close()
return nil, err
}
- } else {
- if fs.dec, err = vom.NewDecoderWithTypeDecoder(flow, typedec.(*vom.TypeDecoder)); err != nil {
+ if fs.dec, err = vom.NewDecoder(flow); err != nil {
flow.Close()
return nil, err
}
- typeenc := flow.VCDataCache().Get(vc.TypeEncoderKey{})
+ } else {
if fs.enc, err = vom.NewEncoderWithTypeEncoder(flow, typeenc.(*vom.TypeEncoder)); err != nil {
flow.Close()
return nil, err
}
+ typedec := flow.VCDataCache().Get(vc.TypeDecoderKey{})
+ if fs.dec, err = vom.NewDecoderWithTypeDecoder(flow, typedec.(*vom.TypeDecoder)); err != nil {
+ flow.Close()
+ return nil, err
+ }
}
return fs, nil
}
diff --git a/profiles/internal/rpc/server_test.go b/profiles/internal/rpc/server_test.go
index 4e30884..900db9a 100644
--- a/profiles/internal/rpc/server_test.go
+++ b/profiles/internal/rpc/server_test.go
@@ -11,8 +11,9 @@
"testing"
"time"
+ "v.io/x/lib/pubsub"
+
"v.io/v23"
- "v.io/v23/config"
"v.io/v23/context"
"v.io/v23/naming"
"v.io/v23/rpc"
@@ -423,21 +424,21 @@
ns := tnaming.NewSimpleNamespace()
ctx, shutdown := initForTest()
defer shutdown()
- server, err := testInternalNewServer(ctx, sm, ns, testutil.NewPrincipal("test"))
- defer server.Stop()
- if err != nil {
- t.Fatal(err)
- }
-
- publisher := config.NewPublisher()
- roaming := make(chan config.Setting)
+ publisher := pubsub.NewPublisher()
+ roaming := make(chan pubsub.Setting)
stop, err := publisher.CreateStream("TestRoaming", "TestRoaming", roaming)
if err != nil {
t.Fatal(err)
}
defer func() { publisher.Shutdown(); <-stop }()
+ server, err := testInternalNewServerWithPubsub(ctx, sm, ns, publisher, "TestRoaming", testutil.NewPrincipal("test"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer server.Stop()
+
ipv4And6 := func(network string, addrs []net.Addr) ([]net.Addr, error) {
accessible := netstate.ConvertToAddresses(addrs)
ipv4 := accessible.Filter(netstate.IsUnicastIPv4)
@@ -450,9 +451,7 @@
{"tcp", ":0"},
{"tcp", ":0"},
},
- StreamName: "TestRoaming",
- StreamPublisher: publisher,
- AddressChooser: ipv4And6,
+ AddressChooser: ipv4And6,
}
eps, err := server.Listen(spec)
@@ -487,7 +486,7 @@
server.WatchNetwork(watcher)
defer close(watcher)
- roaming <- rpc.NewAddAddrsSetting([]net.Addr{n1, n2})
+ roaming <- NewAddAddrsSetting([]net.Addr{n1, n2})
waitForChange := func() *rpc.NetworkChange {
vlog.Infof("Waiting on %p", watcher)
@@ -526,7 +525,7 @@
t.Fatalf("got %d, want %d", got, want)
}
- roaming <- rpc.NewRmAddrsSetting([]net.Addr{n1})
+ roaming <- NewRmAddrsSetting([]net.Addr{n1})
// We expect 2 changes, one for each usable listen spec addr.
change = waitForChange()
@@ -547,7 +546,7 @@
}
// Remove all addresses to mimic losing all connectivity.
- roaming <- rpc.NewRmAddrsSetting(getIPAddrs(nepsR))
+ roaming <- NewRmAddrsSetting(getIPAddrs(nepsR))
// We expect changes for all of the current endpoints
change = waitForChange()
@@ -560,7 +559,7 @@
t.Fatalf("got %d, want %d: %v", got, want, status.Mounts)
}
- roaming <- rpc.NewAddAddrsSetting([]net.Addr{n1})
+ roaming <- NewAddAddrsSetting([]net.Addr{n1})
// We expect 2 changes, one for each usable listen spec addr.
change = waitForChange()
if got, want := len(change.Changed), 2; got != want {
@@ -575,27 +574,25 @@
ns := tnaming.NewSimpleNamespace()
ctx, shutdown := initForTest()
defer shutdown()
- server, err := testInternalNewServer(ctx, sm, ns, testutil.NewPrincipal("test"))
- defer server.Stop()
- if err != nil {
- t.Fatal(err)
- }
-
- publisher := config.NewPublisher()
- roaming := make(chan config.Setting)
+ publisher := pubsub.NewPublisher()
+ roaming := make(chan pubsub.Setting)
stop, err := publisher.CreateStream("TestWatcherDeadlock", "TestWatcherDeadlock", roaming)
if err != nil {
t.Fatal(err)
}
defer func() { publisher.Shutdown(); <-stop }()
+ server, err := testInternalNewServerWithPubsub(ctx, sm, ns, publisher, "TestWatcherDeadlock", testutil.NewPrincipal("test"))
+ if err != nil {
+ t.Fatal(err)
+ }
+ defer server.Stop()
+
spec := rpc.ListenSpec{
Addrs: rpc.ListenAddrs{
{"tcp", ":0"},
},
- StreamName: "TestWatcherDeadlock",
- StreamPublisher: publisher,
}
eps, err := server.Listen(spec)
if err != nil {
@@ -614,12 +611,12 @@
defer close(watcher)
// Remove all addresses to mimic losing all connectivity.
- roaming <- rpc.NewRmAddrsSetting(getIPAddrs(eps))
+ roaming <- NewRmAddrsSetting(getIPAddrs(eps))
// Add in two new addresses
n1 := netstate.NewNetAddr("ip", "1.1.1.1")
n2 := netstate.NewNetAddr("ip", "2.2.2.2")
- roaming <- rpc.NewAddAddrsSetting([]net.Addr{n1, n2})
+ roaming <- NewAddAddrsSetting([]net.Addr{n1, n2})
neps := make([]naming.Endpoint, 0, len(eps))
for _, p := range getUniqPorts(eps) {
diff --git a/profiles/internal/rpc/stream/manager/listener.go b/profiles/internal/rpc/stream/manager/listener.go
index 298d20f..3824089 100644
--- a/profiles/internal/rpc/stream/manager/listener.go
+++ b/profiles/internal/rpc/stream/manager/listener.go
@@ -6,6 +6,7 @@
import (
"fmt"
+ "math/rand"
"net"
"strings"
"sync"
@@ -62,6 +63,9 @@
manager *manager
vifs *vif.Set
+ connsMu sync.Mutex
+ conns map[net.Conn]bool
+
netLoop sync.WaitGroup
vifLoops sync.WaitGroup
}
@@ -87,6 +91,7 @@
manager: m,
netLn: netLn,
vifs: vif.NewSet(),
+ conns: make(map[net.Conn]bool),
}
// Set the default idle timeout for VC. But for "unixfd", we do not set
@@ -114,6 +119,44 @@
return false
}
+func (ln *netListener) killConnections(n int) {
+ ln.connsMu.Lock()
+ if n > len(ln.conns) {
+ n = len(ln.conns)
+ }
+ remaining := make([]net.Conn, 0, len(ln.conns))
+ for c := range ln.conns {
+ remaining = append(remaining, c)
+ }
+ removed := remaining[:n]
+ ln.connsMu.Unlock()
+
+ vlog.Infof("Killing %d Conns", n)
+
+ var wg sync.WaitGroup
+ wg.Add(n)
+ for i := 0; i < n; i++ {
+ idx := rand.Intn(len(remaining))
+ conn := remaining[idx]
+ go func(conn net.Conn) {
+ vlog.Infof("Killing connection (%s, %s)", conn.LocalAddr(), conn.RemoteAddr())
+ conn.Close()
+ ln.manager.killedConns.Incr(1)
+ wg.Done()
+ }(conn)
+ remaining[idx], remaining[0] = remaining[0], remaining[idx]
+ remaining = remaining[1:]
+ }
+
+ ln.connsMu.Lock()
+ for _, conn := range removed {
+ delete(ln.conns, conn)
+ }
+ ln.connsMu.Unlock()
+
+ wg.Wait()
+}
+
func (ln *netListener) netAcceptLoop(principal security.Principal, blessings security.Blessings, opts []stream.ListenerOpt) {
defer ln.netLoop.Done()
opts = append([]stream.ListenerOpt{vc.StartTimeout{defaultStartTimeout}}, opts...)
@@ -126,7 +169,7 @@
vlog.Infof("net.Listener.Accept() failed on %v with %v", ln.netLn, err)
for tokill := 1; isTemporaryError(err); tokill *= 2 {
if isTooManyOpenFiles(err) {
- ln.manager.killConnections(tokill)
+ ln.killConnections(tokill)
} else {
tokill = 1
}
@@ -145,6 +188,10 @@
vlog.VI(1).Infof("Exiting netAcceptLoop: net.Listener.Accept() failed on %v with %v", ln.netLn, err)
return
}
+ ln.connsMu.Lock()
+ ln.conns[conn] = true
+ ln.connsMu.Unlock()
+
vlog.VI(1).Infof("New net.Conn accepted from %s (local address: %s)", conn.RemoteAddr(), conn.LocalAddr())
go func() {
vf, err := vif.InternalNewAcceptedVIF(conn, ln.manager.rid, principal, blessings, nil, ln.deleteVIF, opts...)
@@ -157,7 +204,12 @@
ln.manager.vifs.Insert(vf)
ln.vifLoops.Add(1)
- vifLoop(vf, ln.q, &ln.vifLoops)
+ vifLoop(vf, ln.q, func() {
+ ln.connsMu.Lock()
+ delete(ln.conns, conn)
+ ln.connsMu.Unlock()
+ ln.vifLoops.Done()
+ })
}()
}
}
@@ -226,7 +278,9 @@
}
ln.vif = vf
ln.vifLoop.Add(1)
- go vifLoop(ln.vif, ln.q, &ln.vifLoop)
+ go vifLoop(ln.vif, ln.q, func() {
+ ln.vifLoop.Done()
+ })
return ln, ep, nil
}
@@ -338,8 +392,8 @@
return fmt.Sprintf("stream.Listener: PROXY:%v RoutingID:%v", ln.proxyEP, ln.manager.rid)
}
-func vifLoop(vf *vif.VIF, q *upcqueue.T, wg *sync.WaitGroup) {
- defer wg.Done()
+func vifLoop(vf *vif.VIF, q *upcqueue.T, cleanup func()) {
+ defer cleanup()
for {
cAndf, err := vf.Accept()
switch {
diff --git a/profiles/internal/rpc/stream/manager/manager.go b/profiles/internal/rpc/stream/manager/manager.go
index 371f86a..5fb6232 100644
--- a/profiles/internal/rpc/stream/manager/manager.go
+++ b/profiles/internal/rpc/stream/manager/manager.go
@@ -7,7 +7,6 @@
import (
"fmt"
- "math/rand"
"net"
"strings"
"sync"
@@ -330,29 +329,6 @@
return strings.Join(l, "\n")
}
-func (m *manager) killConnections(n int) {
- vifs := m.vifs.List()
- if n > len(vifs) {
- n = len(vifs)
- }
- vlog.Infof("Killing %d VIFs", n)
- var wg sync.WaitGroup
- wg.Add(n)
- for i := 0; i < n; i++ {
- idx := rand.Intn(len(vifs))
- vf := vifs[idx]
- go func(vf *vif.VIF) {
- vlog.Infof("Killing VIF %v", vf)
- vf.Shutdown()
- m.killedConns.Incr(1)
- wg.Done()
- }(vf)
- vifs[idx], vifs[0] = vifs[0], vifs[idx]
- vifs = vifs[1:]
- }
- wg.Wait()
-}
-
func extractBlessingNames(p security.Principal, b security.Blessings) ([]string, error) {
if !b.IsZero() && p == nil {
return nil, verror.New(stream.ErrBadArg, nil, verror.New(errProvidedServerBlessingsWithoutPrincipal, nil))
diff --git a/profiles/internal/rpc/stream/manager/manager_test.go b/profiles/internal/rpc/stream/manager/manager_test.go
index e28f505..5ae22f3 100644
--- a/profiles/internal/rpc/stream/manager/manager_test.go
+++ b/profiles/internal/rpc/stream/manager/manager_test.go
@@ -918,8 +918,8 @@
if err := h.Shutdown(nil, &stderr); err != nil {
t.Fatal(err)
}
- if log := expect.NewSession(t, bytes.NewReader(stderr.Bytes()), time.Minute).ExpectSetEventuallyRE("manager.go.*Killing [1-9][0-9]* VIFs"); len(log) == 0 {
- t.Errorf("Failed to find log message talking about killing VIFs in:\n%v", stderr.String())
+ if log := expect.NewSession(t, bytes.NewReader(stderr.Bytes()), time.Minute).ExpectSetEventuallyRE("listener.go.*Killing [1-9][0-9]* Conns"); len(log) == 0 {
+ t.Errorf("Failed to find log message talking about killing Conns in:\n%v", stderr.String())
}
t.Logf("Server FD limit:%d", nfiles)
t.Logf("Client connection attempts: %d", nattempts)
diff --git a/profiles/internal/rpc/stream/vc/knobs.go b/profiles/internal/rpc/stream/vc/knobs.go
index c2bdf5b..7271f7a 100644
--- a/profiles/internal/rpc/stream/vc/knobs.go
+++ b/profiles/internal/rpc/stream/vc/knobs.go
@@ -25,10 +25,11 @@
// (and not any specific flow)
SharedFlowID = 0
- // Special flow used for handshaking between VCs (e.g. setting up encryption).
- HandshakeFlowID = 1
// Special flow used for authenticating between VCs.
AuthFlowID = 2
- // Special Flow ID used for interchanging of VOM types between VCs.
+ // Special flow used for interchanging of VOM types between VCs.
TypeFlowID = 3
+ // Special flow over which discharges for third-party caveats
+ // on the server's blessings are sent.
+ DischargeFlowID = 4
)
diff --git a/profiles/internal/rpc/stream/vc/vc.go b/profiles/internal/rpc/stream/vc/vc.go
index 5889cc6..7a8a567 100644
--- a/profiles/internal/rpc/stream/vc/vc.go
+++ b/profiles/internal/rpc/stream/vc/vc.go
@@ -54,17 +54,17 @@
errIgnoringMessageOnClosedVC = reg(".errIgnoringMessageOnClosedVC", "ignoring message for Flow {3} on closed VC {4}")
errVomTypeDecoder = reg(".errVomDecoder", "failed to create vom type decoder{:3}")
errVomTypeEncoder = reg(".errVomEncoder", "failed to create vom type encoder{:3}")
+ errFailedToCreateFlowForAuth = reg(".errFailedToCreateFlowForAuth", "failed to create a Flow for authentication{:3}")
+ errAuthFlowNotAccepted = reg(".errAuthFlowNotAccepted", "authentication Flow not accepted{:3}")
errFailedToCreateFlowForWireType = reg(".errFailedToCreateFlowForWireType", "fail to create a Flow for wire type{:3}")
errFlowForWireTypeNotAccepted = reg(".errFlowForWireTypeNotAccepted", "Flow for wire type not accepted{:3}")
- errFailedToCreateTLSFlow = reg(".errFailedToCreateTLSFlow", "failed to create a Flow for setting up TLS{3:}")
+ errFailedToCreateFlowForDischarge = reg(".errFailedToCreateFlowForDischarge", "fail to create a Flow for discharge{:3}")
+ errFlowForDischargeNotAccepted = reg(".errFlowForDischargesNotAccepted", "Flow for discharge not accepted{:3}")
errFailedToSetupEncryption = reg(".errFailedToSetupEncryption", "failed to setup channel encryption{:3}")
- errFailedToCreateFlowForAuth = reg(".errFailedToCreateFlowForAuth", "failed to create a Flow for authentication{:3}")
errAuthFailed = reg(".errAuthFailed", "authentication failed{:3}")
errNoActiveListener = reg(".errNoActiveListener", "no active listener on VCI {3}")
errFailedToCreateWriterForNewFlow = reg(".errFailedToCreateWriterForNewFlow", "failed to create writer for new flow({3}){:4}")
errFailedToEnqueueFlow = reg(".errFailedToEnqueueFlow", "failed to enqueue flow at listener{:3}")
- errTLSFlowNotAccepted = reg(".errTLSFlowNotAccepted", "TLS handshake Flow not accepted{:3}")
- errAuthFlowNotAccepted = reg(".errAuthFlowNotAccepted", "authentication Flow not accepted{:3}")
errFailedToAcceptSystemFlows = reg(".errFailedToAcceptSystemFlows", "failed to accept system flows{:3}")
)
@@ -306,10 +306,9 @@
payload.Release()
return verror.New(stream.ErrNetwork, nil, verror.New(errIgnoringMessageOnClosedVC, nil, fid, vc.VCI()))
}
- // TLS decryption is stateful, so even if the message will be discarded
- // because of other checks further down in this method, go through with
- // the decryption.
- if fid != HandshakeFlowID && fid != AuthFlowID {
+ // Authentication is done by encrypting/decrypting its payload by itself,
+ // so we do not go through with the decryption for auth flow.
+ if fid != AuthFlowID {
vc.waitForHandshakeLocked()
var err error
if payload, err = vc.crypter.Decrypt(payload); err != nil {
@@ -531,14 +530,6 @@
vers := vc.Version()
// Authenticate (exchange identities)
- // Unfortunately, handshakeConn cannot be used for the authentication protocol.
- // This is because the Crypter implementation uses crypto/tls.Conn,
- // which can consume data beyond the handshake message boundaries (call
- // to readFromUntil in
- // https://code.google.com/p/go/source/browse/src/pkg/crypto/tls/conn.go?spec=svn654b2703fcc466a29692068ab56efedd09fb3d05&r=654b2703fcc466a29692068ab56efedd09fb3d05#539).
- // This is not a problem when tls.Conn is used as intended (to wrap over a stream), but
- // becomes a problem when shoehorning a block encrypter (Crypter interface) over this
- // stream API.
authConn, err := vc.connectFID(AuthFlowID, systemFlowPriority)
if err != nil {
return vc.appendCloseReason(verror.New(stream.ErrSecurity, nil, verror.New(errFailedToCreateFlowForAuth, nil, err)))
@@ -555,7 +546,7 @@
if err != nil {
return vc.appendCloseReason(err)
}
- } else {
+ } else if vers < version.RPCVersion10 {
go vc.recvDischargesLoop(authConn)
}
@@ -689,14 +680,14 @@
vc.acceptHandshakeDone = nil
vc.mu.Unlock()
- if len(lBlessings.ThirdPartyCaveats()) > 0 {
+ if len(lBlessings.ThirdPartyCaveats()) > 0 && vers < version.RPCVersion10 {
go vc.sendDischargesLoop(authConn, dischargeClient, lBlessings.ThirdPartyCaveats(), dischargeExpiryBuffer)
} else {
authConn.Close()
}
// Accept system flows.
- if err = vc.acceptSystemFlows(ln); err != nil {
+ if err = vc.acceptSystemFlows(ln, dischargeClient, dischargeExpiryBuffer); err != nil {
sendErr(verror.New(stream.ErrNetwork, nil, verror.New(errFailedToAcceptSystemFlows, nil, err)))
}
@@ -808,26 +799,59 @@
return verror.New(stream.ErrSecurity, nil, verror.New(errVomTypeDecoder, nil, err))
}
vc.dataCache.Insert(TypeDecoderKey{}, typeDec)
+
+ if vc.Version() < version.RPCVersion10 {
+ return nil
+ }
+
+ vc.mu.Lock()
+ rBlessings := vc.remoteBlessings
+ vc.mu.Unlock()
+ if len(rBlessings.ThirdPartyCaveats()) > 0 {
+ conn, err = vc.connectFID(DischargeFlowID, systemFlowPriority)
+ if err != nil {
+ return verror.New(stream.ErrSecurity, nil, verror.New(errFailedToCreateFlowForDischarge, nil, err))
+ }
+ go vc.recvDischargesLoop(conn)
+ }
+
return nil
}
-func (vc *VC) acceptSystemFlows(ln stream.Listener) error {
+func (vc *VC) acceptSystemFlows(ln stream.Listener, dischargeClient DischargeClient, dischargeExpiryBuffer time.Duration) error {
conn, err := ln.Accept()
if err != nil {
return verror.New(errFlowForWireTypeNotAccepted, nil, err)
}
- typeDec, err := vom.NewTypeDecoder(conn)
- if err != nil {
- conn.Close()
- return verror.New(errVomTypeDecoder, nil, err)
- }
- vc.dataCache.Insert(TypeDecoderKey{}, typeDec)
typeEnc, err := vom.NewTypeEncoder(conn)
if err != nil {
conn.Close()
return verror.New(errVomTypeEncoder, nil, err)
}
vc.dataCache.Insert(TypeEncoderKey{}, typeEnc)
+ typeDec, err := vom.NewTypeDecoder(conn)
+ if err != nil {
+ conn.Close()
+ return verror.New(errVomTypeDecoder, nil, err)
+ }
+ vc.dataCache.Insert(TypeDecoderKey{}, typeDec)
+
+ if vc.Version() < version.RPCVersion10 {
+ return nil
+ }
+
+ vc.mu.Lock()
+ lBlessings := vc.localBlessings
+ vc.mu.Unlock()
+ tpCaveats := lBlessings.ThirdPartyCaveats()
+ if len(tpCaveats) > 0 {
+ conn, err := ln.Accept()
+ if err != nil {
+ return verror.New(errFlowForDischargeNotAccepted, nil, err)
+ }
+ go vc.sendDischargesLoop(conn, dischargeClient, tpCaveats, dischargeExpiryBuffer)
+ }
+
return nil
}
@@ -838,7 +862,7 @@
return nil, nil
}
vc.mu.Lock()
- if fid == HandshakeFlowID || fid == AuthFlowID {
+ if fid == AuthFlowID {
cipherslice = plaintext
} else {
cipherslice, err = vc.crypter.Encrypt(plaintext)
diff --git a/profiles/internal/rpc/stream/vif/vif.go b/profiles/internal/rpc/stream/vif/vif.go
index d20b63e..2342ddd 100644
--- a/profiles/internal/rpc/stream/vif/vif.go
+++ b/profiles/internal/rpc/stream/vif/vif.go
@@ -412,12 +412,6 @@
}
}
-// Shutdown terminates the underlying network connection (any pending reads and
-// writes of flows/VCs over it will be discarded).
-func (vif *VIF) Shutdown() {
- vif.conn.Close()
-}
-
// StartAccepting begins accepting Flows (and VCs) initiated by the remote end
// of a VIF. opts is used to setup the listener on newly established VCs.
func (vif *VIF) StartAccepting(opts ...stream.ListenerOpt) error {
diff --git a/profiles/internal/rpc/test/client_test.go b/profiles/internal/rpc/test/client_test.go
index cb2f6f4..99bf7c2 100644
--- a/profiles/internal/rpc/test/client_test.go
+++ b/profiles/internal/rpc/test/client_test.go
@@ -874,7 +874,7 @@
}
verr := call.Finish()
if verror.ErrorID(verr) != verror.ErrUnknownMethod.ID {
- t.Fatalf("wrong error: %s", verr)
+ t.Errorf("wrong error: %s", verr)
}
logErr("unknown method", verr)
@@ -885,39 +885,49 @@
}
verr = call.Finish()
if verror.ErrorID(verr) != verror.ErrUnknownSuffix.ID {
- t.Fatalf("wrong error: %s", verr)
+ t.Errorf("wrong error: %s", verr)
}
logErr("unknown suffix", verr)
// Too many args.
call, err = clt.StartCall(ctx, name, "Ping", []interface{}{1, 2})
if err != nil {
- t.Fatal(err)
+ // We check for "failed to encode arg" here because sometimes the server detects the
+ // mismatched number of arguments, sends an error response, and closes the connection,
+ // before the client gets through encoding the args. In this case the flow is closed and
+ // encoding of args fails, preventing the client from calling call.Finish, and seeing
+ // the error in the response. In the normal case network time dominates, so this case
+ // will very rarely get hit, but since the client and server in this test are in the
+ // same process we see this race quite a bit.
+ if got, want := err.Error(), "failed to encode arg"; !strings.Contains(got, want) {
+ t.Errorf("want %q to contain %q", got, want)
+ }
+ logErr("too many args", err)
+ } else {
+ r1 := ""
+ verr = call.Finish(&r1)
+ if verror.ErrorID(verr) != verror.ErrBadProtocol.ID {
+ t.Errorf("wrong error: %s", verr)
+ }
+ if got, want := verr.Error(), "wrong number of input arguments"; !strings.Contains(got, want) {
+ t.Errorf("want %q to contain %q", got, want)
+ }
+ logErr("too many args", verr)
}
- r1 := ""
- verr = call.Finish(&r1)
- if verror.ErrorID(verr) != verror.ErrBadProtocol.ID {
- t.Fatalf("wrong error: %s", verr)
- }
- if got, want := verr.Error(), "wrong number of input arguments"; !strings.Contains(got, want) {
- t.Fatalf("want %q to contain %q", got, want)
- }
- logErr("wrong # args", verr)
-
// Too many results.
call, err = clt.StartCall(ctx, name, "Ping", nil)
if err != nil {
t.Fatal(err)
}
- r2 := ""
+ r1, r2 := "", ""
verr = call.Finish(&r1, &r2)
if verror.ErrorID(verr) != verror.ErrBadProtocol.ID {
- t.Fatalf("wrong error: %s", verr)
+ t.Errorf("wrong error: %s", verr)
}
if got, want := verr.Error(), "results, but want"; !strings.Contains(got, want) {
- t.Fatalf("want %q to contain %q", got, want)
+ t.Errorf("want %q to contain %q", got, want)
}
logErr("wrong # results", verr)
@@ -929,10 +939,10 @@
verr = call.Finish(&r2)
if verror.ErrorID(verr) != verror.ErrBadProtocol.ID {
- t.Fatalf("wrong error: %s", verr)
+ t.Errorf("wrong error: %s", verr)
}
if got, want := verr.Error(), "aren't compatible"; !strings.Contains(got, want) {
- t.Fatalf("want %q to contain %q", got, want)
+ t.Errorf("want %q to contain %q", got, want)
}
logErr("wrong arg types", verr)
@@ -945,10 +955,10 @@
r3 := 2
verr = call.Finish(&r3)
if verror.ErrorID(verr) != verror.ErrBadProtocol.ID {
- t.Fatalf("wrong error: %s", verr)
+ t.Errorf("wrong error: %s", verr)
}
if got, want := verr.Error(), "aren't compatible"; !strings.Contains(got, want) {
- t.Fatalf("want %q to contain %q", got, want)
+ t.Errorf("want %q to contain %q", got, want)
}
logErr("wrong result types", verr)
}
diff --git a/profiles/internal/rpc/test/proxy_test.go b/profiles/internal/rpc/test/proxy_test.go
index bd326f5..e6bd616 100644
--- a/profiles/internal/rpc/test/proxy_test.go
+++ b/profiles/internal/rpc/test/proxy_test.go
@@ -191,7 +191,7 @@
}
defer client.Close()
serverCtx, _ := v23.WithPrincipal(ctx, pserver)
- server, err := irpc.InternalNewServer(serverCtx, smserver, ns, nil, pserver)
+ server, err := irpc.InternalNewServer(serverCtx, smserver, ns, nil, "", nil, pserver)
if err != nil {
t.Fatal(err)
}
diff --git a/profiles/internal/rpc/version/version.go b/profiles/internal/rpc/version/version.go
index 2d3119d..c23913b 100644
--- a/profiles/internal/rpc/version/version.go
+++ b/profiles/internal/rpc/version/version.go
@@ -21,7 +21,7 @@
// change that's not both forward and backward compatible.
// Min should be incremented whenever we want to remove
// support for old protocol versions.
- SupportedRange = &Range{Min: version.RPCVersion9, Max: version.RPCVersion9}
+ SupportedRange = &Range{Min: version.RPCVersion9, Max: version.RPCVersion10}
)
const pkgPath = "v.io/x/ref/profiles/internal/rpc/version"
diff --git a/profiles/internal/rt/ipc_test.go b/profiles/internal/rt/ipc_test.go
index 10dae1f..138826f 100644
--- a/profiles/internal/rt/ipc_test.go
+++ b/profiles/internal/rt/ipc_test.go
@@ -265,7 +265,7 @@
ds.mu.Unlock()
caveat := security.UnconstrainedUse()
if called == 0 {
- caveat = mkCaveat(security.ExpiryCaveat(time.Now().Add(-1 * time.Second)))
+ caveat = mkCaveat(security.NewExpiryCaveat(time.Now().Add(-1 * time.Second)))
}
return call.Security().LocalPrincipal().MintDischarge(cav, caveat)
@@ -363,7 +363,7 @@
t.Fatal(err)
}
- rootServerInvalidTPCaveat := mkBlessings(root.NewBlessings(pserver, "server", mkThirdPartyCaveat(pdischarger.PublicKey(), dischargeServerName, mkCaveat(security.ExpiryCaveat(time.Now().Add(-1*time.Second))))))
+ rootServerInvalidTPCaveat := mkBlessings(root.NewBlessings(pserver, "server", mkThirdPartyCaveat(pdischarger.PublicKey(), dischargeServerName, mkCaveat(security.NewExpiryCaveat(time.Now().Add(-1*time.Second))))))
if err := pserver.BlessingStore().SetDefault(rootServerInvalidTPCaveat); err != nil {
t.Fatal(err)
}
diff --git a/profiles/internal/rt/runtime.go b/profiles/internal/rt/runtime.go
index f0ec69f..bc9c3af 100644
--- a/profiles/internal/rt/runtime.go
+++ b/profiles/internal/rt/runtime.go
@@ -13,6 +13,8 @@
"syscall"
"time"
+ "v.io/x/lib/pubsub"
+
"v.io/v23"
"v.io/v23/context"
"v.io/v23/i18n"
@@ -52,9 +54,11 @@
)
type initData struct {
- appCycle v23.AppCycle
- listenSpec *rpc.ListenSpec
- protocols []string
+ appCycle v23.AppCycle
+ listenSpec *rpc.ListenSpec
+ protocols []string
+ settingsPublisher *pubsub.Publisher
+ settingsName string
}
type vtraceDependency struct{}
@@ -71,14 +75,18 @@
appCycle v23.AppCycle,
protocols []string,
listenSpec *rpc.ListenSpec,
+ settingsPublisher *pubsub.Publisher,
+ settingsName string,
flags flags.RuntimeFlags,
reservedDispatcher rpc.Dispatcher) (*Runtime, *context.T, v23.Shutdown, error) {
r := &Runtime{deps: dependency.NewGraph()}
ctx = context.WithValue(ctx, initKey, &initData{
- protocols: protocols,
- listenSpec: listenSpec,
- appCycle: appCycle,
+ protocols: protocols,
+ listenSpec: listenSpec,
+ appCycle: appCycle,
+ settingsPublisher: settingsPublisher,
+ settingsName: settingsName,
})
if reservedDispatcher != nil {
@@ -236,7 +244,7 @@
Blessings: principal.BlessingStore().Default(),
})
}
- server, err := irpc.InternalNewServer(ctx, sm, ns, r.GetClient(ctx), principal, otherOpts...)
+ server, err := irpc.InternalNewServer(ctx, sm, ns, id.settingsPublisher, id.settingsName, r.GetClient(ctx), principal, otherOpts...)
if err != nil {
return nil, err
}
diff --git a/profiles/internal/rt/runtime_test.go b/profiles/internal/rt/runtime_test.go
index cf6706d..f4cded9 100644
--- a/profiles/internal/rt/runtime_test.go
+++ b/profiles/internal/rt/runtime_test.go
@@ -20,7 +20,7 @@
// InitForTest creates a context for use in a test.
func InitForTest(t *testing.T) (*rt.Runtime, *context.T, v23.Shutdown) {
ctx, cancel := context.RootContext()
- r, ctx, shutdown, err := rt.Init(ctx, nil, nil, nil, flags.RuntimeFlags{}, nil)
+ r, ctx, shutdown, err := rt.Init(ctx, nil, nil, nil, nil, "", flags.RuntimeFlags{}, nil)
if err != nil {
t.Fatal(err)
}
diff --git a/profiles/roaming/.api b/profiles/roaming/.api
new file mode 100644
index 0000000..c15af37
--- /dev/null
+++ b/profiles/roaming/.api
@@ -0,0 +1,4 @@
+pkg roaming, const SettingsStreamDesc ideal-string
+pkg roaming, const SettingsStreamName ideal-string
+pkg roaming, func Init(*context.T) (v23.Runtime, *context.T, v23.Shutdown, error)
+pkg roaming, func NewProxy(*context.T, rpc.ListenSpec, ...string) (func(), naming.Endpoint, error)
diff --git a/profiles/roaming/roaminginit.go b/profiles/roaming/roaminginit.go
index 4996320..c6b37f6 100644
--- a/profiles/roaming/roaminginit.go
+++ b/profiles/roaming/roaminginit.go
@@ -8,7 +8,7 @@
// configurations, including 1-1 NATs, dhcp auto-configuration, and Google
// Compute Engine.
//
-// The config.Publisher mechanism is used for communicating networking
+// The pubsub.Publisher mechanism is used for communicating networking
// settings to the rpc.Server implementation of the runtime and publishes
// the Settings it expects.
package roaming
@@ -19,10 +19,10 @@
"v.io/x/lib/netconfig"
"v.io/x/lib/netstate"
+ "v.io/x/lib/pubsub"
"v.io/x/lib/vlog"
"v.io/v23"
- "v.io/v23/config"
"v.io/v23/context"
"v.io/v23/rpc"
@@ -31,6 +31,7 @@
"v.io/x/ref/profiles/internal"
"v.io/x/ref/profiles/internal/lib/appcycle"
"v.io/x/ref/profiles/internal/lib/websocket"
+ irpc "v.io/x/ref/profiles/internal/rpc"
_ "v.io/x/ref/profiles/internal/rpc/protocols/tcp"
_ "v.io/x/ref/profiles/internal/rpc/protocols/ws"
_ "v.io/x/ref/profiles/internal/rpc/protocols/wsh"
@@ -40,6 +41,7 @@
const (
SettingsStreamName = "roaming"
+ SettingsStreamDesc = "pubsub stream used by the roaming profile"
)
var commonFlags *flags.Flags
@@ -74,7 +76,7 @@
// flag to configure both the protocol and address.
return []net.Addr{netstate.NewNetAddr("wsh", addr.String())}, nil
}
- runtime, ctx, shutdown, err := rt.Init(ctx, ac, nil, &listenSpec, commonFlags.RuntimeFlags(), reservedDispatcher)
+ runtime, ctx, shutdown, err := rt.Init(ctx, ac, nil, &listenSpec, nil, "", commonFlags.RuntimeFlags(), reservedDispatcher)
if err != nil {
return nil, nil, shutdown, err
}
@@ -86,12 +88,13 @@
}
}
- publisher := config.NewPublisher()
+ publisher := pubsub.NewPublisher()
// Create stream in Init function to avoid a race between any
// goroutines started here and consumers started after Init returns.
- ch := make(chan config.Setting)
- stop, err := publisher.CreateStream(SettingsStreamName, SettingsStreamName, ch)
+ ch := make(chan pubsub.Setting)
+ // TODO(cnicolaou): use stop to shutdown this stream when the profile shutdowns.
+ stop, err := publisher.CreateStream(SettingsStreamName, SettingsStreamDesc, ch)
if err != nil {
ac.Shutdown()
return nil, nil, nil, err
@@ -113,11 +116,9 @@
cleanupCh := make(chan struct{})
watcherCh := make(chan struct{})
- listenSpec.StreamPublisher = publisher
- listenSpec.StreamName = SettingsStreamName
listenSpec.AddressChooser = internal.IPAddressChooser
- runtime, ctx, shutdown, err := rt.Init(ctx, ac, nil, &listenSpec, commonFlags.RuntimeFlags(), reservedDispatcher)
+ runtime, ctx, shutdown, err := rt.Init(ctx, ac, nil, &listenSpec, publisher, SettingsStreamName, commonFlags.RuntimeFlags(), reservedDispatcher)
if err != nil {
return nil, nil, shutdown, err
}
@@ -141,7 +142,7 @@
prev netstate.AddrList,
pubStop, cleanup <-chan struct{},
watcherLoop chan<- struct{},
- ch chan<- config.Setting) {
+ ch chan<- pubsub.Setting) {
defer close(ch)
listenSpec := runtime.GetListenSpec(ctx)
@@ -170,12 +171,12 @@
}
if len(removed) > 0 {
vlog.VI(2).Infof("Sending removed: %s", removed)
- ch <- rpc.NewRmAddrsSetting(removed.AsNetAddrs())
+ ch <- irpc.NewRmAddrsSetting(removed.AsNetAddrs())
}
// We will always send the best currently available address
if chosen, err := listenSpec.AddressChooser(listenSpec.Addrs[0].Protocol, cur.AsNetAddrs()); err == nil && chosen != nil {
vlog.VI(2).Infof("Sending added and chosen: %s", chosen)
- ch <- rpc.NewAddAddrsSetting(chosen)
+ ch <- irpc.NewAddAddrsSetting(chosen)
} else {
vlog.VI(2).Infof("Ignoring added %s", added)
}
diff --git a/profiles/static/.api b/profiles/static/.api
new file mode 100644
index 0000000..2d3ebb3
--- /dev/null
+++ b/profiles/static/.api
@@ -0,0 +1,2 @@
+pkg static, func Init(*context.T) (v23.Runtime, *context.T, v23.Shutdown, error)
+pkg static, func NewProxy(*context.T, rpc.ListenSpec, ...string) (func(), naming.Endpoint, error)
diff --git a/profiles/static/staticinit.go b/profiles/static/staticinit.go
index 339e32a..dc93eae 100644
--- a/profiles/static/staticinit.go
+++ b/profiles/static/staticinit.go
@@ -57,7 +57,7 @@
listenSpec.AddressChooser = func(string, []net.Addr) ([]net.Addr, error) {
return []net.Addr{addr}, nil
}
- runtime, ctx, shutdown, err := rt.Init(ctx, ac, nil, &listenSpec, commonFlags.RuntimeFlags(), reservedDispatcher)
+ runtime, ctx, shutdown, err := rt.Init(ctx, ac, nil, &listenSpec, nil, "", commonFlags.RuntimeFlags(), reservedDispatcher)
if err != nil {
return nil, nil, nil, err
}
@@ -70,7 +70,7 @@
}
listenSpec.AddressChooser = internal.IPAddressChooser
- runtime, ctx, shutdown, err := rt.Init(ctx, ac, nil, &listenSpec, commonFlags.RuntimeFlags(), reservedDispatcher)
+ runtime, ctx, shutdown, err := rt.Init(ctx, ac, nil, &listenSpec, nil, "", commonFlags.RuntimeFlags(), reservedDispatcher)
if err != nil {
return nil, nil, shutdown, err
}
diff --git a/services/agent/internal/test_principal/main.go b/services/agent/internal/test_principal/main.go
index 5d7a29a..1f27580 100644
--- a/services/agent/internal/test_principal/main.go
+++ b/services/agent/internal/test_principal/main.go
@@ -83,7 +83,7 @@
errorf("signature.Verify: %v", err)
}
// MintDischarge
- cav, err := security.MethodCaveat("method")
+ cav, err := security.NewMethodCaveat("method")
if err != nil {
errorf("security.MethodCaveat: %v", err)
}
diff --git a/services/device/device/doc.go b/services/device/device/doc.go
index cd1ba14..53c9a17 100644
--- a/services/device/device/doc.go
+++ b/services/device/device/doc.go
@@ -41,6 +41,9 @@
-alsologtostderr=true
log to standard error as well as files
+ -chown=false
+ Change owner of files and directories given as command-line arguments to the
+ user specified by this flag
-dryrun=false
Elides root-requiring systemcalls.
-kill=false
diff --git a/services/device/deviced/doc.go b/services/device/deviced/doc.go
index 567ed5c..3468792 100644
--- a/services/device/deviced/doc.go
+++ b/services/device/deviced/doc.go
@@ -43,6 +43,9 @@
-alsologtostderr=true
log to standard error as well as files
+ -chown=false
+ Change owner of files and directories given as command-line arguments to the
+ user specified by this flag
-dryrun=false
Elides root-requiring systemcalls.
-kill=false
diff --git a/services/device/internal/impl/app_service.go b/services/device/internal/impl/app_service.go
index 3f2b49d..066b667 100644
--- a/services/device/internal/impl/app_service.go
+++ b/services/device/internal/impl/app_service.go
@@ -766,6 +766,7 @@
saArgs.workspace = rootDir
logDir := filepath.Join(instanceDir, "logs")
+ suidHelper.chownTree(suidHelper.getCurrentUser(), instanceDir, os.Stdout, os.Stdin)
if err := mkdirPerm(logDir, 0755); err != nil {
return nil, err
}
diff --git a/services/device/internal/impl/helper_manager.go b/services/device/internal/impl/helper_manager.go
index f4369eb..280db2b 100644
--- a/services/device/internal/impl/helper_manager.go
+++ b/services/device/internal/impl/helper_manager.go
@@ -40,6 +40,10 @@
}
}
+func (s suidHelperState) getCurrentUser() string {
+ return s.dmUser
+}
+
// terminatePid sends a SIGKILL to the target pid
func (s suidHelperState) terminatePid(pid int, stdout, stderr io.Writer) error {
if err := s.internalModalOp(stdout, stderr, "--kill", strconv.Itoa(pid)); err != nil {
@@ -56,6 +60,16 @@
return nil
}
+// chown files or directories
+func (s suidHelperState) chownTree(username string, dirOrFile string, stdout, stderr io.Writer) error {
+ args := []string{"--chown", "--username", username, dirOrFile}
+
+ if err := s.internalModalOp(stdout, stderr, args...); err != nil {
+ return fmt.Errorf("devicemanager's invocation of suidhelper chown %v failed: %v", dirOrFile, err)
+ }
+ return nil
+}
+
type suidAppCmdArgs struct {
// args to helper
targetUser, progname, workspace, logdir, binpath string
@@ -116,6 +130,7 @@
if err := cmd.Run(); err != nil {
vlog.Errorf("failed calling helper with args (%v):%v", arg, err)
+ return err
}
return nil
}
diff --git a/services/device/internal/suid/args.go b/services/device/internal/suid/args.go
index 10ccfac..1473654 100644
--- a/services/device/internal/suid/args.go
+++ b/services/device/internal/suid/args.go
@@ -8,6 +8,7 @@
"bytes"
"encoding/json"
"flag"
+ "fmt"
"os"
"os/user"
"strconv"
@@ -38,6 +39,7 @@
envv []string
dryrun bool
remove bool
+ chown bool
kill bool
killPids []int
}
@@ -54,7 +56,7 @@
var (
flagUsername, flagWorkspace, flagLogDir, flagRun, flagProgName *string
flagMinimumUid *int64
- flagRemove, flagKill, flagDryrun *bool
+ flagRemove, flagKill, flagChown, flagDryrun *bool
)
func init() {
@@ -71,6 +73,7 @@
flagMinimumUid = fs.Int64("minuid", uidThreshold, "UIDs cannot be less than this number.")
flagRemove = fs.Bool("rm", false, "Remove the file trees given as command-line arguments.")
flagKill = fs.Bool("kill", false, "Kill process ids given as command-line arguments.")
+ flagChown = fs.Bool("chown", false, "Change owner of files and directories given as command-line arguments to the user specified by this flag")
flagDryrun = fs.Bool("dryrun", false, "Elides root-requiring systemcalls.")
}
@@ -84,29 +87,62 @@
return nenv
}
+// checkFlagCombinations makes sure that a valid combination of flags has been
+// specified for rm/kill/chown
+//
+// --rm and --kill are modal. Complain if any other flag is set along with one of
+// those. --chown allows specification of --username, --dryrun, and --minuid,
+// but nothing else
+func checkFlagCombinations(fs *flag.FlagSet) error {
+ if !(*flagRemove || *flagKill || *flagChown) {
+ return nil
+ }
+
+ // Count flags that are set. The device manager test always sets --minuid=1
+ // and --test.run=TestSuidHelper so when in a test, tolerate those.
+ flagsToIgnore := map[string]string{}
+ if os.Getenv("V23_SUIDHELPER_TEST") != "" {
+ flagsToIgnore["minuid"] = "1"
+ flagsToIgnore["test.run"] = "TestSuidHelper"
+ }
+ if *flagChown {
+ // Allow all values of --username, --dryrun, and --minuid
+ flagsToIgnore["username"] = "*"
+ flagsToIgnore["dryrun"] = "*"
+ flagsToIgnore["minuid"] = "*"
+ }
+
+ counter := 0
+ fs.Visit(func(f *flag.Flag) {
+ if flagsToIgnore[f.Name] != f.Value.String() && flagsToIgnore[f.Name] != "*" {
+ counter++
+ }
+ })
+
+ if counter > 1 {
+ return verror.New(errInvalidFlags, nil, counter, "--rm and --kill cannot be used with any other flag. --chown can only be used with --username, --dryrun, and --minuid")
+ }
+ return nil
+}
+
+// warnMissingSuidPrivs makes it a little easier to debug when suid privs are required but
+// are not present. It's not a comprehensive check -- e.g. we may be running as user
+// <username> and suppress the warning, but still fail to chown a file owned by some other user.
+func warnMissingSuidPrivs(uid int) {
+ osUid, osEuid := os.Getuid(), os.Geteuid()
+ if osUid == 0 || osEuid == 0 || osUid == uid || osEuid == uid {
+ return
+ }
+
+ fmt.Fprintln(os.Stderr, "uid is ", os.Getuid(), ", effective uid is ", os.Geteuid())
+ fmt.Fprintln(os.Stderr, "WARNING: suidhelper is not root. Is your filesystem mounted with nosuid?")
+}
+
// ParseArguments populates the WorkParameter object from the provided args
// and env strings.
func (wp *WorkParameters) ProcessArguments(fs *flag.FlagSet, env []string) error {
- // --rm and --kill are modal. Complain if any other flag is set along with one of those.
- if *flagRemove || *flagKill {
- // Count flags that are set. The device manager test always sets --minuid=1
- // and --test.run=TestSuidHelper so when in a test, tolerate those
- flagsToIgnore := map[string]string{}
- if os.Getenv("V23_SUIDHELPER_TEST") != "" {
- flagsToIgnore["minuid"] = "1"
- flagsToIgnore["test.run"] = "TestSuidHelper"
- }
-
- counter := 0
- fs.Visit(func(f *flag.Flag) {
- if flagsToIgnore[f.Name] != f.Value.String() {
- counter++
- }
- })
-
- if counter > 1 {
- return verror.New(errInvalidFlags, nil, counter, "--rm and --kill cannot be used with any other flag")
- }
+ if err := checkFlagCombinations(fs); err != nil {
+ return err
}
if *flagRemove {
@@ -146,15 +182,25 @@
if err != nil {
return verror.New(errInvalidGID, nil, usr.Gid)
}
+ warnMissingSuidPrivs(int(uid))
// Uids less than 501 can be special so we forbid running as them.
if uid < *flagMinimumUid {
return verror.New(errUIDTooLow, nil,
uid, *flagMinimumUid)
}
+ wp.uid = int(uid)
+ wp.gid = int(gid)
wp.dryrun = *flagDryrun
+ // At this point, all flags allowed by --chown have been processed
+ if *flagChown {
+ wp.chown = true
+ wp.argv = fs.Args()
+ return nil
+ }
+
// Preserve the arguments for examination by the test harness if executed
// in the course of a test.
if os.Getenv("V23_SUIDHELPER_TEST") != "" {
@@ -171,8 +217,6 @@
wp.dryrun = true
}
- wp.uid = int(uid)
- wp.gid = int(gid)
wp.workspace = *flagWorkspace
wp.argv0 = *flagRun
wp.logDir = *flagLogDir
diff --git a/services/device/internal/suid/args_test.go b/services/device/internal/suid/args_test.go
index 092c1ab..491a171 100644
--- a/services/device/internal/suid/args_test.go
+++ b/services/device/internal/suid/args_test.go
@@ -41,6 +41,7 @@
envv: []string{"A=B"},
dryrun: false,
remove: false,
+ chown: false,
kill: false,
killPids: nil,
},
@@ -61,6 +62,7 @@
envv: []string{"A=B"},
dryrun: false,
remove: false,
+ chown: false,
kill: false,
killPids: nil,
},
@@ -87,6 +89,27 @@
envv: nil,
dryrun: false,
remove: true,
+ chown: false,
+ kill: false,
+ killPids: nil,
+ },
+ },
+
+ {
+ []string{"setuidhelper", "--chown", "--username", testUserName, "--dryrun", "--minuid", "1", "/tmp/foo", "/tmp/bar"},
+ []string{"A=B"},
+ "",
+ WorkParameters{
+ uid: testUid,
+ gid: testGid,
+ workspace: "",
+ logDir: "",
+ argv0: "",
+ argv: []string{"/tmp/foo", "/tmp/bar"},
+ envv: nil,
+ dryrun: true,
+ remove: false,
+ chown: true,
kill: false,
killPids: nil,
},
@@ -106,6 +129,7 @@
envv: nil,
dryrun: false,
remove: false,
+ chown: false,
kill: true,
killPids: []int{235, 451},
},
@@ -125,6 +149,7 @@
envv: nil,
dryrun: false,
remove: false,
+ chown: false,
kill: true,
killPids: nil,
},
@@ -145,6 +170,7 @@
envv: []string{"A=B"},
dryrun: true,
remove: false,
+ chown: false,
kill: false,
killPids: nil,
},
diff --git a/services/device/internal/suid/system.go b/services/device/internal/suid/system.go
index 6aad84b..285c4e3 100644
--- a/services/device/internal/suid/system.go
+++ b/services/device/internal/suid/system.go
@@ -39,8 +39,15 @@
return os.Chown(path, hw.uid, hw.gid)
}
- for _, p := range []string{hw.workspace, hw.logDir} {
+ chownPaths := hw.argv
+ if !hw.chown {
+ // Chown was invoked as part of regular suid execution, rather than directly
+ // via --chown. In that case, we chown the workspace and log directory
// TODO(rjkroege): Ensure that the device manager can read log entries.
+ chownPaths = []string{hw.workspace, hw.logDir}
+ }
+
+ for _, p := range chownPaths {
if err := filepath.Walk(p, chown); err != nil {
return verror.New(errChownFailed, nil, p, hw.uid, hw.gid, err)
}
diff --git a/services/identity/internal/auditor/blessing_auditor_test.go b/services/identity/internal/auditor/blessing_auditor_test.go
index 5813382..eb7a4a6 100644
--- a/services/identity/internal/auditor/blessing_auditor_test.go
+++ b/services/identity/internal/auditor/blessing_auditor_test.go
@@ -21,7 +21,7 @@
if err != nil {
t.Fatalf("failed to create principal: %v", err)
}
- expiryCaveat := newCaveat(security.ExpiryCaveat(time.Now().Add(time.Hour)))
+ expiryCaveat := newCaveat(security.NewExpiryCaveat(time.Now().Add(time.Hour)))
revocationCaveat := newThirdPartyCaveat(t, p)
tests := []struct {
@@ -91,7 +91,7 @@
}
func newThirdPartyCaveat(t *testing.T, p security.Principal) security.Caveat {
- tp, err := security.NewPublicKeyCaveat(p.PublicKey(), "location", security.ThirdPartyRequirements{}, newCaveat(security.MethodCaveat("method")))
+ tp, err := security.NewPublicKeyCaveat(p.PublicKey(), "location", security.ThirdPartyRequirements{}, newCaveat(security.NewMethodCaveat("method")))
if err != nil {
t.Fatal(err)
}
diff --git a/services/identity/internal/blesser/macaroon_test.go b/services/identity/internal/blesser/macaroon_test.go
index f2dcca0..95ebbd1 100644
--- a/services/identity/internal/blesser/macaroon_test.go
+++ b/services/identity/internal/blesser/macaroon_test.go
@@ -22,7 +22,7 @@
var (
key = make([]byte, 16)
provider, user = testutil.NewPrincipal(), testutil.NewPrincipal()
- cOnlyMethodFoo = newCaveat(security.MethodCaveat("Foo"))
+ cOnlyMethodFoo = newCaveat(security.NewMethodCaveat("Foo"))
ctx, call = fakeContextAndCall(provider, user)
)
if _, err := rand.Read(key); err != nil {
diff --git a/services/identity/internal/blesser/oauth.go b/services/identity/internal/blesser/oauth.go
index 44a13d9..127658d 100644
--- a/services/identity/internal/blesser/oauth.go
+++ b/services/identity/internal/blesser/oauth.go
@@ -83,7 +83,7 @@
if b.revocationManager != nil {
caveat, err = b.revocationManager.NewCaveat(self.PublicKey(), b.dischargerLocation)
} else {
- caveat, err = security.ExpiryCaveat(time.Now().Add(b.duration))
+ caveat, err = security.NewExpiryCaveat(time.Now().Add(b.duration))
}
if err != nil {
return noblessings, "", err
diff --git a/services/identity/internal/caveats/caveat_factory.go b/services/identity/internal/caveats/caveat_factory.go
index d057a86..d11382e 100644
--- a/services/identity/internal/caveats/caveat_factory.go
+++ b/services/identity/internal/caveats/caveat_factory.go
@@ -50,7 +50,7 @@
if !ok {
return empty, fmt.Errorf("expiry caveat: received arg of type %T, expected time.Time", args[0])
}
- return security.ExpiryCaveat(t)
+ return security.NewExpiryCaveat(t)
}
func methodCaveat(args ...interface{}) (security.Caveat, error) {
@@ -61,7 +61,7 @@
if err != nil {
return security.Caveat{}, fmt.Errorf("method caveat: %v", err)
}
- return security.MethodCaveat(methods[0], methods[1:]...)
+ return security.NewMethodCaveat(methods[0], methods[1:]...)
}
func peerBlessingsCaveat(args ...interface{}) (security.Caveat, error) {
diff --git a/services/identity/internal/dischargerlib/discharger.go b/services/identity/internal/dischargerlib/discharger.go
index cf75370..4fb6d48 100644
--- a/services/identity/internal/dischargerlib/discharger.go
+++ b/services/identity/internal/dischargerlib/discharger.go
@@ -26,7 +26,7 @@
if err := tp.Dischargeable(ctx, call.Security()); err != nil {
return security.Discharge{}, fmt.Errorf("third-party caveat %v cannot be discharged for this context: %v", tp, err)
}
- expiry, err := security.ExpiryCaveat(time.Now().Add(15 * time.Minute))
+ expiry, err := security.NewExpiryCaveat(time.Now().Add(15 * time.Minute))
if err != nil {
return security.Discharge{}, fmt.Errorf("unable to create expiration caveat on the discharge: %v", err)
}
diff --git a/services/identity/internal/oauth/handler.go b/services/identity/internal/oauth/handler.go
index bea1fae..815431f 100644
--- a/services/identity/internal/oauth/handler.go
+++ b/services/identity/internal/oauth/handler.go
@@ -227,7 +227,7 @@
func prettyPrintCaveats(cavs []security.Caveat) ([]string, error) {
s := make([]string, len(cavs))
for i, cav := range cavs {
- if cav.Id == security.PublicKeyThirdPartyCaveatX.Id {
+ if cav.Id == security.PublicKeyThirdPartyCaveat.Id {
c := cav.ThirdPartyDetails()
s[i] = fmt.Sprintf("ThirdPartyCaveat: Requires discharge from %v (ID=%q)", c.Location(), c.ID())
continue
@@ -238,9 +238,9 @@
return nil, err
}
switch cav.Id {
- case security.ExpiryCaveatX.Id:
+ case security.ExpiryCaveat.Id:
s[i] = fmt.Sprintf("Expires at %v", param)
- case security.MethodCaveatX.Id:
+ case security.MethodCaveat.Id:
s[i] = fmt.Sprintf("Restricted to methods %v", param)
case security.PeerBlessingsCaveat.Id:
s[i] = fmt.Sprintf("Restricted to peers with blessings %v", param)
diff --git a/services/role/roled/internal/discharger.go b/services/role/roled/internal/discharger.go
index 5e8f4a0..2a624cc 100644
--- a/services/role/roled/internal/discharger.go
+++ b/services/role/roled/internal/discharger.go
@@ -41,12 +41,12 @@
// TODO(rthellend,ashankar): Do proper logging when the API allows it.
vlog.Infof("Discharge() impetus: %#v", impetus)
- expiry, err := security.ExpiryCaveat(time.Now().Add(5 * time.Minute))
+ expiry, err := security.NewExpiryCaveat(time.Now().Add(5 * time.Minute))
if err != nil {
return security.Discharge{}, verror.Convert(verror.ErrInternal, ctx, err)
}
// Bind the discharge to precisely the purpose the requestor claims it will be used.
- method, err := security.MethodCaveat(impetus.Method)
+ method, err := security.NewMethodCaveat(impetus.Method)
if err != nil {
return security.Discharge{}, verror.Convert(verror.ErrInternal, ctx, err)
}
diff --git a/services/role/roled/internal/role.go b/services/role/roled/internal/role.go
index 2e39f7c..9d0e332 100644
--- a/services/role/roled/internal/role.go
+++ b/services/role/roled/internal/role.go
@@ -90,7 +90,7 @@
if err != nil {
return nil, verror.Convert(verror.ErrInternal, ctx, err)
}
- expiry, err := security.ExpiryCaveat(time.Now().Add(d))
+ expiry, err := security.NewExpiryCaveat(time.Now().Add(d))
if err != nil {
return nil, verror.Convert(verror.ErrInternal, ctx, err)
}
diff --git a/services/wspr/internal/account/account.go b/services/wspr/internal/account/account.go
index f577b59..0289534 100644
--- a/services/wspr/internal/account/account.go
+++ b/services/wspr/internal/account/account.go
@@ -146,9 +146,9 @@
return security.Caveat{}, zeroTime, fmt.Errorf("time.parseDuration(%v) failed: %v", arg, err)
}
expirationTime := time.Now().Add(dur)
- cav, err := security.ExpiryCaveat(expirationTime)
+ cav, err := security.NewExpiryCaveat(expirationTime)
if err != nil {
- return security.Caveat{}, zeroTime, fmt.Errorf("security.ExpiryCaveat(%v) failed: %v", expirationTime, err)
+ return security.Caveat{}, zeroTime, fmt.Errorf("security.NewExpiryCaveat(%v) failed: %v", expirationTime, err)
}
return cav, expirationTime, nil
}
@@ -158,5 +158,5 @@
if len(args) == 0 {
return security.Caveat{}, fmt.Errorf("must pass at least one method")
}
- return security.MethodCaveat(args[0], args[1:]...)
+ return security.NewMethodCaveat(args[0], args[1:]...)
}
diff --git a/services/wspr/internal/principal/principal_test.go b/services/wspr/internal/principal/principal_test.go
index 492688b..2f86ef4 100644
--- a/services/wspr/internal/principal/principal_test.go
+++ b/services/wspr/internal/principal/principal_test.go
@@ -42,7 +42,7 @@
}
// Test AddOrigin.
- cav, err := security.MethodCaveat("Foo")
+ cav, err := security.NewMethodCaveat("Foo")
if err != nil {
return fmt.Errorf("security.MethodCaveat failed: %v", err)
}
@@ -197,7 +197,7 @@
// Test with no expiration caveat.
origin1 := "http://origin-1.com"
- methodCav, err := security.MethodCaveat("Foo")
+ methodCav, err := security.NewMethodCaveat("Foo")
if err != nil {
fmt.Errorf("security.MethodCaveat failed: %v", err)
}
@@ -214,9 +214,9 @@
origin2 := "http://origin-2.com"
futureTime := time.Now().Add(5 * time.Minute)
- futureExpCav, err := security.ExpiryCaveat(futureTime)
+ futureExpCav, err := security.NewExpiryCaveat(futureTime)
if err != nil {
- fmt.Errorf("security.ExpiryCaveat(%v) failed: %v", futureTime, err)
+ fmt.Errorf("security.NewExpiryCaveat(%v) failed: %v", futureTime, err)
}
if err := m.AddOrigin(origin2, googleAccount, []security.Caveat{futureExpCav}, []time.Time{futureTime}); err != nil {
@@ -231,9 +231,9 @@
origin3 := "http://origin-3.com"
pastTime := time.Now().Add(-5 * time.Minute)
- pastExpCav, err := security.ExpiryCaveat(pastTime)
+ pastExpCav, err := security.NewExpiryCaveat(pastTime)
if err != nil {
- fmt.Errorf("security.ExpiryCaveat(%v) failed: %v", pastTime, err)
+ fmt.Errorf("security.NewExpiryCaveat(%v) failed: %v", pastTime, err)
}
if err := m.AddOrigin(origin3, googleAccount, []security.Caveat{futureExpCav, pastExpCav}, []time.Time{futureTime, pastTime}); err != nil {
diff --git a/services/wspr/internal/rpc/server/server.go b/services/wspr/internal/rpc/server/server.go
index 9ab5309..2069d8c 100644
--- a/services/wspr/internal/rpc/server/server.go
+++ b/services/wspr/internal/rpc/server/server.go
@@ -410,7 +410,7 @@
// CaveatValidation implements a function suitable for passing to
// security.OverrideCaveatValidation.
//
-// Certain caveats (PublicKeyThirdPartyCaveatX) are intercepted and handled in
+// Certain caveats (PublicKeyThirdPartyCaveat) are intercepted and handled in
// go, while all other caveats are evaluated in javascript.
func CaveatValidation(ctx *context.T, call security.Call, cavs [][]security.Caveat) []error {
// If the server isn't set in the context, we just perform validation in Go.
@@ -446,7 +446,7 @@
default:
}
switch cav.Id {
- case security.PublicKeyThirdPartyCaveatX.Id:
+ case security.PublicKeyThirdPartyCaveat.Id:
res := cav.Validate(ctx, call)
if res != nil {
valStatus[i] = validationStatus{