wip: migrate to mono-repo. SPN has already been moved to spn/
This commit is contained in:
57
service/updates/helper/electron.go
Normal file
57
service/updates/helper/electron.go
Normal file
@@ -0,0 +1,57 @@
|
||||
package helper
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
|
||||
"github.com/safing/portbase/log"
|
||||
"github.com/safing/portbase/updater"
|
||||
)
|
||||
|
||||
var pmElectronUpdate *updater.File
|
||||
|
||||
const suidBitWarning = `Failed to set SUID permissions for chrome-sandbox. This is required for Linux kernel versions that do not have unprivileged user namespaces (CONFIG_USER_NS_UNPRIVILEGED) enabled. If you're running and up-to-date distribution kernel you can likely ignore this warning. If you encounter issue starting the user interface please either update your kernel or set the SUID bit (mode 0%0o) on %s`
|
||||
|
||||
// EnsureChromeSandboxPermissions makes sure the chrome-sandbox distributed
|
||||
// by our app-electron package has the SUID bit set on systems that do not
|
||||
// allow unprivileged CLONE_NEWUSER (clone(3)).
|
||||
// On non-linux systems or systems that have kernel.unprivileged_userns_clone
|
||||
// set to 1 EnsureChromeSandboPermissions is a NO-OP.
|
||||
func EnsureChromeSandboxPermissions(reg *updater.ResourceRegistry) error {
|
||||
if runtime.GOOS != "linux" {
|
||||
return nil
|
||||
}
|
||||
|
||||
if pmElectronUpdate != nil && !pmElectronUpdate.UpgradeAvailable() {
|
||||
return nil
|
||||
}
|
||||
|
||||
identifier := PlatformIdentifier("app/portmaster-app.zip")
|
||||
|
||||
var err error
|
||||
pmElectronUpdate, err = reg.GetFile(identifier)
|
||||
if err != nil {
|
||||
if errors.Is(err, updater.ErrNotAvailableLocally) {
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("failed to get file: %w", err)
|
||||
}
|
||||
|
||||
unpackedPath := strings.TrimSuffix(
|
||||
pmElectronUpdate.Path(),
|
||||
filepath.Ext(pmElectronUpdate.Path()),
|
||||
)
|
||||
sandboxFile := filepath.Join(unpackedPath, "chrome-sandbox")
|
||||
if err := os.Chmod(sandboxFile, 0o0755|os.ModeSetuid); err != nil {
|
||||
log.Errorf(suidBitWarning, 0o0755|os.ModeSetuid, sandboxFile)
|
||||
|
||||
return fmt.Errorf("failed to chmod: %w", err)
|
||||
}
|
||||
log.Debugf("updates: fixed SUID permission for chrome-sandbox")
|
||||
|
||||
return nil
|
||||
}
|
||||
134
service/updates/helper/indexes.go
Normal file
134
service/updates/helper/indexes.go
Normal file
@@ -0,0 +1,134 @@
|
||||
package helper
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/safing/jess/filesig"
|
||||
"github.com/safing/portbase/updater"
|
||||
)
|
||||
|
||||
// Release Channel Configuration Keys.
|
||||
const (
|
||||
ReleaseChannelKey = "core/releaseChannel"
|
||||
ReleaseChannelJSONKey = "core.releaseChannel"
|
||||
)
|
||||
|
||||
// Release Channels.
|
||||
const (
|
||||
ReleaseChannelStable = "stable"
|
||||
ReleaseChannelBeta = "beta"
|
||||
ReleaseChannelStaging = "staging"
|
||||
ReleaseChannelSupport = "support"
|
||||
)
|
||||
|
||||
// SetIndexes sets the update registry indexes and also configures the registry
|
||||
// to use pre-releases based on the channel.
|
||||
func SetIndexes(
|
||||
registry *updater.ResourceRegistry,
|
||||
releaseChannel string,
|
||||
deleteUnusedIndexes bool,
|
||||
autoDownload bool,
|
||||
autoDownloadIntel bool,
|
||||
) (warning error) {
|
||||
usePreReleases := false
|
||||
|
||||
// Be reminded that the order is important, as indexes added later will
|
||||
// override the current release from earlier indexes.
|
||||
|
||||
// Reset indexes before adding them (again).
|
||||
registry.ResetIndexes()
|
||||
|
||||
// Add the intel index first, in order to be able to override it with the
|
||||
// other indexes when needed.
|
||||
registry.AddIndex(updater.Index{
|
||||
Path: "all/intel/intel.json",
|
||||
AutoDownload: autoDownloadIntel,
|
||||
})
|
||||
|
||||
// Always add the stable index as a base.
|
||||
registry.AddIndex(updater.Index{
|
||||
Path: ReleaseChannelStable + ".json",
|
||||
AutoDownload: autoDownload,
|
||||
})
|
||||
|
||||
// Add beta index if in beta or staging channel.
|
||||
indexPath := ReleaseChannelBeta + ".json"
|
||||
if releaseChannel == ReleaseChannelBeta ||
|
||||
releaseChannel == ReleaseChannelStaging ||
|
||||
(releaseChannel == "" && indexExists(registry, indexPath)) {
|
||||
registry.AddIndex(updater.Index{
|
||||
Path: indexPath,
|
||||
PreRelease: true,
|
||||
AutoDownload: autoDownload,
|
||||
})
|
||||
usePreReleases = true
|
||||
} else if deleteUnusedIndexes {
|
||||
err := deleteIndex(registry, indexPath)
|
||||
if err != nil {
|
||||
warning = fmt.Errorf("failed to delete unused index %s: %w", indexPath, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Add staging index if in staging channel.
|
||||
indexPath = ReleaseChannelStaging + ".json"
|
||||
if releaseChannel == ReleaseChannelStaging ||
|
||||
(releaseChannel == "" && indexExists(registry, indexPath)) {
|
||||
registry.AddIndex(updater.Index{
|
||||
Path: indexPath,
|
||||
PreRelease: true,
|
||||
AutoDownload: autoDownload,
|
||||
})
|
||||
usePreReleases = true
|
||||
} else if deleteUnusedIndexes {
|
||||
err := deleteIndex(registry, indexPath)
|
||||
if err != nil {
|
||||
warning = fmt.Errorf("failed to delete unused index %s: %w", indexPath, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Add support index if in support channel.
|
||||
indexPath = ReleaseChannelSupport + ".json"
|
||||
if releaseChannel == ReleaseChannelSupport ||
|
||||
(releaseChannel == "" && indexExists(registry, indexPath)) {
|
||||
registry.AddIndex(updater.Index{
|
||||
Path: indexPath,
|
||||
AutoDownload: autoDownload,
|
||||
})
|
||||
usePreReleases = true
|
||||
} else if deleteUnusedIndexes {
|
||||
err := deleteIndex(registry, indexPath)
|
||||
if err != nil {
|
||||
warning = fmt.Errorf("failed to delete unused index %s: %w", indexPath, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Set pre-release usage.
|
||||
registry.SetUsePreReleases(usePreReleases)
|
||||
|
||||
return warning
|
||||
}
|
||||
|
||||
func indexExists(registry *updater.ResourceRegistry, indexPath string) bool {
|
||||
_, err := os.Stat(filepath.Join(registry.StorageDir().Path, indexPath))
|
||||
return err == nil
|
||||
}
|
||||
|
||||
func deleteIndex(registry *updater.ResourceRegistry, indexPath string) error {
|
||||
// Remove index itself.
|
||||
err := os.Remove(filepath.Join(registry.StorageDir().Path, indexPath))
|
||||
if err != nil && !errors.Is(err, fs.ErrNotExist) {
|
||||
return err
|
||||
}
|
||||
|
||||
// Remove any accompanying signature.
|
||||
err = os.Remove(filepath.Join(registry.StorageDir().Path, indexPath+filesig.Extension))
|
||||
if err != nil && !errors.Is(err, fs.ErrNotExist) {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
42
service/updates/helper/signing.go
Normal file
42
service/updates/helper/signing.go
Normal file
@@ -0,0 +1,42 @@
|
||||
package helper
|
||||
|
||||
import (
|
||||
"github.com/safing/jess"
|
||||
"github.com/safing/portbase/updater"
|
||||
)
|
||||
|
||||
var (
|
||||
// VerificationConfig holds the complete verification configuration for the registry.
|
||||
VerificationConfig = map[string]*updater.VerificationOptions{
|
||||
"": { // Default.
|
||||
TrustStore: BinarySigningTrustStore,
|
||||
DownloadPolicy: updater.SignaturePolicyRequire,
|
||||
DiskLoadPolicy: updater.SignaturePolicyWarn,
|
||||
},
|
||||
"all/intel/": nil, // Disable until IntelHub supports signing.
|
||||
}
|
||||
|
||||
// BinarySigningKeys holds the signing keys in text format.
|
||||
BinarySigningKeys = []string{
|
||||
// Safing Code Signing Key #1
|
||||
"recipient:public-ed25519-key:safing-code-signing-key-1:92bgBLneQUWrhYLPpBDjqHbpFPuNVCPAaivQ951A4aq72HcTiw7R1QmPJwFM1mdePAvEVDjkeb8S4fp2pmRCsRa8HrCvWQEjd88rfZ6TznJMfY4g7P8ioGFjfpyx2ZJ8WCZJG5Qt4Z9nkabhxo2Nbi3iywBTYDLSbP5CXqi7jryW7BufWWuaRVufFFzhwUC2ryWFWMdkUmsAZcvXwde4KLN9FrkWAy61fGaJ8GCwGnGCSitANnU2cQrsGBXZzxmzxwrYD",
|
||||
// Safing Code Signing Key #2
|
||||
"recipient:public-ed25519-key:safing-code-signing-key-2:92bgBLneQUWrhYLPpBDjqHbPC2d1o5JMyZFdavWBNVtdvbPfzDewLW95ScXfYPHd3QvWHSWCtB4xpthaYWxSkK1kYiGp68DPa2HaU8yQ5dZhaAUuV4Kzv42pJcWkCeVnBYqgGBXobuz52rFqhDJy3rz7soXEmYhJEJWwLwMeioK3VzN3QmGSYXXjosHMMNC76rjufSoLNtUQUWZDSnHmqbuxbKMCCsjFXUGGhtZVyb7bnu7QLTLk6SKHBJDMB6zdL9sw3",
|
||||
}
|
||||
|
||||
// BinarySigningTrustStore is an in-memory trust store with the signing keys.
|
||||
BinarySigningTrustStore = jess.NewMemTrustStore()
|
||||
)
|
||||
|
||||
func init() {
|
||||
for _, signingKey := range BinarySigningKeys {
|
||||
rcpt, err := jess.RecipientFromTextFormat(signingKey)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
err = BinarySigningTrustStore.StoreSignet(rcpt)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
}
|
||||
92
service/updates/helper/updates.go
Normal file
92
service/updates/helper/updates.go
Normal file
@@ -0,0 +1,92 @@
|
||||
package helper
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/tevino/abool"
|
||||
)
|
||||
|
||||
const onWindows = runtime.GOOS == "windows"
|
||||
|
||||
var intelOnly = abool.New()
|
||||
|
||||
// IntelOnly specifies that only intel data is mandatory.
|
||||
func IntelOnly() {
|
||||
intelOnly.Set()
|
||||
}
|
||||
|
||||
// PlatformIdentifier converts identifier for the current platform.
|
||||
func PlatformIdentifier(identifier string) string {
|
||||
// From https://golang.org/pkg/runtime/#GOARCH
|
||||
// GOOS is the running program's operating system target: one of darwin, freebsd, linux, and so on.
|
||||
// GOARCH is the running program's architecture target: one of 386, amd64, arm, s390x, and so on.
|
||||
return fmt.Sprintf("%s_%s/%s", runtime.GOOS, runtime.GOARCH, identifier)
|
||||
}
|
||||
|
||||
// MandatoryUpdates returns mandatory updates that should be loaded on install
|
||||
// or reset.
|
||||
func MandatoryUpdates() (identifiers []string) {
|
||||
// Intel
|
||||
identifiers = append(
|
||||
identifiers,
|
||||
|
||||
// Filter lists data
|
||||
"all/intel/lists/index.dsd",
|
||||
"all/intel/lists/base.dsdl",
|
||||
"all/intel/lists/intermediate.dsdl",
|
||||
"all/intel/lists/urgent.dsdl",
|
||||
|
||||
// Geo IP data
|
||||
"all/intel/geoip/geoipv4.mmdb.gz",
|
||||
"all/intel/geoip/geoipv6.mmdb.gz",
|
||||
)
|
||||
|
||||
// Stop here if we only want intel data.
|
||||
if intelOnly.IsSet() {
|
||||
return identifiers
|
||||
}
|
||||
|
||||
// Binaries
|
||||
if onWindows {
|
||||
identifiers = append(
|
||||
identifiers,
|
||||
PlatformIdentifier("core/portmaster-core.exe"),
|
||||
PlatformIdentifier("kext/portmaster-kext.sys"),
|
||||
PlatformIdentifier("kext/portmaster-kext.pdb"),
|
||||
PlatformIdentifier("start/portmaster-start.exe"),
|
||||
PlatformIdentifier("notifier/portmaster-notifier.exe"),
|
||||
PlatformIdentifier("notifier/portmaster-wintoast.dll"),
|
||||
)
|
||||
} else {
|
||||
identifiers = append(
|
||||
identifiers,
|
||||
PlatformIdentifier("core/portmaster-core"),
|
||||
PlatformIdentifier("start/portmaster-start"),
|
||||
PlatformIdentifier("notifier/portmaster-notifier"),
|
||||
)
|
||||
}
|
||||
|
||||
// Components, Assets and Data
|
||||
identifiers = append(
|
||||
identifiers,
|
||||
|
||||
// User interface components
|
||||
PlatformIdentifier("app/portmaster-app.zip"),
|
||||
"all/ui/modules/portmaster.zip",
|
||||
"all/ui/modules/assets.zip",
|
||||
)
|
||||
|
||||
return identifiers
|
||||
}
|
||||
|
||||
// AutoUnpackUpdates returns assets that need unpacking.
|
||||
func AutoUnpackUpdates() []string {
|
||||
if intelOnly.IsSet() {
|
||||
return []string{}
|
||||
}
|
||||
|
||||
return []string{
|
||||
PlatformIdentifier("app/portmaster-app.zip"),
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user