safing-portmaster/process/matching.go
2018-12-03 20:02:03 +01:00

112 lines
2.7 KiB
Go

package process
import (
"fmt"
"github.com/Safing/portbase/database"
"github.com/Safing/portbase/log"
"github.com/Safing/portmaster/profile"
"github.com/Safing/portmaster/profile/index"
)
// FindProfiles finds and assigns a profile set to the process.
func (p *Process) FindProfiles() error {
// Get fingerprints of process
// Check if user profile already exists, else create new
pathIdentifier := profile.GetPathIdentifier(p.Path)
indexRecord, err := index.Get(pathIdentifier)
if err != nil && err != database.ErrNotFound {
log.Errorf("process: could not get profile index for %s: %s", pathIdentifier, err)
}
var possibleProfiles []*profile.Profile
if indexRecord != nil {
for _, profileID := range indexRecord.UserProfiles {
prof, err := profile.Get(profileID)
if err != nil {
log.Errorf("process: failed to load profile %s: %s", profileID, err)
}
possibleProfiles = append(possibleProfiles, prof)
}
}
}
prof := selectProfile(p, possibleProfiles)
if prof == nil {
// create new profile
prof := profile.New()
prof.Name = p.ExecName
prof.AddFingerprint(&profile.Fingerprint{
Type: "full_path",
Value: p.Path,
})
// TODO: maybe add sha256_sum?
prof.MarkUsed()
prof.Save()
}
// Find/Re-evaluate Stamp profile
// 1. check linked stamp profile
// 2. if last check is was more than a week ago, fetch from stamp:
// 3. send path identifier to stamp
// 4. evaluate all returned profiles
// 5. select best
// 6. link stamp profile to user profile
// FIXME: implement!
if prof.MarkUsed() {
prof.Save()
}
p.UserProfileKey = prof.Key()
p.profileSet = profile.NewSet(prof, nil)
p.Save()
return nil
}
func selectProfile(p *Process, profs []*profile.Profile) (selectedProfile *profile.Profile) {
var highestScore int
for _, prof := range profs {
score := matchProfile(p, prof)
if score > highestScore {
selectedProfile = prof
}
}
return
}
func matchProfile(p *Process, prof *profile.Profile) (score int) {
for _, fp := range prof.Fingerprints {
score += matchFingerprint(p, fp)
}
return
}
func matchFingerprint(p *Process, fp *profile.Fingerprint) (score int) {
if !fp.MatchesOS() {
return 0
}
switch fp.Type {
case "full_path":
if p.Path == fp.Value {
}
return profile.GetFingerprintWeight(fp.Type)
case "partial_path":
// FIXME: if full_path matches, do not match partial paths
return profile.GetFingerprintWeight(fp.Type)
case "md5_sum", "sha1_sum", "sha256_sum":
// FIXME: one sum is enough, check sums in a grouped form, start with the best
sum, err := p.GetExecHash(fp.Type)
if err != nil {
log.Errorf("process: failed to get hash of executable: %s", err)
} else if sum == fp.Value {
return profile.GetFingerprintWeight(fp.Type)
}
}
return 0
}