Fix tests and linters

This commit is contained in:
Daniel
2022-02-02 12:48:42 +01:00
parent f2fcad4d11
commit 60d8664e7b
171 changed files with 944 additions and 874 deletions

View File

@@ -68,17 +68,6 @@ func addActiveProfile(profile *Profile) {
activeProfiles[profile.ScopedID()] = profile
}
// markActiveProfileAsOutdated marks an active profile as outdated.
func markActiveProfileAsOutdated(scopedID string) {
activeProfilesLock.RLock()
defer activeProfilesLock.RUnlock()
profile, ok := activeProfiles[scopedID]
if ok {
profile.outdated.Set()
}
}
func cleanActiveProfiles(ctx context.Context) error {
for {
select {

View File

@@ -15,18 +15,18 @@ var (
cfgIntOptions = make(map[string]config.IntOption)
cfgBoolOptions = make(map[string]config.BoolOption)
// General
// General.
// Enable Filter Order = 0
// Setting "Enable Filter" at order 0.
CfgOptionDefaultActionKey = "filter/defaultAction"
cfgOptionDefaultAction config.StringOption
cfgOptionDefaultActionOrder = 1
// Prompt Desktop Notifications Order = 2
// Prompt Timeout Order = 3
// Setting "Prompt Desktop Notifications" at order 2.
// Setting "Prompt Timeout" at order 3.
// Network Scopes
// Network Scopes.
CfgOptionBlockScopeInternetKey = "filter/blockInternet"
cfgOptionBlockScopeInternet config.IntOption // security level option
@@ -40,7 +40,7 @@ var (
cfgOptionBlockScopeLocal config.IntOption // security level option
cfgOptionBlockScopeLocalOrder = 18
// Connection Types
// Connection Types.
CfgOptionBlockP2PKey = "filter/blockP2P"
cfgOptionBlockP2P config.IntOption // security level option
@@ -50,7 +50,7 @@ var (
cfgOptionBlockInbound config.IntOption // security level option
cfgOptionBlockInboundOrder = 20
// Rules
// Rules.
CfgOptionEndpointsKey = "filter/endpoints"
cfgOptionEndpoints config.StringArrayOption
@@ -68,7 +68,7 @@ var (
cfgOptionFilterSubDomains config.IntOption // security level option
cfgOptionFilterSubDomainsOrder = 35
// DNS Filtering
// DNS Filtering.
CfgOptionFilterCNAMEKey = "filter/includeCNAMEs"
cfgOptionFilterCNAME config.IntOption // security level option
@@ -86,7 +86,7 @@ var (
cfgOptionDomainHeuristics config.IntOption // security level option
cfgOptionDomainHeuristicsOrder = 51
// Advanced
// Advanced.
CfgOptionPreventBypassingKey = "filter/preventBypassing"
cfgOptionPreventBypassing config.IntOption // security level option
@@ -96,7 +96,7 @@ var (
cfgOptionDisableAutoPermit config.IntOption // security level option
cfgOptionDisableAutoPermitOrder = 65
// Permanent Verdicts Order = 96
// Setting "Permanent Verdicts" at order 96.
CfgOptionUseSPNKey = "spn/use"
cfgOptionUseSPN config.BoolOption
@@ -119,7 +119,7 @@ var securityLevelSettings = []string{
CfgOptionDisableAutoPermitKey,
}
func registerConfiguration() error {
func registerConfiguration() error { //nolint:maintidx
// Default Filter Action
// permit - blocklist mode: everything is allowed unless blocked
// ask - ask mode: if not verdict is found, the user is consulted

View File

@@ -6,27 +6,22 @@ import (
"strings"
"github.com/safing/portbase/config"
"github.com/safing/portbase/log"
"github.com/safing/portbase/database"
"github.com/safing/portbase/database/query"
"github.com/safing/portbase/database/record"
"github.com/safing/portbase/log"
)
// Database paths:
// core:profiles/<scope>/<id>
// cache:profiles/index/<identifier>/<value>
const (
profilesDBPath = "core:profiles/"
)
const profilesDBPath = "core:profiles/"
var (
profileDB = database.NewInterface(&database.Options{
Local: true,
Internal: true,
})
)
var profileDB = database.NewInterface(&database.Options{
Local: true,
Internal: true,
})
func makeScopedID(source profileSource, id string) string {
return string(source) + "/" + id

View File

@@ -9,9 +9,7 @@ import (
"github.com/safing/portmaster/intel"
)
var (
asnRegex = regexp.MustCompile("^(AS)?[0-9]+$")
)
var asnRegex = regexp.MustCompile("^(AS)?[0-9]+$")
// EndpointASN matches ASNs.
type EndpointASN struct {

View File

@@ -8,9 +8,7 @@ import (
"github.com/safing/portmaster/intel"
)
var (
countryRegex = regexp.MustCompile(`^[A-Z]{2}$`)
)
var countryRegex = regexp.MustCompile(`^[A-Z]{2}$`)
// EndpointCountry matches countries.
type EndpointCountry struct {

View File

@@ -17,9 +17,7 @@ const (
domainMatchTypeContains
)
var (
allowedDomainChars = regexp.MustCompile(`^[a-z0-9\.-]+$`)
)
var allowedDomainChars = regexp.MustCompile(`^[a-z0-9\.-]+$`)
// EndpointDomain matches domains.
type EndpointDomain struct {

View File

@@ -4,9 +4,8 @@ import (
"context"
"strings"
"github.com/safing/portmaster/network/netutils"
"github.com/safing/portmaster/intel"
"github.com/safing/portmaster/network/netutils"
)
const (
@@ -50,6 +49,8 @@ func (ep *EndpointScope) Matches(_ context.Context, entity *intel.Entity) (EPRes
scope = scopeLAN
case netutils.GlobalMulticast:
scope = scopeInternet
case netutils.Undefined, netutils.Invalid:
return NoMatch, nil
}
if ep.scopes&scope > 0 {

View File

@@ -10,7 +10,7 @@ import (
"github.com/safing/portmaster/network/reference"
)
// Endpoint describes an Endpoint Matcher
// Endpoint describes an Endpoint Matcher.
type Endpoint interface {
Matches(ctx context.Context, entity *intel.Entity) (EPResult, Reason)
String() string
@@ -48,7 +48,9 @@ func (ep *EndpointBase) makeReason(s fmt.Stringer, value, desc string, keyval ..
key := keyval[idx]
val := keyval[idx+1]
r.Extra[key.(string)] = val
if keyName, ok := key.(string); ok {
r.Extra[keyName] = val
}
}
return r

View File

@@ -6,6 +6,8 @@ import (
)
func TestEndpointParsing(t *testing.T) {
t.Parallel()
// any (basics)
testParsing(t, "- *")
testParsing(t, "+ *")
@@ -60,6 +62,8 @@ func TestEndpointParsing(t *testing.T) {
}
func testParsing(t *testing.T, value string) {
t.Helper()
ep, err := parseEndpoint(value)
if err != nil {
t.Error(err)
@@ -71,6 +75,8 @@ func testParsing(t *testing.T, value string) {
}
func testDomainParsing(t *testing.T, value string, matchType uint8, matchValue string) {
t.Helper()
testParsing(t, value)
epGeneric, err := parseTypeDomain(strings.Fields(value))
@@ -78,7 +84,7 @@ func testDomainParsing(t *testing.T, value string, matchType uint8, matchValue s
t.Error(err)
return
}
ep := epGeneric.(*EndpointDomain)
ep := epGeneric.(*EndpointDomain) //nolint:forcetypeassert
if ep.MatchType != matchType {
t.Errorf(`error parsing domain endpoint "%s": match type should be %d, was %d`, value, matchType, ep.MatchType)

View File

@@ -11,10 +11,10 @@ import (
// Endpoints is a list of permitted or denied endpoints.
type Endpoints []Endpoint
// EPResult represents the result of a check against an EndpointPermission
// EPResult represents the result of a check against an EndpointPermission.
type EPResult uint8
// Endpoint matching return values
// Endpoint matching return values.
const (
NoMatch EPResult = iota
MatchError
@@ -50,7 +50,7 @@ entriesLoop:
if firstErr != nil {
if errCnt > 0 {
return endpoints, fmt.Errorf("encountered %d errors, first was: %s", errCnt, firstErr)
return endpoints, fmt.Errorf("encountered %d errors, first was: %w", errCnt, firstErr)
}
return endpoints, firstErr
}

View File

@@ -17,6 +17,8 @@ func TestMain(m *testing.M) {
}
func testEndpointMatch(t *testing.T, ep Endpoint, entity *intel.Entity, expectedResult EPResult) {
t.Helper()
entity.SetDstPort(entity.Port)
result, _ := ep.Matches(context.TODO(), entity)
@@ -33,6 +35,8 @@ func testEndpointMatch(t *testing.T, ep Endpoint, entity *intel.Entity, expected
}
func testFormat(t *testing.T, endpoint string, shouldSucceed bool) {
t.Helper()
_, err := parseEndpoint(endpoint)
if shouldSucceed {
assert.NoError(t, err)
@@ -42,6 +46,8 @@ func testFormat(t *testing.T, endpoint string, shouldSucceed bool) {
}
func TestEndpointFormat(t *testing.T) {
t.Parallel()
testFormat(t, "+ .", false)
testFormat(t, "+ .at", true)
testFormat(t, "+ .at.", true)
@@ -57,7 +63,9 @@ func TestEndpointFormat(t *testing.T) {
testFormat(t, "+ *.sub..and.prefix.*", false)
}
func TestEndpointMatching(t *testing.T) {
func TestEndpointMatching(t *testing.T) { //nolint:maintidx // TODO
t.Parallel()
// ANY
ep, err := parseEndpoint("+ *")
@@ -258,7 +266,7 @@ func TestEndpointMatching(t *testing.T) {
}).Init(), Permitted)
testEndpointMatch(t, ep, (&intel.Entity{
Domain: "example.com.",
}).Init(), Undeterminable)
}).Init(), NoMatch)
// ports
@@ -289,7 +297,7 @@ func TestEndpointMatching(t *testing.T) {
testEndpointMatch(t, ep, (&intel.Entity{
Domain: "example.com.",
}).Init(), Undeterminable)
}).Init(), NoMatch)
// IP
@@ -326,7 +334,7 @@ func TestEndpointMatching(t *testing.T) {
testEndpointMatch(t, ep, (&intel.Entity{
Domain: "example.com.",
}).Init(), Undeterminable)
}).Init(), NoMatch)
// IP Range
@@ -346,17 +354,18 @@ func TestEndpointMatching(t *testing.T) {
// ASN
ep, err = parseEndpoint("+ AS13335")
ep, err = parseEndpoint("+ AS15169")
if err != nil {
t.Fatal(err)
}
testEndpointMatch(t, ep, (&intel.Entity{
IP: net.ParseIP("1.1.1.2"),
}).Init(), Permitted)
testEndpointMatch(t, ep, (&intel.Entity{
IP: net.ParseIP("8.8.8.8"),
}).Init(), NoMatch)
entity = &intel.Entity{}
entity.SetIP(net.ParseIP("8.8.8.8"))
testEndpointMatch(t, ep, entity, Permitted)
entity = &intel.Entity{}
entity.SetIP(net.ParseIP("1.1.1.1"))
testEndpointMatch(t, ep, entity, NoMatch)
// Country
@@ -365,12 +374,13 @@ func TestEndpointMatching(t *testing.T) {
t.Fatal(err)
}
testEndpointMatch(t, ep, (&intel.Entity{
IP: net.ParseIP("194.232.104.1"), // orf.at
}).Init(), Permitted)
testEndpointMatch(t, ep, (&intel.Entity{
IP: net.ParseIP("151.101.1.164"), // nytimes.com
}).Init(), NoMatch)
entity = &intel.Entity{}
entity.SetIP(net.ParseIP("194.232.104.1")) // orf.at
testEndpointMatch(t, ep, entity, Permitted)
entity = &intel.Entity{}
entity.SetIP(net.ParseIP("151.101.1.164")) // nytimes.com
testEndpointMatch(t, ep, entity, NoMatch)
// Scope
@@ -391,8 +401,8 @@ func TestEndpointMatching(t *testing.T) {
if err != nil {
t.Fatal(err)
}
// TODO: write test for lists matcher
// TODO: write test for lists matcher
}
func getLineNumberOfCaller(levels int) int {

View File

@@ -1,6 +1,6 @@
package profile
// Platform identifiers
// Platform identifiers.
const (
PlatformLinux = "linux"
PlatformWindows = "windows"

View File

@@ -1,6 +1,6 @@
package profile
// OS Identifier
// OS Identifier.
const (
osIdentifier = PlatformMac
)

View File

@@ -1,6 +1,6 @@
package profile
// OS Identifier
// OS Identifier.
const (
osIdentifier = PlatformLinux
)

View File

@@ -1,6 +1,6 @@
package profile
// OS Identifier
// OS Identifier.
const (
osIdentifier = PlatformOpenBSD
)

View File

@@ -1,6 +1,6 @@
package profile
// OS Identifier
// OS Identifier.
const (
osIdentifier = PlatformWindows
)

View File

@@ -1,14 +1,12 @@
package profile
var (
fingerprintWeights = map[string]int{
"full_path": 2,
"partial_path": 1,
"md5_sum": 4,
"sha1_sum": 5,
"sha256_sum": 6,
}
)
var fingerprintWeights = map[string]int{
"full_path": 2,
"partial_path": 1,
"md5_sum": 4,
"sha1_sum": 5,
"sha256_sum": 6,
}
// Fingerprint links processes to profiles.
type Fingerprint struct {

View File

@@ -7,7 +7,7 @@ import (
"github.com/safing/portbase/utils"
)
// GetPathIdentifier returns the identifier from the given path
// GetPathIdentifier returns the identifier from the given path.
func GetPathIdentifier(path string) string {
// clean path
// TODO: is this necessary?

View File

@@ -3,6 +3,8 @@ package profile
import "testing"
func testPathID(t *testing.T, execPath, identifierPath string) {
t.Helper()
result := GetPathIdentifier(execPath)
if result != identifierPath {
t.Errorf("unexpected identifier path for %s: got %s, expected %s", execPath, result, identifierPath)
@@ -10,6 +12,8 @@ func testPathID(t *testing.T, execPath, identifierPath string) {
}
func TestGetPathIdentifier(t *testing.T) {
t.Parallel()
testPathID(t, "/bin/bash", "bin/bash")
testPathID(t, "/home/user/bin/bash", "bin/bash")
testPathID(t, "/home/user/project/main", "project/main")

View File

@@ -5,7 +5,6 @@ import (
"sync"
"github.com/safing/portbase/database"
"github.com/safing/portbase/database/query"
"github.com/safing/portbase/database/record"
"github.com/safing/portbase/log"

View File

@@ -4,6 +4,7 @@ import (
"context"
"github.com/hashicorp/go-version"
"github.com/safing/portbase/config"
"github.com/safing/portbase/database"
"github.com/safing/portbase/database/migration"
@@ -21,7 +22,7 @@ func registerMigrations() error {
)
}
func migrateNetworkRatingSystem(ctx context.Context, _, _ *version.Version, db *database.Interface) error {
func migrateNetworkRatingSystem(ctx context.Context, _, to *version.Version, db *database.Interface) error {
// determine the default value for the network rating system by searching for
// a global security level setting that is not set to the default.
networkRatingEnabled := false
@@ -32,7 +33,8 @@ func migrateNetworkRatingSystem(ctx context.Context, _, _ *version.Version, db *
}
intValue := config.Concurrent.GetAsInt(cfgkey, 0)()
if def.DefaultValue.(uint8) != uint8(intValue) {
defaultValue, ok := def.DefaultValue.(uint8)
if ok && defaultValue != uint8(intValue) {
log.Tracer(ctx).Infof("found global security level setting with changed value. 0x%2x (default) != 0x%2x (current)", def.DefaultValue, intValue)
networkRatingEnabled = true
break
@@ -40,7 +42,10 @@ func migrateNetworkRatingSystem(ctx context.Context, _, _ *version.Version, db *
}
if networkRatingEnabled {
status.SetNetworkRating(networkRatingEnabled)
err := status.SetNetworkRating(networkRatingEnabled)
if err != nil {
log.Warningf("profile: migration to %s failed to set network rating level to %v", to, networkRatingEnabled)
}
}
return nil

View File

@@ -6,10 +6,10 @@ import (
"github.com/safing/portbase/database/migration"
"github.com/safing/portbase/log"
"github.com/safing/portbase/modules"
"github.com/safing/portmaster/updates"
// module dependencies
// Dependency.
_ "github.com/safing/portmaster/core/base"
"github.com/safing/portmaster/updates"
)
var (

View File

@@ -24,7 +24,6 @@ func registerRevisionProvider() error {
revisionProviderPrefix,
runtime.SimpleValueGetterFunc(getRevisions),
)
if err != nil {
return err
}

View File

@@ -5,15 +5,13 @@ import (
"sync"
"sync/atomic"
"github.com/safing/portbase/config"
"github.com/safing/portbase/database/record"
"github.com/safing/portbase/log"
"github.com/safing/portbase/runtime"
"github.com/safing/portmaster/status"
"github.com/safing/portbase/config"
"github.com/safing/portmaster/intel"
"github.com/safing/portmaster/profile/endpoints"
"github.com/safing/portmaster/status"
)
// LayeredProfile combines multiple Profiles.
@@ -56,7 +54,7 @@ type LayeredProfile struct {
func NewLayeredProfile(localProfile *Profile) *LayeredProfile {
var securityLevelVal uint32
new := &LayeredProfile{
lp := &LayeredProfile{
localProfile: localProfile,
layers: make([]*Profile, 0, len(localProfile.LinkedProfiles)+1),
LayerIDs: make([]string, 0, len(localProfile.LinkedProfiles)+1),
@@ -65,76 +63,76 @@ func NewLayeredProfile(localProfile *Profile) *LayeredProfile {
securityLevel: &securityLevelVal,
}
new.DisableAutoPermit = new.wrapSecurityLevelOption(
lp.DisableAutoPermit = lp.wrapSecurityLevelOption(
CfgOptionDisableAutoPermitKey,
cfgOptionDisableAutoPermit,
)
new.BlockScopeLocal = new.wrapSecurityLevelOption(
lp.BlockScopeLocal = lp.wrapSecurityLevelOption(
CfgOptionBlockScopeLocalKey,
cfgOptionBlockScopeLocal,
)
new.BlockScopeLAN = new.wrapSecurityLevelOption(
lp.BlockScopeLAN = lp.wrapSecurityLevelOption(
CfgOptionBlockScopeLANKey,
cfgOptionBlockScopeLAN,
)
new.BlockScopeInternet = new.wrapSecurityLevelOption(
lp.BlockScopeInternet = lp.wrapSecurityLevelOption(
CfgOptionBlockScopeInternetKey,
cfgOptionBlockScopeInternet,
)
new.BlockP2P = new.wrapSecurityLevelOption(
lp.BlockP2P = lp.wrapSecurityLevelOption(
CfgOptionBlockP2PKey,
cfgOptionBlockP2P,
)
new.BlockInbound = new.wrapSecurityLevelOption(
lp.BlockInbound = lp.wrapSecurityLevelOption(
CfgOptionBlockInboundKey,
cfgOptionBlockInbound,
)
new.RemoveOutOfScopeDNS = new.wrapSecurityLevelOption(
lp.RemoveOutOfScopeDNS = lp.wrapSecurityLevelOption(
CfgOptionRemoveOutOfScopeDNSKey,
cfgOptionRemoveOutOfScopeDNS,
)
new.RemoveBlockedDNS = new.wrapSecurityLevelOption(
lp.RemoveBlockedDNS = lp.wrapSecurityLevelOption(
CfgOptionRemoveBlockedDNSKey,
cfgOptionRemoveBlockedDNS,
)
new.FilterSubDomains = new.wrapSecurityLevelOption(
lp.FilterSubDomains = lp.wrapSecurityLevelOption(
CfgOptionFilterSubDomainsKey,
cfgOptionFilterSubDomains,
)
new.FilterCNAMEs = new.wrapSecurityLevelOption(
lp.FilterCNAMEs = lp.wrapSecurityLevelOption(
CfgOptionFilterCNAMEKey,
cfgOptionFilterCNAME,
)
new.PreventBypassing = new.wrapSecurityLevelOption(
lp.PreventBypassing = lp.wrapSecurityLevelOption(
CfgOptionPreventBypassingKey,
cfgOptionPreventBypassing,
)
new.DomainHeuristics = new.wrapSecurityLevelOption(
lp.DomainHeuristics = lp.wrapSecurityLevelOption(
CfgOptionDomainHeuristicsKey,
cfgOptionDomainHeuristics,
)
new.UseSPN = new.wrapBoolOption(
lp.UseSPN = lp.wrapBoolOption(
CfgOptionUseSPNKey,
cfgOptionUseSPN,
)
new.LayerIDs = append(new.LayerIDs, localProfile.ScopedID())
new.layers = append(new.layers, localProfile)
lp.LayerIDs = append(lp.LayerIDs, localProfile.ScopedID())
lp.layers = append(lp.layers, localProfile)
// TODO: Load additional profiles.
new.updateCaches()
lp.updateCaches()
new.CreateMeta()
new.SetKey(runtime.DefaultRegistry.DatabaseName() + ":" + revisionProviderPrefix + localProfile.ScopedID())
lp.CreateMeta()
lp.SetKey(runtime.DefaultRegistry.DatabaseName() + ":" + revisionProviderPrefix + localProfile.ScopedID())
// Inform database subscribers about the new layered profile.
new.Lock()
defer new.Unlock()
lp.Lock()
defer lp.Unlock()
pushLayeredProfile(new)
pushLayeredProfile(lp)
return new
return lp
}
// LockForUsage locks the layered profile, including all layers individually.
@@ -167,7 +165,7 @@ func (lp *LayeredProfile) LocalProfile() *Profile {
// increaseRevisionCounter increases the revision counter and pushes the
// layered profile to listeners.
func (lp *LayeredProfile) increaseRevisionCounter(lock bool) (revisionCounter uint64) {
func (lp *LayeredProfile) increaseRevisionCounter(lock bool) (revisionCounter uint64) { //nolint:unparam // This is documentation.
if lp == nil {
return 0
}

View File

@@ -21,14 +21,10 @@ import (
"github.com/safing/portmaster/profile/endpoints"
)
var (
lastUsedUpdateThreshold = 24 * time.Hour
)
// profileSource is the source of the profile.
type profileSource string
// Profile Sources
// Profile Sources.
const (
SourceLocal profileSource = "local" // local, editable
SourceSpecial profileSource = "special" // specials (read-only)
@@ -37,7 +33,7 @@ const (
SourceEnterprise profileSource = "enterprise"
)
// Default Action IDs
// Default Action IDs.
const (
DefaultActionNotSet uint8 = 0
DefaultActionBlock uint8 = 1
@@ -266,7 +262,7 @@ func (profile *Profile) makeKey() {
profile.SetKey(makeProfileKey(profile.Source, profile.ID))
}
// Save saves the profile to the database
// Save saves the profile to the database.
func (profile *Profile) Save() error {
if profile.ID == "" {
return errors.New("profile: tried to save profile without ID")
@@ -414,20 +410,20 @@ func EnsureProfile(r record.Record) (*Profile, error) {
// unwrap
if r.IsWrapped() {
// only allocate a new struct, if we need it
new := &Profile{}
err := record.Unwrap(r, new)
newProfile := &Profile{}
err := record.Unwrap(r, newProfile)
if err != nil {
return nil, err
}
return new, nil
return newProfile, nil
}
// or adjust type
new, ok := r.(*Profile)
newProfile, ok := r.(*Profile)
if !ok {
return nil, fmt.Errorf("record not of type *Profile, but %T", r)
}
return new, nil
return newProfile, nil
}
// UpdateMetadata updates meta data fields on the profile and returns whether