]> Cypherpunks repositories - gostls13.git/commitdiff
crypto/x509: abstract SAN parsing function
authorAdam Langley <agl@golang.org>
Sat, 9 Sep 2017 23:52:58 +0000 (16:52 -0700)
committerAdam Langley <agl@golang.org>
Mon, 2 Oct 2017 18:30:34 +0000 (18:30 +0000)
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 <agl@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: David Crawshaw <crawshaw@golang.org>
src/crypto/x509/x509.go

index 7d8150c1757909bcabcb8c613d3049ebb68bfc51..2a8ee599adb10547053462e142b53fe8ae0b95d0 100644 (file)
@@ -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
 }