...

Source file src/github.com/google/certificate-transparency-go/x509/names.go

Documentation: github.com/google/certificate-transparency-go/x509

     1  // Copyright 2009 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package x509
     6  
     7  import (
     8  	"fmt"
     9  	"net"
    10  
    11  	"github.com/google/certificate-transparency-go/asn1"
    12  	"github.com/google/certificate-transparency-go/x509/pkix"
    13  )
    14  
    15  const (
    16  	// GeneralName tag values from RFC 5280, 4.2.1.6
    17  	tagOtherName     = 0
    18  	tagRFC822Name    = 1
    19  	tagDNSName       = 2
    20  	tagX400Address   = 3
    21  	tagDirectoryName = 4
    22  	tagEDIPartyName  = 5
    23  	tagURI           = 6
    24  	tagIPAddress     = 7
    25  	tagRegisteredID  = 8
    26  )
    27  
    28  // OtherName describes a name related to a certificate which is not in one
    29  // of the standard name formats. RFC 5280, 4.2.1.6:
    30  //
    31  //	OtherName ::= SEQUENCE {
    32  //	     type-id    OBJECT IDENTIFIER,
    33  //	     value      [0] EXPLICIT ANY DEFINED BY type-id }
    34  type OtherName struct {
    35  	TypeID asn1.ObjectIdentifier
    36  	Value  asn1.RawValue
    37  }
    38  
    39  // GeneralNames holds a collection of names related to a certificate.
    40  type GeneralNames struct {
    41  	DNSNames       []string
    42  	EmailAddresses []string
    43  	DirectoryNames []pkix.Name
    44  	URIs           []string
    45  	IPNets         []net.IPNet
    46  	RegisteredIDs  []asn1.ObjectIdentifier
    47  	OtherNames     []OtherName
    48  }
    49  
    50  // Len returns the total number of names in a GeneralNames object.
    51  func (gn GeneralNames) Len() int {
    52  	return (len(gn.DNSNames) + len(gn.EmailAddresses) + len(gn.DirectoryNames) +
    53  		len(gn.URIs) + len(gn.IPNets) + len(gn.RegisteredIDs) + len(gn.OtherNames))
    54  }
    55  
    56  // Empty indicates whether a GeneralNames object is empty.
    57  func (gn GeneralNames) Empty() bool {
    58  	return gn.Len() == 0
    59  }
    60  
    61  func parseGeneralNames(value []byte, gname *GeneralNames) error {
    62  	// RFC 5280, 4.2.1.6
    63  	// GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
    64  	//
    65  	// GeneralName ::= CHOICE {
    66  	//      otherName                       [0]     OtherName,
    67  	//      rfc822Name                      [1]     IA5String,
    68  	//      dNSName                         [2]     IA5String,
    69  	//      x400Address                     [3]     ORAddress,
    70  	//      directoryName                   [4]     Name,
    71  	//      ediPartyName                    [5]     EDIPartyName,
    72  	//      uniformResourceIdentifier       [6]     IA5String,
    73  	//      iPAddress                       [7]     OCTET STRING,
    74  	//      registeredID                    [8]     OBJECT IDENTIFIER }
    75  	var seq asn1.RawValue
    76  	var rest []byte
    77  	if rest, err := asn1.Unmarshal(value, &seq); err != nil {
    78  		return fmt.Errorf("x509: failed to parse GeneralNames: %v", err)
    79  	} else if len(rest) != 0 {
    80  		return fmt.Errorf("x509: trailing data after GeneralNames")
    81  	}
    82  	if !seq.IsCompound || seq.Tag != asn1.TagSequence || seq.Class != asn1.ClassUniversal {
    83  		return fmt.Errorf("x509: failed to parse GeneralNames sequence, tag %+v", seq)
    84  	}
    85  
    86  	rest = seq.Bytes
    87  	for len(rest) > 0 {
    88  		var err error
    89  		rest, err = parseGeneralName(rest, gname, false)
    90  		if err != nil {
    91  			return fmt.Errorf("x509: failed to parse GeneralName: %v", err)
    92  		}
    93  	}
    94  	return nil
    95  }
    96  
    97  func parseGeneralName(data []byte, gname *GeneralNames, withMask bool) ([]byte, error) {
    98  	var v asn1.RawValue
    99  	var rest []byte
   100  	var err error
   101  	rest, err = asn1.Unmarshal(data, &v)
   102  	if err != nil {
   103  		return nil, fmt.Errorf("x509: failed to unmarshal GeneralNames: %v", err)
   104  	}
   105  	switch v.Tag {
   106  	case tagOtherName:
   107  		if !v.IsCompound {
   108  			return nil, fmt.Errorf("x509: failed to unmarshal GeneralNames.otherName: not compound")
   109  		}
   110  		var other OtherName
   111  		v.FullBytes = append([]byte{}, v.FullBytes...)
   112  		v.FullBytes[0] = asn1.TagSequence | 0x20
   113  		_, err = asn1.Unmarshal(v.FullBytes, &other)
   114  		if err != nil {
   115  			return nil, fmt.Errorf("x509: failed to unmarshal GeneralNames.otherName: %v", err)
   116  		}
   117  		gname.OtherNames = append(gname.OtherNames, other)
   118  	case tagRFC822Name:
   119  		gname.EmailAddresses = append(gname.EmailAddresses, string(v.Bytes))
   120  	case tagDNSName:
   121  		dns := string(v.Bytes)
   122  		gname.DNSNames = append(gname.DNSNames, dns)
   123  	case tagDirectoryName:
   124  		var rdnSeq pkix.RDNSequence
   125  		if _, err := asn1.Unmarshal(v.Bytes, &rdnSeq); err != nil {
   126  			return nil, fmt.Errorf("x509: failed to unmarshal GeneralNames.directoryName: %v", err)
   127  		}
   128  		var dirName pkix.Name
   129  		dirName.FillFromRDNSequence(&rdnSeq)
   130  		gname.DirectoryNames = append(gname.DirectoryNames, dirName)
   131  	case tagURI:
   132  		gname.URIs = append(gname.URIs, string(v.Bytes))
   133  	case tagIPAddress:
   134  		vlen := len(v.Bytes)
   135  		if withMask {
   136  			switch vlen {
   137  			case (2 * net.IPv4len), (2 * net.IPv6len):
   138  				ipNet := net.IPNet{IP: v.Bytes[0 : vlen/2], Mask: v.Bytes[vlen/2:]}
   139  				gname.IPNets = append(gname.IPNets, ipNet)
   140  			default:
   141  				return nil, fmt.Errorf("x509: invalid IP/mask length %d in GeneralNames.iPAddress", vlen)
   142  			}
   143  		} else {
   144  			switch vlen {
   145  			case net.IPv4len, net.IPv6len:
   146  				ipNet := net.IPNet{IP: v.Bytes}
   147  				gname.IPNets = append(gname.IPNets, ipNet)
   148  			default:
   149  				return nil, fmt.Errorf("x509: invalid IP length %d in GeneralNames.iPAddress", vlen)
   150  			}
   151  		}
   152  	case tagRegisteredID:
   153  		var oid asn1.ObjectIdentifier
   154  		v.FullBytes = append([]byte{}, v.FullBytes...)
   155  		v.FullBytes[0] = asn1.TagOID
   156  		_, err = asn1.Unmarshal(v.FullBytes, &oid)
   157  		if err != nil {
   158  			return nil, fmt.Errorf("x509: failed to unmarshal GeneralNames.registeredID: %v", err)
   159  		}
   160  		gname.RegisteredIDs = append(gname.RegisteredIDs, oid)
   161  	default:
   162  		return nil, fmt.Errorf("x509: failed to unmarshal GeneralName: unknown tag %d", v.Tag)
   163  	}
   164  	return rest, nil
   165  }
   166  

View as plain text