mirror of
https://github.com/safing/portmaster
synced 2025-09-05 03:59:11 +00:00
Add database integrations for status and updates modules
This commit is contained in:
parent
321f3feec5
commit
12e1eb0917
10 changed files with 182 additions and 26 deletions
|
@ -48,7 +48,7 @@ func DecideOnConnectionBeforeIntel(connection *network.Connection, fqdn string)
|
||||||
connection.Deny("no profile set")
|
connection.Deny("no profile set")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
profileSet.Update(status.CurrentSecurityLevel())
|
profileSet.Update(status.ActiveSecurityLevel())
|
||||||
|
|
||||||
// check for any network access
|
// check for any network access
|
||||||
if !profileSet.CheckFlag(profile.Internet) && !profileSet.CheckFlag(profile.LAN) {
|
if !profileSet.CheckFlag(profile.Internet) && !profileSet.CheckFlag(profile.LAN) {
|
||||||
|
@ -152,7 +152,7 @@ func DecideOnConnectionAfterIntel(connection *network.Connection, fqdn string, r
|
||||||
connection.Deny("no profile")
|
connection.Deny("no profile")
|
||||||
return rrCache
|
return rrCache
|
||||||
}
|
}
|
||||||
profileSet.Update(status.CurrentSecurityLevel())
|
profileSet.Update(status.ActiveSecurityLevel())
|
||||||
|
|
||||||
// TODO: Stamp integration
|
// TODO: Stamp integration
|
||||||
|
|
||||||
|
@ -188,7 +188,7 @@ func DecideOnConnection(connection *network.Connection, pkt packet.Packet) {
|
||||||
connection.Deny("no profile")
|
connection.Deny("no profile")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
profileSet.Update(status.CurrentSecurityLevel())
|
profileSet.Update(status.ActiveSecurityLevel())
|
||||||
|
|
||||||
// check connection type
|
// check connection type
|
||||||
switch connection.Domain {
|
switch connection.Domain {
|
||||||
|
@ -286,7 +286,7 @@ func DecideOnLink(connection *network.Connection, link *network.Link, pkt packet
|
||||||
link.Block("no profile")
|
link.Block("no profile")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
profileSet.Update(status.CurrentSecurityLevel())
|
profileSet.Update(status.ActiveSecurityLevel())
|
||||||
|
|
||||||
// get host
|
// get host
|
||||||
var domainOrIP string
|
var domainOrIP string
|
||||||
|
|
|
@ -251,13 +251,13 @@ func intelligentResolve(fqdn string, qtype dns.Type, securityLevel uint8) *RRCac
|
||||||
|
|
||||||
func tryResolver(resolver *Resolver, lastFailBoundary int64, fqdn string, qtype dns.Type, securityLevel uint8) (*RRCache, bool) {
|
func tryResolver(resolver *Resolver, lastFailBoundary int64, fqdn string, qtype dns.Type, securityLevel uint8) (*RRCache, bool) {
|
||||||
// skip if not allowed in current security level
|
// skip if not allowed in current security level
|
||||||
if resolver.AllowedSecurityLevel < status.CurrentSecurityLevel() || resolver.AllowedSecurityLevel < securityLevel {
|
if resolver.AllowedSecurityLevel < status.ActiveSecurityLevel() || resolver.AllowedSecurityLevel < securityLevel {
|
||||||
log.Tracef("intel: skipping resolver %s, because it isn't allowed to operate on the current security level: %d|%d", resolver, status.CurrentSecurityLevel(), securityLevel)
|
log.Tracef("intel: skipping resolver %s, because it isn't allowed to operate on the current security level: %d|%d", resolver, status.ActiveSecurityLevel(), securityLevel)
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
// skip if not security level denies assigned dns servers
|
// skip if not security level denies assigned dns servers
|
||||||
if doNotUseAssignedNameservers(securityLevel) && resolver.Source == "dhcp" {
|
if doNotUseAssignedNameservers(securityLevel) && resolver.Source == "dhcp" {
|
||||||
log.Tracef("intel: skipping resolver %s, because assigned nameservers are not allowed on the current security level: %d|%d", resolver, status.CurrentSecurityLevel(), securityLevel)
|
log.Tracef("intel: skipping resolver %s, because assigned nameservers are not allowed on the current security level: %d|%d", resolver, status.ActiveSecurityLevel(), securityLevel)
|
||||||
return nil, false
|
return nil, false
|
||||||
}
|
}
|
||||||
// check if failed recently
|
// check if failed recently
|
||||||
|
|
|
@ -26,15 +26,18 @@ func (sh *statusHook) UsesPrePut() bool {
|
||||||
|
|
||||||
// PrePut implements the Hook interface.
|
// PrePut implements the Hook interface.
|
||||||
func (sh *statusHook) PrePut(r record.Record) (record.Record, error) {
|
func (sh *statusHook) PrePut(r record.Record) (record.Record, error) {
|
||||||
|
// record is already locked!
|
||||||
|
|
||||||
newStatus, err := EnsureSystemStatus(r)
|
newStatus, err := EnsureSystemStatus(r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
newStatus.Lock()
|
|
||||||
defer newStatus.Unlock()
|
|
||||||
|
|
||||||
// apply applicable settings
|
// apply applicable settings
|
||||||
setSelectedSecurityLevel(newStatus.SelectedSecurityLevel)
|
if SelectedSecurityLevel() != newStatus.SelectedSecurityLevel {
|
||||||
|
go setSelectedSecurityLevel(newStatus.SelectedSecurityLevel)
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: allow setting of Gate17 status (on/off)
|
// TODO: allow setting of Gate17 status (on/off)
|
||||||
|
|
||||||
// return original status
|
// return original status
|
||||||
|
|
|
@ -11,7 +11,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
modules.Register("status", nil, start, stop)
|
modules.Register("status", nil, start, stop, "database")
|
||||||
}
|
}
|
||||||
|
|
||||||
func start() error {
|
func start() error {
|
||||||
|
|
|
@ -33,7 +33,7 @@ func getLatestFilePath(identifier string) (versionedFilePath, version string, st
|
||||||
updatesLock.RLock()
|
updatesLock.RLock()
|
||||||
version, ok = stableUpdates[identifier]
|
version, ok = stableUpdates[identifier]
|
||||||
if !ok {
|
if !ok {
|
||||||
version, ok = latestUpdates[identifier]
|
version, ok = localUpdates[identifier]
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Tracef("updates: file %s does not exist", identifier)
|
log.Tracef("updates: file %s does not exist", identifier)
|
||||||
return "", "", false, false
|
return "", "", false, false
|
||||||
|
@ -58,6 +58,7 @@ func loadOrFetchFile(identifier string) (*File, error) {
|
||||||
realFilePath := filepath.Join(updateStoragePath, versionedFilePath)
|
realFilePath := filepath.Join(updateStoragePath, versionedFilePath)
|
||||||
if _, err := os.Stat(realFilePath); err == nil {
|
if _, err := os.Stat(realFilePath); err == nil {
|
||||||
// file exists
|
// file exists
|
||||||
|
updateUsedStatus(identifier, version)
|
||||||
return newFile(realFilePath, version, stable), nil
|
return newFile(realFilePath, version, stable), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -69,6 +70,7 @@ func loadOrFetchFile(identifier string) (*File, error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Tracef("updates: failed to download %s: %s, retrying (%d)", versionedFilePath, err, tries+1)
|
log.Tracef("updates: failed to download %s: %s, retrying (%d)", versionedFilePath, err, tries+1)
|
||||||
} else {
|
} else {
|
||||||
|
updateUsedStatus(identifier, version)
|
||||||
return newFile(realFilePath, version, stable), nil
|
return newFile(realFilePath, version, stable), nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,24 +17,26 @@ import (
|
||||||
var (
|
var (
|
||||||
stableUpdates = make(map[string]string)
|
stableUpdates = make(map[string]string)
|
||||||
betaUpdates = make(map[string]string)
|
betaUpdates = make(map[string]string)
|
||||||
latestUpdates = make(map[string]string)
|
localUpdates = make(map[string]string)
|
||||||
updatesLock sync.RWMutex
|
updatesLock sync.RWMutex
|
||||||
)
|
)
|
||||||
|
|
||||||
// ReloadLatest reloads available updates from disk.
|
// ReloadLatest reloads available updates from disk.
|
||||||
func ReloadLatest() error {
|
func ReloadLatest() error {
|
||||||
newLatestUpdates := make(map[string]string)
|
newLocalUpdates := make(map[string]string)
|
||||||
|
|
||||||
// all
|
// all
|
||||||
new, err1 := ScanForLatest(filepath.Join(updateStoragePath, "all"), false)
|
prefix := "all"
|
||||||
|
new, err1 := ScanForLatest(filepath.Join(updateStoragePath, prefix), false)
|
||||||
for key, val := range new {
|
for key, val := range new {
|
||||||
newLatestUpdates[key] = val
|
newLocalUpdates[filepath.Join(prefix, key)] = val
|
||||||
}
|
}
|
||||||
|
|
||||||
// os_platform
|
// os_platform
|
||||||
new, err2 := ScanForLatest(filepath.Join(updateStoragePath, fmt.Sprintf("%s_%s", runtime.GOOS, runtime.GOARCH)), false)
|
prefix = fmt.Sprintf("%s_%s", runtime.GOOS, runtime.GOARCH)
|
||||||
|
new, err2 := ScanForLatest(filepath.Join(updateStoragePath, prefix), false)
|
||||||
for key, val := range new {
|
for key, val := range new {
|
||||||
newLatestUpdates[key] = val
|
newLocalUpdates[filepath.Join(prefix, key)] = val
|
||||||
}
|
}
|
||||||
|
|
||||||
if err1 != nil && err2 != nil {
|
if err1 != nil && err2 != nil {
|
||||||
|
@ -43,12 +45,12 @@ func ReloadLatest() error {
|
||||||
|
|
||||||
log.Tracef("updates: loading latest updates:")
|
log.Tracef("updates: loading latest updates:")
|
||||||
|
|
||||||
for key, val := range newLatestUpdates {
|
for key, val := range newLocalUpdates {
|
||||||
log.Tracef("updates: %s v%s", key, val)
|
log.Tracef("updates: %s v%s", key, val)
|
||||||
}
|
}
|
||||||
|
|
||||||
updatesLock.Lock()
|
updatesLock.Lock()
|
||||||
latestUpdates = newLatestUpdates
|
localUpdates = newLocalUpdates
|
||||||
updatesLock.Unlock()
|
updatesLock.Unlock()
|
||||||
|
|
||||||
log.Tracef("updates: load complete")
|
log.Tracef("updates: load complete")
|
||||||
|
@ -60,6 +62,11 @@ func ReloadLatest() error {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update version status
|
||||||
|
updatesLock.RLock()
|
||||||
|
defer updatesLock.RUnlock()
|
||||||
|
updateStatus(versionClassLocal, localUpdates)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -137,5 +144,10 @@ func loadIndexesFromDisk() error {
|
||||||
stableUpdates = newStableUpdates
|
stableUpdates = newStableUpdates
|
||||||
updatesLock.Unlock()
|
updatesLock.Unlock()
|
||||||
|
|
||||||
|
// update version status
|
||||||
|
updatesLock.RLock()
|
||||||
|
defer updatesLock.RUnlock()
|
||||||
|
updateStatus(versionClassStable, stableUpdates)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,14 +32,14 @@ func testLoadLatestScope(t *testing.T, basePath, filePath, expectedIdentifier, e
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for key, val := range latest {
|
for key, val := range latest {
|
||||||
latestUpdates[key] = val
|
localUpdates[key] = val
|
||||||
}
|
}
|
||||||
|
|
||||||
// test result
|
// test result
|
||||||
version, ok := latestUpdates[expectedIdentifier]
|
version, ok := localUpdates[expectedIdentifier]
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("identifier %s not in map", expectedIdentifier)
|
t.Errorf("identifier %s not in map", expectedIdentifier)
|
||||||
t.Errorf("current map: %v", latestUpdates)
|
t.Errorf("current map: %v", localUpdates)
|
||||||
}
|
}
|
||||||
if version != expectedVersion {
|
if version != expectedVersion {
|
||||||
t.Errorf("unexpected version for %s: %s", filePath, version)
|
t.Errorf("unexpected version for %s: %s", filePath, version)
|
||||||
|
|
|
@ -15,7 +15,7 @@ var (
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
modules.Register("updates", prep, start, nil, "database")
|
modules.Register("updates", prep, start, nil, "global", "database")
|
||||||
}
|
}
|
||||||
|
|
||||||
func prep() error {
|
func prep() error {
|
||||||
|
@ -30,7 +30,12 @@ func prep() error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func start() error {
|
func start() error {
|
||||||
err := ReloadLatest()
|
err := initUpdateStatusHook()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
err = ReloadLatest()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
129
updates/status.go
Normal file
129
updates/status.go
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
package updates
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"github.com/Safing/portbase/database"
|
||||||
|
"github.com/Safing/portbase/database/query"
|
||||||
|
"github.com/Safing/portbase/database/record"
|
||||||
|
"github.com/Safing/portbase/log"
|
||||||
|
"github.com/tevino/abool"
|
||||||
|
)
|
||||||
|
|
||||||
|
// database key for update information
|
||||||
|
const (
|
||||||
|
statusDBKey = "core:status/updates"
|
||||||
|
)
|
||||||
|
|
||||||
|
// version type
|
||||||
|
type versionClass int
|
||||||
|
|
||||||
|
const (
|
||||||
|
versionClassLocal versionClass = iota
|
||||||
|
versionClassStable
|
||||||
|
versionClassBeta
|
||||||
|
)
|
||||||
|
|
||||||
|
// working vars
|
||||||
|
var (
|
||||||
|
status *versionStatus
|
||||||
|
|
||||||
|
statusDB = database.NewInterface(nil)
|
||||||
|
statusHook *database.RegisteredHook
|
||||||
|
enableStatusSave = abool.NewBool(false)
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
status = &versionStatus{
|
||||||
|
Versions: make(map[string]*versionStatusEntry),
|
||||||
|
}
|
||||||
|
status.SetKey(statusDBKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
// versionStatus holds update version status information.
|
||||||
|
type versionStatus struct {
|
||||||
|
record.Base
|
||||||
|
sync.Mutex
|
||||||
|
Versions map[string]*versionStatusEntry
|
||||||
|
}
|
||||||
|
|
||||||
|
func (vs *versionStatus) save() {
|
||||||
|
enableStatusSave.SetTo(true)
|
||||||
|
err := statusDB.Put(vs)
|
||||||
|
if err != nil {
|
||||||
|
log.Warningf("could not save updates version status: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// versionStatusEntry holds information about the update status of a module.
|
||||||
|
type versionStatusEntry struct {
|
||||||
|
LastVersionUsed string
|
||||||
|
LocalVersion string
|
||||||
|
StableVersion string
|
||||||
|
BetaVersion string
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateUsedStatus(identifier string, version string) {
|
||||||
|
status.Lock()
|
||||||
|
defer status.Unlock()
|
||||||
|
|
||||||
|
entry, ok := status.Versions[identifier]
|
||||||
|
if !ok {
|
||||||
|
entry = &versionStatusEntry{}
|
||||||
|
status.Versions[identifier] = entry
|
||||||
|
}
|
||||||
|
|
||||||
|
entry.LastVersionUsed = version
|
||||||
|
|
||||||
|
log.Tracef("updates: updated last used version of %s: %s", identifier, version)
|
||||||
|
|
||||||
|
go status.save()
|
||||||
|
}
|
||||||
|
|
||||||
|
func updateStatus(vClass versionClass, state map[string]string) {
|
||||||
|
status.Lock()
|
||||||
|
defer status.Unlock()
|
||||||
|
|
||||||
|
for identifier, version := range state {
|
||||||
|
|
||||||
|
entry, ok := status.Versions[identifier]
|
||||||
|
if !ok {
|
||||||
|
entry = &versionStatusEntry{}
|
||||||
|
status.Versions[identifier] = entry
|
||||||
|
}
|
||||||
|
|
||||||
|
switch vClass {
|
||||||
|
case versionClassLocal:
|
||||||
|
entry.LocalVersion = version
|
||||||
|
case versionClassStable:
|
||||||
|
entry.StableVersion = version
|
||||||
|
case versionClassBeta:
|
||||||
|
entry.BetaVersion = version
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
go status.save()
|
||||||
|
}
|
||||||
|
|
||||||
|
type updateStatusHook struct {
|
||||||
|
database.HookBase
|
||||||
|
}
|
||||||
|
|
||||||
|
// UsesPrePut implements the Hook interface.
|
||||||
|
func (sh *updateStatusHook) UsesPrePut() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrePut implements the Hook interface.
|
||||||
|
func (sh *updateStatusHook) PrePut(r record.Record) (record.Record, error) {
|
||||||
|
if enableStatusSave.SetToIf(true, false) {
|
||||||
|
return r, nil
|
||||||
|
}
|
||||||
|
return nil, errors.New("may only be changed by updates module")
|
||||||
|
}
|
||||||
|
|
||||||
|
func initUpdateStatusHook() (err error) {
|
||||||
|
statusHook, err = database.RegisterHook(query.New(statusDBKey), &updateStatusHook{})
|
||||||
|
return err
|
||||||
|
}
|
|
@ -53,7 +53,7 @@ func checkForUpdates() error {
|
||||||
log.Tracef("updates: updating existing files")
|
log.Tracef("updates: updating existing files")
|
||||||
updatesLock.RLock()
|
updatesLock.RLock()
|
||||||
for identifier, newVersion := range newStableUpdates {
|
for identifier, newVersion := range newStableUpdates {
|
||||||
oldVersion, ok := latestUpdates[identifier]
|
oldVersion, ok := localUpdates[identifier]
|
||||||
if ok && newVersion != oldVersion {
|
if ok && newVersion != oldVersion {
|
||||||
|
|
||||||
filePath := getVersionedPath(identifier, newVersion)
|
filePath := getVersionedPath(identifier, newVersion)
|
||||||
|
@ -84,5 +84,10 @@ func checkForUpdates() error {
|
||||||
log.Warningf("updates: failed to save new version of stable.json: %s", err)
|
log.Warningf("updates: failed to save new version of stable.json: %s", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update version status
|
||||||
|
updatesLock.RLock()
|
||||||
|
defer updatesLock.RUnlock()
|
||||||
|
updateStatus(versionClassStable, stableUpdates)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue