"veyron/runtimes/google/security": Mistrusted IDs should be as
authorized as Unknown IDs

Andres cleverly pointed out that there is no gain in forbidding
Mistrusted PublicIDs and allowing Unknown PublicIDs -- an agent
with a Mistrusted id can always create an Unknown id (e.g., a
self-signed id) and get through.

This CL makes the following changes:
1) Modifies the implementation of the Authorize method for
chainPublicIDs to not take the trust-level of the identity
provider into account. The trust-level is instead checked
by the Names method.
2) Remove the UntrustedIDProviderPrefix constant from the
wire package and define two prefix constants for unknown
and mistrusted ids in the runtimes/security package.
3) Fix a bug in newChainPrivateID so that it returns an error
when the provided name is not a valid blessing name.

Change-Id: I29dc637dcdbbf225bcbd9411926061f79093944a
diff --git a/runtimes/google/ipc/server.go b/runtimes/google/ipc/server.go
index f1c8718..fb4406d 100644
--- a/runtimes/google/ipc/server.go
+++ b/runtimes/google/ipc/server.go
@@ -370,9 +370,7 @@
 	}
 	acl := make(security.ACL)
 	for _, n := range id.Names() {
-		if !strings.HasPrefix(n, wire.UntrustedIDProviderPrefix) {
-			acl[security.PrincipalPattern(n+wire.ChainSeparator+security.AllPrincipals)] = security.AllLabels
-		}
+		acl[security.PrincipalPattern(n+wire.ChainSeparator+security.AllPrincipals)] = security.AllLabels
 	}
 	return acl
 }
diff --git a/runtimes/google/security/identity_chain.go b/runtimes/google/security/identity_chain.go
index b8439e0..b6ad17b 100644
--- a/runtimes/google/security/identity_chain.go
+++ b/runtimes/google/security/identity_chain.go
@@ -19,6 +19,17 @@
 	"veyron2/vom"
 )
 
+const (
+	// unknownIDProviderPrefix is the prefix added when stringifying
+	// an identity for which there is no entry for the root certificate
+	// in the trusted keys set.
+	unknownIDProviderPrefix = "unknown/"
+	// mistrustedIDProviderPrefix is the prefix added when stringifying
+	// an identity whose root certificate has a public key that does
+	// not exist in the (non-empty) set of trusted keys for that root.
+	mistrustedIDProviderPrefix = "mistrusted/"
+)
+
 // chainPublicID implements security.PublicID.
 type chainPublicID struct {
 	certificates []wire.Certificate
@@ -50,10 +61,14 @@
 
 func (id *chainPublicID) String() string {
 	// Add a prefix if the identity provider is not trusted.
-	if keys.LevelOfTrust(id.rootKey, id.certificates[0].Name) != keys.Trusted {
-		return wire.UntrustedIDProviderPrefix + id.name
+	switch keys.LevelOfTrust(id.rootKey, id.certificates[0].Name) {
+	case keys.Trusted:
+		return id.name
+	case keys.Mistrusted:
+		return mistrustedIDProviderPrefix + id.name
+	default:
+		return unknownIDProviderPrefix + id.name
 	}
-	return id.name
 }
 
 func (id *chainPublicID) VomEncode() (*wire.ChainPublicID, error) {
@@ -80,24 +95,10 @@
 }
 
 // Authorize checks if all caveats on the PublicID validate with respect to the
-// provided context and that the identity provider (root public key) is not
-// mistrusted. If so returns the original PublicID. This method assumes that
+// provided context and if so returns the original PublicID. This method assumes that
 // the existing PublicID was obtained after successfully decoding a serialized
 // PublicID and hence has integrity.
 func (id *chainPublicID) Authorize(context security.Context) (security.PublicID, error) {
-	rootCert := id.certificates[0]
-	rootKey, err := rootCert.PublicKey.Decode()
-	if err != nil {
-		// unlikely to hit this case, as chainPublicID would have integrity.
-		return nil, err
-	}
-	// Implicit "caveat": The identity provider should not be mistrusted.
-	switch tl := keys.LevelOfTrust(rootKey, rootCert.Name); tl {
-	case keys.Unknown, keys.Trusted:
-		// No-op
-	default:
-		return nil, fmt.Errorf("%v public key(%v) for identity provider %q", tl, rootKey, rootCert.Name)
-	}
 	for _, c := range id.certificates {
 		if err := c.ValidateCaveats(context); err != nil {
 			return nil, fmt.Errorf("not authorized because %v", err)
@@ -217,6 +218,9 @@
 // private key, and a single self-signed certificate specifying the provided
 // name and the public key corresponding to the generated private key.
 func newChainPrivateID(name string) (security.PrivateID, error) {
+	if err := wire.ValidateBlessingName(name); err != nil {
+		return nil, err
+	}
 	key, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
 	if err != nil {
 		return nil, err
diff --git a/runtimes/google/security/identity_test.go b/runtimes/google/security/identity_test.go
index 5c3a141..18b43bf 100644
--- a/runtimes/google/security/identity_test.go
+++ b/runtimes/google/security/identity_test.go
@@ -16,6 +16,28 @@
 
 type S []string
 
+func TestNewPrivateID(t *testing.T) {
+	testdata := []struct {
+		name, err string
+	}{
+		{"alice", ""},
+		{"alice#google", ""},
+		{"alice@google", ""},
+		{"bob.smith", ""},
+		{"", "invalid blessing name"},
+		{"/", "invalid blessing name"},
+		{"/alice", "invalid blessing name"},
+		{"alice/", "invalid blessing name"},
+		{"google/alice", "invalid blessing name"},
+		{"google/alice/bob", "invalid blessing name"},
+	}
+	for _, d := range testdata {
+		if _, err := NewPrivateID(d.name); !matchesErrorPattern(err, d.err) {
+			t.Errorf("NewPrivateID(%q): got: %s, want to match: %s", d.name, err, d.err)
+		}
+	}
+}
+
 func TestNameAndAuth(t *testing.T) {
 	var (
 		cUnknownAlice    = newChain("alice").PublicID()
@@ -30,11 +52,10 @@
 	testdata := []struct {
 		id    security.PublicID
 		names []string
-		err   string
 	}{
 		{id: cUnknownAlice},
 		{id: cTrustedAlice, names: S{"veyron/alice"}},
-		{id: cMistrustedAlice, err: "Mistrusted"},
+		{id: cMistrustedAlice},
 		{id: sAlice, names: S{"veyron/alice", "google/alice"}},
 		{id: sBadAlice},
 		{id: sGoogleAlice, names: S{"google/alice"}},
@@ -48,9 +69,6 @@
 			t.Errorf("%q.Authorize returned: (%v, %v), exactly one return value must be nil", d.id, authID, err)
 			continue
 		}
-		if !matchesErrorPattern(err, d.err) {
-			t.Errorf("%q.Authorize returned error: %v, want to match: %q", d.id, err, d.err)
-		}
 		if err := verifyAuthorizedID(d.id, authID, d.names); err != nil {
 			t.Error(err)
 		}