Working on portmaster restructure
This commit is contained in:
@@ -20,8 +20,8 @@ func (d Domains) IsSet() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// CheckStatus checks if the given domain is governed in the list of domains and returns whether it is permitted.
|
||||
func (d Domains) CheckStatus(domain string) (permit, ok bool) {
|
||||
// Check checks if the given domain is governed in the list of domains and returns whether it is permitted.
|
||||
func (d Domains) Check(domain string) (permit, ok bool) {
|
||||
// check for exact domain
|
||||
dd, ok := d[domain]
|
||||
if ok {
|
||||
|
||||
@@ -7,8 +7,8 @@ import (
|
||||
"github.com/Safing/portmaster/status"
|
||||
)
|
||||
|
||||
// ProfileFlags are used to quickly add common attributes to profiles
|
||||
type ProfileFlags map[uint8]uint8
|
||||
// Flags are used to quickly add common attributes to profiles
|
||||
type Flags map[uint8]uint8
|
||||
|
||||
// Profile Flags
|
||||
const (
|
||||
@@ -31,8 +31,8 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrProfileFlagsParseFailed is returned if a an invalid flag is encountered while parsing
|
||||
ErrProfileFlagsParseFailed = errors.New("profiles: failed to parse flags")
|
||||
// ErrFlagsParseFailed is returned if a an invalid flag is encountered while parsing
|
||||
ErrFlagsParseFailed = errors.New("profiles: failed to parse flags")
|
||||
|
||||
sortedFlags = []uint8{
|
||||
Prompt,
|
||||
@@ -77,34 +77,33 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
// FlagsFromNames creates ProfileFlags from a comma seperated list of flagnames (e.g. "System,Strict,Secure")
|
||||
// func FlagsFromNames(words []string) (*ProfileFlags, error) {
|
||||
// var flags ProfileFlags
|
||||
// FlagsFromNames creates Flags from a comma seperated list of flagnames (e.g. "System,Strict,Secure")
|
||||
// func FlagsFromNames(words []string) (*Flags, error) {
|
||||
// var flags Flags
|
||||
// for _, entry := range words {
|
||||
// flag, ok := flagIDs[entry]
|
||||
// if !ok {
|
||||
// return nil, ErrProfileFlagsParseFailed
|
||||
// return nil, ErrFlagsParseFailed
|
||||
// }
|
||||
// flags = append(flags, flag)
|
||||
// }
|
||||
// return &flags, nil
|
||||
// }
|
||||
|
||||
// IsSet returns whether the ProfileFlags object is "set".
|
||||
func (pf ProfileFlags) IsSet() bool {
|
||||
if pf != nil {
|
||||
return true
|
||||
// Check checks if a flag is set at all and if it's active in the given security level.
|
||||
func (flags Flags) Check(flag, level uint8) (active bool, ok bool) {
|
||||
if flags == nil {
|
||||
return false, false
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Has checks if a ProfileFlags object has a flag set in the given security level
|
||||
func (pf ProfileFlags) Has(flag, level uint8) bool {
|
||||
setting, ok := pf[flag]
|
||||
if ok && setting&level > 0 {
|
||||
return true
|
||||
setting, ok := flags[flag]
|
||||
if ok {
|
||||
if setting&level > 0 {
|
||||
return true, true
|
||||
}
|
||||
return false, true
|
||||
}
|
||||
return false
|
||||
return false, false
|
||||
}
|
||||
|
||||
func getLevelMarker(levels, level uint8) string {
|
||||
@@ -114,11 +113,11 @@ func getLevelMarker(levels, level uint8) string {
|
||||
return "-"
|
||||
}
|
||||
|
||||
// String return a string representation of ProfileFlags
|
||||
func (pf ProfileFlags) String() string {
|
||||
var namedFlags []string
|
||||
// String return a string representation of Flags
|
||||
func (flags Flags) String() string {
|
||||
var markedFlags []string
|
||||
for _, flag := range sortedFlags {
|
||||
levels, ok := pf[flag]
|
||||
levels, ok := flags[flag]
|
||||
if ok {
|
||||
s := flagNames[flag]
|
||||
if levels != status.SecurityLevelsAll {
|
||||
@@ -126,20 +125,18 @@ func (pf ProfileFlags) String() string {
|
||||
s += getLevelMarker(levels, status.SecurityLevelSecure)
|
||||
s += getLevelMarker(levels, status.SecurityLevelFortress)
|
||||
}
|
||||
markedFlags = append(markedFlags, s)
|
||||
}
|
||||
}
|
||||
for _, flag := range pf {
|
||||
namedFlags = append(namedFlags, flagNames[flag])
|
||||
}
|
||||
return strings.Join(namedFlags, ", ")
|
||||
return strings.Join(markedFlags, ", ")
|
||||
}
|
||||
|
||||
// Add adds a flag to the Flags with the given level.
|
||||
func (pf ProfileFlags) Add(flag, levels uint8) {
|
||||
pf[flag] = levels
|
||||
func (flags Flags) Add(flag, levels uint8) {
|
||||
flags[flag] = levels
|
||||
}
|
||||
|
||||
// Remove removes a flag from the Flags.
|
||||
func (pf ProfileFlags) Remove(flag uint8) {
|
||||
delete(pf, flag)
|
||||
func (flags Flags) Remove(flag uint8) {
|
||||
delete(flags, flag)
|
||||
}
|
||||
|
||||
@@ -2,6 +2,8 @@ package profile
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/Safing/portmaster/status"
|
||||
)
|
||||
|
||||
func TestProfileFlags(t *testing.T) {
|
||||
@@ -20,6 +22,19 @@ func TestProfileFlags(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
testFlags := Flags{
|
||||
Prompt: status.SecurityLevelsAll,
|
||||
Internet: status.SecurityLevelsDynamicAndSecure,
|
||||
LAN: status.SecurityLevelsDynamicAndSecure,
|
||||
Localhost: status.SecurityLevelsAll,
|
||||
Related: status.SecurityLevelDynamic,
|
||||
RequireGate17: status.SecurityLevelsSecureAndFortress,
|
||||
}
|
||||
|
||||
if testFlags.String() != "Prompt, Internet++-, LAN++-, Localhost, Related+--, RequireGate17-++" {
|
||||
t.Errorf("unexpected output: %s", testFlags.String())
|
||||
}
|
||||
|
||||
// // check Has
|
||||
// emptyFlags := ProfileFlags{}
|
||||
// for flag, name := range flagNames {
|
||||
|
||||
@@ -9,19 +9,12 @@ import (
|
||||
// Ports is a list of permitted or denied ports
|
||||
type Ports map[string][]*Port
|
||||
|
||||
// IsSet returns whether the Ports object is "set".
|
||||
func (p Ports) IsSet() bool {
|
||||
if p != nil {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// CheckStatus returns whether listening/connecting to a certain port is allowed, and if this option is even set.
|
||||
func (p Ports) CheckStatus(listen bool, protocol string, port uint16) (permit, ok bool) {
|
||||
// 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) {
|
||||
if p == nil {
|
||||
return false, false
|
||||
}
|
||||
|
||||
if listen {
|
||||
protocol = "<" + protocol
|
||||
}
|
||||
@@ -33,7 +26,7 @@ func (p Ports) CheckStatus(listen bool, protocol string, port uint16) (permit, o
|
||||
}
|
||||
}
|
||||
}
|
||||
return false, true
|
||||
return false, false
|
||||
}
|
||||
|
||||
func (p Ports) String() string {
|
||||
|
||||
@@ -29,7 +29,7 @@ type Profile struct {
|
||||
|
||||
// The mininum security level to apply to connections made with this profile
|
||||
SecurityLevel uint8
|
||||
Flags ProfileFlags
|
||||
Flags Flags
|
||||
Domains Domains
|
||||
Ports Ports
|
||||
|
||||
@@ -42,6 +42,7 @@ type Profile struct {
|
||||
ApproxLastUsed int64
|
||||
}
|
||||
|
||||
// New returns a new Profile.
|
||||
func New() *Profile {
|
||||
return &Profile{}
|
||||
}
|
||||
@@ -49,12 +50,10 @@ func New() *Profile {
|
||||
// Save saves the profile to the database
|
||||
func (profile *Profile) Save(namespace string) error {
|
||||
if profile.ID == "" {
|
||||
// FIXME: this is weird, the docs says that it also returns an error
|
||||
u := uuid.NewV4()
|
||||
// u, err := uuid.NewV4()
|
||||
// if err != nil {
|
||||
// return err
|
||||
// }
|
||||
u, err := uuid.NewV4()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
profile.ID = u.String()
|
||||
}
|
||||
|
||||
|
||||
@@ -1,119 +1,132 @@
|
||||
package profile
|
||||
|
||||
import "github.com/Safing/portmaster/status"
|
||||
|
||||
var (
|
||||
emptyFlags = ProfileFlags{}
|
||||
emptyPorts = Ports{}
|
||||
emptyFlags = Flags{}
|
||||
emptyPorts = Ports{}
|
||||
)
|
||||
|
||||
// ProfileSet handles Profile chaining.
|
||||
type ProfileSet struct {
|
||||
Profiles [4]*Profile
|
||||
// Set handles Profile chaining.
|
||||
type Set struct {
|
||||
profiles [4]*Profile
|
||||
// Application
|
||||
// Global
|
||||
// Stamp
|
||||
// Default
|
||||
|
||||
Independent bool
|
||||
securityLevel uint8
|
||||
independent bool
|
||||
}
|
||||
|
||||
// NewSet returns a new profile set with given the profiles.
|
||||
func NewSet(user, stamp *Profile) *ProfileSet {
|
||||
new := &ProfileSet{
|
||||
Profiles: [4]*Profile{
|
||||
user, // Application
|
||||
nil, // Global
|
||||
func NewSet(user, stamp *Profile) *Set {
|
||||
new := &Set{
|
||||
profiles: [4]*Profile{
|
||||
user, // Application
|
||||
nil, // Global
|
||||
stamp, // Stamp
|
||||
nil, // Default
|
||||
nil, // Default
|
||||
},
|
||||
}
|
||||
new.Update()
|
||||
return new
|
||||
new.Update(status.SecurityLevelFortress)
|
||||
return new
|
||||
}
|
||||
|
||||
// Update gets the new global and default profile and updates the independence status. It must be called when reusing a profile set for a series of calls.
|
||||
func (ps *ProfileSet) Update() {
|
||||
specialProfileLock.RLock()
|
||||
defer specialProfileLock.RUnlock()
|
||||
func (set *Set) Update(securityLevel uint8) {
|
||||
specialProfileLock.RLock()
|
||||
defer specialProfileLock.RUnlock()
|
||||
|
||||
// update profiles
|
||||
ps.Profiles[1] = globalProfile
|
||||
ps.Profiles[3] = defaultProfile
|
||||
// update profiles
|
||||
set.profiles[1] = globalProfile
|
||||
set.profiles[3] = defaultProfile
|
||||
|
||||
// update independence
|
||||
if ps.Flags().Has(Independent, ps.SecurityLevel()) {
|
||||
// Stamp profiles do not have the Independent flag
|
||||
ps.Independent = true
|
||||
} else {
|
||||
ps.Independent = false
|
||||
}
|
||||
}
|
||||
|
||||
// Flags returns the highest prioritized ProfileFlags configuration.
|
||||
func (ps *ProfileSet) Flags() ProfileFlags {
|
||||
|
||||
for _, profile := range ps.Profiles {
|
||||
if profile != nil {
|
||||
if profile.Flags.IsSet() {
|
||||
return profile.Flags
|
||||
}
|
||||
}
|
||||
// update security level
|
||||
profileSecurityLevel := set.getProfileSecurityLevel()
|
||||
if profileSecurityLevel > securityLevel {
|
||||
set.securityLevel = profileSecurityLevel
|
||||
} else {
|
||||
set.securityLevel = securityLevel
|
||||
}
|
||||
|
||||
return emptyFlags
|
||||
// update independence
|
||||
if active, ok := set.CheckFlag(Independent); active && ok {
|
||||
set.independent = true
|
||||
} else {
|
||||
set.independent = false
|
||||
}
|
||||
}
|
||||
|
||||
// CheckDomainStatus checks if the given domain is governed in any the lists of domains and returns whether it is permitted.
|
||||
func (ps *ProfileSet) CheckDomainStatus(domain string) (permit, ok bool) {
|
||||
// CheckFlag returns whether a given flag is set.
|
||||
func (set *Set) CheckFlag(flag) (active bool) {
|
||||
|
||||
for i, profile := range ps.Profiles {
|
||||
if i == 2 && ps.Independent {
|
||||
continue
|
||||
}
|
||||
for i, profile := range set.profiles {
|
||||
if i == 2 && set.independent {
|
||||
continue
|
||||
}
|
||||
|
||||
if profile != nil {
|
||||
if profile.Domains.IsSet() {
|
||||
permit, ok = profile.Domains.CheckStatus(domain)
|
||||
if ok {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
if profile != nil {
|
||||
active, ok := profile.Flags.Check(flag, set.securityLevel)
|
||||
if ok {
|
||||
return active
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// CheckDomain checks if the given domain is governed in any the lists of domains and returns whether it is permitted.
|
||||
func (set *Set) CheckDomain(domain string) (permit, ok bool) {
|
||||
|
||||
for i, profile := range set.profiles {
|
||||
if i == 2 && set.independent {
|
||||
continue
|
||||
}
|
||||
|
||||
if profile != nil {
|
||||
permit, ok = profile.Domains.Check(domain)
|
||||
if ok {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false, false
|
||||
}
|
||||
|
||||
// Ports returns the highest prioritized Ports configuration.
|
||||
func (set *Set) CheckPort() (permit, ok bool) {
|
||||
|
||||
for i, profile := range set.profiles {
|
||||
if i == 2 && set.independent {
|
||||
continue
|
||||
}
|
||||
|
||||
if profile != nil {
|
||||
if profile.Ports.Check() {
|
||||
return profile.Ports
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false, false
|
||||
}
|
||||
|
||||
// Ports returns the highest prioritized Ports configuration.
|
||||
func (ps *ProfileSet) Ports() Ports {
|
||||
|
||||
for i, profile := range ps.Profiles {
|
||||
if i == 2 && ps.Independent {
|
||||
continue
|
||||
}
|
||||
|
||||
if profile != nil {
|
||||
if profile.Ports.IsSet() {
|
||||
return profile.Ports
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return emptyPorts
|
||||
}
|
||||
|
||||
// SecurityLevel returns the highest prioritized security level.
|
||||
func (ps *ProfileSet) SecurityLevel() uint8 {
|
||||
func (set *Set) getProfileSecurityLevel() uint8 {
|
||||
|
||||
for i, profile := range ps.Profiles {
|
||||
if i == 2 {
|
||||
// Stamp profiles do not have the SecurityLevel setting
|
||||
continue
|
||||
}
|
||||
for i, profile := range set.profiles {
|
||||
if i == 2 {
|
||||
// Stamp profiles do not have the SecurityLevel setting
|
||||
continue
|
||||
}
|
||||
|
||||
if profile != nil {
|
||||
if profile.SecurityLevel > 0 {
|
||||
return profile.SecurityLevel
|
||||
}
|
||||
if profile != nil {
|
||||
if profile.SecurityLevel > 0 {
|
||||
return profile.SecurityLevel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user