[WIP] New updater first working prototype

This commit is contained in:
Vladimir Stoilov
2024-08-16 16:05:01 +03:00
parent abf444630b
commit 9bae1afd73
46 changed files with 4107 additions and 4149 deletions

View File

@@ -1,57 +1,58 @@
package helper
import (
"errors"
"fmt"
"os"
"path/filepath"
"runtime"
"strings"
// import (
// "errors"
// "fmt"
// "os"
// "path/filepath"
// "runtime"
// "strings"
"github.com/safing/portmaster/base/log"
"github.com/safing/portmaster/base/updater"
)
// "github.com/safing/portmaster/base/log"
// "github.com/safing/portmaster/base/updater"
// "github.com/safing/portmaster/service/updates/registry"
// )
var pmElectronUpdate *updater.File
// var pmElectronUpdate *registry.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`
// 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
}
// // 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
}
// if pmElectronUpdate != nil && !pmElectronUpdate.UpgradeAvailable() {
// return nil
// }
identifier := PlatformIdentifier("app/portmaster-app.zip")
// 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)
}
// 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)
// 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 fmt.Errorf("failed to chmod: %w", err)
// }
// log.Debugf("updates: fixed SUID permission for chrome-sandbox")
return nil
}
// return nil
// }

View File

@@ -1,136 +1,136 @@
package helper
import (
"errors"
"fmt"
"io/fs"
"os"
"path/filepath"
// import (
// "errors"
// "fmt"
// "io/fs"
// "os"
// "path/filepath"
"github.com/safing/jess/filesig"
"github.com/safing/portmaster/base/updater"
)
// "github.com/safing/jess/filesig"
// "github.com/safing/portmaster/base/updater"
// )
// Release Channel Configuration Keys.
const (
ReleaseChannelKey = "core/releaseChannel"
ReleaseChannelJSONKey = "core.releaseChannel"
)
// // Release Channel Configuration Keys.
// const (
// ReleaseChannelKey = "core/releaseChannel"
// ReleaseChannelJSONKey = "core.releaseChannel"
// )
// Release Channels.
const (
ReleaseChannelStable = "stable"
ReleaseChannelBeta = "beta"
ReleaseChannelStaging = "staging"
ReleaseChannelSupport = "support"
)
// // Release Channels.
// const (
// ReleaseChannelStable = "stable"
// ReleaseChannelBeta = "beta"
// ReleaseChannelStaging = "staging"
// ReleaseChannelSupport = "support"
// )
const jsonSuffix = ".json"
// const jsonSuffix = ".json"
// 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
// // 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.
// // 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()
// // 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,
})
// // 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 + jsonSuffix,
AutoDownload: autoDownload,
})
// // Always add the stable index as a base.
// registry.AddIndex(updater.Index{
// Path: ReleaseChannelStable + jsonSuffix,
// AutoDownload: autoDownload,
// })
// Add beta index if in beta or staging channel.
indexPath := ReleaseChannelBeta + jsonSuffix
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 beta index if in beta or staging channel.
// indexPath := ReleaseChannelBeta + jsonSuffix
// 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 + jsonSuffix
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 staging index if in staging channel.
// indexPath = ReleaseChannelStaging + jsonSuffix
// 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 + jsonSuffix
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)
}
}
// // Add support index if in support channel.
// indexPath = ReleaseChannelSupport + jsonSuffix
// 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)
// // Set pre-release usage.
// registry.SetUsePreReleases(usePreReleases)
return warning
}
// return warning
// }
func indexExists(registry *updater.ResourceRegistry, indexPath string) bool {
_, err := os.Stat(filepath.Join(registry.StorageDir().Path, indexPath))
return err == nil
}
// 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
}
// 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
}
// // 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
}
// return nil
// }

View File

@@ -1,42 +1,42 @@
package helper
import (
"github.com/safing/jess"
"github.com/safing/portmaster/base/updater"
)
// import (
// "github.com/safing/jess"
// "github.com/safing/portmaster/base/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.
}
// 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",
}
// // 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()
)
// // 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)
}
}
}
// 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)
// }
// }
// }

View File

@@ -1,95 +1,95 @@
package helper
import (
"fmt"
"runtime"
// import (
// "fmt"
// "runtime"
"github.com/tevino/abool"
)
// "github.com/tevino/abool"
// )
const onWindows = runtime.GOOS == "windows"
// const onWindows = runtime.GOOS == "windows"
var intelOnly = abool.New()
// var intelOnly = abool.New()
// IntelOnly specifies that only intel data is mandatory.
func IntelOnly() {
intelOnly.Set()
}
// // 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)
}
// // 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,
// // 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",
// // 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",
)
// // 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
}
// // 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"),
PlatformIdentifier("app2/portmaster-app.zip"),
)
} else {
identifiers = append(
identifiers,
PlatformIdentifier("core/portmaster-core"),
PlatformIdentifier("start/portmaster-start"),
PlatformIdentifier("notifier/portmaster-notifier"),
PlatformIdentifier("app2/portmaster-app"),
)
}
// // 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"),
// PlatformIdentifier("app2/portmaster-app.zip"),
// )
// } else {
// identifiers = append(
// identifiers,
// PlatformIdentifier("core/portmaster-core"),
// PlatformIdentifier("start/portmaster-start"),
// PlatformIdentifier("notifier/portmaster-notifier"),
// PlatformIdentifier("app2/portmaster-app"),
// )
// }
// Components, Assets and Data
identifiers = append(
identifiers,
// // 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",
)
// // User interface components
// PlatformIdentifier("app/portmaster-app.zip"),
// "all/ui/modules/portmaster.zip",
// "all/ui/modules/assets.zip",
// )
return identifiers
}
// return identifiers
// }
// AutoUnpackUpdates returns assets that need unpacking.
func AutoUnpackUpdates() []string {
if intelOnly.IsSet() {
return []string{}
}
// // AutoUnpackUpdates returns assets that need unpacking.
// func AutoUnpackUpdates() []string {
// if intelOnly.IsSet() {
// return []string{}
// }
return []string{
PlatformIdentifier("app/portmaster-app.zip"),
PlatformIdentifier("app2/portmaster-app.zip"),
}
}
// return []string{
// PlatformIdentifier("app/portmaster-app.zip"),
// PlatformIdentifier("app2/portmaster-app.zip"),
// }
// }