Fix deleting profiles

This commit is contained in:
Daniel 2022-02-15 14:35:28 +01:00
parent 2cbaf126e9
commit 888b33918a
8 changed files with 89 additions and 32 deletions

View file

@ -259,7 +259,7 @@ func saveResponse(p *profile.Profile, entity *intel.Entity, promptResponse strin
// Update the profile if necessary. // Update the profile if necessary.
if p.IsOutdated() { if p.IsOutdated() {
var err error var err error
p, err = profile.GetProfile(p.Source, p.ID, p.LinkedPath) p, err = profile.GetProfile(p.Source, p.ID, p.LinkedPath, false)
if err != nil { if err != nil {
return err return err
} }

View file

@ -64,7 +64,7 @@ func GetNetworkHost(ctx context.Context, remoteIP net.IP) (process *Process, err
} }
// Get the (linked) local profile. // Get the (linked) local profile.
networkHostProfile, err := profile.GetProfile(profile.SourceNetwork, remoteIP.String(), "") networkHostProfile, err := profile.GetProfile(profile.SourceNetwork, remoteIP.String(), "", false)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View file

@ -81,7 +81,7 @@ func (p *Process) GetProfile(ctx context.Context) (changed bool, err error) {
} }
// Get the (linked) local profile. // Get the (linked) local profile.
localProfile, err := profile.GetProfile(profile.SourceLocal, profileID, p.Path) localProfile, err := profile.GetProfile(profile.SourceLocal, profileID, p.Path, false)
if err != nil { if err != nil {
return false, err return false, err
} }

View file

@ -61,25 +61,31 @@ func startProfileUpdateChecker() error {
// Get active profile. // Get active profile.
activeProfile := getActiveProfile(strings.TrimPrefix(r.Key(), profilesDBPath)) activeProfile := getActiveProfile(strings.TrimPrefix(r.Key(), profilesDBPath))
if activeProfile == nil { if activeProfile == nil {
// Don't do any additional actions if the profile is not active.
continue profileFeed continue profileFeed
} }
// If the record is being deleted, but there is an active profile, // If the record is being deleted, reset the profile.
// create an empty profile instead. // create an empty profile instead.
if r.Meta().IsDeleted() { if r.Meta().IsDeleted() {
newProfile := New( newProfile, err := GetProfile(
activeProfile.Source, activeProfile.Source,
activeProfile.ID, activeProfile.ID,
activeProfile.LinkedPath, activeProfile.LinkedPath,
nil, true,
) )
// Copy some metadata from the old profile. if err != nil {
newProfile.Name = activeProfile.Name log.Errorf("profile: failed to create new profile after reset: %s", err)
} else {
// Copy metadata from the old profile.
newProfile.copyMetadataFrom(activeProfile)
// Save the new profile. // Save the new profile.
err := newProfile.Save() err := newProfile.Save()
if err != nil { if err != nil {
log.Errorf("profile: failed to save new profile for profile reset: %s", err) log.Errorf("profile: failed to save new profile after reset: %s", err)
} }
}
// Set to outdated, so it is loaded in the layered profiles. // Set to outdated, so it is loaded in the layered profiles.
activeProfile.outdated.Set() activeProfile.outdated.Set()
} }

View file

@ -17,7 +17,7 @@ var getProfileLock sync.Mutex
// linkedPath parameters whenever available. The linkedPath is used as the key // linkedPath parameters whenever available. The linkedPath is used as the key
// for locking concurrent requests, so it must be supplied if available. // for locking concurrent requests, so it must be supplied if available.
// If linkedPath is not supplied, source and id make up the key instead. // If linkedPath is not supplied, source and id make up the key instead.
func GetProfile(source profileSource, id, linkedPath string) ( //nolint:gocognit func GetProfile(source profileSource, id, linkedPath string, reset bool) ( //nolint:gocognit
profile *Profile, profile *Profile,
err error, err error,
) { ) {
@ -40,28 +40,23 @@ func GetProfile(source profileSource, id, linkedPath string) ( //nolint:gocognit
if profile != nil { if profile != nil {
profile.MarkStillActive() profile.MarkStillActive()
if profile.outdated.IsSet() { if profile.outdated.IsSet() || reset {
previousVersion = profile previousVersion = profile
} else { } else {
return profile, nil return profile, nil
} }
} }
// Get from database. // Get from database.
if !reset {
profile, err = getProfile(scopedID) profile, err = getProfile(scopedID)
// Check if the profile is special and needs a reset.
// Check if the request is for a special profile that may need a reset.
if err == nil && specialProfileNeedsReset(profile) { if err == nil && specialProfileNeedsReset(profile) {
// Trigger creation of special profile.
err = database.ErrNotFound
}
// If we cannot find a profile, check if the request is for a special
// profile we can create.
if errors.Is(err, database.ErrNotFound) {
profile = getSpecialProfile(id, linkedPath) profile = getSpecialProfile(id, linkedPath)
if profile != nil {
err = nil
} }
} else {
// Simulate missing profile to create new one.
err = database.ErrNotFound
} }
case linkedPath != "": case linkedPath != "":
@ -70,23 +65,48 @@ func GetProfile(source profileSource, id, linkedPath string) ( //nolint:gocognit
// the linked path. // the linked path.
profile = findActiveProfile(linkedPath) profile = findActiveProfile(linkedPath)
if profile != nil { if profile != nil {
if profile.outdated.IsSet() { if profile.outdated.IsSet() || reset {
previousVersion = profile previousVersion = profile
} else { } else {
return profile, nil return profile, nil
} }
} }
// Get from database. // Get from database.
if !reset {
profile, err = findProfile(linkedPath) profile, err = findProfile(linkedPath)
// Check if the profile is special and needs a reset.
if err == nil && specialProfileNeedsReset(profile) {
profile = getSpecialProfile(id, linkedPath)
}
} else {
// Simulate missing profile to create new one.
err = database.ErrNotFound
}
default: default:
return nil, errors.New("cannot fetch profile without ID or path") return nil, errors.New("cannot fetch profile without ID or path")
} }
// Create new profile if none was found.
if errors.Is(err, database.ErrNotFound) {
err = nil
// Check if there is a special profile for this ID.
profile = getSpecialProfile(id, linkedPath)
// If not, create a standard profile.
if profile == nil {
profile = New(SourceLocal, id, linkedPath, nil)
}
}
// If there was a non-recoverable error, return here.
if err != nil { if err != nil {
return nil, err return nil, err
} }
// Process profiles coming directly from the database. // Process profiles are coming directly from the database or are new.
// As we don't use any caching, these will be new objects. // As we don't use any caching, these will be new objects.
// Add a layeredProfile to local and network profiles. // Add a layeredProfile to local and network profiles.

View file

@ -239,9 +239,9 @@ func (lp *LayeredProfile) Update() (revisionCounter uint64) {
if layer.outdated.IsSet() { if layer.outdated.IsSet() {
changed = true changed = true
// update layer // update layer
newLayer, err := GetProfile(layer.Source, layer.ID, layer.LinkedPath) newLayer, err := GetProfile(layer.Source, layer.ID, layer.LinkedPath, false)
if err != nil { if err != nil {
log.Errorf("profiles: failed to update profile %s", layer.ScopedID()) log.Errorf("profiles: failed to update profile %s: %s", layer.ScopedID(), err)
} else { } else {
lp.layers[i] = newLayer lp.layers[i] = newLayer
} }

View file

@ -445,6 +445,31 @@ func (profile *Profile) UpdateMetadata(binaryPath string) (changed bool) {
return changed return changed
} }
func (profile *Profile) copyMetadataFrom(otherProfile *Profile) (changed bool) {
if profile.Name != otherProfile.Name {
profile.Name = otherProfile.Name
changed = true
}
if profile.Description != otherProfile.Description {
profile.Description = otherProfile.Description
changed = true
}
if profile.Homepage != otherProfile.Homepage {
profile.Homepage = otherProfile.Homepage
changed = true
}
if profile.Icon != otherProfile.Icon {
profile.Icon = otherProfile.Icon
changed = true
}
if profile.IconType != otherProfile.IconType {
profile.IconType = otherProfile.IconType
changed = true
}
return
}
// updateMetadataFromSystem updates the profile metadata with data from the // updateMetadataFromSystem updates the profile metadata with data from the
// operating system and saves it afterwards. // operating system and saves it afterwards.
func (profile *Profile) updateMetadataFromSystem(ctx context.Context) error { func (profile *Profile) updateMetadataFromSystem(ctx context.Context) error {

View file

@ -36,6 +36,8 @@ In order to respect the app settings of the actual application, DNS requests fro
- Outgoing Rules (without global rules) - Outgoing Rules (without global rules)
- Block Bypassing - Block Bypassing
- Filter Lists - Filter Lists
If you think you might have messed up the settings of the System DNS Client, just delete the profile below to reset it to the defaults.
` `
// PortmasterProfileID is the profile ID used for the Portmaster Core itself. // PortmasterProfileID is the profile ID used for the Portmaster Core itself.
@ -193,6 +195,10 @@ func getSpecialProfile(profileID, linkedPath string) *Profile {
// check if the special profile has not been changed by the user and if not, // check if the special profile has not been changed by the user and if not,
// check if the profile is outdated and can be upgraded. // check if the profile is outdated and can be upgraded.
func specialProfileNeedsReset(profile *Profile) bool { func specialProfileNeedsReset(profile *Profile) bool {
if profile == nil {
return false
}
switch { switch {
case profile.Source != SourceLocal: case profile.Source != SourceLocal:
// Special profiles live in the local scope only. // Special profiles live in the local scope only.