diff --git a/network/connection.go b/network/connection.go index e61d12fa..d87964f9 100644 --- a/network/connection.go +++ b/network/connection.go @@ -14,6 +14,7 @@ import ( "github.com/safing/portmaster/network/netutils" "github.com/safing/portmaster/network/packet" "github.com/safing/portmaster/process" + _ "github.com/safing/portmaster/process/tags" "github.com/safing/portmaster/resolver" "github.com/safing/spn/navigator" ) diff --git a/process/find.go b/process/find.go index 9c395f14..9f021426 100644 --- a/process/find.go +++ b/process/find.go @@ -69,13 +69,18 @@ func GetNetworkHost(ctx context.Context, remoteIP net.IP) (process *Process, err UserID: NetworkHostProcessID, Pid: NetworkHostProcessID, ParentPid: NetworkHostProcessID, - Path: fmt.Sprintf("net:%s", remoteIP), + Tags: []profile.Tag{ + { + Key: "net", + Value: remoteIP.String(), + }, + }, FirstSeen: now, LastSeen: now, } // Get the (linked) local profile. - networkHostProfile, err := profile.GetProfile(profile.SourceNetwork, remoteIP.String(), "", false) + networkHostProfile, err := profile.GetLocalProfile("", networkHost.MatchingData(), networkHost.CreateProfileCallback) if err != nil { return nil, err } diff --git a/process/process_default.go b/process/process_default.go index 97f093e9..4d9d58dd 100644 --- a/process/process_default.go +++ b/process/process_default.go @@ -1,11 +1,7 @@ -//+build !windows,!linux +//go:build !windows && !linux +// +build !windows,!linux package process // SystemProcessID is the PID of the System/Kernel itself. const SystemProcessID = 0 - -// specialOSInit does special OS specific Process initialization. -func (p *Process) specialOSInit() { - -} diff --git a/process/process_linux.go b/process/process_linux.go index 64268a66..3d62bb9b 100644 --- a/process/process_linux.go +++ b/process/process_linux.go @@ -2,6 +2,3 @@ package process // SystemProcessID is the PID of the System/Kernel itself. const SystemProcessID = 0 - -// specialOSInit does special OS specific Process initialization. -func (p *Process) specialOSInit() {} diff --git a/process/process_windows.go b/process/process_windows.go index c0f722c2..e350f5a7 100644 --- a/process/process_windows.go +++ b/process/process_windows.go @@ -1,28 +1,4 @@ package process -import ( - "fmt" - - "github.com/safing/portbase/log" - "github.com/safing/portbase/utils/osdetail" -) - // SystemProcessID is the PID of the System/Kernel itself. const SystemProcessID = 4 - -// specialOSInit does special OS specific Process initialization. -func (p *Process) specialOSInit() { - // add svchost.exe service names to Name - if p.ExecName == "svchost.exe" { - svcNames, err := osdetail.GetServiceNames(int32(p.Pid)) - switch err { - case nil: - p.Name += fmt.Sprintf(" (%s)", svcNames) - p.SpecialDetail = svcNames - case osdetail.ErrServiceNotFound: - log.Tracef("process: failed to get service name for svchost.exe (pid %d): %s", p.Pid, err) - default: - log.Warningf("process: failed to get service name for svchost.exe (pid %d): %s", p.Pid, err) - } - } -} diff --git a/process/tags/appimage_unix.go b/process/tags/appimage_unix.go new file mode 100644 index 00000000..54e9d8bb --- /dev/null +++ b/process/tags/appimage_unix.go @@ -0,0 +1,87 @@ +package tags + +import ( + "strings" + + "github.com/safing/portmaster/process" + "github.com/safing/portmaster/profile" +) + +func init() { + err := process.RegisterTagHandler(new(AppImageHandler)) + if err != nil { + panic(err) + } +} + +const ( + appImageName = "AppImage" + appImagePathTagKey = "app-image-path" +) + +// AppImageHandler handles AppImage processes on Unix systems. +type AppImageHandler struct{} + +// Name returns the tag handler name. +func (h *AppImageHandler) Name() string { + return appImageName +} + +// TagDescriptions returns a list of all possible tags and their description +// of this handler. +func (h *AppImageHandler) TagDescriptions() []process.TagDescription { + return []process.TagDescription{ + { + ID: appImagePathTagKey, + Name: "App Image Path", + Description: "Path to the app image file itself.", + }, + } +} + +// AddTags adds tags to the given process. +func (h *AppImageHandler) AddTags(p *process.Process) { + // Get and verify AppImage location. + appImageLocation, ok := p.Env["APPIMAGE"] + if !ok { + return + } + appImageMountDir, ok := p.Env["APPDIR"] + if !ok { + return + } + // Check if the process path is in the mount dir. + if !strings.HasPrefix(p.Path, appImageMountDir) { + return + } + + // Add matching path for regular profile matching. + p.MatchingPath = appImageLocation + + // Add app image tags. + p.Tags = append(p.Tags, profile.Tag{ + Key: appImagePathTagKey, + Value: appImageLocation, + }) +} + +// CreateProfile creates a profile based on the tags of the process. +// Returns nil to skip. +func (h *AppImageHandler) CreateProfile(p *process.Process) *profile.Profile { + for _, tag := range p.Tags { + if tag.Key == appImagePathTagKey { + return profile.New(&profile.Profile{ + Source: profile.SourceLocal, + PresentationPath: p.Path, + Fingerprints: []profile.Fingerprint{ + { + Type: profile.FingerprintTypePathID, + Operation: profile.FingerprintOperationEqualsID, + Value: tag.Value, // Value of appImagePathTagKey. + }, + }, + }) + } + } + return nil +} diff --git a/process/tags/net.go b/process/tags/net.go new file mode 100644 index 00000000..db2848b0 --- /dev/null +++ b/process/tags/net.go @@ -0,0 +1,65 @@ +package tags + +import ( + "github.com/safing/portmaster/process" + "github.com/safing/portmaster/profile" +) + +func init() { + err := process.RegisterTagHandler(new(NetworkHandler)) + if err != nil { + panic(err) + } +} + +const ( + netName = "Network" + netTagKey = "net" +) + +// NetworkHandler handles AppImage processes on Unix systems. +type NetworkHandler struct{} + +// Name returns the tag handler name. +func (h *NetworkHandler) Name() string { + return netName +} + +// TagDescriptions returns a list of all possible tags and their description +// of this handler. +func (h *NetworkHandler) TagDescriptions() []process.TagDescription { + return []process.TagDescription{ + { + ID: netTagKey, + Name: "Things on the Network", + Description: "Other (virtual) devices that make requests to Portmaster, if enabled in Portmaster.", + }, + } +} + +// AddTags adds tags to the given process. +func (h *NetworkHandler) AddTags(p *process.Process) { + // The "net" tag is added directly when creating the virtual process. +} + +// CreateProfile creates a profile based on the tags of the process. +// Returns nil to skip. +func (h *NetworkHandler) CreateProfile(p *process.Process) *profile.Profile { + for _, tag := range p.Tags { + if tag.Key == netTagKey { + return profile.New(&profile.Profile{ + Source: profile.SourceLocal, + Name: p.Name, + Fingerprints: []profile.Fingerprint{ + { + Type: profile.FingerprintTypeTagID, + Key: tag.Key, + Operation: profile.FingerprintOperationEqualsID, + Value: tag.Value, + }, + }, + }) + } + } + return nil +} diff --git a/process/tags/svchost_windows.go b/process/tags/svchost_windows.go new file mode 100644 index 00000000..724c29a8 --- /dev/null +++ b/process/tags/svchost_windows.go @@ -0,0 +1,97 @@ +package tags + +import ( + "fmt" + "strings" + + "github.com/safing/portbase/log" + "github.com/safing/portmaster/process" + "github.com/safing/portmaster/profile" +) + +func init() { + err := process.RegisterTagHandler(new(SVCHostTagHandler)) + if err != nil { + panic(err) + } +} + +const ( + svchostName = "SvcHost" + svchostTagKey = "svchost" +) + +// SVCHostTagHandler handles svchost processes on Windows. +type SVCHostTagHandler struct{} + +// Name returns the tag handler name. +func (h *SVCHostTagHandler) Name() string { + return svcHostName +} + +// TagDescriptions returns a list of all possible tags and their description +// of this handler. +func (h *SVCHostTagHandler) TagDescriptions() []process.TagDescription { + return []process.TagDescription{ + process.TagDescription{ + ID: svcHostTagKey, + Name: "SvcHost Service Name", + Description: "Name of a service running in svchost.exe as reported by Windows.", + }, + } +} + +// TagKeys returns a list of all possible tag keys of this handler. +func (h *SVCHostTagHandler) TagKeys() []string { + return []string{svcHostTagKey} +} + +// AddTags adds tags to the given process. +func (h *SVCHostTagHandler) AddTags(p *process.Process) { + // Check for svchost.exe. + if p.ExecName != "svchost.exe" { + return + } + + // Get services of svchost instance. + svcNames, err := osdetail.GetServiceNames(int32(p.Pid)) + switch err { + case nil: + // Append service names to process name. + p.Name += fmt.Sprintf(" (%s)", strings.Join(svcNames, ", ")) + // Add services as tags. + for _, svcName := range svcNames { + p.Tag = append(p.Tag, profile.Tag{ + Key: svchostTagKey, + Value: svcName, + }) + } + case osdetail.ErrServiceNotFound: + log.Tracef("process/tags: failed to get service name for svchost.exe (pid %d): %s", p.Pid, err) + default: + log.Warningf("process/tags: failed to get service name for svchost.exe (pid %d): %s", p.Pid, err) + } +} + +// CreateProfile creates a profile based on the tags of the process. +// Returns nil to skip. +func (h *SVCHostTagHandler) CreateProfile(p *process.Process) *profile.Profile { + for _, tag := range p.Tags { + if tag.Key == svchostTagKey { + return profile.New( + profile.SourceLocal, + "", + "Windows Service: "+tag.Value, + p.Path, + []profile.Fingerprint{profile.Fingerprint{ + Type: profile.FingerprintTypeTagID, + Key: tag.Key, + Operation: profile.FingerprintOperationEqualsID, + Value: tag.Value, + }}, + nil, + ) + } + } + return nil +}