// countCertificatesByNames returns, for a single domain, the count of // certificates issued in the given time range for that domain and its // subdomains. // The highest count this function can return is 10,000. If there are more // certificates than that matching one of the provided domain names, it will return // TooManyCertificatesError. func (ssa *SQLStorageAuthority) countCertificatesByName(domain string, earliest, latest time.Time) (int, error) { var count int64 const max = 10000 var serials []struct { Serial string } _, err := ssa.dbMap.Select( &serials, `SELECT serial from issuedNames WHERE (reversedName = :reversedDomain OR reversedName LIKE CONCAT(:reversedDomain, ".%")) AND notBefore > :earliest AND notBefore <= :latest LIMIT :limit;`, map[string]interface{}{ "reversedDomain": core.ReverseName(domain), "earliest": earliest, "latest": latest, "limit": max + 1, }) if err == sql.ErrNoRows { return 0, nil } else if err != nil { return -1, err } else if count > max { return max, TooManyCertificatesError(fmt.Sprintf("More than %d issuedName entries for %s.", max, domain)) } serialMap := make(map[string]struct{}, len(serials)) for _, s := range serials { serialMap[s.Serial] = struct{}{} } return len(serialMap), nil }
// LoadRules loads the whitelist and blacklist into the database in a transaction // deleting any previous content func (padb *PolicyAuthorityDatabaseImpl) LoadRules(rs RuleSet) error { tx, err := padb.dbMap.Begin() if err != nil { tx.Rollback() return err } _, err = tx.Exec("DELETE FROM blacklist") if err != nil { tx.Rollback() return err } for _, r := range rs.Blacklist { r.Host = core.ReverseName(r.Host) tx.Insert(&r) } _, err = tx.Exec("DELETE FROM whitelist") if err != nil { tx.Rollback() return err } for _, r := range rs.Whitelist { tx.Insert(&r) } err = tx.Commit() return err }
func addIssuedNames(tx execable, cert *x509.Certificate) error { var qmarks []string var values []interface{} for _, name := range cert.DNSNames { values = append(values, core.ReverseName(name), core.SerialToString(cert.SerialNumber), cert.NotBefore) qmarks = append(qmarks, "(?, ?, ?)") } query := `INSERT INTO issuedNames (reversedName, serial, notBefore) VALUES ` + strings.Join(qmarks, ", ") + `;` _, err := tx.Exec(query, values...) return err }
// CheckHostLists will query the database for white/blacklist rules that match host, // if both whitelist and blacklist rules are found the blacklist will always win func (padb *PolicyAuthorityDatabaseImpl) CheckHostLists(host string, requireWhitelisted bool) error { if requireWhitelisted { if !padb.allowedByWhitelist(host) { // return fmt.Errorf("Domain is not whitelisted for issuance") return ErrNotWhitelisted } } // Overrides the whitelist if a blacklist rule is found host = core.ReverseName(host) if !padb.allowedByBlacklist(host) { // return fmt.Errorf("Domain is blacklisted for issuance") return ErrBlacklisted } return nil }
// DumpRules retrieves all domainRules in the database so they can be written to // disk func (padb *PolicyAuthorityDatabaseImpl) DumpRules() (rs RuleSet, err error) { var bList []BlacklistRule _, err = padb.dbMap.Select(&bList, "SELECT * FROM blacklist") if err != nil { return } for _, r := range bList { r.Host = core.ReverseName(r.Host) rs.Blacklist = append(rs.Blacklist, r) } var wList []WhitelistRule _, err = padb.dbMap.Select(&wList, "SELECT * FROM whitelist") if err != nil { return } rs.Whitelist = wList return rs, err }
// AddCertificate stores an issued certificate. func (ssa *SQLStorageAuthority) AddCertificate(certDER []byte, regID int64) (digest string, err error) { var parsedCertificate *x509.Certificate parsedCertificate, err = x509.ParseCertificate(certDER) if err != nil { return } digest = core.Fingerprint256(certDER) serial := core.SerialToString(parsedCertificate.SerialNumber) cert := &core.Certificate{ RegistrationID: regID, Serial: serial, Digest: digest, DER: certDER, Issued: ssa.clk.Now(), Expires: parsedCertificate.NotAfter, } certStatus := &core.CertificateStatus{ SubscriberApproved: false, Status: core.OCSPStatus("good"), OCSPLastUpdated: time.Time{}, OCSPResponse: []byte{}, Serial: serial, RevokedDate: time.Time{}, RevokedReason: 0, LockCol: 0, } issuedNames := make([]issuedNameModel, len(parsedCertificate.DNSNames)) for i, name := range parsedCertificate.DNSNames { issuedNames[i] = issuedNameModel{ ReversedName: core.ReverseName(name), Serial: serial, NotBefore: parsedCertificate.NotBefore, } } tx, err := ssa.dbMap.Begin() if err != nil { return } // TODO Verify that the serial number doesn't yet exist err = tx.Insert(cert) if err != nil { tx.Rollback() return } err = tx.Insert(certStatus) if err != nil { tx.Rollback() return } for _, issuedName := range issuedNames { err = tx.Insert(&issuedName) if err != nil { tx.Rollback() return } } err = tx.Commit() return }