Fix certificate validation.

asn1: add support for T61String because this is the string type which
    several www.google.com certificates are now using for fields like
    CommonName
tls: force a handshake in Dial so that certificates are ready
    afterwards.

Fixes #1114.

R=rsc
CC=golang-dev
https://golang.org/cl/2216043
diff --git a/src/pkg/asn1/asn1.go b/src/pkg/asn1/asn1.go
index 3e3bb10..cd23fd7 100644
--- a/src/pkg/asn1/asn1.go
+++ b/src/pkg/asn1/asn1.go
@@ -290,6 +290,14 @@
 	return
 }
 
+// T61String
+
+// parseT61String parses a ASN.1 T61String (8-bit clean string) from the given
+// byte array and returns it.
+func parseT61String(bytes []byte) (ret string, err os.Error) {
+	return string(bytes), nil
+}
+
 // A RawValue represents an undecoded ASN.1 object.
 type RawValue struct {
 	Class, Tag int
@@ -472,6 +480,8 @@
 				result, err = parsePrintableString(innerBytes)
 			case tagIA5String:
 				result, err = parseIA5String(innerBytes)
+			case tagT61String:
+				result, err = parseT61String(innerBytes)
 			case tagInteger:
 				result, err = parseInt64(innerBytes)
 			case tagBitString:
@@ -689,6 +699,8 @@
 			v, err = parsePrintableString(innerBytes)
 		case tagIA5String:
 			v, err = parseIA5String(innerBytes)
+		case tagT61String:
+			v, err = parseT61String(innerBytes)
 		default:
 			err = SyntaxError{fmt.Sprintf("internal error: unknown string type %d", universalTag)}
 		}
diff --git a/src/pkg/asn1/common.go b/src/pkg/asn1/common.go
index 3ea0f09..4a5eca1 100644
--- a/src/pkg/asn1/common.go
+++ b/src/pkg/asn1/common.go
@@ -28,6 +28,7 @@
 	tagSequence        = 16
 	tagSet             = 17
 	tagPrintableString = 19
+	tagT61String       = 20
 	tagIA5String       = 22
 	tagUTCTime         = 23
 	tagGeneralizedTime = 24
diff --git a/src/pkg/crypto/tls/conn.go b/src/pkg/crypto/tls/conn.go
index 78566fa..9bf9f21 100644
--- a/src/pkg/crypto/tls/conn.go
+++ b/src/pkg/crypto/tls/conn.go
@@ -675,5 +675,13 @@
 // connecting to host.  If so, it returns nil; if not, it returns an os.Error
 // describing the problem.
 func (c *Conn) VerifyHostname(host string) os.Error {
-	return c.PeerCertificates()[0].VerifyHostname(host)
+	c.handshakeMutex.Lock()
+	defer c.handshakeMutex.Unlock()
+	if !c.isClient {
+		return os.ErrorString("VerifyHostname called on TLS server connection")
+	}
+	if !c.handshakeComplete {
+		return os.ErrorString("TLS handshake has not yet been performed")
+	}
+	return c.peerCertificates[0].VerifyHostname(host)
 }
diff --git a/src/pkg/crypto/tls/tls.go b/src/pkg/crypto/tls/tls.go
index 27e32cc..2aec160 100644
--- a/src/pkg/crypto/tls/tls.go
+++ b/src/pkg/crypto/tls/tls.go
@@ -67,7 +67,13 @@
 	if err != nil {
 		return nil, err
 	}
-	return Client(c, nil), nil
+	conn := Client(c, nil)
+	err = conn.Handshake()
+	if err == nil {
+		return conn, nil
+	}
+	c.Close()
+	return nil, err
 }
 
 // LoadX509KeyPair