capi/lib/lint/x509lint/x509lint.go (79 lines of code) (raw):
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package x509lint
import (
"crypto/x509"
go_x509lint "github.com/crtsh/go-x509lint"
"log"
"reflect"
"strings"
"sync"
)
type X509Lint struct {
Errors []string
Warnings []string
Info []string
CmdError *string
}
type certType int
const (
subscriber certType = iota
intermediate
ca
)
var certTypeToStr = map[certType]string{
subscriber: "subscriber",
intermediate: "intermediate",
ca: "ca",
}
func LintChain(certificates []*x509.Certificate) ([]X509Lint, error) {
results := make([]X509Lint, len(certificates))
for i, cert := range certificates {
var ct certType
switch {
case i == 0:
ct = subscriber
case reflect.DeepEqual(cert.Subject, cert.Issuer):
ct = ca
default:
ct = intermediate
}
results[i] = Lint(cert, ct)
}
return results, nil
}
// go_x509lint.Init() and go_x509lint.Finish() both mutate global state.
//
// Concurrent read/writes MAY be safe for some roundabout reason that I cannot see,
// but given that there are no docs on the matter it seems prudent to simply
// lock the library for a given certificate check.
var x509LintLock = sync.Mutex{}
func Lint(certificate *x509.Certificate, ctype certType) X509Lint {
x509LintLock.Lock()
defer x509LintLock.Unlock()
go_x509lint.Init()
defer go_x509lint.Finish()
got := go_x509lint.Check(certificate.Raw, int(ctype))
return parseOutput(got)
}
func NewX509Lint() X509Lint {
return X509Lint{
Errors: make([]string, 0),
Warnings: make([]string, 0),
Info: make([]string, 0),
}
}
func parseOutput(output string) X509Lint {
result := NewX509Lint()
for _, line := range strings.Split(output, "\n") {
if len(line) == 0 {
continue
}
if strings.HasPrefix(line, "E: ") {
if strings.Contains(line, "Fails decoding the characterset") {
// @TODO We currently have no notion as why this happens, so we are ignoring it for now.
continue
}
result.Errors = append(result.Errors, line[3:])
} else if strings.HasPrefix(line, "W: ") {
result.Warnings = append(result.Warnings, line[3:])
} else if strings.HasPrefix(line, "I: ") {
result.Info = append(result.Info, line[3:])
} else {
log.Printf(`unexpected x509Lint output: "%s"`, line)
}
}
return result
}