// 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
}
Exemple #2
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
}