}
}
-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
// 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
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
}