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