github.com/google/syzkaller@v0.0.0-20240517125934-c0f1611a36d6/syz-hub/hub.go (about) 1 // Copyright 2016 syzkaller project authors. All rights reserved. 2 // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. 3 4 package main 5 6 import ( 7 "flag" 8 "fmt" 9 "strings" 10 "sync" 11 "time" 12 13 "github.com/google/syzkaller/pkg/auth" 14 "github.com/google/syzkaller/pkg/config" 15 "github.com/google/syzkaller/pkg/log" 16 "github.com/google/syzkaller/pkg/rpctype" 17 "github.com/google/syzkaller/syz-hub/state" 18 ) 19 20 var ( 21 flagConfig = flag.String("config", "", "config file") 22 ) 23 24 type Config struct { 25 HTTP string 26 RPC string 27 Workdir string 28 Clients []struct { 29 Name string 30 Key string 31 } 32 } 33 34 type Hub struct { 35 mu sync.Mutex 36 st *state.State 37 keys map[string]string 38 auth auth.Endpoint 39 } 40 41 func main() { 42 flag.Parse() 43 cfg := new(Config) 44 if err := config.LoadFile(*flagConfig, cfg); err != nil { 45 log.Fatal(err) 46 } 47 log.EnableLogCaching(1000, 1<<20) 48 49 st, err := state.Make(cfg.Workdir) 50 if err != nil { 51 log.Fatalf("failed to load state: %v", err) 52 } 53 hub := &Hub{ 54 st: st, 55 keys: make(map[string]string), 56 auth: auth.MakeEndpoint(auth.GoogleTokenInfoEndpoint), 57 } 58 for _, mgr := range cfg.Clients { 59 hub.keys[mgr.Name] = mgr.Key 60 } 61 62 hub.initHTTP(cfg.HTTP) 63 64 s, err := rpctype.NewRPCServer(cfg.RPC, "Hub", hub) 65 if err != nil { 66 log.Fatalf("failed to create rpc server: %v", err) 67 } 68 log.Logf(0, "serving rpc on tcp://%v", s.Addr()) 69 s.Serve() 70 } 71 72 func (hub *Hub) Connect(a *rpctype.HubConnectArgs, r *int) error { 73 name, err := hub.checkManager(a.Client, a.Key, a.Manager) 74 if err != nil { 75 return err 76 } 77 hub.mu.Lock() 78 defer hub.mu.Unlock() 79 80 log.Logf(0, "connect from %v: domain=%v fresh=%v calls=%v corpus=%v", 81 name, a.Domain, a.Fresh, len(a.Calls), len(a.Corpus)) 82 if err := hub.st.Connect(name, a.Domain, a.Fresh, a.Calls, a.Corpus); err != nil { 83 log.Logf(0, "connect error: %v", err) 84 return err 85 } 86 return nil 87 } 88 89 func (hub *Hub) Sync(a *rpctype.HubSyncArgs, r *rpctype.HubSyncRes) error { 90 name, err := hub.checkManager(a.Client, a.Key, a.Manager) 91 if err != nil { 92 return err 93 } 94 hub.mu.Lock() 95 defer hub.mu.Unlock() 96 97 domain, inputs, more, err := hub.st.Sync(name, a.Add, a.Del) 98 if err != nil { 99 log.Logf(0, "sync error: %v", err) 100 return err 101 } 102 if domain != "" { 103 r.Inputs = inputs 104 } else { 105 for _, inp := range inputs { 106 r.Progs = append(r.Progs, inp.Prog) 107 } 108 } 109 r.More = more 110 for _, repro := range a.Repros { 111 if err := hub.st.AddRepro(name, repro); err != nil { 112 log.Logf(0, "add repro error: %v", err) 113 } 114 } 115 if a.NeedRepros { 116 repro, err := hub.st.PendingRepro(name) 117 if err != nil { 118 log.Logf(0, "sync error: %v", err) 119 } 120 if repro != nil { 121 r.Repros = [][]byte{repro} 122 } 123 } 124 log.Logf(0, "sync from %v: recv: add=%v del=%v repros=%v; send: progs=%v repros=%v pending=%v", 125 name, len(a.Add), len(a.Del), len(a.Repros), len(inputs), len(r.Repros), more) 126 return nil 127 } 128 129 func (hub *Hub) verifyKey(key, expectedKey string) error { 130 if strings.HasPrefix(expectedKey, auth.OauthMagic) { 131 subj, err := hub.auth.DetermineAuthSubj(time.Now(), []string{key}) 132 if err != nil { 133 return err 134 } 135 if subj != expectedKey { 136 return fmt.Errorf("bad token") 137 } 138 // Success due to correct token. 139 return nil 140 } 141 if key != expectedKey { 142 return fmt.Errorf("bad password") 143 } 144 // Success due to correct password. 145 return nil 146 } 147 148 // Returns the verified manager identity or error. 149 func (hub *Hub) checkManager(client, key, manager string) (string, error) { 150 expectedKey, ok := hub.keys[client] 151 if !ok { 152 log.Logf(0, "connect from unauthorized client %v", client) 153 return "", fmt.Errorf("unauthorized manager") 154 } 155 if err := hub.verifyKey(key, expectedKey); err != nil { 156 log.Logf(0, "connect from unauthorized client %v", client) 157 return "", fmt.Errorf("unauthorized manager") 158 } 159 if manager == "" { 160 manager = client 161 } else if !strings.HasPrefix(manager, client) { 162 log.Logf(0, "manager %v does not have client prefix %v", manager, client) 163 return "", fmt.Errorf("unauthorized manager") 164 } 165 return manager, nil 166 }