From 62b1c03edc2ac99858c2884540d6838e2cfab61a Mon Sep 17 00:00:00 2001 From: Daniel Date: Fri, 30 Nov 2018 22:11:00 +0100 Subject: [PATCH] Work on portmaster restructuring --- firewall/master.go | 97 ++++++++++++++++----------------- network/reference/protocols.go | 43 +++++++++++++++ process/executable.go | 43 +++++++++++++++ process/fileinfo.go | 37 ------------- process/matching.go | 51 ++++++++++++++++++ process/process.go | 21 +++++--- profile/const_darwin.go | 4 +- profile/const_linux.go | 4 +- profile/fingerprint.go | 99 ++++++++++++++++++++++++++++++++++ profile/ports.go | 22 +++++--- profile/profile.go | 6 +-- profile/profileset.go | 17 +++--- profile/profileset_test.go | 17 ++++++ 13 files changed, 349 insertions(+), 112 deletions(-) create mode 100644 network/reference/protocols.go create mode 100644 process/executable.go delete mode 100644 process/fileinfo.go create mode 100644 process/matching.go create mode 100644 profile/fingerprint.go create mode 100644 profile/profileset_test.go diff --git a/firewall/master.go b/firewall/master.go index ef258a9b..3307a5ff 100644 --- a/firewall/master.go +++ b/firewall/master.go @@ -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) } diff --git a/network/reference/protocols.go b/network/reference/protocols.go new file mode 100644 index 00000000..ba1dbd13 --- /dev/null +++ b/network/reference/protocols.go @@ -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 +} diff --git a/process/executable.go b/process/executable.go new file mode 100644 index 00000000..3bb6c00d --- /dev/null +++ b/process/executable.go @@ -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 +} diff --git a/process/fileinfo.go b/process/fileinfo.go deleted file mode 100644 index 0bfa2018..00000000 --- a/process/fileinfo.go +++ /dev/null @@ -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(), - } -} diff --git a/process/matching.go b/process/matching.go new file mode 100644 index 00000000..ad821770 --- /dev/null +++ b/process/matching.go @@ -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 +} diff --git a/process/process.go b/process/process.go index 5f1b39c7..89f8e3b1 100644 --- a/process/process.go +++ b/process/process.go @@ -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]) } diff --git a/profile/const_darwin.go b/profile/const_darwin.go index 23c9f82a..4868ddf5 100644 --- a/profile/const_darwin.go +++ b/profile/const_darwin.go @@ -1,6 +1,6 @@ package profile -// OS Identifier Prefix +// OS Identifier const ( - IdentifierPrefix = "mac:" + osIdentifier = "mac" ) diff --git a/profile/const_linux.go b/profile/const_linux.go index 62ae967d..25d1c56f 100644 --- a/profile/const_linux.go +++ b/profile/const_linux.go @@ -1,6 +1,6 @@ package profile -// OS Identifier Prefix +// OS Identifier const ( - IdentifierPrefix = "lin:" + osIdentifier = "lin" ) diff --git a/profile/fingerprint.go b/profile/fingerprint.go new file mode 100644 index 00000000..79297bcd --- /dev/null +++ b/profile/fingerprint.go @@ -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) { +// +// } diff --git a/profile/ports.go b/profile/ports.go index 0b29f7be..8215e292 100644 --- a/profile/ports.go +++ b/profile/ports.go @@ -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 { diff --git a/profile/profile.go b/profile/profile.go index 863f7c3b..3afba39e 100644 --- a/profile/profile.go +++ b/profile/profile.go @@ -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"` diff --git a/profile/profileset.go b/profile/profileset.go index 5ba72e7c..a29d5cce 100644 --- a/profile/profileset.go +++ b/profile/profileset.go @@ -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. diff --git a/profile/profileset_test.go b/profile/profileset_test.go new file mode 100644 index 00000000..5513c7a8 --- /dev/null +++ b/profile/profileset_test.go @@ -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) + +}