| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- // Copyright 2020 The go-ethereum Authors
- // This file is part of go-ethereum.
- //
- // go-ethereum is free software: you can redistribute it and/or modify
- // it under the terms of the GNU General Public License as published by
- // the Free Software Foundation, either version 3 of the License, or
- // (at your option) any later version.
- //
- // go-ethereum is distributed in the hope that it will be useful,
- // but WITHOUT ANY WARRANTY; without even the implied warranty of
- // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- // GNU General Public License for more details.
- //
- // You should have received a copy of the GNU General Public License
- // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
- package main
- import (
- "encoding/json"
- "errors"
- "fmt"
- "io/ioutil"
- "net/http"
- "regexp"
- "strings"
- "github.com/ethereum/go-ethereum/log"
- "github.com/jedisct1/go-minisign"
- "gopkg.in/urfave/cli.v1"
- )
- var gethPubKeys []string = []string{
- //@holiman, minisign public key FB1D084D39BAEC24
- "RWQk7Lo5TQgd+wxBNZM+Zoy+7UhhMHaWKzqoes9tvSbFLJYZhNTbrIjx",
- //minisign public key 138B1CA303E51687
- "RWSHFuUDoxyLEzjszuWZI1xStS66QTyXFFZG18uDfO26CuCsbckX1e9J",
- //minisign public key FD9813B2D2098484
- "RWSEhAnSshOY/b+GmaiDkObbCWefsAoavjoLcPjBo1xn71yuOH5I+Lts",
- }
- type vulnJson struct {
- Name string
- Uid string
- Summary string
- Description string
- Links []string
- Introduced string
- Fixed string
- Published string
- Severity string
- Check string
- CVE string
- }
- func versionCheck(ctx *cli.Context) error {
- url := ctx.String(VersionCheckUrlFlag.Name)
- version := ctx.String(VersionCheckVersionFlag.Name)
- log.Info("Checking vulnerabilities", "version", version, "url", url)
- return checkCurrent(url, version)
- }
- func checkCurrent(url, current string) error {
- var (
- data []byte
- sig []byte
- err error
- )
- if data, err = fetch(url); err != nil {
- return fmt.Errorf("could not retrieve data: %w", err)
- }
- if sig, err = fetch(fmt.Sprintf("%v.minisig", url)); err != nil {
- return fmt.Errorf("could not retrieve signature: %w", err)
- }
- if err = verifySignature(gethPubKeys, data, sig); err != nil {
- return err
- }
- var vulns []vulnJson
- if err = json.Unmarshal(data, &vulns); err != nil {
- return err
- }
- allOk := true
- for _, vuln := range vulns {
- r, err := regexp.Compile(vuln.Check)
- if err != nil {
- return err
- }
- if r.MatchString(current) {
- allOk = false
- fmt.Printf("## Vulnerable to %v (%v)\n\n", vuln.Uid, vuln.Name)
- fmt.Printf("Severity: %v\n", vuln.Severity)
- fmt.Printf("Summary : %v\n", vuln.Summary)
- fmt.Printf("Fixed in: %v\n", vuln.Fixed)
- if len(vuln.CVE) > 0 {
- fmt.Printf("CVE: %v\n", vuln.CVE)
- }
- if len(vuln.Links) > 0 {
- fmt.Printf("References:\n")
- for _, ref := range vuln.Links {
- fmt.Printf("\t- %v\n", ref)
- }
- }
- fmt.Println()
- }
- }
- if allOk {
- fmt.Println("No vulnerabilities found")
- }
- return nil
- }
- // fetch makes an HTTP request to the given url and returns the response body
- func fetch(url string) ([]byte, error) {
- if filep := strings.TrimPrefix(url, "file://"); filep != url {
- return ioutil.ReadFile(filep)
- }
- res, err := http.Get(url)
- if err != nil {
- return nil, err
- }
- defer res.Body.Close()
- body, err := ioutil.ReadAll(res.Body)
- if err != nil {
- return nil, err
- }
- return body, nil
- }
- // verifySignature checks that the sigData is a valid signature of the given
- // data, for pubkey GethPubkey
- func verifySignature(pubkeys []string, data, sigdata []byte) error {
- sig, err := minisign.DecodeSignature(string(sigdata))
- if err != nil {
- return err
- }
- // find the used key
- var key *minisign.PublicKey
- for _, pubkey := range pubkeys {
- pub, err := minisign.NewPublicKey(pubkey)
- if err != nil {
- // our pubkeys should be parseable
- return err
- }
- if pub.KeyId != sig.KeyId {
- continue
- }
- key = &pub
- break
- }
- if key == nil {
- log.Info("Signing key not trusted", "keyid", keyID(sig.KeyId), "error", err)
- return errors.New("signature could not be verified")
- }
- if ok, err := key.Verify(data, sig); !ok || err != nil {
- log.Info("Verification failed error", "keyid", keyID(key.KeyId), "error", err)
- return errors.New("signature could not be verified")
- }
- return nil
- }
- // keyID turns a binary minisign key ID into a hex string.
- // Note: key IDs are printed in reverse byte order.
- func keyID(id [8]byte) string {
- var rev [8]byte
- for i := range id {
- rev[len(rev)-1-i] = id[i]
- }
- return fmt.Sprintf("%X", rev)
- }
|