133 lines
3.1 KiB
Go
133 lines
3.1 KiB
Go
package profile
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"sync"
|
|
"time"
|
|
|
|
"github.com/safing/portbase/config"
|
|
"github.com/safing/portbase/modules"
|
|
"github.com/safing/portmaster/intel/filterlists"
|
|
"github.com/safing/portmaster/profile/endpoints"
|
|
)
|
|
|
|
var (
|
|
cfgLock sync.RWMutex
|
|
|
|
cfgDefaultAction uint8
|
|
cfgEndpoints endpoints.Endpoints
|
|
cfgServiceEndpoints endpoints.Endpoints
|
|
cfgFilterLists []string
|
|
)
|
|
|
|
func registerConfigUpdater() error {
|
|
return module.RegisterEventHook(
|
|
"config",
|
|
"config change",
|
|
"update global config profile",
|
|
func(ctx context.Context, _ interface{}) error {
|
|
return updateGlobalConfigProfile(ctx, nil)
|
|
},
|
|
)
|
|
}
|
|
|
|
const globalConfigProfileErrorID = "profile:global-profile-error"
|
|
|
|
func updateGlobalConfigProfile(ctx context.Context, task *modules.Task) error {
|
|
cfgLock.Lock()
|
|
defer cfgLock.Unlock()
|
|
|
|
var err error
|
|
var lastErr error
|
|
|
|
action := cfgOptionDefaultAction()
|
|
switch action {
|
|
case "permit":
|
|
cfgDefaultAction = DefaultActionPermit
|
|
case "ask":
|
|
cfgDefaultAction = DefaultActionAsk
|
|
case "block":
|
|
cfgDefaultAction = DefaultActionBlock
|
|
default:
|
|
// TODO: module error?
|
|
lastErr = fmt.Errorf(`default action "%s" invalid`, action)
|
|
cfgDefaultAction = DefaultActionBlock // default to block in worst case
|
|
}
|
|
|
|
list := cfgOptionEndpoints()
|
|
cfgEndpoints, err = endpoints.ParseEndpoints(list)
|
|
if err != nil {
|
|
// TODO: module error?
|
|
lastErr = err
|
|
}
|
|
|
|
list = cfgOptionServiceEndpoints()
|
|
cfgServiceEndpoints, err = endpoints.ParseEndpoints(list)
|
|
if err != nil {
|
|
// TODO: module error?
|
|
lastErr = err
|
|
}
|
|
|
|
list = cfgOptionFilterLists()
|
|
cfgFilterLists, err = filterlists.ResolveListIDs(list)
|
|
if err != nil {
|
|
lastErr = err
|
|
}
|
|
|
|
// build global profile for reference
|
|
profile := New(SourceSpecial, "global-config", "", nil)
|
|
profile.Name = "Global Configuration"
|
|
profile.Internal = true
|
|
|
|
newConfig := make(map[string]interface{})
|
|
// fill profile config options
|
|
for key, value := range cfgStringOptions {
|
|
newConfig[key] = value()
|
|
}
|
|
for key, value := range cfgStringArrayOptions {
|
|
newConfig[key] = value()
|
|
}
|
|
for key, value := range cfgIntOptions {
|
|
newConfig[key] = value()
|
|
}
|
|
for key, value := range cfgBoolOptions {
|
|
newConfig[key] = value()
|
|
}
|
|
|
|
// expand and assign
|
|
profile.Config = config.Expand(newConfig)
|
|
|
|
// save profile
|
|
err = profile.Save()
|
|
if err != nil && lastErr == nil {
|
|
// other errors are more important
|
|
lastErr = err
|
|
}
|
|
|
|
// If there was any error, try again later until it succeeds.
|
|
if lastErr == nil {
|
|
module.Resolve(globalConfigProfileErrorID)
|
|
} else {
|
|
// Create task after first failure.
|
|
if task == nil {
|
|
task = module.NewTask(
|
|
"retry updating global config profile",
|
|
updateGlobalConfigProfile,
|
|
)
|
|
}
|
|
|
|
// Schedule task.
|
|
task.Schedule(time.Now().Add(15 * time.Second))
|
|
|
|
// Add module warning to inform user.
|
|
module.Warning(
|
|
globalConfigProfileErrorID,
|
|
"Internal Settings Failure",
|
|
fmt.Sprintf("The app settings layering system failed to process the global settings. This means that some global settings might not be applied correctly. You can try restarting the Portmaster to resolve this problem. Refer to the error for more details: %s", err),
|
|
)
|
|
}
|
|
|
|
return lastErr
|
|
}
|