github.com/google/syzkaller@v0.0.0-20251211124644-a066d2bc4b02/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 go hub.purgeOldManagers() 64 65 s, err := rpctype.NewRPCServer(cfg.RPC, "Hub", hub) 66 if err != nil { 67 log.Fatalf("failed to create rpc server: %v", err) 68 } 69 log.Logf(0, "serving rpc on tcp://%v", s.Addr()) 70 s.Serve() 71 } 72 73 func (hub *Hub) Connect(a *rpctype.HubConnectArgs, r *int) error { 74 name, err := hub.checkManager(a.Client, a.Key, a.Manager) 75 if err != nil { 76 return err 77 } 78 hub.mu.Lock() 79 defer hub.mu.Unlock() 80 81 log.Logf(0, "connect from %v (%v): domain=%v fresh=%v calls=%v corpus=%v", 82 name, a.HTTP, a.Domain, a.Fresh, len(a.Calls), len(a.Corpus)) 83 if err := hub.st.Connect(name, a.HTTP, a.Domain, a.Fresh, a.Calls, a.Corpus); err != nil { 84 log.Logf(0, "connect error: %v", err) 85 return err 86 } 87 return nil 88 } 89 90 func (hub *Hub) Sync(a *rpctype.HubSyncArgs, r *rpctype.HubSyncRes) error { 91 name, err := hub.checkManager(a.Client, a.Key, a.Manager) 92 if err != nil { 93 return err 94 } 95 hub.mu.Lock() 96 defer hub.mu.Unlock() 97 98 domain, inputs, more, err := hub.st.Sync(name, a.Add, a.Del) 99 if err != nil { 100 log.Logf(0, "sync error: %v", err) 101 return err 102 } 103 if domain != "" { 104 r.Inputs = inputs 105 } else { 106 for _, inp := range inputs { 107 r.Progs = append(r.Progs, inp.Prog) 108 } 109 } 110 r.More = more 111 for _, repro := range a.Repros { 112 if err := hub.st.AddRepro(name, repro); err != nil { 113 log.Logf(0, "add repro error: %v", err) 114 } 115 } 116 if a.NeedRepros { 117 repro, err := hub.st.PendingRepro(name) 118 if err != nil { 119 log.Logf(0, "sync error: %v", err) 120 } 121 if repro != nil { 122 r.Repros = [][]byte{repro} 123 } 124 } 125 log.Logf(0, "sync from %v: recv: add=%v del=%v repros=%v; send: progs=%v repros=%v pending=%v", 126 name, len(a.Add), len(a.Del), len(a.Repros), len(inputs), len(r.Repros), more) 127 return nil 128 } 129 130 func (hub *Hub) purgeOldManagers() { 131 for range time.NewTicker(time.Hour).C { 132 hub.mu.Lock() 133 if err := hub.st.PurgeOldManagers(); err != nil { 134 log.Logf(0, "failed to purge managers: %v", err) 135 } 136 hub.mu.Unlock() 137 } 138 } 139 140 func (hub *Hub) verifyKey(key, expectedKey string) error { 141 if strings.HasPrefix(expectedKey, auth.OauthMagic) { 142 subj, err := hub.auth.DetermineAuthSubj(time.Now(), []string{key}) 143 if err != nil { 144 return err 145 } 146 if subj != expectedKey { 147 return fmt.Errorf("bad token") 148 } 149 // Success due to correct token. 150 return nil 151 } 152 if key != expectedKey { 153 return fmt.Errorf("bad password") 154 } 155 // Success due to correct password. 156 return nil 157 } 158 159 // Returns the verified manager identity or error. 160 func (hub *Hub) checkManager(client, key, manager string) (string, error) { 161 expectedKey, ok := hub.keys[client] 162 if !ok { 163 log.Logf(0, "connect from unauthorized client %v", client) 164 return "", fmt.Errorf("unauthorized manager") 165 } 166 if err := hub.verifyKey(key, expectedKey); err != nil { 167 log.Logf(0, "connect from unauthorized client %v", client) 168 return "", fmt.Errorf("unauthorized manager") 169 } 170 if manager == "" { 171 manager = client 172 } else if !strings.HasPrefix(manager, client) { 173 log.Logf(0, "manager %v does not have client prefix %v", manager, client) 174 return "", fmt.Errorf("unauthorized manager") 175 } 176 return manager, nil 177 }