summaryrefslogtreecommitdiff
path: root/diff.go
diff options
context:
space:
mode:
authorLuke Shumaker <lukeshu@sbcglobal.net>2016-11-19 18:21:50 -0500
committerLuke Shumaker <lukeshu@sbcglobal.net>2016-11-19 18:21:50 -0500
commit6895534e0d59eae1b66a080dd390be7ee9c7db0b (patch)
treea86d2584f25796c372653589ffc47010bff8bde2 /diff.go
parent0ee58619c74a8ab086a8ebc9b74bb21de2df25a1 (diff)
separate diff logic from templating
Diffstat (limited to 'diff.go')
-rw-r--r--diff.go173
1 files changed, 43 insertions, 130 deletions
diff --git a/diff.go b/diff.go
index 4a8a559..83b1d2e 100644
--- a/diff.go
+++ b/diff.go
@@ -4,8 +4,8 @@ import (
"crypto/x509"
"encoding/pem"
"fmt"
+ "io"
"io/ioutil"
- "html/template"
"os"
"sort"
)
@@ -18,7 +18,24 @@ func handleErr(err error, str string, a ...interface{}) {
}
}
-func readTLS(filename string) (map[string]*x509.Certificate, error) {
+type Cert struct {
+ Url string
+ X509 *x509.Certificate
+}
+
+func (cert Cert) WriteTo(w io.Writer, action string) error {
+ block := pem.Block{
+ Type: "CERTIFICATE",
+ Headers: map[string]string{
+ "X-Crt-Sh-Url": cert.Url,
+ "X-Diff-Action": action,
+ },
+ Bytes: cert.X509.Raw,
+ }
+ return pem.Encode(w, &block)
+}
+
+func readTLS(filename string) (map[string]Cert, error) {
file, err := os.Open(filename)
if err != nil {
return nil, err
@@ -28,7 +45,7 @@ func readTLS(filename string) (map[string]*x509.Certificate, error) {
return nil, err
}
- ret := make(map[string]*x509.Certificate)
+ ret := make(map[string]Cert)
for len(data) > 0 {
var certPem *pem.Block
certPem, data = pem.Decode(data)
@@ -36,12 +53,15 @@ func readTLS(filename string) (map[string]*x509.Certificate, error) {
if err != nil {
return nil, err
}
- ret[certX509.Subject.CommonName] = certX509
+ ret[certX509.Subject.CommonName] = Cert{
+ Url: fmt.Sprintf("https://crt.sh/?serial=%036x", certX509.SerialNumber),
+ X509: certX509,
+ }
}
return ret, nil
}
-func readCrtSh(filename string, hosts []string) (map[string]*x509.Certificate, error) {
+func readCrtSh(filename string, hosts []string) (map[string]Cert, error) {
file, err := os.Open(filename)
if err != nil {
return nil, err
@@ -51,7 +71,7 @@ func readCrtSh(filename string, hosts []string) (map[string]*x509.Certificate, e
return nil, err
}
- ret := make(map[string]*x509.Certificate)
+ ret := make(map[string]Cert)
for len(data) > 0 {
var certPem *pem.Block
certPem, data = pem.Decode(data)
@@ -61,8 +81,11 @@ func readCrtSh(filename string, hosts []string) (map[string]*x509.Certificate, e
}
for _, host := range hosts {
if certX509.VerifyHostname(host) == nil {
- if old, haveold := ret[host]; !haveold || certX509.NotBefore.After(old.NotBefore) {
- ret[host] = certX509
+ if old, haveold := ret[host]; !haveold || certX509.NotBefore.After(old.X509.NotBefore) {
+ ret[host] = Cert{
+ Url: certPem.Headers["X-Crt-Sh-Url"],
+ X509: certX509,
+ }
}
}
}
@@ -70,7 +93,7 @@ func readCrtSh(filename string, hosts []string) (map[string]*x509.Certificate, e
return ret, nil
}
-func keys(m map[string]*x509.Certificate) []string {
+func keys(m map[string]Cert) []string {
ret := make([]string, len(m))
i := 0
for k := range m {
@@ -79,113 +102,6 @@ func keys(m map[string]*x509.Certificate) []string {
}
sort.Strings(ret)
return ret
-}
-
-func fmtCert(cert *x509.Certificate) string {
- return fmt.Sprintf("%s\t%s\t%s",
- cert.Subject.CommonName,
- cert.NotBefore.Format("2006-01-02 15:04:05 MST(-07)"),
- 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 a {
- background-color: #AAAAF3;
- }
- td a {
- text-decoration: none;
- padding: 0.1em 0.25em;
- display: block;
- width: 100%;
- height: 100%;
- color: black;
- }
- </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}}">{{if eq .pfix " "}}&nbsp;{{else}}{{.pfix}}{{end}}</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() {
@@ -198,20 +114,17 @@ func main() {
certsCrtSh, err := readCrtSh(os.Args[2], hostsTLS)
handleErr(err, "Could load crt.sh file: %v\n")
- certs := make([]Cert, len(certsTLS))
- i := 0
for _, host := range hostsTLS {
- var cert Cert
- cert.TLS = certsTLS[host]
- cert.CrtSh = certsCrtSh[host]
- certs[i] = cert
- i++
+ certTLS := certsTLS[host]
+ certCrtSh, haveCrtSh := certsCrtSh[host]
+
+ if !haveCrtSh {
+ handleErr(certTLS.WriteTo(os.Stdout, "del"), "Could not encode PEM: %v\n")
+ } else if ! certTLS.X509.Equal(certCrtSh.X509) {
+ handleErr(certTLS.WriteTo(os.Stdout, "del"), "Could not encode PEM: %v\n")
+ handleErr(certCrtSh.WriteTo(os.Stdout, "add"), "Could not encode PEM: %v\n")
+ } else {
+ handleErr(certCrtSh.WriteTo(os.Stdout, "ctx"), "Could not encode PEM: %v\n")
+ }
}
- 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")
}