Fix new profiles with custom config and implement review suggestions

This commit is contained in:
Daniel 2021-02-11 14:53:33 +01:00
parent 7d6d679929
commit 9bf89c32c0
7 changed files with 108 additions and 51 deletions

View file

@ -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
}

View file

@ -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()

View file

@ -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

View file

@ -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.

View file

@ -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 {

View file

@ -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

View file

@ -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: