131 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			131 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
// 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"
 | 
						|
	"fmt"
 | 
						|
	"io/ioutil"
 | 
						|
	"path/filepath"
 | 
						|
	"regexp"
 | 
						|
	"strconv"
 | 
						|
	"strings"
 | 
						|
	"testing"
 | 
						|
)
 | 
						|
 | 
						|
func TestVerification(t *testing.T) {
 | 
						|
	// Signatures generated with `minisign`
 | 
						|
	t.Run("minisig", func(t *testing.T) {
 | 
						|
		// For this test, the pubkey is in testdata/minisign.pub
 | 
						|
		// (the privkey is `minisign.sec`, if we want to expand this test. Password 'test' )
 | 
						|
		pub := "RWQkliYstQBOKOdtClfgC3IypIPX6TAmoEi7beZ4gyR3wsaezvqOMWsp"
 | 
						|
		testVerification(t, pub, "./testdata/vcheck/minisig-sigs/")
 | 
						|
	})
 | 
						|
	// Signatures generated with `signify-openbsd`
 | 
						|
	t.Run("signify-openbsd", func(t *testing.T) {
 | 
						|
		t.Skip("This currently fails, minisign expects 4 lines of data, signify provides only 2")
 | 
						|
		// For this test, the pubkey is in testdata/signifykey.pub
 | 
						|
		// (the privkey is `signifykey.sec`, if we want to expand this test. Password 'test' )
 | 
						|
		pub := "RWSKLNhZb0KdATtRT7mZC/bybI3t3+Hv/O2i3ye04Dq9fnT9slpZ1a2/"
 | 
						|
		testVerification(t, pub, "./testdata/vcheck/signify-sigs/")
 | 
						|
	})
 | 
						|
}
 | 
						|
 | 
						|
func testVerification(t *testing.T, pubkey, sigdir string) {
 | 
						|
	// Data to verify
 | 
						|
	data, err := ioutil.ReadFile("./testdata/vcheck/data.json")
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	// Signatures, with and without comments, both trusted and untrusted
 | 
						|
	files, err := ioutil.ReadDir(sigdir)
 | 
						|
	if err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	for _, f := range files {
 | 
						|
		sig, err := ioutil.ReadFile(filepath.Join(sigdir, f.Name()))
 | 
						|
		if err != nil {
 | 
						|
			t.Fatal(err)
 | 
						|
		}
 | 
						|
		err = verifySignature([]string{pubkey}, data, sig)
 | 
						|
		if err != nil {
 | 
						|
			t.Fatal(err)
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
func versionUint(v string) int {
 | 
						|
	mustInt := func(s string) int {
 | 
						|
		a, err := strconv.Atoi(s)
 | 
						|
		if err != nil {
 | 
						|
			panic(v)
 | 
						|
		}
 | 
						|
		return a
 | 
						|
	}
 | 
						|
	components := strings.Split(strings.TrimPrefix(v, "v"), ".")
 | 
						|
	a := mustInt(components[0])
 | 
						|
	b := mustInt(components[1])
 | 
						|
	c := mustInt(components[2])
 | 
						|
	return a*100*100 + b*100 + c
 | 
						|
}
 | 
						|
 | 
						|
// TestMatching can be used to check that the regexps are correct
 | 
						|
func TestMatching(t *testing.T) {
 | 
						|
	data, _ := ioutil.ReadFile("./testdata/vcheck/vulnerabilities.json")
 | 
						|
	var vulns []vulnJson
 | 
						|
	if err := json.Unmarshal(data, &vulns); err != nil {
 | 
						|
		t.Fatal(err)
 | 
						|
	}
 | 
						|
	check := func(version string) {
 | 
						|
		vFull := fmt.Sprintf("Geth/%v-unstable-15339cf1-20201204/linux-amd64/go1.15.4", version)
 | 
						|
		for _, vuln := range vulns {
 | 
						|
			r, err := regexp.Compile(vuln.Check)
 | 
						|
			vulnIntro := versionUint(vuln.Introduced)
 | 
						|
			vulnFixed := versionUint(vuln.Fixed)
 | 
						|
			current := versionUint(version)
 | 
						|
			if err != nil {
 | 
						|
				t.Fatal(err)
 | 
						|
			}
 | 
						|
			if vuln.Name == "Denial of service due to Go CVE-2020-28362" {
 | 
						|
				// this one is not tied to geth-versions
 | 
						|
				continue
 | 
						|
			}
 | 
						|
			if vulnIntro <= current && vulnFixed > current {
 | 
						|
				// Should be vulnerable
 | 
						|
				if !r.MatchString(vFull) {
 | 
						|
					t.Errorf("Should be vulnerable, version %v, intro: %v, fixed: %v %v %v",
 | 
						|
						version, vuln.Introduced, vuln.Fixed, vuln.Name, vuln.Check)
 | 
						|
				}
 | 
						|
			} else {
 | 
						|
				if r.MatchString(vFull) {
 | 
						|
					t.Errorf("Should not be flagged vulnerable, version %v, intro: %v, fixed: %v %v %d %d %d",
 | 
						|
						version, vuln.Introduced, vuln.Fixed, vuln.Name, vulnIntro, current, vulnFixed)
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
		}
 | 
						|
	}
 | 
						|
	for major := 1; major < 2; major++ {
 | 
						|
		for minor := 0; minor < 30; minor++ {
 | 
						|
			for patch := 0; patch < 30; patch++ {
 | 
						|
				vShort := fmt.Sprintf("v%d.%d.%d", major, minor, patch)
 | 
						|
				check(vShort)
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 |