123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- // Copyright 2009 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package x509
- import (
- "fmt"
- "net"
- "github.com/google/certificate-transparency-go/asn1"
- "github.com/google/certificate-transparency-go/x509/pkix"
- )
- const (
- // GeneralName tag values from RFC 5280, 4.2.1.6
- tagOtherName = 0
- tagRFC822Name = 1
- tagDNSName = 2
- tagX400Address = 3
- tagDirectoryName = 4
- tagEDIPartyName = 5
- tagURI = 6
- tagIPAddress = 7
- tagRegisteredID = 8
- )
- // OtherName describes a name related to a certificate which is not in one
- // of the standard name formats. RFC 5280, 4.2.1.6:
- //
- // OtherName ::= SEQUENCE {
- // type-id OBJECT IDENTIFIER,
- // value [0] EXPLICIT ANY DEFINED BY type-id }
- type OtherName struct {
- TypeID asn1.ObjectIdentifier
- Value asn1.RawValue
- }
- // GeneralNames holds a collection of names related to a certificate.
- type GeneralNames struct {
- DNSNames []string
- EmailAddresses []string
- DirectoryNames []pkix.Name
- URIs []string
- IPNets []net.IPNet
- RegisteredIDs []asn1.ObjectIdentifier
- OtherNames []OtherName
- }
- // Len returns the total number of names in a GeneralNames object.
- func (gn GeneralNames) Len() int {
- return (len(gn.DNSNames) + len(gn.EmailAddresses) + len(gn.DirectoryNames) +
- len(gn.URIs) + len(gn.IPNets) + len(gn.RegisteredIDs) + len(gn.OtherNames))
- }
- // Empty indicates whether a GeneralNames object is empty.
- func (gn GeneralNames) Empty() bool {
- return gn.Len() == 0
- }
- func parseGeneralNames(value []byte, gname *GeneralNames) error {
- // RFC 5280, 4.2.1.6
- // GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
- //
- // GeneralName ::= CHOICE {
- // otherName [0] OtherName,
- // rfc822Name [1] IA5String,
- // dNSName [2] IA5String,
- // x400Address [3] ORAddress,
- // directoryName [4] Name,
- // ediPartyName [5] EDIPartyName,
- // uniformResourceIdentifier [6] IA5String,
- // 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 fmt.Errorf("x509: failed to parse GeneralNames: %v", err)
- } else if len(rest) != 0 {
- return fmt.Errorf("x509: trailing data after GeneralNames")
- }
- if !seq.IsCompound || seq.Tag != asn1.TagSequence || seq.Class != asn1.ClassUniversal {
- return fmt.Errorf("x509: failed to parse GeneralNames sequence, tag %+v", seq)
- }
- rest = seq.Bytes
- for len(rest) > 0 {
- var err error
- rest, err = parseGeneralName(rest, gname, false)
- if err != nil {
- return fmt.Errorf("x509: failed to parse GeneralName: %v", err)
- }
- }
- return nil
- }
- func parseGeneralName(data []byte, gname *GeneralNames, withMask bool) ([]byte, error) {
- var v asn1.RawValue
- var rest []byte
- var err error
- rest, err = asn1.Unmarshal(data, &v)
- if err != nil {
- return nil, fmt.Errorf("x509: failed to unmarshal GeneralNames: %v", err)
- }
- switch v.Tag {
- case tagOtherName:
- if !v.IsCompound {
- return nil, fmt.Errorf("x509: failed to unmarshal GeneralNames.otherName: not compound")
- }
- var other OtherName
- v.FullBytes = append([]byte{}, v.FullBytes...)
- v.FullBytes[0] = asn1.TagSequence | 0x20
- _, err = asn1.Unmarshal(v.FullBytes, &other)
- if err != nil {
- return nil, fmt.Errorf("x509: failed to unmarshal GeneralNames.otherName: %v", err)
- }
- gname.OtherNames = append(gname.OtherNames, other)
- case tagRFC822Name:
- gname.EmailAddresses = append(gname.EmailAddresses, string(v.Bytes))
- case tagDNSName:
- dns := string(v.Bytes)
- gname.DNSNames = append(gname.DNSNames, dns)
- case tagDirectoryName:
- var rdnSeq pkix.RDNSequence
- if _, err := asn1.Unmarshal(v.Bytes, &rdnSeq); err != nil {
- return nil, fmt.Errorf("x509: failed to unmarshal GeneralNames.directoryName: %v", err)
- }
- var dirName pkix.Name
- dirName.FillFromRDNSequence(&rdnSeq)
- gname.DirectoryNames = append(gname.DirectoryNames, dirName)
- case tagURI:
- gname.URIs = append(gname.URIs, string(v.Bytes))
- case tagIPAddress:
- vlen := len(v.Bytes)
- if withMask {
- switch vlen {
- case (2 * net.IPv4len), (2 * net.IPv6len):
- ipNet := net.IPNet{IP: v.Bytes[0 : vlen/2], Mask: v.Bytes[vlen/2:]}
- gname.IPNets = append(gname.IPNets, ipNet)
- default:
- return nil, fmt.Errorf("x509: invalid IP/mask length %d in GeneralNames.iPAddress", vlen)
- }
- } else {
- switch vlen {
- case net.IPv4len, net.IPv6len:
- ipNet := net.IPNet{IP: v.Bytes}
- gname.IPNets = append(gname.IPNets, ipNet)
- default:
- return nil, fmt.Errorf("x509: invalid IP length %d in GeneralNames.iPAddress", vlen)
- }
- }
- case tagRegisteredID:
- var oid asn1.ObjectIdentifier
- v.FullBytes = append([]byte{}, v.FullBytes...)
- v.FullBytes[0] = asn1.TagOID
- _, err = asn1.Unmarshal(v.FullBytes, &oid)
- if err != nil {
- return nil, fmt.Errorf("x509: failed to unmarshal GeneralNames.registeredID: %v", err)
- }
- gname.RegisteredIDs = append(gname.RegisteredIDs, oid)
- default:
- return nil, fmt.Errorf("x509: failed to unmarshal GeneralName: unknown tag %d", v.Tag)
- }
- return rest, nil
- }
|