Merge "veyron/tools/naming/simulator: add support for running proxies, sundry fixes."
diff --git a/lib/expect/expect.go b/lib/expect/expect.go
index 4950758..e7da3a3 100644
--- a/lib/expect/expect.go
+++ b/lib/expect/expect.go
@@ -272,6 +272,59 @@
 	return m[0][1]
 }
 
+// ExpectSetRE verifies whether the supplied set of regular expression
+// parameters matches the next n (where n is the number of parameters)
+// lines of input. Each line is read and matched against the supplied
+// patterns in the order that they are supplied as parameters. Consequently
+// the set may contain repetitions if the same pattern is expected multiple
+// times.
+func (s *Session) ExpectSetRE(expected ...string) {
+	if s.Failed() {
+		return
+	}
+	regexps := make([]*regexp.Regexp, len(expected))
+	for i, expRE := range expected {
+		re, err := regexp.Compile(expRE)
+		if err != nil {
+			s.error(err)
+			return
+		}
+		regexps[i] = re
+	}
+	actual := make([]string, len(expected))
+	for i := 0; i < len(expected); i++ {
+		line, err := s.read(readLine)
+		line = strings.TrimRight(line, "\n")
+		s.log(err, "ExpectSetRE: %s", line)
+		if err != nil {
+			s.error(err)
+			return
+		}
+		actual[i] = line
+	}
+	// Match each line against all regexp's and remove each regexp
+	// that matches.
+	for _, l := range actual {
+		found := false
+		for i, re := range regexps {
+			if re == nil {
+				continue
+			}
+			if re.MatchString(l) {
+				// We remove each RE that matches.
+				found = true
+				regexps[i] = nil
+				break
+			}
+		}
+		if !found {
+			s.error(fmt.Errorf("found no match for %q", l))
+			return
+		}
+	}
+
+}
+
 // ReadLine reads the next line, if any, from the input stream. It will set
 // the error state to io.EOF if it has read past the end of the stream.
 // ReadLine has no effect if an error has already occurred.
diff --git a/lib/expect/expect_test.go b/lib/expect/expect_test.go
index c85d803..8fa62da 100644
--- a/lib/expect/expect_test.go
+++ b/lib/expect/expect_test.go
@@ -87,6 +87,27 @@
 	s.ExpectEOF()
 }
 
+func TestExpectSetRE(t *testing.T) {
+	buf := []byte{}
+	buffer := bytes.NewBuffer(buf)
+	buffer.WriteString("bar=baz\n")
+	buffer.WriteString("abc\n")
+	buffer.WriteString("def\n")
+	buffer.WriteString("abc\n")
+	s := expect.NewSession(nil, bufio.NewReader(buffer), time.Minute)
+	s.ExpectSetRE("^bar=.*$", "def$", "^abc$", "^a..$")
+	if s.Error() != nil {
+		t.Errorf("unexpected error: %s", s.Error())
+	}
+	buffer.WriteString("ooh\n")
+	buffer.WriteString("aah\n")
+	s.ExpectSetRE("bar=.*", "def")
+	if got, want := s.Error(), "expect_test.go:104: found no match for \"ooh\""; got == nil || got.Error() != want {
+		t.Errorf("got %v, want %q", got, want)
+	}
+	s.ExpectEOF()
+}
+
 func TestRead(t *testing.T) {
 	buf := []byte{}
 	buffer := bytes.NewBuffer(buf)
diff --git a/runtimes/google/ipc/client.go b/runtimes/google/ipc/client.go
index d20e598..940b43c 100644
--- a/runtimes/google/ipc/client.go
+++ b/runtimes/google/ipc/client.go
@@ -245,18 +245,24 @@
 		}
 		flow.SetDeadline(ctx.Done())
 
-		// Validate caveats on the server's identity for the context associated with this call.
-		serverB, grantedB, err := c.authorizeServer(flow, name, suffix, method, opts)
-		if err != nil {
-			lastErr = verror.NoAccessf("ipc: client unwilling to invoke %q.%q on server %v: %v", name, method, flow.RemoteBlessings(), err)
-			flow.Close()
-			continue
-		}
-		// Fetch any discharges for third-party caveats on the client's blessings.
+		var serverB []string
+		var grantedB security.Blessings
 		var discharges []security.Discharge
