package main import ( "context" "encoding/hex" "fmt" "sync" "time" pb "code.hackerspace.pl/hscloud/bgpwtf/cccampix/proto" "code.hackerspace.pl/hscloud/bgpwtf/cccampix/verifier/model" "github.com/golang/glog" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) type pgp struct { pgpc pb.PGPEncryptorClient } func newPGP(pgpc pb.PGPEncryptorClient) (*pgp, error) { return &pgp{ pgpc: pgpc, }, nil } func (p *pgp) Name() string { return "PGP" } func (p *pgp) NextRun(now time.Time, lastRun bool) time.Time { if lastRun { return now.Add(1 * time.Minute) } return now.Add(15 * time.Minute) } func (p *pgp) RunAll(ctx context.Context, m model.Model) error { keys, err := m.GetPGPKeysRequiringAttention(ctx) if err != nil { return fmt.Errorf("GetPGPKeysRequiringAttention: %v", err) } if len(keys) == 0 { return nil } s := make(chan struct{}, 20) errC := make(chan error, len(keys)) knownC := make(chan *model.PeerPGPKey, len(keys)) unknownC := make(chan *model.PeerPGPKey, len(keys)) var wg sync.WaitGroup wg.Add(len(keys)) for _, key := range keys { go func(k *model.PeerPGPKey) { s <- struct{}{} defer func() { wg.Done() <-s }() glog.Infof("PGP: Processing %v", *k) // HACK(q3k) if k.State == "known" { knownC <- k return } fp, err := hex.DecodeString(k.Fingerprint) if err != nil { errC <- fmt.Errorf("could not decode fingerprint %q: %v", k.Fingerprint, err) return } req := &pb.KeyInfoRequest{ Fingerprint: fp, Caching: pb.KeyInfoRequest_CACHING_FORCE_REMOTE, } _, err = p.pgpc.KeyInfo(ctx, req) s, ok := status.FromError(err) switch { case err == nil: knownC <- k case ok && s.Code() == codes.NotFound: unknownC <- k default: errC <- err } }(key) } wg.Wait() close(errC) close(knownC) close(unknownC) pcr := []*model.PeerCheckResult{} positive := []string{} for p := range knownC { positive = append(positive, p.Fingerprint) pcr = append(pcr, &model.PeerCheckResult{ PeerASN: p.PeerASN, CheckName: "pgp", Time: time.Now(), Status: model.PeerCheckStatus_Okay, }) } negative := []string{} for n := range unknownC { negative = append(negative, n.Fingerprint) pcr = append(pcr, &model.PeerCheckResult{ PeerASN: n.PeerASN, CheckName: "pgp", Time: time.Now(), Status: model.PeerCheckStatus_Failed, Message: fmt.Sprintf("key %q not found on keyservers", n.Fingerprint), }) } glog.Infof("%v, %v", positive, negative) if len(positive) > 0 || len(negative) > 0 { err := m.ValidatePGPKeys(ctx, positive, negative) if err != nil { return fmt.Errorf("ValidatePGPKeys(%v, %v): %v", positive, negative, err) } } if len(pcr) > 0 { err = m.SubmitPeerCheckResults(ctx, "pgp", pcr) if err != nil { return err } } errs := []error{} for err := range errC { errs = append(errs, err) } if len(errs) > 0 { glog.Errorf("Errors while processing keys: %v", errs) return fmt.Errorf("Errors ocurred while processing keys") } return nil }