go.crypto/ssh: prevent concurrent reads and concurrent writes over the same agent connection

minor fix for v01 cert parsing when algo is not supported

R=golang-dev, agl, dave
CC=golang-dev
https://golang.org/cl/6116052
diff --git a/ssh/agent.go b/ssh/agent.go
index 3c701b7..28d52df 100644
--- a/ssh/agent.go
+++ b/ssh/agent.go
@@ -11,6 +11,7 @@
 	"encoding/base64"
 	"errors"
 	"io"
+	"sync"
 )
 
 // See PROTOCOL.agent, section 3.
@@ -126,24 +127,37 @@
 }
 
 // AgentClient provides a means to communicate with an ssh agent process based
-// on the protocol described in PROTOCOL.agent?rev=1.6.  It contains an
-// embedded io.ReadWriter that is typically represented by using a *net.UnixConn.
+// on the protocol described in PROTOCOL.agent?rev=1.6.
 type AgentClient struct {
-	io.ReadWriter
+	// conn is typically represented by using a *net.UnixConn
+	conn io.ReadWriter
+	// mu is used to prevent concurrent access to the agent
+	mu sync.Mutex
+}
+
+// NewAgentClient creates and returns a new *AgentClient using the
+// passed in io.ReadWriter as a connection to a ssh agent.
+func NewAgentClient(rw io.ReadWriter) *AgentClient {
+	return &AgentClient{conn: rw}
 }
 
 // sendAndReceive sends req to the agent and waits for a reply. On success,
 // the reply is unmarshaled into reply and replyType is set to the first byte of
 // the reply, which contains the type of the message.
 func (ac *AgentClient) sendAndReceive(req []byte) (reply interface{}, replyType uint8, err error) {
+	// ac.mu prevents multiple, concurrent requests. Since the agent is typically
+	// on the same machine, we don't attempt to pipeline the requests.
+	ac.mu.Lock()
+	defer ac.mu.Unlock()
+
 	msg := make([]byte, stringLength(len(req)))
 	marshalString(msg, req)
-	if _, err = ac.Write(msg); err != nil {
+	if _, err = ac.conn.Write(msg); err != nil {
 		return
 	}
 
 	var respSizeBuf [4]byte
-	if _, err = io.ReadFull(ac, respSizeBuf[:]); err != nil {
+	if _, err = io.ReadFull(ac.conn, respSizeBuf[:]); err != nil {
 		return
 	}
 	respSize, _, _ := parseUint32(respSizeBuf[:])
@@ -154,7 +168,7 @@
 	}
 
 	buf := make([]byte, respSize)
-	if _, err = io.ReadFull(ac, buf); err != nil {
+	if _, err = io.ReadFull(ac.conn, buf); err != nil {
 		return
 	}
 	return unmarshalAgentMsg(buf)
diff --git a/ssh/certs.go b/ssh/certs.go
index 107fd1a..40cf706 100644
--- a/ssh/certs.go
+++ b/ssh/certs.go
@@ -78,6 +78,7 @@
 		}
 		cert.Key = dsaPubKey
 	default:
+		ok = false
 		return
 	}