blob: 423cb7edbfea1b9e05072cd11d0fb26b92cc2f27 [file] [log] [blame]
Serge Bazanskiec71cb52019-08-22 18:13:13 +02001package main
2
3import (
4 "context"
5 "encoding/hex"
6 "fmt"
7 "sync"
8 "time"
9
10 pb "code.hackerspace.pl/hscloud/bgpwtf/cccampix/proto"
11 "code.hackerspace.pl/hscloud/bgpwtf/cccampix/verifier/model"
12 "github.com/golang/glog"
13 "google.golang.org/grpc/codes"
14 "google.golang.org/grpc/status"
15)
16
17type pgp struct {
18 pgpc pb.PGPEncryptorClient
19}
20
21func newPGP(pgpc pb.PGPEncryptorClient) (*pgp, error) {
22 return &pgp{
23 pgpc: pgpc,
24 }, nil
25}
26
27func (p *pgp) Name() string {
28 return "PGP"
29}
30
31func (p *pgp) NextRun(now time.Time, lastRun bool) time.Time {
32 if lastRun {
33 return now.Add(1 * time.Minute)
34 }
35 return now.Add(15 * time.Minute)
36}
37
38func (p *pgp) RunAll(ctx context.Context, m model.Model) error {
39 keys, err := m.GetPGPKeysRequiringAttention(ctx)
40 if err != nil {
41 return fmt.Errorf("GetPGPKeysRequiringAttention: %v", err)
42 }
43
44 if len(keys) == 0 {
45 return nil
46 }
47
48 s := make(chan struct{}, 20)
49 errC := make(chan error, len(keys))
50 knownC := make(chan *model.PeerPGPKey, len(keys))
51 unknownC := make(chan *model.PeerPGPKey, len(keys))
52
53 var wg sync.WaitGroup
54 wg.Add(len(keys))
55
56 for _, key := range keys {
57 go func(k *model.PeerPGPKey) {
58 s <- struct{}{}
59 defer func() {
60 wg.Done()
61 <-s
62 }()
63
64 glog.Infof("PGP: Processing %v", *k)
65
66 // HACK(q3k)
67 if k.State == "known" {
68 knownC <- k
69 return
70 }
71
72 fp, err := hex.DecodeString(k.Fingerprint)
73 if err != nil {
74 errC <- fmt.Errorf("could not decode fingerprint %q: %v", k.Fingerprint, err)
75 return
76 }
77
78 req := &pb.KeyInfoRequest{
79 Fingerprint: fp,
80 Caching: pb.KeyInfoRequest_CACHING_FORCE_REMOTE,
81 }
82
83 _, err = p.pgpc.KeyInfo(ctx, req)
84 s, ok := status.FromError(err)
85 switch {
86 case err == nil:
87 knownC <- k
88 case ok && s.Code() == codes.NotFound:
89 unknownC <- k
90 default:
91 errC <- err
92 }
93 }(key)
94 }
95
96 wg.Wait()
97 close(errC)
98 close(knownC)
99 close(unknownC)
100
101 pcr := []*model.PeerCheckResult{}
102
103 positive := []string{}
104 for p := range knownC {
105 positive = append(positive, p.Fingerprint)
106 pcr = append(pcr, &model.PeerCheckResult{
107 PeerASN: p.PeerASN,
108 CheckName: "pgp",
109 Time: time.Now(),
110 Status: model.PeerCheckStatus_Okay,
111 })
112 }
113 negative := []string{}
114 for n := range unknownC {
115 negative = append(negative, n.Fingerprint)
116 pcr = append(pcr, &model.PeerCheckResult{
117 PeerASN: n.PeerASN,
118 CheckName: "pgp",
119 Time: time.Now(),
120 Status: model.PeerCheckStatus_Failed,
121 Message: fmt.Sprintf("key %q not found on keyservers", n.Fingerprint),
122 })
123 }
124
125 glog.Infof("%v, %v", positive, negative)
126
127 if len(positive) > 0 || len(negative) > 0 {
128 err := m.ValidatePGPKeys(ctx, positive, negative)
129 if err != nil {
130 return fmt.Errorf("ValidatePGPKeys(%v, %v): %v", positive, negative, err)
131 }
132 }
133
134 if len(pcr) > 0 {
135 err = m.SubmitPeerCheckResults(ctx, "pgp", pcr)
136 if err != nil {
137 return err
138 }
139 }
140
141 errs := []error{}
142 for err := range errC {
143 errs = append(errs, err)
144 }
145
146 if len(errs) > 0 {
147 glog.Errorf("Errors while processing keys: %v", errs)
148 return fmt.Errorf("Errors ocurred while processing keys")
149 }
150
151 return nil
152
153}