-		if self := flow.LocalBlessings(); self != nil {
-			if tpcavs := self.ThirdPartyCaveats(); len(tpcavs) > 0 {
-				discharges = c.prepareDischarges(ctx, tpcavs, mkDischargeImpetus(serverB, method, args), opts)
+
+		// LocalPrincipal is nil means that the client wanted to avoid authentication,
+		// and thus wanted to skip authorization as well.
+		if flow.LocalPrincipal() != nil {
+			// Validate caveats on the server's identity for the context associated with this call.
+			if serverB, grantedB, err = c.authorizeServer(flow, name, suffix, method, opts); err != nil {
+				lastErr = verror.NoAccessf("ipc: client unwilling to invoke %q.%q on server %v: %v", name, method, flow.RemoteBlessings(), err)
+				flow.Close()
+				continue
+			}
+			// Fetch any discharges for third-party caveats on the client's blessings.
+			if self := flow.LocalBlessings(); self != nil {
+				if tpcavs := self.ThirdPartyCaveats(); len(tpcavs) > 0 {
+					discharges = c.prepareDischarges(ctx, tpcavs, mkDischargeImpetus(serverB, method, args), opts)
+				}
 			}
 		}
 
diff --git a/runtimes/google/ipc/full_test.go b/runtimes/google/ipc/full_test.go
index a26570f..0f0f3a9 100644
--- a/runtimes/google/ipc/full_test.go
+++ b/runtimes/google/ipc/full_test.go
@@ -1044,6 +1044,41 @@
 	}
 }
 
+func TestSecurityNone(t *testing.T) {
+	sm := imanager.InternalNew(naming.FixedRoutingID(0x66666666))
+	defer sm.Shutdown()
+	ns := tnaming.NewSimpleNamespace()
+	server, err := InternalNewServer(testContext(), sm, ns, options.VCSecurityNone)
+	if err != nil {
+		t.Fatalf("InternalNewServer failed: %v", err)
+	}
+	if _, err = server.Listen(listenSpec); err != nil {
+		t.Fatalf("server.Listen failed: %v", err)
+	}
+	disp := &testServerDisp{&testServer{}}
+	if err := server.Serve("mp/server", disp); err != nil {
+		t.Fatalf("server.Serve failed: %v", err)
+	}
+	client, err := InternalNewClient(sm, ns, options.VCSecurityNone)
+	if err != nil {
+		t.Fatalf("InternalNewClient failed: %v", err)
+	}
+	// When using VCSecurityNone, all authorization checks should be skipped, so
+	// unauthorized methods shoudl be callable.
+	call, err := client.StartCall(testContext(), "mp/server", "Unauthorized", nil)
+	if err != nil {
+		t.Fatalf("client.StartCall failed: %v", err)
+	}
+	var got string
+	var ierr error
+	if err := call.Finish(&got, &ierr); err != nil {
+		t.Errorf("call.Finish failed: %v", err)
+	}
+	if want := "UnauthorizedResult"; got != want {
+		t.Errorf("got (%v), want (%v)", got, want)
+	}
+}
+
 func init() {
 	testutil.Init()
 	vom.Register(fakeTimeCaveat(0))
diff --git a/runtimes/google/ipc/server.go b/runtimes/google/ipc/server.go
index 514377f..e9139b7 100644
--- a/runtimes/google/ipc/server.go
+++ b/runtimes/google/ipc/server.go
@@ -857,12 +857,18 @@
 			return nil, verror.NoAccessf("%v is not authorized to call %q.%q (%v)", fs.RemoteID(), fs.Name(), fs.Method(), err)
 		}
 	}
+
+	fs.allowDebug = fs.LocalPrincipal() == nil
 	// Check application's authorization policy and invoke the method.
-	if err := fs.authorize(auth); err != nil {
-		return nil, err
+	// LocalPrincipal is nil means that the server wanted to avoid authentication,
+	// and thus wanted to skip authorization as well.
+	if fs.LocalPrincipal() != nil {
+		// Check if the caller is permitted to view debug information.
+		if err := fs.authorize(auth); err != nil {
+			return nil, err
+		}
+		fs.allowDebug = fs.authorizeForDebug(auth) == nil
 	}
-	// Check if the caller is permitted to view debug information.
-	fs.allowDebug = fs.authorizeForDebug(auth) == nil
 
 	results, err := invoker.Invoke(req.Method, fs, argptrs)
 	fs.server.stats.record(req.Method, time.Since(start))