From: Adam Langley Date: Sat, 9 Sep 2017 23:52:58 +0000 (-0700) Subject: crypto/x509: abstract SAN parsing function X-Git-Tag: go1.10beta1~919 X-Git-Url: http://www.git.cypherpunks.su/?a=commitdiff_plain;h=c4d63a0d34d1876868245f5bafc86d3cc00e3763;p=gostls13.git crypto/x509: abstract SAN parsing function We'll need this for handling name constraints during verification. Change-Id: I4ef19d9489fb2a9ae9a62699d81cef92a21fda28 Reviewed-on: https://go-review.googlesource.com/62692 Run-TryBot: Adam Langley TryBot-Result: Gobot Gobot Reviewed-by: David Crawshaw --- diff --git a/src/crypto/x509/x509.go b/src/crypto/x509/x509.go index 7d8150c175..2a8ee599ad 100644 --- a/src/crypto/x509/x509.go +++ b/src/crypto/x509/x509.go @@ -1042,7 +1042,7 @@ func parsePublicKey(algo PublicKeyAlgorithm, keyData *publicKeyInfo) (interface{ } } -func parseSANExtension(value []byte) (dnsNames, emailAddresses []string, ipAddresses []net.IP, err error) { +func forEachSAN(extension []byte, callback func(tag int, data []byte) error) error { // RFC 5280, 4.2.1.6 // SubjectAltName ::= GeneralNames @@ -1060,16 +1060,14 @@ func parseSANExtension(value []byte) (dnsNames, emailAddresses []string, ipAddre // iPAddress [7] OCTET STRING, // registeredID [8] OBJECT IDENTIFIER } var seq asn1.RawValue - var rest []byte - if rest, err = asn1.Unmarshal(value, &seq); err != nil { - return + rest, err := asn1.Unmarshal(extension, &seq) + if err != nil { + return err } else if len(rest) != 0 { - err = errors.New("x509: trailing data after X.509 extension") - return + return errors.New("x509: trailing data after X.509 extension") } if !seq.IsCompound || seq.Tag != 16 || seq.Class != 0 { - err = asn1.StructuralError{Msg: "bad SAN sequence"} - return + return asn1.StructuralError{Msg: "bad SAN sequence"} } rest = seq.Bytes @@ -1077,23 +1075,35 @@ func parseSANExtension(value []byte) (dnsNames, emailAddresses []string, ipAddre var v asn1.RawValue rest, err = asn1.Unmarshal(rest, &v) if err != nil { - return + return err + } + + if err := callback(v.Tag, v.Bytes); err != nil { + return err } - switch v.Tag { + } + + return nil +} + +func parseSANExtension(value []byte) (dnsNames, emailAddresses []string, ipAddresses []net.IP, err error) { + err = forEachSAN(value, func(tag int, data []byte) error { + switch tag { case 1: - emailAddresses = append(emailAddresses, string(v.Bytes)) + emailAddresses = append(emailAddresses, string(data)) case 2: - dnsNames = append(dnsNames, string(v.Bytes)) + dnsNames = append(dnsNames, string(data)) case 7: - switch len(v.Bytes) { + switch len(data) { case net.IPv4len, net.IPv6len: - ipAddresses = append(ipAddresses, v.Bytes) + ipAddresses = append(ipAddresses, data) default: - err = errors.New("x509: certificate contained IP address of length " + strconv.Itoa(len(v.Bytes))) - return + return errors.New("x509: certificate contained IP address of length " + strconv.Itoa(len(data))) } } - } + + return nil + }) return }