Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 33 additions & 26 deletions eget.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,6 @@ func IsDirectory(path string) bool {
return fileInfo.IsDir()
}

// searches for an asset thaat has the same name as the requested one but
// ending with .sha256 or .sha256sum
func checksumAsset(asset string, assets []string) string {
for _, a := range assets {
if a == asset+".sha256sum" || a == asset+".sha256" {
return a
}
}
return ""
}

// Determine the appropriate Finder to use. If opts.URL is provided, we use
// a DirectAssetFinder. Otherwise we use a GithubAssetFinder. When a Github
// repo is provided, we assume the repo name is the 'tool' name (for direct
Expand Down Expand Up @@ -135,19 +124,41 @@ func getFinder(project string, opts *Flags) (finder Finder, tool string) {
return finder, tool
}

func getVerifier(sumAsset string, opts *Flags) (verifier Verifier, err error) {
func getVerifier(asset string, assets []string, opts *Flags) (verifier Verifier, err error) {
if opts.Verify != "" {
verifier, err = NewSha256Verifier(opts.Verify)
} else if sumAsset != "" {
verifier = &Sha256AssetVerifier{
AssetURL: sumAsset,
if err != nil {
return nil, fmt.Errorf("create Sha256Verifier: %w", err)
}
} else if opts.Hash {
verifier = &Sha256Printer{}
} else {
verifier = &NoVerifier{}
return verifier, nil
}

for _, a := range assets {
if a == asset+".sha256sum" || a == asset+".sha256" {
fmt.Printf("verify against %s\n", a)
return &Sha256AssetVerifier{
AssetURL: a,
}, nil
}
if strings.Contains(a, "checksum") {
binaryUrl, err := url.Parse(asset)
if err != nil {
return nil, fmt.Errorf("extract binary name from asset url: %s: %w", asset, err)
}
binaryName := path.Base(binaryUrl.Path)
fmt.Printf("verify against %s\n", a)
return &Sha256SumFileAssetVerifier{
Sha256SumAssetURL: a,
BinaryName: binaryName,
}, nil
}
}

if opts.Hash {
return &Sha256Printer{}, nil
}
return verifier, err

return &NoVerifier{}, nil
}

// Determine the appropriate detector. If the --system is 'all', we use an
Expand Down Expand Up @@ -479,19 +490,15 @@ func main() {

body := buf.Bytes()

sumAsset := checksumAsset(url, assets)
verifier, err := getVerifier(sumAsset, &opts)
verifier, err := getVerifier(url, assets, &opts)
if err != nil {
fatal(err)
}
err = verifier.Verify(body)
if err != nil {
fatal(err)
} else if opts.Verify == "" && sumAsset != "" {
fmt.Fprintf(output, "Checksum verified with %s\n", path.Base(sumAsset))
} else if opts.Verify != "" {
fmt.Fprintf(output, "Checksum verified\n")
}
fmt.Fprintf(output, "%s\n", verifier)

extractor, err := getExtractor(url, tool, &opts)
if err != nil {
Expand Down
63 changes: 63 additions & 0 deletions verify.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
package main

import (
"bufio"
"bytes"
"crypto/sha256"
"encoding/hex"
"fmt"
"io"
"regexp"
)

type Verifier interface {
Verify(b []byte) error
String() string
}

type NoVerifier struct{}
Expand All @@ -18,6 +21,10 @@ func (n *NoVerifier) Verify(b []byte) error {
return nil
}

func (n *NoVerifier) String() string {
return fmt.Sprintf("checksum verification skipped.\n")
}

type Sha256Error struct {
Expected []byte
Got []byte
Expand Down Expand Up @@ -52,6 +59,10 @@ func (s256 *Sha256Verifier) Verify(b []byte) error {
}
}

func (n *Sha256Verifier) String() string {
return fmt.Sprintf("checksum verified: %s\n", n.Expected)
}

type Sha256Printer struct{}

func (s256 *Sha256Printer) Verify(b []byte) error {
Expand All @@ -60,6 +71,10 @@ func (s256 *Sha256Printer) Verify(b []byte) error {
return nil
}

func (n *Sha256Printer) String() string {
return ""
}

type Sha256AssetVerifier struct {
AssetURL string
}
Expand All @@ -76,6 +91,9 @@ func (s256 *Sha256AssetVerifier) Verify(b []byte) error {
}
expected := make([]byte, sha256.Size)
n, err := hex.Decode(expected, data)
if err != nil {
return fmt.Errorf("decode data: %w", err)
}
if n < sha256.Size {
return fmt.Errorf("sha256sum (%s) too small: %d bytes decoded", string(data), n)
}
Expand All @@ -88,3 +106,48 @@ func (s256 *Sha256AssetVerifier) Verify(b []byte) error {
Got: sum[:],
}
}

func (n *Sha256AssetVerifier) String() string {
return fmt.Sprintf("checksum verified with %s", n.AssetURL)
}

type Sha256SumFileAssetVerifier struct {
Sha256SumAssetURL string
BinaryName string
}

func (s256 *Sha256SumFileAssetVerifier) Verify(b []byte) error {
got := sha256.Sum256(b)

resp, err := Get(s256.Sha256SumAssetURL)
if err != nil {
return err
}
defer resp.Body.Close()

expectedFound := false
scanner := bufio.NewScanner(resp.Body)
sha256sumLinePattern := regexp.MustCompile(fmt.Sprintf("(%x)\\s+(%s)", got, s256.BinaryName))
for scanner.Scan() {
line := scanner.Bytes()
matches := sha256sumLinePattern.FindSubmatch(line)
if matches == nil {
continue
}
expectedFound = true
break
}
if err := scanner.Err(); err != nil {
return fmt.Errorf("read sha256sum %s: %w", s256.Sha256SumAssetURL, err)
}
if !expectedFound {
return &Sha256Error{
Got: got[:],
}
}
return nil
}

func (n *Sha256SumFileAssetVerifier) String() string {
return fmt.Sprintf("checksum verified with %s", n.Sha256SumAssetURL)
}