github.com/kisexp/xdchain@v0.0.0-20211206025815-490d6b732aa7/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/ioutil" 24 "net/http" 25 "regexp" 26 "strings" 27 28 "github.com/kisexp/xdchain/log" 29 "github.com/jedisct1/go-minisign" 30 "gopkg.in/urfave/cli.v1" 31 ) 32 33 var gethPubKeys []string = []string{ 34 //@holiman, minisign public key FB1D084D39BAEC24 35 "RWQk7Lo5TQgd+wxBNZM+Zoy+7UhhMHaWKzqoes9tvSbFLJYZhNTbrIjx", 36 //minisign public key 138B1CA303E51687 37 "RWSHFuUDoxyLEzjszuWZI1xStS66QTyXFFZG18uDfO26CuCsbckX1e9J", 38 //minisign public key FD9813B2D2098484 39 "RWSEhAnSshOY/b+GmaiDkObbCWefsAoavjoLcPjBo1xn71yuOH5I+Lts", 40 } 41 42 type vulnJson struct { 43 Name string 44 Uid string 45 Summary string 46 Description string 47 Links []string 48 Introduced string 49 Fixed string 50 Published string 51 Severity string 52 Check string 53 CVE string 54 } 55 56 func versionCheck(ctx *cli.Context) error { 57 url := ctx.String(VersionCheckUrlFlag.Name) 58 version := ctx.String(VersionCheckVersionFlag.Name) 59 log.Info("Checking vulnerabilities", "version", version, "url", url) 60 return checkCurrent(url, version) 61 } 62 63 func checkCurrent(url, current string) error { 64 var ( 65 data []byte 66 sig []byte 67 err error 68 ) 69 if data, err = fetch(url); err != nil { 70 return fmt.Errorf("could not retrieve data: %w", err) 71 } 72 if sig, err = fetch(fmt.Sprintf("%v.minisig", url)); err != nil { 73 return fmt.Errorf("could not retrieve signature: %w", err) 74 } 75 if err = verifySignature(gethPubKeys, data, sig); err != nil { 76 return err 77 } 78 var vulns []vulnJson 79 if err = json.Unmarshal(data, &vulns); err != nil { 80 return err 81 } 82 allOk := true 83 for _, vuln := range vulns { 84 r, err := regexp.Compile(vuln.Check) 85 if err != nil { 86 return err 87 } 88 if r.MatchString(current) { 89 allOk = false 90 fmt.Printf("## Vulnerable to %v (%v)\n\n", vuln.Uid, vuln.Name) 91 fmt.Printf("Severity: %v\n", vuln.Severity) 92 fmt.Printf("Summary : %v\n", vuln.Summary) 93 fmt.Printf("Fixed in: %v\n", vuln.Fixed) 94 if len(vuln.CVE) > 0 { 95 fmt.Printf("CVE: %v\n", vuln.CVE) 96 } 97 if len(vuln.Links) > 0 { 98 fmt.Printf("References:\n") 99 for _, ref := range vuln.Links { 100 fmt.Printf("\t- %v\n", ref) 101 } 102 } 103 fmt.Println() 104 } 105 } 106 if allOk { 107 fmt.Println("No vulnerabilities found") 108 } 109 return nil 110 } 111 112 // fetch makes an HTTP request to the given url and returns the response body 113 func fetch(url string) ([]byte, error) { 114 if filep := strings.TrimPrefix(url, "file://"); filep != url { 115 return ioutil.ReadFile(filep) 116 } 117 res, err := http.Get(url) 118 if err != nil { 119 return nil, err 120 } 121 defer res.Body.Close() 122 body, err := ioutil.ReadAll(res.Body) 123 if err != nil { 124 return nil, err 125 } 126 return body, nil 127 } 128 129 // verifySignature checks that the sigData is a valid signature of the given 130 // data, for pubkey GethPubkey 131 func verifySignature(pubkeys []string, data, sigdata []byte) error { 132 sig, err := minisign.DecodeSignature(string(sigdata)) 133 if err != nil { 134 return err 135 } 136 // find the used key 137 var key *minisign.PublicKey 138 for _, pubkey := range pubkeys { 139 pub, err := minisign.NewPublicKey(pubkey) 140 if err != nil { 141 // our pubkeys should be parseable 142 return err 143 } 144 if pub.KeyId != sig.KeyId { 145 continue 146 } 147 key = &pub 148 break 149 } 150 if key == nil { 151 log.Info("Signing key not trusted", "keyid", keyID(sig.KeyId), "error", err) 152 return errors.New("signature could not be verified") 153 } 154 if ok, err := key.Verify(data, sig); !ok || err != nil { 155 log.Info("Verification failed error", "keyid", keyID(key.KeyId), "error", err) 156 return errors.New("signature could not be verified") 157 } 158 return nil 159 } 160 161 // keyID turns a binary minisign key ID into a hex string. 162 // Note: key IDs are printed in reverse byte order. 163 func keyID(id [8]byte) string { 164 var rev [8]byte 165 for i := range id { 166 rev[len(rev)-1-i] = id[i] 167 } 168 return fmt.Sprintf("%X", rev) 169 }