package main import ( "os" "log" "flag" "time" "math" "strings" "crypto/tls" "encoding/hex" "encoding/json" ) type zzz struct{ Data map[string]any } func pp(out *zzz, n string, v any) { b, ok := v.([]byte) if ok { out.Data[n] = hex.EncodeToString(b) } else { out.Data[n] = v } if false { log.Println(n, ":", out.Data[n]) } } func Proc(ipport string, arg... int) ([]map[string]interface{}, error) { var err error now := time.Now() ret := make([]map[string]interface{}, 0) conf := &tls.Config{ InsecureSkipVerify: true, } var ccnt int = 5 if len(arg) > 0 && arg[0] > 0 { ccnt = arg[0] } // log.Println("Connect", ipport, "max-count", ccnt) conn, err := tls.Dial("tcp", ipport, conf) if err != nil { return nil, err } defer conn.Close() cstat := conn.ConnectionState() certs := cstat.PeerCertificates for i, cert := range certs { if i >= ccnt { break } var out zzz = zzz{ Data: make(map[string]any), } DnsList := make([]string, 0) for _, dns := range cert.DNSNames { DnsList = append(DnsList, dns) } pp(&out, "Subject" , cert.Subject.String() ) pp(&out, "SerialNumber" , cert.SerialNumber.Bytes() ) pp(&out, "AuthorityKeyId" , cert.AuthorityKeyId ) pp(&out, "IssuerName" , cert.Issuer.String() ) pp(&out, "IssuerCommonName" , cert.Issuer.CommonName ) pp(&out, "ExpiryDateTime" , cert.NotAfter.Format(time.DateTime) ) pp(&out, "ExpiryDeltaDay" , math.Floor(cert.NotAfter.Sub( now ).Hours()/24) ) pp(&out, "DnsList" , DnsList ) // log.Println(out) ret = append(ret, out.Data) // log.Println("End") } return ret, nil } func main() { addr := flag.String("a", "google.com:443", "Checked host") ccnt := flag.Int("c", 1, "Max count certificates chain") mday := flag.Float64("m", 50, "Min day's cert valid, or return 2") flag.Parse() tail := flag.Args() for { if len(tail) == 0 { break } if len(tail) == 1 { addr = &tail[0] break } flag.PrintDefaults() os.Exit(1) } var ipport string = *addr aipp := strings.Split(*addr, ":") if len(aipp) < 2 { ipport = aipp[0] + ":443" } list, err := Proc(ipport, *ccnt) if err != nil { log.Println(err) os.Exit(1) } jsonResp, _ := json.MarshalIndent(list, "", "\t") log.Println(string(jsonResp)) if list[0]["ExpiryDeltaDay"].(float64) < *mday { os.Exit(2) } os.Exit(0) }