...

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

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

     1  package x509
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"strconv"
     7  	"strings"
     8  )
     9  
    10  // Error implements the error interface and describes a single error in an X.509 certificate or CRL.
    11  type Error struct {
    12  	ID       ErrorID
    13  	Category ErrCategory
    14  	Summary  string
    15  	Field    string
    16  	SpecRef  string
    17  	SpecText string
    18  	// Fatal indicates that parsing has been aborted.
    19  	Fatal bool
    20  }
    21  
    22  func (err Error) Error() string {
    23  	var msg bytes.Buffer
    24  	if err.ID != ErrInvalidID {
    25  		if err.Fatal {
    26  			msg.WriteRune('E')
    27  		} else {
    28  			msg.WriteRune('W')
    29  		}
    30  		msg.WriteString(fmt.Sprintf("%03d: ", err.ID))
    31  	}
    32  	msg.WriteString(err.Summary)
    33  	return msg.String()
    34  }
    35  
    36  // VerboseError creates a more verbose error string, including spec details.
    37  func (err Error) VerboseError() string {
    38  	var msg bytes.Buffer
    39  	msg.WriteString(err.Error())
    40  	if len(err.Field) > 0 || err.Category != UnknownCategory || len(err.SpecRef) > 0 || len(err.SpecText) > 0 {
    41  		msg.WriteString(" (")
    42  		needSep := false
    43  		if len(err.Field) > 0 {
    44  			msg.WriteString(err.Field)
    45  			needSep = true
    46  		}
    47  		if err.Category != UnknownCategory {
    48  			if needSep {
    49  				msg.WriteString(": ")
    50  			}
    51  			msg.WriteString(err.Category.String())
    52  			needSep = true
    53  		}
    54  		if len(err.SpecRef) > 0 {
    55  			if needSep {
    56  				msg.WriteString(": ")
    57  			}
    58  			msg.WriteString(err.SpecRef)
    59  			needSep = true
    60  		}
    61  		if len(err.SpecText) > 0 {
    62  			if needSep {
    63  				if len(err.SpecRef) > 0 {
    64  					msg.WriteString(", ")
    65  				} else {
    66  					msg.WriteString(": ")
    67  				}
    68  			}
    69  			msg.WriteString("'")
    70  			msg.WriteString(err.SpecText)
    71  			msg.WriteString("'")
    72  		}
    73  		msg.WriteString(")")
    74  	}
    75  
    76  	return msg.String()
    77  }
    78  
    79  // ErrCategory indicates the category of an x509.Error.
    80  type ErrCategory int
    81  
    82  // ErrCategory values.
    83  const (
    84  	UnknownCategory ErrCategory = iota
    85  	// Errors in ASN.1 encoding
    86  	InvalidASN1Encoding
    87  	InvalidASN1Content
    88  	InvalidASN1DER
    89  	// Errors in ASN.1 relative to schema
    90  	InvalidValueRange
    91  	InvalidASN1Type
    92  	UnexpectedAdditionalData
    93  	// Errors in X.509
    94  	PoorlyFormedCertificate // Fails a SHOULD clause
    95  	MalformedCertificate    // Fails a MUST clause
    96  	PoorlyFormedCRL         // Fails a SHOULD clause
    97  	MalformedCRL            // Fails a MUST clause
    98  	// Errors relative to CA/Browser Forum guidelines
    99  	BaselineRequirementsFailure
   100  	EVRequirementsFailure
   101  	// Other errors
   102  	InsecureAlgorithm
   103  	UnrecognizedValue
   104  )
   105  
   106  func (category ErrCategory) String() string {
   107  	switch category {
   108  	case InvalidASN1Encoding:
   109  		return "Invalid ASN.1 encoding"
   110  	case InvalidASN1Content:
   111  		return "Invalid ASN.1 content"
   112  	case InvalidASN1DER:
   113  		return "Invalid ASN.1 distinguished encoding"
   114  	case InvalidValueRange:
   115  		return "Invalid value for range given in schema"
   116  	case InvalidASN1Type:
   117  		return "Invalid ASN.1 type for schema"
   118  	case UnexpectedAdditionalData:
   119  		return "Unexpected additional data present"
   120  	case PoorlyFormedCertificate:
   121  		return "Certificate does not comply with SHOULD clause in spec"
   122  	case MalformedCertificate:
   123  		return "Certificate does not comply with MUST clause in spec"
   124  	case PoorlyFormedCRL:
   125  		return "Certificate Revocation List does not comply with SHOULD clause in spec"
   126  	case MalformedCRL:
   127  		return "Certificate Revocation List does not comply with MUST clause in spec"
   128  	case BaselineRequirementsFailure:
   129  		return "Certificate does not comply with CA/BF baseline requirements"
   130  	case EVRequirementsFailure:
   131  		return "Certificate does not comply with CA/BF EV requirements"
   132  	case InsecureAlgorithm:
   133  		return "Certificate uses an insecure algorithm"
   134  	case UnrecognizedValue:
   135  		return "Certificate uses an unrecognized value"
   136  	default:
   137  		return fmt.Sprintf("Unknown (%d)", category)
   138  	}
   139  }
   140  
   141  // ErrorID is an identifier for an x509.Error, to allow filtering.
   142  type ErrorID int
   143  
   144  // Errors implements the error interface and holds a collection of errors found in a certificate or CRL.
   145  type Errors struct {
   146  	Errs []Error
   147  }
   148  
   149  // Error converts to a string.
   150  func (e *Errors) Error() string {
   151  	return e.combineErrors(Error.Error)
   152  }
   153  
   154  // VerboseError creates a more verbose error string, including spec details.
   155  func (e *Errors) VerboseError() string {
   156  	return e.combineErrors(Error.VerboseError)
   157  }
   158  
   159  // Fatal indicates whether e includes a fatal error
   160  func (e *Errors) Fatal() bool {
   161  	return (e.FirstFatal() != nil)
   162  }
   163  
   164  // Empty indicates whether e has no errors.
   165  func (e *Errors) Empty() bool {
   166  	if e == nil {
   167  		return true
   168  	}
   169  	return len(e.Errs) == 0
   170  }
   171  
   172  // FirstFatal returns the first fatal error in e, or nil
   173  // if there is no fatal error.
   174  func (e *Errors) FirstFatal() error {
   175  	if e == nil {
   176  		return nil
   177  	}
   178  	for _, err := range e.Errs {
   179  		if err.Fatal {
   180  			return err
   181  		}
   182  	}
   183  	return nil
   184  
   185  }
   186  
   187  // AddID adds the Error identified by the given id to an x509.Errors.
   188  func (e *Errors) AddID(id ErrorID, args ...interface{}) {
   189  	e.Errs = append(e.Errs, NewError(id, args...))
   190  }
   191  
   192  func (e Errors) combineErrors(errfn func(Error) string) string {
   193  	if len(e.Errs) == 0 {
   194  		return ""
   195  	}
   196  	if len(e.Errs) == 1 {
   197  		return errfn((e.Errs)[0])
   198  	}
   199  	var msg bytes.Buffer
   200  	msg.WriteString("Errors:")
   201  	for _, err := range e.Errs {
   202  		msg.WriteString("\n  ")
   203  		msg.WriteString(errfn(err))
   204  	}
   205  	return msg.String()
   206  }
   207  
   208  // Filter creates a new Errors object with any entries from the filtered
   209  // list of IDs removed.
   210  func (e Errors) Filter(filtered []ErrorID) Errors {
   211  	var results Errors
   212  eloop:
   213  	for _, v := range e.Errs {
   214  		for _, f := range filtered {
   215  			if v.ID == f {
   216  				break eloop
   217  			}
   218  		}
   219  		results.Errs = append(results.Errs, v)
   220  	}
   221  	return results
   222  }
   223  
   224  // ErrorFilter builds a list of error IDs (suitable for use with Errors.Filter) from a comma-separated string.
   225  func ErrorFilter(ignore string) []ErrorID {
   226  	var ids []ErrorID
   227  	filters := strings.Split(ignore, ",")
   228  	for _, f := range filters {
   229  		v, err := strconv.Atoi(f)
   230  		if err != nil {
   231  			continue
   232  		}
   233  		ids = append(ids, ErrorID(v))
   234  	}
   235  	return ids
   236  }
   237  

View as plain text