From 9bf89c32c02ff29832a74fae3a30e16133d13b8a Mon Sep 17 00:00:00 2001 From: Daniel Date: Thu, 11 Feb 2021 14:53:33 +0100 Subject: [PATCH] Fix new profiles with custom config and implement review suggestions --- process/module.go | 6 ++- process/profile.go | 7 +++- profile/config-update.go | 2 +- profile/get.go | 2 +- profile/module.go | 7 ++-- profile/profile.go | 47 +++++++++++---------- profile/special.go | 88 +++++++++++++++++++++++++++++++--------- 7 files changed, 108 insertions(+), 51 deletions(-) diff --git a/process/module.go b/process/module.go index 5b0d2a09..4134d755 100644 --- a/process/module.go +++ b/process/module.go @@ -3,6 +3,7 @@ package process import ( "os" + "github.com/safing/portbase/log" "github.com/safing/portbase/modules" "github.com/safing/portmaster/updates" ) @@ -13,7 +14,7 @@ var ( ) func init() { - module = modules.Register("processes", prep, start, nil, "profiles") + module = modules.Register("processes", prep, start, nil, "profiles", "updates") } func prep() error { @@ -21,10 +22,11 @@ func prep() error { } func start() error { - updatesPath = updates.RootPath() + string(os.PathSeparator) + updatesPath = updates.RootPath() if updatesPath != "" { updatesPath += string(os.PathSeparator) } + log.Warningf("process: using updates path %s", updatesPath) return nil } diff --git a/process/profile.go b/process/profile.go index 9c0e3a4a..792c11f8 100644 --- a/process/profile.go +++ b/process/profile.go @@ -47,6 +47,11 @@ func (p *Process) GetProfile(ctx context.Context) (changed bool, err error) { profileID = profile.PortmasterAppProfileID case strings.Contains(p.Path, "portmaster-notifier"): profileID = profile.PortmasterNotifierProfileID + default: + // Unexpected binary from within the Portmaster updates directpry. + log.Warningf("process: unexpected binary in the updates directory: %s", p.Path) + // TODO: Assign a fully restricted profile in the future when we are + // sure that we won't kill any of our own things. } } } @@ -74,7 +79,7 @@ func (p *Process) UpdateProfileMetadata() { } // Update metadata of profile. - metadataUpdated := localProfile.UpdateMetadata(p.Name, p.Path) + metadataUpdated := localProfile.UpdateMetadata(p.Path) // Mark profile as used. profileChanged := localProfile.MarkUsed() diff --git a/profile/config-update.go b/profile/config-update.go index 22b76c60..c403112a 100644 --- a/profile/config-update.go +++ b/profile/config-update.go @@ -76,7 +76,7 @@ func updateGlobalConfigProfile(ctx context.Context, task *modules.Task) error { } // build global profile for reference - profile := New(SourceSpecial, "global-config", "") + profile := New(SourceSpecial, "global-config", "", nil) profile.Name = "Global Configuration" profile.Internal = true diff --git a/profile/get.go b/profile/get.go index 8a99cd8c..b1f84ad8 100644 --- a/profile/get.go +++ b/profile/get.go @@ -152,7 +152,7 @@ func findProfile(linkedPath string) (profile *Profile, err error) { } // If there was no profile in the database, create a new one, and return it. - profile = New(SourceLocal, "", linkedPath) + profile = New(SourceLocal, "", linkedPath, nil) // Check if the profile should be marked as internal. // This is the case whenever the binary resides within the data root dir. diff --git a/profile/module.go b/profile/module.go index 71f18306..7a62aa1a 100644 --- a/profile/module.go +++ b/profile/module.go @@ -4,13 +4,11 @@ import ( "os" "github.com/safing/portbase/log" - "github.com/safing/portbase/modules" + "github.com/safing/portmaster/updates" // module dependencies _ "github.com/safing/portmaster/core/base" - "github.com/safing/portmaster/updates" - _ "github.com/safing/portmaster/updates" // dependency of semi-dependency filterlists ) var ( @@ -37,10 +35,11 @@ func prep() error { } func start() error { - updatesPath = updates.RootPath() + string(os.PathSeparator) + updatesPath = updates.RootPath() if updatesPath != "" { updatesPath += string(os.PathSeparator) } + log.Warningf("profile: using updates path %s", updatesPath) err := registerValidationDBHook() if err != nil { diff --git a/profile/profile.go b/profile/profile.go index 3eb428aa..aaf69304 100644 --- a/profile/profile.go +++ b/profile/profile.go @@ -193,13 +193,25 @@ func (profile *Profile) parseConfig() error { } // New returns a new Profile. -func New(source profileSource, id string, linkedPath string) *Profile { +// Optionally, you may supply custom configuration in the flat (key=value) form. +func New( + source profileSource, + id string, + linkedPath string, + customConfig map[string]interface{}, +) *Profile { + if customConfig != nil { + customConfig = config.Expand(customConfig) + } else { + customConfig = make(map[string]interface{}) + } + profile := &Profile{ ID: id, Source: source, LinkedPath: linkedPath, Created: time.Now().Unix(), - Config: make(map[string]interface{}), + Config: customConfig, } // Generate random ID if none is given. @@ -210,9 +222,13 @@ func New(source profileSource, id string, linkedPath string) *Profile { // Make key from ID and source. profile.makeKey() - // Prepare profile to create placeholders. - _ = profile.prepConfig() - _ = profile.parseConfig() + // Prepare and parse initial profile config. + if err := profile.prepConfig(); err != nil { + log.Errorf("profile: failed to prep new profile: %s", err) + } + if err := profile.parseConfig(); err != nil { + log.Errorf("profile: failed to parse new profile: %s", err) + } return profile } @@ -372,7 +388,7 @@ func EnsureProfile(r record.Record) (*Profile, error) { // the profile was changed. If there is data that needs to be fetched from the // operating system, it will start an async worker to fetch that data and save // the profile afterwards. -func (profile *Profile) UpdateMetadata(processName, binaryPath string) (changed bool) { +func (profile *Profile) UpdateMetadata(binaryPath string) (changed bool) { // Check if this is a local profile, else warn and return. if profile.Source != SourceLocal { log.Warningf("tried to update metadata for non-local profile %s", profile.ScopedID()) @@ -382,22 +398,9 @@ func (profile *Profile) UpdateMetadata(processName, binaryPath string) (changed profile.Lock() defer profile.Unlock() - // Check if this is a special profile. - if binaryPath == "" { - // This is a special profile, just assign the processName, if needed, and - // return. - if profile.Name != processName { - profile.Name = processName - return true - } - return false - } - - // Update LinkedPath if if differs from the process path. - // This will be the case for profiles that are assigned in a special way. - if profile.LinkedPath != binaryPath { - profile.LinkedPath = binaryPath - changed = true + // Update special profile and return if it was one. + if ok, changed := updateSpecialProfileMetadata(profile, binaryPath); ok { + return changed } var needsUpdateFromSystem bool diff --git a/profile/special.go b/profile/special.go index da7027de..754cdc67 100644 --- a/profile/special.go +++ b/profile/special.go @@ -3,56 +3,104 @@ package profile const ( // UnidentifiedProfileID is the profile ID used for unidentified processes. UnidentifiedProfileID = "_unidentified" + // UnidentifiedProfileName is the name used for unidentified processes. + UnidentifiedProfileName = "Unidentified Processes" // SystemProfileID is the profile ID used for the system/kernel. SystemProfileID = "_system" + // SystemProfileName is the name used for the system/kernel. + SystemProfileName = "Operating System" // PortmasterProfileID is the profile ID used for the Portmaster Core itself. PortmasterProfileID = "_portmaster" + // PortmasterProfileName is the name used for the Portmaster Core itself. + PortmasterProfileName = "Portmaster Core Service" // PortmasterAppProfileID is the profile ID used for the Portmaster App. PortmasterAppProfileID = "_portmaster-app" + // PortmasterAppProfileName is the name used for the Portmaster App. + PortmasterAppProfileName = "Portmaster User Interface" // PortmasterNotifierProfileID is the profile ID used for the Portmaster Notifier. PortmasterNotifierProfileID = "_portmaster-notifier" + // PortmasterNotifierProfileName is the name used for the Portmaster Notifier. + PortmasterNotifierProfileName = "Portmaster Notifier" ) +func updateSpecialProfileMetadata(profile *Profile, binaryPath string) (ok, changed bool) { + // Get new profile name and check if profile is applicable to special handling. + var newProfileName string + switch profile.ID { + case UnidentifiedProfileID: + newProfileName = UnidentifiedProfileName + case SystemProfileID: + newProfileName = SystemProfileName + case PortmasterProfileID: + newProfileName = PortmasterProfileName + case PortmasterAppProfileID: + newProfileName = PortmasterAppProfileName + case PortmasterNotifierProfileID: + newProfileName = PortmasterNotifierProfileName + default: + return false, false + } + + // Update profile name if needed. + if profile.Name != newProfileName { + profile.Name = newProfileName + changed = true + } + + // Update LinkedPath to new value. + if profile.LinkedPath != binaryPath { + profile.LinkedPath = binaryPath + changed = true + } + + return true, changed +} + func getSpecialProfile(profileID, linkedPath string) *Profile { switch profileID { case UnidentifiedProfileID: - return New(SourceLocal, UnidentifiedProfileID, linkedPath) + return New(SourceLocal, UnidentifiedProfileID, linkedPath, nil) case SystemProfileID: - return New(SourceLocal, SystemProfileID, linkedPath) + return New(SourceLocal, SystemProfileID, linkedPath, nil) case PortmasterProfileID: - profile := New(SourceLocal, PortmasterProfileID, linkedPath) - profile.Name = "Portmaster Core Service" + profile := New(SourceLocal, PortmasterProfileID, linkedPath, nil) profile.Internal = true return profile case PortmasterAppProfileID: - profile := New(SourceLocal, PortmasterAppProfileID, linkedPath) - profile.Name = "Portmaster User Interface" - profile.Internal = true - profile.Config = map[string]interface{}{ - CfgOptionDefaultActionKey: "block", - CfgOptionEndpointsKey: []string{ - "+ Localhost", + profile := New( + SourceLocal, + PortmasterAppProfileID, + linkedPath, + map[string]interface{}{ + CfgOptionDefaultActionKey: "block", + CfgOptionEndpointsKey: []string{ + "+ Localhost", + }, }, - } + ) + profile.Internal = true return profile case PortmasterNotifierProfileID: - profile := New(SourceLocal, PortmasterNotifierProfileID, linkedPath) - profile.Name = "Portmaster Notifier" - profile.Internal = true - profile.Config = map[string]interface{}{ - CfgOptionDefaultActionKey: "block", - CfgOptionEndpointsKey: []string{ - "+ Localhost", + profile := New( + SourceLocal, + PortmasterNotifierProfileID, + linkedPath, + map[string]interface{}{ + CfgOptionDefaultActionKey: "block", + CfgOptionEndpointsKey: []string{ + "+ Localhost", + }, }, - } + ) + profile.Internal = true return profile default: