// CompareExpiryUbiquity ranks two certificate chains based on the exiry dates of intermediates and roots. // Certs expire later are ranked higher than ones expire earlier. The ranking between chains are determined by // the first pair of intermediates, scanned from the root level, that ar ranked differently. func CompareExpiryUbiquity(chain1, chain2 []*x509.Certificate) int { for i := 0; ; i++ { if i >= len(chain1) || i >= len(chain2) { break } c1 := chain1[len(chain1)-1-i] c2 := chain2[len(chain2)-1-i] t1 := c1.NotAfter t2 := c2.NotAfter // Check if expiry dates valid. Return if one or other is invalid. // Otherwise rank by expiry date. Later is ranked higher. c1Valid := helpers.ValidExpiry(c1) c2Valid := helpers.ValidExpiry(c2) if c1Valid && !c2Valid { return 1 } if !c1Valid && c2Valid { return -1 } r := compareTime(t1, t2) // Return when we find rank difference. if r != 0 { return r } } return 0 }
func chainValidation(addr, hostname string) (grade Grade, output Output, err error) { chain, err := getChain(addr, defaultTLSConfig(hostname)) if err != nil { return } var warnings []string for i := 0; i < len(chain)-1; i++ { cert, parent := chain[i], chain[i+1] valid := helpers.ValidExpiry(cert) if !valid { warnings = append(warnings, fmt.Sprintf("Certificate for %s is valid for too long", cert.Subject.CommonName)) } revoked, ok := revoke.VerifyCertificate(cert) if !ok { warnings = append(warnings, fmt.Sprintf("couldn't check if %s is revoked", cert.Subject.CommonName)) } if revoked { err = fmt.Errorf("%s is revoked", cert.Subject.CommonName) return } if !parent.IsCA { err = fmt.Errorf("%s is not a CA", parent.Subject.CommonName) return } if !bytes.Equal(cert.AuthorityKeyId, parent.SubjectKeyId) { err = fmt.Errorf("%s AuthorityKeyId differs from %s SubjectKeyId", cert.Subject.CommonName, parent.Subject.CommonName) return } if err = cert.CheckSignatureFrom(parent); err != nil { return } switch cert.SignatureAlgorithm { case x509.ECDSAWithSHA1: warnings = append(warnings, fmt.Sprintf("%s is signed by ECDSAWithSHA1", cert.Subject.CommonName)) case x509.SHA1WithRSA: warnings = append(warnings, fmt.Sprintf("%s is signed by RSAWithSHA1", cert.Subject.CommonName)) } } if len(warnings) == 0 { grade = Good } else { grade = Warning output = warnings } return }