github.com/carter-ya/go-ethereum@v0.0.0-20230628080049-d2309be3983b/cmd/geth/version_check.go (about) 1 // Copyright 2020 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // go-ethereum is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 package main 18 19 import ( 20 "encoding/json" 21 "errors" 22 "fmt" 23 "io" 24 "net/http" 25 "os" 26 "regexp" 27 "strings" 28 29 "github.com/ethereum/go-ethereum/log" 30 "github.com/jedisct1/go-minisign" 31 "github.com/urfave/cli/v2" 32 ) 33 34 var gethPubKeys []string = []string{ 35 //@holiman, minisign public key FB1D084D39BAEC24 36 "RWQk7Lo5TQgd+wxBNZM+Zoy+7UhhMHaWKzqoes9tvSbFLJYZhNTbrIjx", 37 //minisign public key 138B1CA303E51687 38 "RWSHFuUDoxyLEzjszuWZI1xStS66QTyXFFZG18uDfO26CuCsbckX1e9J", 39 //minisign public key FD9813B2D2098484 40 "RWSEhAnSshOY/b+GmaiDkObbCWefsAoavjoLcPjBo1xn71yuOH5I+Lts", 41 } 42 43 type vulnJson struct { 44 Name string 45 Uid string 46 Summary string 47 Description string 48 Links []string 49 Introduced string 50 Fixed string 51 Published string 52 Severity string 53 Check string 54 CVE string 55 } 56 57 func versionCheck(ctx *cli.Context) error { 58 url := ctx.String(VersionCheckUrlFlag.Name) 59 version := ctx.String(VersionCheckVersionFlag.Name) 60 log.Info("Checking vulnerabilities", "version", version, "url", url) 61 return checkCurrent(url, version) 62 } 63 64 func checkCurrent(url, current string) error { 65 var ( 66 data []byte 67 sig []byte 68 err error 69 ) 70 if data, err = fetch(url); err != nil { 71 return fmt.Errorf("could not retrieve data: %w", err) 72 } 73 if sig, err = fetch(fmt.Sprintf("%v.minisig", url)); err != nil { 74 return fmt.Errorf("could not retrieve signature: %w", err) 75 } 76 if err = verifySignature(gethPubKeys, data, sig); err != nil { 77 return err 78 } 79 var vulns []vulnJson 80 if err = json.Unmarshal(data, &vulns); err != nil { 81 return err 82 } 83 allOk := true 84 for _, vuln := range vulns { 85 r, err := regexp.Compile(vuln.Check) 86 if err != nil { 87 return err 88 } 89 if r.MatchString(current) { 90 allOk = false 91 fmt.Printf("## Vulnerable to %v (%v)\n\n", vuln.Uid, vuln.Name) 92 fmt.Printf("Severity: %v\n", vuln.Severity) 93 fmt.Printf("Summary : %v\n", vuln.Summary) 94 fmt.Printf("Fixed in: %v\n", vuln.Fixed) 95 if len(vuln.CVE) > 0 { 96 fmt.Printf("CVE: %v\n", vuln.CVE) 97 } 98 if len(vuln.Links) > 0 { 99 fmt.Printf("References:\n") 100 for _, ref := range vuln.Links { 101 fmt.Printf("\t- %v\n", ref) 102 } 103 } 104 fmt.Println() 105 } 106 } 107 if allOk { 108 fmt.Println("No vulnerabilities found") 109 } 110 return nil 111 } 112 113 // fetch makes an HTTP request to the given url and returns the response body 114 func fetch(url string) ([]byte, error) { 115 if filep := strings.TrimPrefix(url, "file://"); filep != url { 116 return os.ReadFile(filep) 117 } 118 res, err := http.Get(url) 119 if err != nil { 120 return nil, err 121 } 122 defer res.Body.Close() 123 body, err := io.ReadAll(res.Body) 124 if err != nil { 125 return nil, err 126 } 127 return body, nil 128 } 129 130 // verifySignature checks that the sigData is a valid signature of the given 131 // data, for pubkey GethPubkey 132 func verifySignature(pubkeys []string, data, sigdata []byte) error { 133 sig, err := minisign.DecodeSignature(string(sigdata)) 134 if err != nil { 135 return err 136 } 137 // find the used key 138 var key *minisign.PublicKey 139 for _, pubkey := range pubkeys { 140 pub, err := minisign.NewPublicKey(pubkey) 141 if err != nil { 142 // our pubkeys should be parseable 143 return err 144 } 145 if pub.KeyId != sig.KeyId { 146 continue 147 } 148 key = &pub 149 break 150 } 151 if key == nil { 152 log.Info("Signing key not trusted", "keyid", keyID(sig.KeyId), "error", err) 153 return errors.New("signature could not be verified") 154 } 155 if ok, err := key.Verify(data, sig); !ok || err != nil { 156 log.Info("Verification failed error", "keyid", keyID(key.KeyId), "error", err) 157 return errors.New("signature could not be verified") 158 } 159 return nil 160 } 161 162 // keyID turns a binary minisign key ID into a hex string. 163 // Note: key IDs are printed in reverse byte order. 164 func keyID(id [8]byte) string { 165 var rev [8]byte 166 for i := range id { 167 rev[len(rev)-1-i] = id[i] 168 } 169 return fmt.Sprintf("%X", rev) 170 }