aboutsummaryrefslogtreecommitdiff
path: root/update.go
blob: baeb8c869dd6fb30259c1b4c3064007e32d3881d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
package main

import (
	"bytes"
	"crypto/ed25519"
	"encoding/base64"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"strings"
)

type updateui struct {
	serverVersion string
	available     bool
	triggered     bool
	updatingText  string
}

func updateable() bool {
	return updateURL != "" && publicKeyString != ""
}

func updateCheck(ctx *ntcontext) {
	if !updateable() {
		return
	}
	log.Println("Checking for updates")
	bodybuf, err := fetchFile("version.txt")
	if err != nil {
		log.Println("Couldn't fetch version", err)
		return
	}
	body := strings.TrimSpace(string(bodybuf))

	ctx.update.serverVersion = body
	if ctx.update.serverVersion != version {
		ctx.update.available = true
	}

}

func update(ctx *ntcontext) {
	if !updateable() {
		return
	}
	sig, err := fetchFile("NoiseTorch_x64.tgz.sig")
	if err != nil {
		log.Println("Couldn't fetch signature", err)
		ctx.update.updatingText = "Update failed!"
		(*ctx.masterWindow).Changed()
		return
	}

	tgz, err := fetchFile("NoiseTorch_x64.tgz")
	if err != nil {
		log.Println("Couldn't fetch tgz", err)
		ctx.update.updatingText = "Update failed!"
		(*ctx.masterWindow).Changed()
		return
	}

	verified := ed25519.Verify(publickey(), tgz, sig)

	log.Printf("VERIFIED UPDATE: %t\n", verified)

	if !verified {
		log.Printf("SIGNATURE VERIFICATION FAILED, ABORTING UPDATE!\n")
		ctx.update.updatingText = "Update failed!"
		(*ctx.masterWindow).Changed()
		return
	}

	untar(bytes.NewReader(tgz), os.Getenv("HOME"))
	pkexecSetcapSelf()

	log.Printf("Update installed!\n")
	ctx.update.updatingText = "Update installed! (Restart NoiseTorch to apply)"
	(*ctx.masterWindow).Changed()
}

func fetchFile(file string) ([]byte, error) {
	resp, err := http.Get(updateURL + "/" + file)
	if err != nil {
		return nil, err
	}
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("received on 200 status code when fetching %s. Status: %s", file, resp.Status)
	}
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	return body, nil

}

func publickey() []byte {
	pub, err := base64.StdEncoding.DecodeString(publicKeyString)
	if err != nil { // Should only happen when distributor ships an invalid public key
		log.Fatalf("Error while reading public key: %s\nContact the distribution '%s' about this error.\n", err, distribution)
		os.Exit(1)
	}
	return pub
}