diff --git a/cmd/ctwatch/main.go b/cmd/ctwatch/main.go index a1fc2a4..fd1c20a 100644 --- a/cmd/ctwatch/main.go +++ b/cmd/ctwatch/main.go @@ -71,14 +71,17 @@ func processEntry (scanner *ctwatch.Scanner, entry *ct.LogEntry) { info.CertInfo, info.ParseError = ctwatch.MakeCertInfoFromLogEntry(entry) - if info.ParseError == nil && info.CertInfo.DNSNamesParseError == nil { - // Match DNS names - if !anyDnsNameMatches(info.CertInfo.DNSNames) { - return - } + // If there's any sort of parse error related to the identifiers, report + // the certificate because we can't say for sure it doesn't match a domain + // we care about (fail safe behavior). Treat common names as DNS names + // because many TLS clients do. + if info.ParseError != nil || + info.CertInfo.CommonNamesParseError != nil || + info.CertInfo.DNSNamesParseError != nil || + anyDnsNameMatches(info.CertInfo.CommonNames) || + anyDnsNameMatches(info.CertInfo.DNSNames) { + cmd.LogEntry(&info) } - - cmd.LogEntry(&info) } func main() { diff --git a/helpers.go b/helpers.go index c33f8f9..485a15e 100644 --- a/helpers.go +++ b/helpers.go @@ -102,6 +102,8 @@ type EntryInfo struct { type CertInfo struct { TBS *TBSCertificate + CommonNames []string + CommonNamesParseError error DNSNames []string DNSNamesParseError error Subject RDNSequence @@ -119,6 +121,7 @@ type CertInfo struct { func MakeCertInfoFromTBS (tbs *TBSCertificate) *CertInfo { info := &CertInfo{TBS: tbs} + info.CommonNames, info.CommonNamesParseError = tbs.ParseCommonNames() info.DNSNames, info.DNSNamesParseError = tbs.ParseDNSNames() info.Subject, info.SubjectParseError = tbs.ParseSubject() info.Issuer, info.IssuerParseError = tbs.ParseIssuer() @@ -158,6 +161,14 @@ func MakeCertInfoFromLogEntry (entry *ct.LogEntry) (*CertInfo, error) { } } +func (info *CertInfo) commonNamesString () string { + if info.CommonNamesParseError == nil { + return strings.Join(info.CommonNames, ", ") + } else { + return "" + } +} + func (info *CertInfo) dnsNamesString () string { if info.DNSNamesParseError == nil { return strings.Join(info.DNSNames, ", ") @@ -195,6 +206,12 @@ func (info *CertInfo) Environ () []string { env = append(env, "PUBKEY_HASH=" + info.PubkeyHash()) + if info.CommonNamesParseError != nil { + env = append(env, "COMMON_NAMES_PARSE_ERROR=" + info.CommonNamesParseError.Error()) + } else { + env = append(env, "COMMON_NAMES=" + strings.Join(info.CommonNames, ",")) + } + if info.DNSNamesParseError != nil { env = append(env, "DNS_NAMES_PARSE_ERROR=" + info.DNSNamesParseError.Error()) } else { @@ -233,6 +250,7 @@ func (info *CertInfo) Environ () []string { func (info *EntryInfo) HasParseErrors () bool { return info.ParseError != nil || + info.CertInfo.CommonNamesParseError != nil || info.CertInfo.DNSNamesParseError != nil || info.CertInfo.SubjectParseError != nil || info.CertInfo.IssuerParseError != nil || @@ -317,6 +335,7 @@ func (info *EntryInfo) Write (out io.Writer) { if info.ParseError != nil { writeField(out, "Parse Error", "*** " + info.ParseError.Error() + " ***", nil) } else { + writeField(out, "Common Name", info.CertInfo.commonNamesString(), info.CertInfo.CommonNamesParseError) writeField(out, "DNS Names", info.CertInfo.dnsNamesString(), info.CertInfo.DNSNamesParseError) writeField(out, "Pubkey", info.CertInfo.PubkeyHash(), nil) writeField(out, "Subject", info.CertInfo.Subject, info.CertInfo.SubjectParseError) diff --git a/x509.go b/x509.go index cc5484a..50c5e48 100644 --- a/x509.go +++ b/x509.go @@ -222,10 +222,7 @@ func (tbs *TBSCertificate) ParseIssuer () (RDNSequence, error) { return issuer, nil } -func (tbs *TBSCertificate) ParseDNSNames () ([]string, error) { - dnsNames := []string{} - - // Extract Common Name from Subject +func (tbs *TBSCertificate) ParseCommonNames () ([]string, error) { subject, err := tbs.ParseSubject() if err != nil { return nil, err @@ -234,7 +231,12 @@ func (tbs *TBSCertificate) ParseDNSNames () ([]string, error) { if err != nil { return nil, errors.New("failed to process certificate subject: " + err.Error()) } - dnsNames = append(dnsNames, cns...) + + return cns, nil +} + +func (tbs *TBSCertificate) ParseDNSNames () ([]string, error) { + dnsNames := []string{} // Extract DNS names from SubjectAlternativeName extension for _, sanExt := range tbs.GetExtension(oidExtensionSubjectAltName) {