diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | diff.go | 121 |
2 files changed, 109 insertions, 14 deletions
@@ -18,7 +18,7 @@ tls.pem: tls-getcerts config-sockets.txt NET-tls tls.html: %.html: %.pem tls-pem2html ./tls-pem2html < $< > $@ -diff.txt: diff tls.pem crtsh.pem +diff.html: diff tls.pem crtsh.pem ./diff tls.pem crtsh.pem > $@ NET-%: @@ -5,6 +5,7 @@ import ( "encoding/pem" "fmt" "io/ioutil" + "html/template" "os" "sort" ) @@ -87,6 +88,99 @@ func fmtCert(cert *x509.Certificate) string { cert.NotAfter.Format("2006-01-02 15:04:05 MST(-07)")) } +var tmpl = template.Must(template.New("2html"). + Funcs(template.FuncMap{ + "class": class, + "link": link, + "join": join, + "isNil": isNil, + }).Parse(`<!DOCTYPE html> +<html lang="en"> +<head> + <meta charset="utf-8"> + <title>CT log accuracy</title> + <style> + html { + height: 100%; + } + body { + font-size: 10px; + font-family: monospace; + height: 100%; + margin: 0; + display: flex; + align-items: center; + } + body > * { + margin: auto; + } + .diff-del, .diff-del a { color: red; } + .diff-add, .diff-add a { color: green; } + .diff-dat, .diff-dat a { color: blue; } + .diff-ctx, .diff-ctx a { color: black; } + tr:hover td { + background-color: #AAAAF3; + } + a { text-decoration: none; } + </style> + <script src="sorttable.js"></script> + <base target="_parent" /> +</head> +<body> +<table> + <tr class="diff-del"><td colspan=4>--- {{.fileTLS}}</td></tr> + <tr class="diff-add"><td colspan=4>+++ {{.fileCrtSh}}</td></tr> + <tr class="diff-dat"><td colspan=4>@@ -1,{{len .certsTLS}} +1,{{len .certsCrtSh}} @@</td></tr> +{{define "Row"}} + <tr class={{.pfix | class}}> + <td><a href="{{.cert | link}}">{{.pfix}}</a></td> + <td><a href="{{.cert | link}}">{{.cert.Subject.CommonName}}</a></td> + <td><a href="{{.cert | link}}">{{.cert.NotBefore.Local.Format "2006-01-02 15:04:05"}}</a></td> + <td><a href="{{.cert | link}}">{{.cert.NotAfter.Local.Format "2006-01-02 15:04:05"}}</a></td> + </tr> +{{end}} +{{range $cert := .certs}} +{{if isNil $cert.CrtSh}} +{{template "Row" join "-" $cert.TLS}} +{{else if $cert.TLS.Equal $cert.CrtSh | not}} +{{template "Row" join "-" $cert.TLS}} +{{template "Row" join "+" $cert.CrtSh}} +{{else}} +{{template "Row" join " " $cert.TLS}} +{{end}} +{{end}} +</table> +</body> +</html> +`)) + +type Cert struct { + TLS, CrtSh *x509.Certificate +} + +func link(cert *x509.Certificate) string { + return fmt.Sprintf("https://crt.sh/?serial=%036x", cert.SerialNumber) +} + +func isNil(cert *x509.Certificate) bool { + return cert == nil +} + +func class(pfix string) string { + return map[string]string { + "+": "diff-add", + "-": "diff-del", + " ": "diff-ctx", + }[pfix] +} + +func join(pfix string, cert *x509.Certificate) map[string]interface{} { + return map[string]interface{} { + "pfix": pfix, + "cert": cert, + } +} + func main() { if len(os.Args) != 3 { fmt.Fprintf(os.Stderr, "Usage: %s TLS-file crt.sh-file\n", os.Args[0]) @@ -97,19 +191,20 @@ func main() { certsCrtSh, err := readCrtSh(os.Args[2], hostsTLS) handleErr(err, "Could load crt.sh file: %v\n") - fmt.Printf("--- %s\n", os.Args[1]) - fmt.Printf("+++ %s\n", os.Args[2]) - fmt.Printf("@@ -1,%d +1,%d @@\n", len(hostsTLS), len(hostsTLS)) + certs := make([]Cert, len(certsTLS)) + i := 0 for _, host := range hostsTLS { - certTLS := certsTLS[host] - certCrtSh, okCrtSh := certsCrtSh[host] - if !okCrtSh { - fmt.Printf("-%s\t%s\n", host, fmtCert(certTLS)) - } else if !certTLS.Equal(certCrtSh) { - fmt.Printf("-%s\t%s\n", host, fmtCert(certTLS)) - fmt.Printf("+%s\t%s\n", host, fmtCert(certCrtSh)) - } else { - fmt.Printf(" %s\t%s\n", host, fmtCert(certTLS)) - } + var cert Cert + cert.TLS = certsTLS[host] + cert.CrtSh = certsCrtSh[host] + certs[i] = cert + i++ } + handleErr(tmpl.Execute(os.Stdout, map[string]interface{}{ + "certs": certs, + "certsTLS": certsTLS, + "certsCrtSh": certsCrtSh, + "fileTLS": os.Args[1], + "fileCrtSh": os.Args[2], + }), "Could not execute template: %v\n") } |