1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
package main
import (
"crypto/sha256"
"encoding/base64"
"encoding/json"
"io"
"log"
"net/http"
"os"
"sync"
"github.com/google/certificate-transparency/go/fixchain"
"github.com/google/certificate-transparency/go/fixchain/ratelimiter"
"github.com/google/certificate-transparency/go/x509"
)
// Assumes chains to be stores in a file in JSON encoded with the certificates
// in DER format.
func processChains(file string, fl *fixchain.FixAndLog) {
f, err := os.Open(file)
if err != nil {
log.Fatalf("Can't open %q: %s", file, err)
}
defer f.Close()
type Chain struct {
Chain [][]byte
}
dec := json.NewDecoder(f)
for {
var m Chain
if err := dec.Decode(&m); err == io.EOF {
break
} else if err != nil {
log.Fatal(err)
}
var chain []*x509.Certificate
for _, derBytes := range m.Chain {
cert, err := x509.ParseCertificate(derBytes)
switch err.(type) {
case nil, x509.NonFatalErrors:
// ignore
default:
log.Fatalf("can't parse certificate: %s %#v",
err, derBytes)
}
chain = append(chain, cert)
}
fl.QueueAllCertsInChain(chain)
}
}
// A simple function to save the FixErrors that are spat out by the FixAndLog to
// a directory. contentStore() is the function to alter to store the errors
// wherever/however they need to be stored. Both logStringErrors() and
// logJSONErrors() use this function as a way of storing the resulting
// FixErrors.
func contentStore(baseDir string, subDir string, content []byte) {
r := sha256.Sum256(content)
h := base64.URLEncoding.EncodeToString(r[:])
d := baseDir + "/" + subDir
os.MkdirAll(d, 0777)
fn := d + "/" + h
f, err := os.Create(fn)
if err != nil {
log.Fatalf("Can't create %q: %s", fn, err)
}
defer f.Close()
f.Write(content)
}
func logStringErrors(wg *sync.WaitGroup, errors chan *fixchain.FixError, baseDir string) {
defer wg.Done()
for err := range errors {
contentStore(baseDir, err.TypeString(), []byte(err.String()))
}
}
func logJSONErrors(wg *sync.WaitGroup, errors chan *fixchain.FixError, baseDir string) {
defer wg.Done()
for err := range errors {
b, err2 := err.MarshalJSON()
if err2 != nil {
log.Fatalf("JSON encode failed: %s", err2)
}
contentStore(baseDir, err.TypeString(), b)
}
}
func main() {
logURL := os.Args[1]
chainsFile := os.Args[2]
errDir := os.Args[3]
var wg sync.WaitGroup
wg.Add(1)
errors := make(chan *fixchain.FixError)
// Functions to log errors as strings or as JSON are provided.
// As-is, this will log errors as strings.
go logStringErrors(&wg, errors, errDir)
limiter := ratelimiter.NewLimiter(1000)
client := &http.Client{}
fl := fixchain.NewFixAndLog(100, 100, errors, client, client, logURL, limiter, true)
processChains(chainsFile, fl)
log.Printf("Wait for fixers and loggers")
fl.Wait()
close(errors)
log.Printf("Wait for errors")
wg.Wait()
}
|