diff options
author | Luke Shumaker <lukeshu@sbcglobal.net> | 2016-11-18 01:21:27 -0500 |
---|---|---|
committer | Luke Shumaker <lukeshu@sbcglobal.net> | 2016-11-18 01:21:27 -0500 |
commit | c4f6d3489ef91c539ba88e372635e4d0d87e6ad2 (patch) | |
tree | fbfc8755e3ba011e789723e4407b908b39bd5aad | |
parent | e339617040bde6ef57f4ccc896f9feba60dbe12f (diff) |
Check crt.sh against actual used certs
-rw-r--r-- | .gitignore | 9 | ||||
-rw-r--r-- | Makefile | 21 | ||||
-rw-r--r-- | config-domains.txt (renamed from domains.txt) | 0 | ||||
-rwxr-xr-x | cron-daily | 3 | ||||
-rwxr-xr-x | crtsh-getcerts (renamed from getcerts) | 0 | ||||
-rw-r--r-- | crtsh-pem2html.go (renamed from pem2html.go) | 0 | ||||
-rw-r--r-- | diff.go | 108 | ||||
-rw-r--r-- | tls-getcerts.go | 35 |
8 files changed, 167 insertions, 9 deletions
@@ -1,3 +1,8 @@ -certs.* -pem2html +*.html +*.pem +*.txt NET-* + +crtsh-pem2html +tls-getcerts +diff @@ -1,13 +1,22 @@ -all: certs.html +all: index.html -pem2html: %: %.go +index.html: crtsh.html + cp $< $@ + +%: %.go go build $< -certs.pem: getcerts domains.txt NET-crt.sh - ./getcerts $$(cat domains.txt) > $@ +crtsh.pem: crtsh-getcerts config-domains.txt NET-crtsh + ./crtsh-getcerts $$(cat config-domains.txt) > $@ + +crtsh.html: %.html: %.pem crtsh-pem2html + ./crtsh-pem2html < $< > $@ + +tls.pem: tls-getcerts config-servers.txt NET-tls + ./tls-getcerts $$(cat config-servers.txt) > $@ -certs.html: %.html: %.pem pem2html - ./pem2html < $< > $@ +diff.txt: diff tls.pem crtsh.pem + ./diff tls.pem crtsh.pem > $@ NET-%: date > $@ diff --git a/domains.txt b/config-domains.txt index 390a92e..390a92e 100644 --- a/domains.txt +++ b/config-domains.txt @@ -1,4 +1,5 @@ #!/bin/sh cd "$(dirname -- "$0")" -date > NET-crt.sh +date > NET-crtsh +date > NET-tls make diff --git a/getcerts b/crtsh-getcerts index 0191e2e..0191e2e 100755 --- a/getcerts +++ b/crtsh-getcerts diff --git a/pem2html.go b/crtsh-pem2html.go index b6effa4..b6effa4 100644 --- a/pem2html.go +++ b/crtsh-pem2html.go @@ -0,0 +1,108 @@ +package main + +import ( + "crypto/x509" + "encoding/pem" + "fmt" + "io/ioutil" + "os" + "sort" +) + +func handleErr(err error, str string, a ...interface{}) { + a = append([]interface{}{err}, a...) + if err != nil { + fmt.Fprintf(os.Stderr, str, a...) + os.Exit(1) + } +} + +func readTLS(filename string) (map[string]*x509.Certificate, error) { + file, err := os.Open(filename) + if err != nil { + return nil, err + } + data, err := ioutil.ReadAll(file) + if err != nil { + return nil, err + } + + ret := make(map[string]*x509.Certificate) + for len(data) > 0 { + var certPem *pem.Block + certPem, data = pem.Decode(data) + certX509, err := x509.ParseCertificate(certPem.Bytes) + if err != nil { + return nil, err + } + ret[certX509.Subject.CommonName] = certX509 + } + return ret, nil +} + +func readCrtSh(filename string, hosts []string) (map[string]*x509.Certificate, error) { + file, err := os.Open(filename) + if err != nil { + return nil, err + } + data, err := ioutil.ReadAll(file) + if err != nil { + return nil, err + } + + ret := make(map[string]*x509.Certificate) + for len(data) > 0 { + var certPem *pem.Block + certPem, data = pem.Decode(data) + certX509, err := x509.ParseCertificate(certPem.Bytes) + if err != nil { + return nil, err + } + for _, host := range hosts { + if certX509.VerifyHostname(host) == nil { + if old, haveold := ret[host]; !haveold || certX509.NotBefore.After(old.NotBefore) { + ret[host] = certX509 + } + } + } + } + return ret, nil +} + +func keys(m map[string]*x509.Certificate) []string { + ret := make([]string, len(m)) + i := 0 + for k := range m { + ret[i] = k + i++ + } + sort.Strings(ret) + return ret +} + +func main() { + if len(os.Args) != 3 { + fmt.Fprintf(os.Stderr, "Usage: %s TLS-file crt.sh-file\n", os.Args[0]) + } + certsTLS, err := readTLS(os.Args[1]) + handleErr(err, "Could load TLS file: %v\n") + hostsTLS := keys(certsTLS) + 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)) + for _, host := range hostsTLS { + certTLS := certsTLS[host] + certCrtSh, okCrtSh := certsCrtSh[host] + if !okCrtSh { + fmt.Printf("-%s %s\n", host, certTLS.NotBefore.Format("2006-01-02 15:04:05 MST(-07)")) + } else if !certTLS.Equal(certCrtSh) { + fmt.Printf("-%s %s\n", host, certTLS.NotBefore.Format("2006-01-02 15:04:05 MST(-07)")) + fmt.Printf("+%s %s\n", host, certCrtSh.NotBefore.Format("2006-01-02 15:04:05 MST(-07)")) + } else { + fmt.Printf(" %s %s\n", host, certTLS.NotBefore.Format("2006-01-02 15:04:05 MST(-07)")) + } + } +} diff --git a/tls-getcerts.go b/tls-getcerts.go new file mode 100644 index 0000000..b0d4533 --- /dev/null +++ b/tls-getcerts.go @@ -0,0 +1,35 @@ +package main + +import ( + "crypto/tls" + "crypto/x509" + "fmt" + "os" + "encoding/pem" +) + +func getcert(server string) (*x509.Certificate, error){ + conn, err := tls.Dial("tcp", fmt.Sprintf("%s:443", server), &tls.Config{ServerName: server}) + if err != nil { + return nil, err + } + defer conn.Close() + chain := conn.ConnectionState().PeerCertificates + return chain[len(chain)-2], nil +} + +func main() { + for _, server := range os.Args[1:] { + cert, err := getcert(server) + if err != nil { + fmt.Fprintf(os.Stderr, "Could not get certificate from server %q: %q\n", server, err) + os.Exit(1) + } + block := pem.Block{ + Type: "CERTIFICATE", + Headers: nil, + Bytes: cert.Raw, + } + pem.Encode(os.Stdout, &block) + } +} |