diff options
-rw-r--r-- | tls-getcerts.go | 22 | ||||
-rw-r--r-- | tls-pem2html.go | 36 |
2 files changed, 47 insertions, 11 deletions
diff --git a/tls-getcerts.go b/tls-getcerts.go index ba951c9..49e15a2 100644 --- a/tls-getcerts.go +++ b/tls-getcerts.go @@ -5,16 +5,33 @@ import ( "crypto/x509" "encoding/pem" "fmt" + "net" "os" ) func getcert(socket string) (*x509.Certificate, error){ + host, _, err := net.SplitHostPort(socket) + if err != nil { + return nil, err + } conn, err := tls.Dial("tcp", socket, &tls.Config{InsecureSkipVerify: true}) if err != nil { return nil, err } defer conn.Close() - return conn.ConnectionState().PeerCertificates[0], nil + cstate := conn.ConnectionState() + + opts := x509.VerifyOptions{ + DNSName: host, + Intermediates: x509.NewCertPool(), + } + for _, cert := range cstate.PeerCertificates[1:] { + opts.Intermediates.AddCert(cert) + } + + cert := cstate.PeerCertificates[0] + _, err = cert.Verify(opts) + return cert, err } func main() { @@ -29,6 +46,9 @@ func main() { Headers: map[string]string{"X-Socket": socket}, Bytes: cert.Raw, } + if err != nil { + block.Headers["X-Error"] = err.Error() + } pem.Encode(os.Stdout, &block) } } diff --git a/tls-pem2html.go b/tls-pem2html.go index efefd68..a68a58a 100644 --- a/tls-pem2html.go +++ b/tls-pem2html.go @@ -33,7 +33,7 @@ var tmpl = template.Must(template.New("pem2html"). <html lang="en"> <head> <meta charset="utf-8"> - <title>CT log</title> + <title>Live Certs</title> <style> html { height: 100%; @@ -63,7 +63,10 @@ var tmpl = template.Must(template.New("pem2html"). td { background-color: #F3F3F3; } - tr:hover td { + tr.invalid td { + background-color: #F30000 !important; + } + tr:hover td, tr.invalid:hover td { background-color: #AAAAF3 !important; } td a { @@ -73,9 +76,6 @@ var tmpl = template.Must(template.New("pem2html"). height: 100%; color: black; } - tr.expired td { - background-color: #F30000; - } </style> <script src="sorttable.js"></script> </head> @@ -91,11 +91,11 @@ var tmpl = template.Must(template.New("pem2html"). <th>Socket</th> </tr> {{range $cert := .certs}} - <tr> - <td style="background-color: ${$cert.X509.NotBefore | green}}">{{$cert.X509.NotBefore.Local.Format "2006-01-02"}}</td> - <td style="background-color: {{$cert.X509.NotAfter | red}}" >{{$cert.X509.NotAfter.Local.Format "2006-01-02"}}</td> - <td>{{$cert.X509.Subject.CommonName | html}}</td> - <td>{{$cert.Socket | html}}</td> + <tr class="{{$cert.Class}}"> + <td style="background-color: {{$cert.X509.NotBefore | green}}"><a href="{{$cert.Link}}" title="{{$cert.Error}}">{{$cert.X509.NotBefore.Local.Format "2006-01-02"}}</a></td> + <td style="background-color: {{$cert.X509.NotAfter | red }}"><a href="{{$cert.Link}}" title="{{$cert.Error}}">{{$cert.X509.NotAfter.Local.Format "2006-01-02"}}</a></td> + <td><a href="{{$cert.Link}}" title="{{$cert.Error}}">{{$cert.X509.Subject.CommonName | html}}</a></td> + <td><a href="{{$cert.Link}}" title="{{$cert.Error}}">{{$cert.Socket | html}}</a></td> </tr> {{end}} </table> @@ -153,9 +153,23 @@ func red(t time.Time) string { type Cert struct { Socket string + Error string X509 *x509.Certificate } +func (cert Cert) Link() string { + return fmt.Sprintf("https://crt.sh/?serial=%036x", cert.X509.SerialNumber) +} + +func (cert Cert) Class() string { + if cert.Error == "" { + return "" + } else { + return "invalid" + } +} + + type Certs []Cert // Len is the number of elements in the collection. @@ -191,6 +205,8 @@ func main() { cert.Socket, ok = certPem.Headers["X-Socket"] handleBool(ok, "Did not get X-Socket\n") + cert.Error, ok = certPem.Headers["X-Error"] + cert.X509, err = x509.ParseCertificate(certPem.Bytes) handleErr(err, "Error parsing cert: %v\n") |