Save consistency proof along with evidence of misbehavior

Although the consistency proof is neither necessary nor sufficient
to prove misbehavior by a log, this will help with debugging if a
log returns a bogus consistency proof erroneously (which seems to
be happening with the Rocketeer log lately...).
This commit is contained in:
Andrew Ayer 2016-04-06 08:10:06 -07:00
parent db2cd2c458
commit e091186d83
3 changed files with 26 additions and 11 deletions

View File

@ -84,20 +84,25 @@ func defangLogUri (logUri string) string {
return strings.Replace(strings.Replace(logUri, "://", "_", 1), "/", "_", -1) return strings.Replace(strings.Replace(logUri, "://", "_", 1), "/", "_", -1)
} }
func saveEvidence (logUri string, firstSTH *ct.SignedTreeHead, secondSTH *ct.SignedTreeHead) (string, string, error) { func saveEvidence (logUri string, firstSTH *ct.SignedTreeHead, secondSTH *ct.SignedTreeHead, proof ct.ConsistencyProof) (string, string, string, error) {
now := strconv.FormatInt(time.Now().Unix(), 10) now := strconv.FormatInt(time.Now().Unix(), 10)
firstFilename := filepath.Join(stateDir, "evidence", defangLogUri(logUri) + ".inconsistent." + now + ".first") firstFilename := filepath.Join(stateDir, "evidence", defangLogUri(logUri) + ".inconsistent." + now + ".first")
if err := ctwatch.WriteSTHFile(firstFilename, firstSTH); err != nil { if err := ctwatch.WriteSTHFile(firstFilename, firstSTH); err != nil {
return "", "", err return "", "", "", err
} }
secondFilename := filepath.Join(stateDir, "evidence", defangLogUri(logUri) + ".inconsistent." + now + ".second") secondFilename := filepath.Join(stateDir, "evidence", defangLogUri(logUri) + ".inconsistent." + now + ".second")
if err := ctwatch.WriteSTHFile(secondFilename, secondSTH); err != nil { if err := ctwatch.WriteSTHFile(secondFilename, secondSTH); err != nil {
return "", "", err return "", "", "", err
} }
return firstFilename, secondFilename, nil proofFilename := filepath.Join(stateDir, "evidence", defangLogUri(logUri) + ".inconsistent." + now + ".proof")
if err := ctwatch.WriteProofFile(proofFilename, proof); err != nil {
return "", "", "", err
}
return firstFilename, secondFilename, proofFilename, nil
} }
func Main (argStateDir string, processCallback ctwatch.ProcessCallback) { func Main (argStateDir string, processCallback ctwatch.ProcessCallback) {
@ -200,18 +205,19 @@ func Main (argStateDir string, processCallback ctwatch.ProcessCallback) {
if prevSTH != nil { if prevSTH != nil {
var valid bool var valid bool
var err error var err error
valid, treeBuilder, err = scanner.CheckConsistency(prevSTH, latestSTH) var proof ct.ConsistencyProof
valid, treeBuilder, proof, err = scanner.CheckConsistency(prevSTH, latestSTH)
if err != nil { if err != nil {
log.Printf("Error fetching consistency proof: %s\n", err) log.Printf("Error fetching consistency proof: %s\n", err)
exitCode |= 4 exitCode |= 4
continue continue
} }
if !valid { if !valid {
firstFilename, secondFilename, err := saveEvidence(logUri, prevSTH, latestSTH) firstFilename, secondFilename, proofFilename, err := saveEvidence(logUri, prevSTH, latestSTH, proof)
if err != nil { if err != nil {
log.Printf("Consistency proof failed - the log has misbehaved! Saving evidence of misbehavior failed: %s\n", err) log.Printf("Consistency proof failed - the log has misbehaved! Saving evidence of misbehavior failed: %s\n", err)
} else { } else {
log.Printf("Consistency proof failed - the log has misbehaved! Evidence of misbehavior has been saved to '%s' and '%s'.\n", firstFilename, secondFilename) log.Printf("Consistency proof failed - the log has misbehaved! Evidence of misbehavior has been saved to '%s' and '%s' (with proof in '%s').\n", firstFilename, secondFilename, proofFilename)
} }
exitCode |= 8 exitCode |= 8
continue continue

View File

@ -46,6 +46,15 @@ func WriteSTHFile (path string, sth *ct.SignedTreeHead) error {
return ioutil.WriteFile(path, sthJson, 0666) return ioutil.WriteFile(path, sthJson, 0666)
} }
func WriteProofFile (path string, proof ct.ConsistencyProof) error {
proofJson, err := json.MarshalIndent(proof, "", "\t")
if err != nil {
return err
}
proofJson = append(proofJson, byte('\n'))
return ioutil.WriteFile(path, proofJson, 0666)
}
func IsPrecert (entry *ct.LogEntry) bool { func IsPrecert (entry *ct.LogEntry) bool {
return entry.Leaf.TimestampedEntry.EntryType == ct.PrecertLogEntryType return entry.Leaf.TimestampedEntry.EntryType == ct.PrecertLogEntryType
} }

View File

@ -202,12 +202,12 @@ func (s *Scanner) GetSTH() (*ct.SignedTreeHead, error) {
return latestSth, nil return latestSth, nil
} }
func (s *Scanner) CheckConsistency(first *ct.SignedTreeHead, second *ct.SignedTreeHead) (bool, *MerkleTreeBuilder, error) { func (s *Scanner) CheckConsistency(first *ct.SignedTreeHead, second *ct.SignedTreeHead) (bool, *MerkleTreeBuilder, ct.ConsistencyProof, error) {
var proof ct.ConsistencyProof var proof ct.ConsistencyProof
if first.TreeSize > second.TreeSize { if first.TreeSize > second.TreeSize {
// No way this can be valid // No way this can be valid
return false, nil, nil return false, nil, nil, nil
} else if first.TreeSize == second.TreeSize { } else if first.TreeSize == second.TreeSize {
// The proof *should* be empty, so don't bother contacting the server. // The proof *should* be empty, so don't bother contacting the server.
// This is necessary because the digicert server returns a 400 error if first==second. // This is necessary because the digicert server returns a 400 error if first==second.
@ -216,12 +216,12 @@ func (s *Scanner) CheckConsistency(first *ct.SignedTreeHead, second *ct.SignedTr
var err error var err error
proof, err = s.logClient.GetConsistencyProof(int64(first.TreeSize), int64(second.TreeSize)) proof, err = s.logClient.GetConsistencyProof(int64(first.TreeSize), int64(second.TreeSize))
if err != nil { if err != nil {
return false, nil, err return false, nil, nil, err
} }
} }
valid, treeBuilder := VerifyConsistencyProof(proof, first, second) valid, treeBuilder := VerifyConsistencyProof(proof, first, second)
return valid, treeBuilder, nil return valid, treeBuilder, proof, nil
} }
func (s *Scanner) Scan(startIndex int64, endIndex int64, processCert ProcessCallback, treeBuilder *MerkleTreeBuilder) error { func (s *Scanner) Scan(startIndex int64, endIndex int64, processCert ProcessCallback, treeBuilder *MerkleTreeBuilder) error {