github.com/zmap/zlint@v1.1.0/zlint.go (about)

     1  /*
     2   * ZLint Copyright 2018 Regents of the University of Michigan
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License"); you may not
     5   * use this file except in compliance with the License. You may obtain a copy
     6   * of the License at http://www.apache.org/licenses/LICENSE-2.0
     7   *
     8   * Unless required by applicable law or agreed to in writing, software
     9   * distributed under the License is distributed on an "AS IS" BASIS,
    10   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
    11   * implied. See the License for the specific language governing
    12   * permissions and limitations under the License.
    13   */
    14  
    15  // Used to check parsed info from certificate for compliance
    16  
    17  package zlint
    18  
    19  import (
    20  	"encoding/json"
    21  	"io"
    22  	"regexp"
    23  	"time"
    24  
    25  	"github.com/zmap/zcrypto/x509"
    26  	"github.com/zmap/zlint/lints"
    27  )
    28  
    29  const Version int64 = 3
    30  
    31  // ResultSet contains the output of running all lints against a single certificate.
    32  type ResultSet struct {
    33  	Version         int64                        `json:"version"`
    34  	Timestamp       int64                        `json:"timestamp"`
    35  	Results         map[string]*lints.LintResult `json:"lints"`
    36  	NoticesPresent  bool                         `json:"notices_present"`
    37  	WarningsPresent bool                         `json:"warnings_present"`
    38  	ErrorsPresent   bool                         `json:"errors_present"`
    39  	FatalsPresent   bool                         `json:"fatals_present"`
    40  }
    41  
    42  func (z *ResultSet) execute(cert *x509.Certificate, filter *regexp.Regexp) {
    43  	z.Results = make(map[string]*lints.LintResult, len(lints.Lints))
    44  	for name, l := range lints.Lints {
    45  		if filter != nil && !filter.MatchString(name) {
    46  			continue
    47  		}
    48  		res := l.Execute(cert)
    49  		z.Results[name] = res
    50  		z.updateErrorStatePresent(res)
    51  	}
    52  }
    53  
    54  func (z *ResultSet) updateErrorStatePresent(result *lints.LintResult) {
    55  	switch result.Status {
    56  	case lints.Notice:
    57  		z.NoticesPresent = true
    58  	case lints.Warn:
    59  		z.WarningsPresent = true
    60  	case lints.Error:
    61  		z.ErrorsPresent = true
    62  	case lints.Fatal:
    63  		z.FatalsPresent = true
    64  	}
    65  }
    66  
    67  // EncodeLintDescriptionsToJSON outputs a description of each lint as JSON
    68  // object, one object per line.
    69  func EncodeLintDescriptionsToJSON(w io.Writer) {
    70  	enc := json.NewEncoder(w)
    71  	enc.SetEscapeHTML(false)
    72  	for _, lint := range lints.Lints {
    73  		enc.Encode(lint)
    74  	}
    75  }
    76  
    77  // LintCertificate runs all registered lints on c, producing a ZLint.
    78  func LintCertificate(c *x509.Certificate) *ResultSet {
    79  	// Instead of panicing on nil certificate, just returns nil and let the client
    80  	// panic when accessing ZLint, if they're into panicing.
    81  	if c == nil {
    82  		return nil
    83  	}
    84  
    85  	// Run all tests
    86  	return LintCertificateFiltered(c, nil)
    87  }
    88  
    89  // LintCertificateFiltered runs all lints with names matching the provided
    90  // regexp on c, producing a ResultSet.
    91  func LintCertificateFiltered(c *x509.Certificate, filter *regexp.Regexp) *ResultSet {
    92  	if c == nil {
    93  		return nil
    94  	}
    95  
    96  	// Run tests with provided filter
    97  	res := new(ResultSet)
    98  	res.execute(c, filter)
    99  	res.Version = Version
   100  	res.Timestamp = time.Now().Unix()
   101  	return res
   102  }