mirror of
https://github.com/safing/portmaster
synced 2025-09-01 18:19:12 +00:00
Work on portmaster restructuring
This commit is contained in:
parent
3990790f17
commit
62b1c03edc
13 changed files with 349 additions and 112 deletions
|
@ -34,40 +34,40 @@ func DecideOnConnectionBeforeIntel(connection *network.Connection, fqdn string)
|
|||
|
||||
// grant self
|
||||
if connection.Process().Pid == os.Getpid() {
|
||||
log.Infof("sheriff: granting own connection %s", connection)
|
||||
log.Infof("firewall: granting own connection %s", connection)
|
||||
connection.Accept()
|
||||
return
|
||||
}
|
||||
|
||||
// check if there is a profile
|
||||
profile := connection.Process().Profile
|
||||
profileSet := connection.Process().ProfileSetSet
|
||||
if profile == nil {
|
||||
log.Infof("sheriff: no profile, denying connection %s", connection)
|
||||
log.Infof("firewall: no profile, denying connection %s", connection)
|
||||
connection.AddReason("no profile")
|
||||
connection.Block()
|
||||
return
|
||||
}
|
||||
|
||||
// check user class
|
||||
if profile.Flags.Has(profile.System) {
|
||||
if profileSet.CheckFlag(profile.System) {
|
||||
if !connection.Process().IsSystem() {
|
||||
log.Infof("sheriff: denying connection %s, profile has System flag set, but process is not executed by System", connection)
|
||||
log.Infof("firewall: denying connection %s, profile has System flag set, but process is not executed by System", connection)
|
||||
connection.AddReason("must be executed by system")
|
||||
connection.Block()
|
||||
return
|
||||
}
|
||||
}
|
||||
if profile.Flags.Has(profile.Admin) {
|
||||
if profileSet.CheckFlag(profile.Admin) {
|
||||
if !connection.Process().IsAdmin() {
|
||||
log.Infof("sheriff: denying connection %s, profile has Admin flag set, but process is not executed by Admin", connection)
|
||||
log.Infof("firewall: denying connection %s, profile has Admin flag set, but process is not executed by Admin", connection)
|
||||
connection.AddReason("must be executed by admin")
|
||||
connection.Block()
|
||||
return
|
||||
}
|
||||
}
|
||||
if profile.Flags.Has(profile.User) {
|
||||
if profileSet.CheckFlag(profile.User) {
|
||||
if !connection.Process().IsUser() {
|
||||
log.Infof("sheriff: denying connection %s, profile has User flag set, but process is not executed by a User", connection)
|
||||
log.Infof("firewall: denying connection %s, profile has User flag set, but process is not executed by a User", connection)
|
||||
connection.AddReason("must be executed by user")
|
||||
connection.Block()
|
||||
return
|
||||
|
@ -75,8 +75,8 @@ func DecideOnConnectionBeforeIntel(connection *network.Connection, fqdn string)
|
|||
}
|
||||
|
||||
// check for any network access
|
||||
if !profile.Flags.Has(profile.Internet) && !profile.Flags.Has(profile.LocalNet) {
|
||||
log.Infof("sheriff: denying connection %s, profile denies Internet and local network access", connection)
|
||||
if !profileSet.CheckFlag(profile.Internet) && !profileSet.CheckFlag(profile.LocalNet) {
|
||||
log.Infof("firewall: denying connection %s, profile denies Internet and local network access", connection)
|
||||
connection.Block()
|
||||
return
|
||||
}
|
||||
|
@ -102,14 +102,14 @@ func DecideOnConnectionBeforeIntel(connection *network.Connection, fqdn string)
|
|||
}
|
||||
if matched {
|
||||
if profile.DomainWhitelistIsBlacklist {
|
||||
log.Infof("sheriff: denying connection %s, profile has %s in domain blacklist", connection, fqdn)
|
||||
log.Infof("firewall: denying connection %s, profile has %s in domain blacklist", connection, fqdn)
|
||||
connection.AddReason("domain blacklisted")
|
||||
connection.Block()
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if !profile.DomainWhitelistIsBlacklist {
|
||||
log.Infof("sheriff: denying connection %s, profile does not have %s in domain whitelist", connection, fqdn)
|
||||
log.Infof("firewall: denying connection %s, profile does not have %s in domain whitelist", connection, fqdn)
|
||||
connection.AddReason("domain not in whitelist")
|
||||
connection.Block()
|
||||
return
|
||||
|
@ -127,9 +127,10 @@ func DecideOnConnectionAfterIntel(connection *network.Connection, fqdn string, r
|
|||
// - network specific: Strict
|
||||
|
||||
// check if there is a profile
|
||||
profile := connection.Process().Profile
|
||||
if profile == nil {
|
||||
log.Infof("sheriff: no profile, denying connection %s", connection)
|
||||
profileSet := connection.Process().ProfileSet
|
||||
// FIXME: there should always be a profile
|
||||
if profileSet == nil {
|
||||
log.Infof("firewall: no profile, denying connection %s", connection)
|
||||
connection.AddReason("no profile")
|
||||
connection.Block()
|
||||
return rrCache
|
||||
|
@ -137,7 +138,7 @@ func DecideOnConnectionAfterIntel(connection *network.Connection, fqdn string, r
|
|||
|
||||
// check Strict flag
|
||||
// TODO: drastically improve this!
|
||||
if profile.Flags.Has(profile.Strict) {
|
||||
if profileSet.CheckFlag(profile.Related) {
|
||||
matched := false
|
||||
pathElements := strings.Split(connection.Process().Path, "/")
|
||||
if len(pathElements) > 2 {
|
||||
|
@ -162,7 +163,7 @@ func DecideOnConnectionAfterIntel(connection *network.Connection, fqdn string, r
|
|||
}
|
||||
}
|
||||
if !matched {
|
||||
log.Infof("sheriff: denying connection %s, profile has declared Strict flag and no match to domain was found", connection)
|
||||
log.Infof("firewall: denying connection %s, profile has declared Strict flag and no match to domain was found", connection)
|
||||
connection.AddReason("domain does not relate to process")
|
||||
connection.Block()
|
||||
return rrCache
|
||||
|
@ -195,40 +196,40 @@ func DecideOnConnection(connection *network.Connection, pkt packet.Packet) {
|
|||
|
||||
// grant self
|
||||
if connection.Process().Pid == os.Getpid() {
|
||||
log.Infof("sheriff: granting own connection %s", connection)
|
||||
log.Infof("firewall: granting own connection %s", connection)
|
||||
connection.Accept()
|
||||
return
|
||||
}
|
||||
|
||||
// check if there is a profile
|
||||
profile := connection.Process().Profile
|
||||
profileSet := connection.Process().ProfileSet
|
||||
if profile == nil {
|
||||
log.Infof("sheriff: no profile, denying connection %s", connection)
|
||||
log.Infof("firewall: no profile, denying connection %s", connection)
|
||||
connection.AddReason("no profile")
|
||||
connection.Block()
|
||||
return
|
||||
}
|
||||
|
||||
// check user class
|
||||
if profile.Flags.Has(profile.System) {
|
||||
if profileSet.CheckFlag(profile.System) {
|
||||
if !connection.Process().IsSystem() {
|
||||
log.Infof("sheriff: denying connection %s, profile has System flag set, but process is not executed by System", connection)
|
||||
log.Infof("firewall: denying connection %s, profile has System flag set, but process is not executed by System", connection)
|
||||
connection.AddReason("must be executed by system")
|
||||
connection.Block()
|
||||
return
|
||||
}
|
||||
}
|
||||
if profile.Flags.Has(profile.Admin) {
|
||||
if profileSet.CheckFlag(profile.Admin) {
|
||||
if !connection.Process().IsAdmin() {
|
||||
log.Infof("sheriff: denying connection %s, profile has Admin flag set, but process is not executed by Admin", connection)
|
||||
log.Infof("firewall: denying connection %s, profile has Admin flag set, but process is not executed by Admin", connection)
|
||||
connection.AddReason("must be executed by admin")
|
||||
connection.Block()
|
||||
return
|
||||
}
|
||||
}
|
||||
if profile.Flags.Has(profile.User) {
|
||||
if profileSet.CheckFlag(profile.User) {
|
||||
if !connection.Process().IsUser() {
|
||||
log.Infof("sheriff: denying connection %s, profile has User flag set, but process is not executed by a User", connection)
|
||||
log.Infof("firewall: denying connection %s, profile has User flag set, but process is not executed by a User", connection)
|
||||
connection.AddReason("must be executed by user")
|
||||
connection.Block()
|
||||
return
|
||||
|
@ -236,8 +237,8 @@ func DecideOnConnection(connection *network.Connection, pkt packet.Packet) {
|
|||
}
|
||||
|
||||
// check for any network access
|
||||
if !profile.Flags.Has(profile.Internet) && !profile.Flags.Has(profile.LocalNet) {
|
||||
log.Infof("sheriff: denying connection %s, profile denies Internet and local network access", connection)
|
||||
if !profileSet.CheckFlag(profile.Internet) && !profileSet.CheckFlag(profile.LocalNet) {
|
||||
log.Infof("firewall: denying connection %s, profile denies Internet and local network access", connection)
|
||||
connection.AddReason("no network access allowed")
|
||||
connection.Block()
|
||||
return
|
||||
|
@ -246,29 +247,29 @@ func DecideOnConnection(connection *network.Connection, pkt packet.Packet) {
|
|||
switch connection.Domain {
|
||||
case "I":
|
||||
// check Service flag
|
||||
if !profile.Flags.Has(profile.Service) {
|
||||
log.Infof("sheriff: denying connection %s, profile does not declare service", connection)
|
||||
if !profileSet.CheckFlag(profile.Service) {
|
||||
log.Infof("firewall: denying connection %s, profile does not declare service", connection)
|
||||
connection.AddReason("not a service")
|
||||
connection.Drop()
|
||||
return
|
||||
}
|
||||
// check if incoming connections are allowed on any port, but only if there no other restrictions
|
||||
if !!profile.Flags.Has(profile.Internet) && !!profile.Flags.Has(profile.LocalNet) && len(profile.ListenPorts) == 0 {
|
||||
log.Infof("sheriff: granting connection %s, profile allows incoming connections from anywhere and on any port", connection)
|
||||
if !!profileSet.CheckFlag(profile.Internet) && !!profileSet.CheckFlag(profile.LocalNet) && len(profile.ListenPorts) == 0 {
|
||||
log.Infof("firewall: granting connection %s, profile allows incoming connections from anywhere and on any port", connection)
|
||||
connection.Accept()
|
||||
return
|
||||
}
|
||||
case "D":
|
||||
// check Directconnect flag
|
||||
if !profile.Flags.Has(profile.Directconnect) {
|
||||
log.Infof("sheriff: denying connection %s, profile does not declare direct connections", connection)
|
||||
// check PeerToPeer flag
|
||||
if !profileSet.CheckFlag(profile.PeerToPeer) {
|
||||
log.Infof("firewall: denying connection %s, profile does not declare direct connections", connection)
|
||||
connection.AddReason("direct connections (without DNS) not allowed")
|
||||
connection.Drop()
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
log.Infof("sheriff: could not decide on connection %s, deciding on per-link basis", connection)
|
||||
log.Infof("firewall: could not decide on connection %s, deciding on per-link basis", connection)
|
||||
connection.CantSay()
|
||||
}
|
||||
|
||||
|
@ -280,9 +281,9 @@ func DecideOnLink(connection *network.Connection, link *network.Link, pkt packet
|
|||
// Profile.ListenPorts
|
||||
|
||||
// check if there is a profile
|
||||
profile := connection.Process().Profile
|
||||
profileSet := connection.Process().ProfileSet
|
||||
if profile == nil {
|
||||
log.Infof("sheriff: no profile, denying %s", link)
|
||||
log.Infof("firewall: no profile, denying %s", link)
|
||||
link.AddReason("no profile")
|
||||
link.UpdateVerdict(network.BLOCK)
|
||||
return
|
||||
|
@ -296,15 +297,15 @@ func DecideOnLink(connection *network.Connection, link *network.Link, pkt packet
|
|||
remoteIP = pkt.GetIPHeader().Dst
|
||||
}
|
||||
if netutils.IPIsLocal(remoteIP) {
|
||||
if !profile.Flags.Has(profile.LocalNet) {
|
||||
log.Infof("sheriff: dropping link %s, profile does not allow communication in the local network", link)
|
||||
if !profileSet.CheckFlag(profile.LocalNet) {
|
||||
log.Infof("firewall: dropping link %s, profile does not allow communication in the local network", link)
|
||||
link.AddReason("profile does not allow access to local network")
|
||||
link.UpdateVerdict(network.BLOCK)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if !profile.Flags.Has(profile.Internet) {
|
||||
log.Infof("sheriff: dropping link %s, profile does not allow communication with the Internet", link)
|
||||
if !profileSet.CheckFlag(profile.Internet) {
|
||||
log.Infof("firewall: dropping link %s, profile does not allow communication with the Internet", link)
|
||||
link.AddReason("profile does not allow access to the Internet")
|
||||
link.UpdateVerdict(network.BLOCK)
|
||||
return
|
||||
|
@ -316,7 +317,7 @@ func DecideOnLink(connection *network.Connection, link *network.Link, pkt packet
|
|||
|
||||
tcpUdpHeader := pkt.GetTCPUDPHeader()
|
||||
if tcpUdpHeader == nil {
|
||||
log.Infof("sheriff: blocking link %s, profile has declared connect port whitelist, but link is not TCP/UDP", link)
|
||||
log.Infof("firewall: blocking link %s, profile has declared connect port whitelist, but link is not TCP/UDP", link)
|
||||
link.AddReason("profile has declared connect port whitelist, but link is not TCP/UDP")
|
||||
link.UpdateVerdict(network.BLOCK)
|
||||
return
|
||||
|
@ -339,7 +340,7 @@ func DecideOnLink(connection *network.Connection, link *network.Link, pkt packet
|
|||
}
|
||||
|
||||
if !matched {
|
||||
log.Infof("sheriff: blocking link %s, remote port %d not in profile connect port whitelist", link, remotePort)
|
||||
log.Infof("firewall: blocking link %s, remote port %d not in profile connect port whitelist", link, remotePort)
|
||||
link.AddReason("destination port not in whitelist")
|
||||
link.UpdateVerdict(network.BLOCK)
|
||||
return
|
||||
|
@ -352,7 +353,7 @@ func DecideOnLink(connection *network.Connection, link *network.Link, pkt packet
|
|||
|
||||
tcpUdpHeader := pkt.GetTCPUDPHeader()
|
||||
if tcpUdpHeader == nil {
|
||||
log.Infof("sheriff: dropping link %s, profile has declared listen port whitelist, but link is not TCP/UDP", link)
|
||||
log.Infof("firewall: dropping link %s, profile has declared listen port whitelist, but link is not TCP/UDP", link)
|
||||
link.AddReason("profile has declared listen port whitelist, but link is not TCP/UDP")
|
||||
link.UpdateVerdict(network.DROP)
|
||||
return
|
||||
|
@ -375,7 +376,7 @@ func DecideOnLink(connection *network.Connection, link *network.Link, pkt packet
|
|||
}
|
||||
|
||||
if !matched {
|
||||
log.Infof("sheriff: blocking link %s, local port %d not in profile listen port whitelist", link, localPort)
|
||||
log.Infof("firewall: blocking link %s, local port %d not in profile listen port whitelist", link, localPort)
|
||||
link.AddReason("listen port not in whitelist")
|
||||
link.UpdateVerdict(network.BLOCK)
|
||||
return
|
||||
|
@ -383,7 +384,7 @@ func DecideOnLink(connection *network.Connection, link *network.Link, pkt packet
|
|||
|
||||
}
|
||||
|
||||
log.Infof("sheriff: accepting link %s", link)
|
||||
log.Infof("firewall: accepting link %s", link)
|
||||
link.UpdateVerdict(network.ACCEPT)
|
||||
|
||||
}
|
||||
|
|
43
network/reference/protocols.go
Normal file
43
network/reference/protocols.go
Normal file
|
@ -0,0 +1,43 @@
|
|||
package reference
|
||||
|
||||
import "strconv"
|
||||
|
||||
var (
|
||||
protocolNames = map[uint8]string{
|
||||
1: "ICMP",
|
||||
2: "IGMP",
|
||||
6: "TCP",
|
||||
17: "UDP",
|
||||
27: "RDP",
|
||||
33: "DCCP",
|
||||
136: "UDPLite",
|
||||
}
|
||||
|
||||
protocolNumbers = map[string]uint8{
|
||||
"ICMP": 1,
|
||||
"IGMP": 2,
|
||||
"TCP": 6,
|
||||
"UDP": 17,
|
||||
"RDP": 27,
|
||||
"DCCP": 33,
|
||||
"UDPLite": 136,
|
||||
}
|
||||
)
|
||||
|
||||
// GetProtocolName returns the name of a IP protocol number.
|
||||
func GetProtocolName(protocol uint8) (name string) {
|
||||
name, ok := protocolNames[protocol]
|
||||
if ok {
|
||||
return name
|
||||
}
|
||||
return strconv.Itoa(int(protocol))
|
||||
}
|
||||
|
||||
// GetProtocolNumber returns the number of a IP protocol name.
|
||||
func GetProtocolNumber(protocol string) (number uint8, ok bool) {
|
||||
number, ok = protocolNumbers[protocol]
|
||||
if ok {
|
||||
return number, true
|
||||
}
|
||||
return 0, false
|
||||
}
|
43
process/executable.go
Normal file
43
process/executable.go
Normal file
|
@ -0,0 +1,43 @@
|
|||
// Copyright Safing ICS Technologies GmbH. Use of this source code is governed by the AGPL license that can be found in the LICENSE file.
|
||||
|
||||
package process
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"encoding/hex"
|
||||
"hash"
|
||||
"io"
|
||||
"os"
|
||||
)
|
||||
|
||||
// GetExecHash returns the hash of the executable with the given algorithm.
|
||||
func (p *Process) GetExecHash(algorithm string) (string, error) {
|
||||
sum, ok := p.ExecHashes[algorithm]
|
||||
if ok {
|
||||
return sum, nil
|
||||
}
|
||||
|
||||
var hasher hash.Hash
|
||||
switch algorithm {
|
||||
case "md5":
|
||||
hasher = crypto.MD5.New()
|
||||
case "sha1":
|
||||
hasher = crypto.SHA1.New()
|
||||
case "sha256":
|
||||
hasher = crypto.SHA256.New()
|
||||
}
|
||||
|
||||
file, err := os.Open(p.Path)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
_, err = io.Copy(hasher, file)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
sum = hex.EncodeToString(hasher.Sum(nil))
|
||||
p.ExecHashes[algorithm] = sum
|
||||
return sum, nil
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
// Copyright Safing ICS Technologies GmbH. Use of this source code is governed by the AGPL license that can be found in the LICENSE file.
|
||||
|
||||
package process
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/Safing/portbase/database/record"
|
||||
)
|
||||
|
||||
// ExecutableSignature stores a signature of an executable.
|
||||
type ExecutableSignature []byte
|
||||
|
||||
// FileInfo stores (security) information about a file.
|
||||
type FileInfo struct {
|
||||
record.Base
|
||||
sync.Mutex
|
||||
|
||||
HumanName string
|
||||
Owners []string
|
||||
ApproxLastSeen int64
|
||||
Signature *ExecutableSignature
|
||||
}
|
||||
|
||||
// GetFileInfo gathers information about a file and returns *FileInfo
|
||||
func GetFileInfo(path string) *FileInfo {
|
||||
// TODO: actually get file information
|
||||
// TODO: try to load from DB
|
||||
// TODO: save to DB (key: hash of some sorts)
|
||||
splittedPath := strings.Split("/", path)
|
||||
return &FileInfo{
|
||||
HumanName: splittedPath[len(splittedPath)-1],
|
||||
ApproxLastSeen: time.Now().Unix(),
|
||||
}
|
||||
}
|
51
process/matching.go
Normal file
51
process/matching.go
Normal file
|
@ -0,0 +1,51 @@
|
|||
package process
|
||||
|
||||
import (
|
||||
"github.com/Safing/portbase/log"
|
||||
"github.com/Safing/portmaster/profile"
|
||||
)
|
||||
|
||||
// FindProfiles finds and assigns a profile set to the process.
|
||||
func (p *Process) FindProfiles() {
|
||||
|
||||
// Get fingerprints of process
|
||||
|
||||
// Check if user profile already exists, else create new
|
||||
|
||||
// Find/Re-evaluate Stamp profile
|
||||
|
||||
// p.UserProfileKey
|
||||
// p.profileSet
|
||||
|
||||
}
|
||||
|
||||
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":
|
||||
return profile.GetFingerprintWeight(fp.Type)
|
||||
case "md5_sum", "sha1_sum", "sha256_sum":
|
||||
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
|
||||
}
|
|
@ -5,6 +5,7 @@ package process
|
|||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
|
@ -27,13 +28,18 @@ type Process struct {
|
|||
ParentPid int
|
||||
Path string
|
||||
Cwd string
|
||||
FileInfo *FileInfo
|
||||
CmdLine string
|
||||
FirstArg string
|
||||
|
||||
profileSet *profile.Set
|
||||
Name string
|
||||
Icon string
|
||||
ExecName string
|
||||
ExecHashes map[string]string
|
||||
// ExecOwner ...
|
||||
// ExecSignature ...
|
||||
|
||||
UserProfileKey string
|
||||
profileSet *profile.Set
|
||||
Name string
|
||||
Icon string
|
||||
// Icon is a path to the icon and is either prefixed "f:" for filepath, "d:" for database cache path or "c:"/"a:" for a the icon key to fetch it from a company / authoritative node and cache it in its own cache.
|
||||
|
||||
FirstConnectionEstablished int64
|
||||
|
@ -226,8 +232,11 @@ func GetOrFindProcess(pid int) (*Process, error) {
|
|||
// }
|
||||
// }
|
||||
|
||||
// get FileInfo
|
||||
new.FileInfo = GetFileInfo(new.Path)
|
||||
// Executable Information
|
||||
|
||||
// FIXME: use os specific path seperator
|
||||
splittedPath := strings.Split("/", new.Path)
|
||||
new.ExecName = strings.ToTitle(splittedPath[len(splittedPath)-1])
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package profile
|
||||
|
||||
// OS Identifier Prefix
|
||||
// OS Identifier
|
||||
const (
|
||||
IdentifierPrefix = "mac:"
|
||||
osIdentifier = "mac"
|
||||
)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
package profile
|
||||
|
||||
// OS Identifier Prefix
|
||||
// OS Identifier
|
||||
const (
|
||||
IdentifierPrefix = "lin:"
|
||||
osIdentifier = "lin"
|
||||
)
|
||||
|
|
99
profile/fingerprint.go
Normal file
99
profile/fingerprint.go
Normal file
|
@ -0,0 +1,99 @@
|
|||
package profile
|
||||
|
||||
var (
|
||||
fingerprintWeights = map[string]int{
|
||||
"full_path": 2,
|
||||
"partial_path": 1,
|
||||
"md5_sum": 4,
|
||||
"sha1_sum": 5,
|
||||
"sha256_sum": 6,
|
||||
}
|
||||
)
|
||||
|
||||
type Fingerprint struct {
|
||||
OS string
|
||||
Type string
|
||||
Value string
|
||||
Comment string
|
||||
}
|
||||
|
||||
func (fp *Fingerprint) MatchesOS() bool {
|
||||
return fp.OS == osIdentifier
|
||||
}
|
||||
|
||||
//
|
||||
// func (fp *Fingerprint) Equals(other *Fingerprint) bool {
|
||||
// return fp.OS == other.OS &&
|
||||
// fp.Type == other.Type &&
|
||||
// fp.Value == other.Value
|
||||
// }
|
||||
//
|
||||
// func (fp *Fingerprint) Check(type, value string) (weight int) {
|
||||
// if fp.Match(fpType, value) {
|
||||
// return GetFingerprintWeight(fpType)
|
||||
// }
|
||||
// return 0
|
||||
// }
|
||||
//
|
||||
// func (fp *Fingerprint) Match(fpType, value string) (matches bool) {
|
||||
// switch fp.Type {
|
||||
// case "partial_path":
|
||||
// return
|
||||
// default:
|
||||
// return fp.OS == osIdentifier &&
|
||||
// fp.Type == fpType &&
|
||||
// fp.Value == value
|
||||
// }
|
||||
//
|
||||
func GetFingerprintWeight(fpType string) (weight int) {
|
||||
weight, ok := fingerprintWeights[fpType]
|
||||
if ok {
|
||||
return weight
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
//
|
||||
// func (p *Profile) GetApplicableFingerprints() (fingerprints []*Fingerprint) {
|
||||
// for _, fp := range p.Fingerprints {
|
||||
// if fp.OS == osIdentifier {
|
||||
// fingerprints = append(fingerprints, fp)
|
||||
// }
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// func (p *Profile) AddFingerprint(fp *Fingerprint) error {
|
||||
// if fp.OS == "" {
|
||||
// fp.OS = osIdentifier
|
||||
// }
|
||||
//
|
||||
// p.Fingerprints = append(p.Fingerprints, fp)
|
||||
// return p.Save()
|
||||
// }
|
||||
//
|
||||
// func (p *Profile) GetApplicableFingerprintTypes() (types []string) {
|
||||
// for _, fp := range p.Fingerprints {
|
||||
// if fp.OS == osIdentifier && !utils.StringInSlice(types, fp.Type) {
|
||||
// types = append(types, fp.Type)
|
||||
// }
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// func (p *Profile) MatchFingerprints(fingerprints map[string]string) (score int) {
|
||||
// for _, fp := range p.Fingerprints {
|
||||
// if fp.OS == osIdentifier {
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// return
|
||||
// }
|
||||
//
|
||||
// func FindUserProfiles() {
|
||||
//
|
||||
// }
|
||||
//
|
||||
// func FindProfiles(path string) (*ProfileSet, error) {
|
||||
//
|
||||
// }
|
|
@ -4,21 +4,20 @@ import (
|
|||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/Safing/portmaster/network/reference"
|
||||
)
|
||||
|
||||
// Ports is a list of permitted or denied ports
|
||||
type Ports map[string][]*Port
|
||||
type Ports map[int16][]*Port
|
||||
|
||||
// Check returns whether listening/connecting to a certain port is allowed, if set.
|
||||
func (p Ports) Check(listen bool, protocol string, port uint16) (permit, ok bool) {
|
||||
func (p Ports) Check(signedProtocol int16, port uint16) (permit, ok bool) {
|
||||
if p == nil {
|
||||
return false, false
|
||||
}
|
||||
|
||||
if listen {
|
||||
protocol = "<" + protocol
|
||||
}
|
||||
portDefinitions, ok := p[protocol]
|
||||
portDefinitions, ok := p[signedProtocol]
|
||||
if ok {
|
||||
for _, portD := range portDefinitions {
|
||||
if portD.Matches(port) {
|
||||
|
@ -29,16 +28,23 @@ func (p Ports) Check(listen bool, protocol string, port uint16) (permit, ok bool
|
|||
return false, false
|
||||
}
|
||||
|
||||
func formatSignedProtocol(sP int16) string {
|
||||
if sP < 0 {
|
||||
return fmt.Sprintf("<%s", reference.GetProtocolName(uint8(-1*sP)))
|
||||
}
|
||||
return reference.GetProtocolName(uint8(sP))
|
||||
}
|
||||
|
||||
func (p Ports) String() string {
|
||||
var s []string
|
||||
|
||||
for protocol, ports := range p {
|
||||
for signedProtocol, ports := range p {
|
||||
var portStrings []string
|
||||
for _, port := range ports {
|
||||
portStrings = append(portStrings, port.String())
|
||||
}
|
||||
|
||||
s = append(s, fmt.Sprintf("%s:[%s]", protocol, strings.Join(portStrings, ", ")))
|
||||
s = append(s, fmt.Sprintf("%s:[%s]", formatSignedProtocol(signedProtocol), strings.Join(portStrings, ", ")))
|
||||
}
|
||||
|
||||
if len(s) == 0 {
|
||||
|
|
|
@ -23,8 +23,7 @@ type Profile struct {
|
|||
// Icon is a path to the icon and is either prefixed "f:" for filepath, "d:" for a database path or "e:" for the encoded data.
|
||||
Icon string
|
||||
|
||||
// Identification
|
||||
Identifiers []string
|
||||
// Fingerprints
|
||||
Fingerprints []string
|
||||
|
||||
// The mininum security level to apply to connections made with this profile
|
||||
|
@ -33,7 +32,8 @@ type Profile struct {
|
|||
Domains Domains
|
||||
Ports Ports
|
||||
|
||||
StampProfileKey string
|
||||
StampProfileKey string
|
||||
StampProfileAssigned int64
|
||||
|
||||
// If a Profile is declared as a Framework (i.e. an Interpreter and the likes), then the real process must be found
|
||||
// Framework *Framework `json:",omitempty bson:",omitempty"`
|
||||
|
|
|
@ -51,7 +51,7 @@ func (set *Set) Update(securityLevel uint8) {
|
|||
}
|
||||
|
||||
// update independence
|
||||
if active, ok := set.CheckFlag(Independent); active && ok {
|
||||
if set.CheckFlag(Independent) {
|
||||
set.independent = true
|
||||
} else {
|
||||
set.independent = false
|
||||
|
@ -59,7 +59,7 @@ func (set *Set) Update(securityLevel uint8) {
|
|||
}
|
||||
|
||||
// CheckFlag returns whether a given flag is set.
|
||||
func (set *Set) CheckFlag(flag) (active bool) {
|
||||
func (set *Set) CheckFlag(flag uint8) (active bool) {
|
||||
|
||||
for i, profile := range set.profiles {
|
||||
if i == 2 && set.independent {
|
||||
|
@ -97,7 +97,12 @@ func (set *Set) CheckDomain(domain string) (permit, ok bool) {
|
|||
}
|
||||
|
||||
// Ports returns the highest prioritized Ports configuration.
|
||||
func (set *Set) CheckPort() (permit, ok bool) {
|
||||
func (set *Set) CheckPort(listen bool, protocol uint8, port uint16) (permit, ok bool) {
|
||||
|
||||
signedProtocol := int16(protocol)
|
||||
if listen {
|
||||
signedProtocol = -1 * signedProtocol
|
||||
}
|
||||
|
||||
for i, profile := range set.profiles {
|
||||
if i == 2 && set.independent {
|
||||
|
@ -105,13 +110,13 @@ func (set *Set) CheckPort() (permit, ok bool) {
|
|||
}
|
||||
|
||||
if profile != nil {
|
||||
if profile.Ports.Check() {
|
||||
return profile.Ports
|
||||
if permit, ok = profile.Ports.Check(signedProtocol, port); ok {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false, false
|
||||
return false, false
|
||||
}
|
||||
|
||||
// SecurityLevel returns the highest prioritized security level.
|
||||
|
|
17
profile/profileset_test.go
Normal file
17
profile/profileset_test.go
Normal file
|
@ -0,0 +1,17 @@
|
|||
package profile
|
||||
|
||||
import "testing"
|
||||
|
||||
func TestProfileSet(t *testing.T) {
|
||||
|
||||
// new := &Set{
|
||||
// profiles: [4]*Profile{
|
||||
// user, // Application
|
||||
// nil, // Global
|
||||
// stamp, // Stamp
|
||||
// nil, // Default
|
||||
// },
|
||||
// }
|
||||
// new.Update(status.SecurityLevelFortress)
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue