[WIP] Updater support for windows
This commit is contained in:
@@ -8,14 +8,11 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"log/slog"
|
"log/slog"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"runtime/pprof"
|
"runtime/pprof"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/safing/portmaster/base/info"
|
"github.com/safing/portmaster/base/info"
|
||||||
"github.com/safing/portmaster/base/log"
|
|
||||||
"github.com/safing/portmaster/base/metrics"
|
"github.com/safing/portmaster/base/metrics"
|
||||||
"github.com/safing/portmaster/service"
|
"github.com/safing/portmaster/service"
|
||||||
"github.com/safing/portmaster/service/mgr"
|
"github.com/safing/portmaster/service/mgr"
|
||||||
@@ -36,6 +33,11 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
instance := initialize()
|
||||||
|
run(instance)
|
||||||
|
}
|
||||||
|
|
||||||
|
func initialize() *service.Instance {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
// set information
|
// set information
|
||||||
@@ -80,91 +82,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
return instance
|
||||||
// Set default log level.
|
|
||||||
log.SetLogLevel(log.WarningLevel)
|
|
||||||
_ = log.Start()
|
|
||||||
|
|
||||||
// Start
|
|
||||||
go func() {
|
|
||||||
err = instance.Start()
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("instance start failed: %s\n", err)
|
|
||||||
|
|
||||||
// Print stack on start failure, if enabled.
|
|
||||||
if printStackOnExit {
|
|
||||||
printStackTo(os.Stdout, "PRINTING STACK ON START FAILURE")
|
|
||||||
}
|
|
||||||
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Wait for signal.
|
|
||||||
signalCh := make(chan os.Signal, 1)
|
|
||||||
if enableInputSignals {
|
|
||||||
go inputSignals(signalCh)
|
|
||||||
}
|
|
||||||
signal.Notify(
|
|
||||||
signalCh,
|
|
||||||
os.Interrupt,
|
|
||||||
syscall.SIGHUP,
|
|
||||||
syscall.SIGINT,
|
|
||||||
syscall.SIGTERM,
|
|
||||||
syscall.SIGQUIT,
|
|
||||||
sigUSR1,
|
|
||||||
)
|
|
||||||
|
|
||||||
select {
|
|
||||||
case sig := <-signalCh:
|
|
||||||
// Only print and continue to wait if SIGUSR1
|
|
||||||
if sig == sigUSR1 {
|
|
||||||
printStackTo(os.Stderr, "PRINTING STACK ON REQUEST")
|
|
||||||
} else {
|
|
||||||
fmt.Println(" <INTERRUPT>") // CLI output.
|
|
||||||
slog.Warn("program was interrupted, stopping")
|
|
||||||
}
|
|
||||||
|
|
||||||
case <-instance.Stopped():
|
|
||||||
log.Shutdown()
|
|
||||||
os.Exit(instance.ExitCode())
|
|
||||||
}
|
|
||||||
|
|
||||||
// Catch signals during shutdown.
|
|
||||||
// Rapid unplanned disassembly after 5 interrupts.
|
|
||||||
go func() {
|
|
||||||
forceCnt := 5
|
|
||||||
for {
|
|
||||||
<-signalCh
|
|
||||||
forceCnt--
|
|
||||||
if forceCnt > 0 {
|
|
||||||
fmt.Printf(" <INTERRUPT> again, but already shutting down - %d more to force\n", forceCnt)
|
|
||||||
} else {
|
|
||||||
printStackTo(os.Stderr, "PRINTING STACK ON FORCED EXIT")
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Rapid unplanned disassembly after 3 minutes.
|
|
||||||
go func() {
|
|
||||||
time.Sleep(3 * time.Minute)
|
|
||||||
printStackTo(os.Stderr, "PRINTING STACK - TAKING TOO LONG FOR SHUTDOWN")
|
|
||||||
os.Exit(1)
|
|
||||||
}()
|
|
||||||
|
|
||||||
// Stop instance.
|
|
||||||
if err := instance.Stop(); err != nil {
|
|
||||||
slog.Error("failed to stop", "err", err)
|
|
||||||
}
|
|
||||||
log.Shutdown()
|
|
||||||
|
|
||||||
// Print stack on shutdown, if enabled.
|
|
||||||
if printStackOnExit {
|
|
||||||
printStackTo(os.Stdout, "PRINTING STACK ON EXIT")
|
|
||||||
}
|
|
||||||
|
|
||||||
os.Exit(instance.ExitCode())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func printStackTo(writer io.Writer, msg string) {
|
func printStackTo(writer io.Writer, msg string) {
|
||||||
|
|||||||
100
cmds/portmaster-core/main_linux.go
Normal file
100
cmds/portmaster-core/main_linux.go
Normal file
@@ -0,0 +1,100 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/safing/portmaster/base/log"
|
||||||
|
"github.com/safing/portmaster/service"
|
||||||
|
)
|
||||||
|
|
||||||
|
func run(instance *service.Instance) {
|
||||||
|
// Set default log level.
|
||||||
|
log.SetLogLevel(log.WarningLevel)
|
||||||
|
_ = log.Start()
|
||||||
|
|
||||||
|
// Start
|
||||||
|
go func() {
|
||||||
|
err := instance.Start()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("instance start failed: %s\n", err)
|
||||||
|
|
||||||
|
// Print stack on start failure, if enabled.
|
||||||
|
if printStackOnExit {
|
||||||
|
printStackTo(os.Stdout, "PRINTING STACK ON START FAILURE")
|
||||||
|
}
|
||||||
|
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Wait for signal.
|
||||||
|
signalCh := make(chan os.Signal, 1)
|
||||||
|
if enableInputSignals {
|
||||||
|
go inputSignals(signalCh)
|
||||||
|
}
|
||||||
|
signal.Notify(
|
||||||
|
signalCh,
|
||||||
|
os.Interrupt,
|
||||||
|
syscall.SIGHUP,
|
||||||
|
syscall.SIGINT,
|
||||||
|
syscall.SIGTERM,
|
||||||
|
syscall.SIGQUIT,
|
||||||
|
sigUSR1,
|
||||||
|
)
|
||||||
|
|
||||||
|
select {
|
||||||
|
case sig := <-signalCh:
|
||||||
|
// Only print and continue to wait if SIGUSR1
|
||||||
|
if sig == sigUSR1 {
|
||||||
|
printStackTo(os.Stderr, "PRINTING STACK ON REQUEST")
|
||||||
|
} else {
|
||||||
|
fmt.Println(" <INTERRUPT>") // CLI output.
|
||||||
|
slog.Warn("program was interrupted, stopping")
|
||||||
|
}
|
||||||
|
|
||||||
|
case <-instance.Stopped():
|
||||||
|
log.Shutdown()
|
||||||
|
os.Exit(instance.ExitCode())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Catch signals during shutdown.
|
||||||
|
// Rapid unplanned disassembly after 5 interrupts.
|
||||||
|
go func() {
|
||||||
|
forceCnt := 5
|
||||||
|
for {
|
||||||
|
<-signalCh
|
||||||
|
forceCnt--
|
||||||
|
if forceCnt > 0 {
|
||||||
|
fmt.Printf(" <INTERRUPT> again, but already shutting down - %d more to force\n", forceCnt)
|
||||||
|
} else {
|
||||||
|
printStackTo(os.Stderr, "PRINTING STACK ON FORCED EXIT")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Rapid unplanned disassembly after 3 minutes.
|
||||||
|
go func() {
|
||||||
|
time.Sleep(3 * time.Minute)
|
||||||
|
printStackTo(os.Stderr, "PRINTING STACK - TAKING TOO LONG FOR SHUTDOWN")
|
||||||
|
os.Exit(1)
|
||||||
|
}()
|
||||||
|
|
||||||
|
// Stop instance.
|
||||||
|
if err := instance.Stop(); err != nil {
|
||||||
|
slog.Error("failed to stop", "err", err)
|
||||||
|
}
|
||||||
|
log.Shutdown()
|
||||||
|
|
||||||
|
// Print stack on shutdown, if enabled.
|
||||||
|
if printStackOnExit {
|
||||||
|
printStackTo(os.Stdout, "PRINTING STACK ON EXIT")
|
||||||
|
}
|
||||||
|
|
||||||
|
os.Exit(instance.ExitCode())
|
||||||
|
}
|
||||||
180
cmds/portmaster-core/main_windows.go
Normal file
180
cmds/portmaster-core/main_windows.go
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
// Based on the official Go examples from
|
||||||
|
// https://github.com/golang/sys/blob/master/windows/svc/example
|
||||||
|
// by The Go Authors.
|
||||||
|
// Original LICENSE (sha256sum: 2d36597f7117c38b006835ae7f537487207d8ec407aa9d9980794b2030cbc067) can be found in vendor/pkg cache directory.
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"sync"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/safing/portmaster/base/log"
|
||||||
|
"github.com/safing/portmaster/service"
|
||||||
|
"golang.org/x/sys/windows/svc"
|
||||||
|
"golang.org/x/sys/windows/svc/debug"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// wait groups
|
||||||
|
runWg sync.WaitGroup
|
||||||
|
finishWg sync.WaitGroup
|
||||||
|
)
|
||||||
|
|
||||||
|
const serviceName = "PortmasterCore"
|
||||||
|
|
||||||
|
type windowsService struct {
|
||||||
|
instance *service.Instance
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ws *windowsService) Execute(args []string, changeRequests <-chan svc.ChangeRequest, changes chan<- svc.Status) (ssec bool, errno uint32) {
|
||||||
|
const cmdsAccepted = svc.AcceptStop | svc.AcceptShutdown
|
||||||
|
changes <- svc.Status{State: svc.StartPending}
|
||||||
|
|
||||||
|
startupComplete := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
for !ws.instance.Ready() {
|
||||||
|
time.Sleep(1 * time.Second)
|
||||||
|
}
|
||||||
|
startupComplete <- struct{}{}
|
||||||
|
}()
|
||||||
|
|
||||||
|
service:
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-startupComplete:
|
||||||
|
changes <- svc.Status{State: svc.Running, Accepts: cmdsAccepted}
|
||||||
|
case <-ws.instance.Stopped():
|
||||||
|
changes <- svc.Status{State: svc.StopPending}
|
||||||
|
break service
|
||||||
|
case c := <-changeRequests:
|
||||||
|
switch c.Cmd {
|
||||||
|
case svc.Interrogate:
|
||||||
|
changes <- c.CurrentStatus
|
||||||
|
case svc.Stop, svc.Shutdown:
|
||||||
|
ws.instance.Shutdown()
|
||||||
|
default:
|
||||||
|
log.Errorf("unexpected control request: #%d\n", c)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait until everything else is finished
|
||||||
|
finishWg.Wait()
|
||||||
|
|
||||||
|
log.Shutdown()
|
||||||
|
|
||||||
|
// send stopped status
|
||||||
|
changes <- svc.Status{State: svc.Stopped}
|
||||||
|
// wait a little for the status to reach Windows
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
|
||||||
|
return ssec, errno
|
||||||
|
}
|
||||||
|
|
||||||
|
func run(instance *service.Instance) error {
|
||||||
|
log.SetLogLevel(log.WarningLevel)
|
||||||
|
_ = log.Start()
|
||||||
|
// check if we are running interactively
|
||||||
|
isService, err := svc.IsWindowsService()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("could not determine if running interactively: %s", err)
|
||||||
|
}
|
||||||
|
// select service run type
|
||||||
|
svcRun := svc.Run
|
||||||
|
if !isService {
|
||||||
|
log.Warningf("running interactively, switching to debug execution (no real service).\n")
|
||||||
|
svcRun = debug.Run
|
||||||
|
go registerSignalHandler(instance)
|
||||||
|
}
|
||||||
|
|
||||||
|
runWg.Add(2)
|
||||||
|
|
||||||
|
// run service client
|
||||||
|
go func() {
|
||||||
|
sErr := svcRun(serviceName, &windowsService{
|
||||||
|
instance: instance,
|
||||||
|
})
|
||||||
|
if sErr != nil {
|
||||||
|
log.Infof("shuting down service with error: %s", sErr)
|
||||||
|
} else {
|
||||||
|
log.Infof("shuting down service")
|
||||||
|
}
|
||||||
|
instance.Shutdown()
|
||||||
|
runWg.Done()
|
||||||
|
}()
|
||||||
|
|
||||||
|
finishWg.Add(1)
|
||||||
|
// run service
|
||||||
|
go func() {
|
||||||
|
// run slightly delayed
|
||||||
|
time.Sleep(250 * time.Millisecond)
|
||||||
|
instance.Start()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("instance start failed: %s\n", err)
|
||||||
|
|
||||||
|
// Print stack on start failure, if enabled.
|
||||||
|
if printStackOnExit {
|
||||||
|
printStackTo(os.Stdout, "PRINTING STACK ON START FAILURE")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
runWg.Done()
|
||||||
|
finishWg.Done()
|
||||||
|
}()
|
||||||
|
|
||||||
|
runWg.Wait()
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func registerSignalHandler(instance *service.Instance) {
|
||||||
|
// Wait for signal.
|
||||||
|
signalCh := make(chan os.Signal, 1)
|
||||||
|
if enableInputSignals {
|
||||||
|
go inputSignals(signalCh)
|
||||||
|
}
|
||||||
|
signal.Notify(
|
||||||
|
signalCh,
|
||||||
|
os.Interrupt,
|
||||||
|
syscall.SIGHUP,
|
||||||
|
syscall.SIGINT,
|
||||||
|
syscall.SIGTERM,
|
||||||
|
syscall.SIGQUIT,
|
||||||
|
sigUSR1,
|
||||||
|
)
|
||||||
|
|
||||||
|
select {
|
||||||
|
case sig := <-signalCh:
|
||||||
|
// Only print and continue to wait if SIGUSR1
|
||||||
|
if sig == sigUSR1 {
|
||||||
|
printStackTo(os.Stderr, "PRINTING STACK ON REQUEST")
|
||||||
|
} else {
|
||||||
|
fmt.Println(" <INTERRUPT>") // CLI output.
|
||||||
|
slog.Warn("program was interrupted, stopping")
|
||||||
|
instance.Shutdown()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Catch signals during shutdown.
|
||||||
|
// Rapid unplanned disassembly after 5 interrupts.
|
||||||
|
go func() {
|
||||||
|
forceCnt := 5
|
||||||
|
for {
|
||||||
|
<-signalCh
|
||||||
|
forceCnt--
|
||||||
|
if forceCnt > 0 {
|
||||||
|
fmt.Printf(" <INTERRUPT> again, but already shutting down - %d more to force\n", forceCnt)
|
||||||
|
} else {
|
||||||
|
printStackTo(os.Stderr, "PRINTING STACK ON FORCED EXIT")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
||||||
@@ -120,6 +120,7 @@ fn show_webview_not_installed_dialog() -> i32 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
|
env::set_var("GDK_BACKEND", "x11");
|
||||||
if tauri::webview_version().is_err() {
|
if tauri::webview_version().is_err() {
|
||||||
std::process::exit(show_webview_not_installed_dialog());
|
std::process::exit(show_webview_not_installed_dialog());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,6 +60,17 @@
|
|||||||
"desktopTemplate": "../../../packaging/linux/portmaster.desktop",
|
"desktopTemplate": "../../../packaging/linux/portmaster.desktop",
|
||||||
"files": {
|
"files": {
|
||||||
"/usr/lib/systemd/system/portmaster.service": "../../../packaging/linux/portmaster.service",
|
"/usr/lib/systemd/system/portmaster.service": "../../../packaging/linux/portmaster.service",
|
||||||
|
"/usr/lib/portmaster/bin-index.json": "binaries/bin-index.json",
|
||||||
|
"/usr/lib/portmaster/portmaster-core": "binaries/portmaster-core",
|
||||||
|
"/usr/lib/portmaster/portmaster.zip": "binaries/portmaster.zip",
|
||||||
|
"/usr/lib/portmaster/assets.zip": "binaries/assets.zip",
|
||||||
|
"/var/lib/portmaster/intel/intel-index.json": "binaries/intel-index.json",
|
||||||
|
"/var/lib/portmaster/intel/base.dsdl": "binaries/base.dsdl",
|
||||||
|
"/var/lib/portmaster/intel/geoipv4.mmdb": "binaries/geoipv4.mmdb",
|
||||||
|
"/var/lib/portmaster/intel/geoipv6.mmdb": "binaries/geoipv6.mmdb",
|
||||||
|
"/var/lib/portmaster/intel/index.dsd": "binaries/index.dsd",
|
||||||
|
"/var/lib/portmaster/intel/intermediate.dsdl": "binaries/intermediate.dsdl",
|
||||||
|
"/var/lib/portmaster/intel/urgent.dsdl": "binaries/urgent.dsdl",
|
||||||
"/etc/xdg/autostart/portmaster.desktop": "../../../packaging/linux/portmaster-autostart.desktop"
|
"/etc/xdg/autostart/portmaster.desktop": "../../../packaging/linux/portmaster-autostart.desktop"
|
||||||
},
|
},
|
||||||
"postInstallScript": "../../../packaging/linux/postinst",
|
"postInstallScript": "../../../packaging/linux/postinst",
|
||||||
@@ -73,7 +84,17 @@
|
|||||||
"release": "1",
|
"release": "1",
|
||||||
"files": {
|
"files": {
|
||||||
"/usr/lib/systemd/system/portmaster.service": "../../../packaging/linux/portmaster.service",
|
"/usr/lib/systemd/system/portmaster.service": "../../../packaging/linux/portmaster.service",
|
||||||
|
"/usr/lib/portmaster/bin-index.json": "binaries/bin-index.json",
|
||||||
"/usr/lib/portmaster/portmaster-core": "binaries/portmaster-core",
|
"/usr/lib/portmaster/portmaster-core": "binaries/portmaster-core",
|
||||||
|
"/usr/lib/portmaster/portmaster.zip": "binaries/portmaster.zip",
|
||||||
|
"/usr/lib/portmaster/assets.zip": "binaries/assets.zip",
|
||||||
|
"/var/lib/portmaster/intel/intel-index.json": "binaries/intel-index.json",
|
||||||
|
"/var/lib/portmaster/intel/base.dsdl": "binaries/base.dsdl",
|
||||||
|
"/var/lib/portmaster/intel/geoipv4.mmdb": "binaries/geoipv4.mmdb",
|
||||||
|
"/var/lib/portmaster/intel/geoipv6.mmdb": "binaries/geoipv6.mmdb",
|
||||||
|
"/var/lib/portmaster/intel/index.dsd": "binaries/index.dsd",
|
||||||
|
"/var/lib/portmaster/intel/intermediate.dsdl": "binaries/intermediate.dsdl",
|
||||||
|
"/var/lib/portmaster/intel/urgent.dsdl": "binaries/urgent.dsdl",
|
||||||
"/etc/xdg/autostart/portmaster.desktop": "../../../packaging/linux/portmaster-autostart.desktop"
|
"/etc/xdg/autostart/portmaster.desktop": "../../../packaging/linux/portmaster-autostart.desktop"
|
||||||
},
|
},
|
||||||
"postInstallScript": "../../../packaging/linux/postinst",
|
"postInstallScript": "../../../packaging/linux/postinst",
|
||||||
@@ -106,4 +127,4 @@
|
|||||||
"../../../assets/data/icons/pm_light.ico"
|
"../../../assets/data/icons/pm_light.ico"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,14 +10,13 @@ import (
|
|||||||
"github.com/safing/portmaster/service/mgr"
|
"github.com/safing/portmaster/service/mgr"
|
||||||
"github.com/safing/portmaster/service/network"
|
"github.com/safing/portmaster/service/network"
|
||||||
"github.com/safing/portmaster/service/network/packet"
|
"github.com/safing/portmaster/service/network/packet"
|
||||||
"github.com/safing/portmaster/service/updates"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var useOldKext = false
|
var useOldKext = false
|
||||||
|
|
||||||
// start starts the interception.
|
// start starts the interception.
|
||||||
func startInterception(packets chan packet.Packet) error {
|
func startInterception(packets chan packet.Packet) error {
|
||||||
kextFile, err := updates.GetPlatformFile("kext/portmaster-kext.sys")
|
kextFile, err := module.instance.BinaryUpdates().GetFile("portmaster-kext.sys")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("interception: could not get kext sys: %s", err)
|
return fmt.Errorf("interception: could not get kext sys: %s", err)
|
||||||
}
|
}
|
||||||
@@ -77,7 +76,6 @@ func startInterception(packets chan packet.Packet) error {
|
|||||||
case <-w.Done():
|
case <-w.Done():
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -95,7 +93,6 @@ func startInterception(packets chan packet.Packet) error {
|
|||||||
case <-w.Done():
|
case <-w.Done():
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -112,7 +109,6 @@ func startInterception(packets chan packet.Packet) error {
|
|||||||
case <-w.Done():
|
case <-w.Done():
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -159,5 +155,4 @@ func GetKextVersion() (string, error) {
|
|||||||
}
|
}
|
||||||
return version.String(), nil
|
return version.String(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/safing/portmaster/base/log"
|
"github.com/safing/portmaster/base/log"
|
||||||
"github.com/safing/portmaster/service/mgr"
|
"github.com/safing/portmaster/service/mgr"
|
||||||
"github.com/safing/portmaster/service/network/packet"
|
"github.com/safing/portmaster/service/network/packet"
|
||||||
|
"github.com/safing/portmaster/service/updates"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Interception is the packet interception module.
|
// Interception is the packet interception module.
|
||||||
@@ -97,4 +98,6 @@ func New(instance instance) (*Interception, error) {
|
|||||||
return module, nil
|
return module, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
type instance interface{}
|
type instance interface {
|
||||||
|
BinaryUpdates() *updates.Updates
|
||||||
|
}
|
||||||
|
|||||||
@@ -62,6 +62,9 @@ func GetKextServiceHandle() windows.Handle {
|
|||||||
|
|
||||||
// Stop intercepting.
|
// Stop intercepting.
|
||||||
func Stop() error {
|
func Stop() error {
|
||||||
|
if kextFile == nil {
|
||||||
|
return fmt.Errorf("kextfile is nil")
|
||||||
|
}
|
||||||
// Prepare kernel for shutdown
|
// Prepare kernel for shutdown
|
||||||
err := shutdownRequest()
|
err := shutdownRequest()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package service
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
go_runtime "runtime"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -47,23 +48,6 @@ import (
|
|||||||
"github.com/safing/portmaster/spn/terminal"
|
"github.com/safing/portmaster/spn/terminal"
|
||||||
)
|
)
|
||||||
|
|
||||||
var binaryUpdateIndex = registry.UpdateIndex{
|
|
||||||
Directory: "/usr/lib/portmaster",
|
|
||||||
DownloadDirectory: "/var/lib/portmaster/new_bin",
|
|
||||||
Ignore: []string{"databases", "intel", "config.json"},
|
|
||||||
IndexURLs: []string{"http://localhost:8000/test-binary.json"},
|
|
||||||
IndexFile: "bin-index.json",
|
|
||||||
AutoApply: false,
|
|
||||||
}
|
|
||||||
|
|
||||||
var intelUpdateIndex = registry.UpdateIndex{
|
|
||||||
Directory: "/var/lib/portmaster/intel",
|
|
||||||
DownloadDirectory: "/var/lib/portmaster/new_intel",
|
|
||||||
IndexURLs: []string{"http://localhost:8000/test-intel.json"},
|
|
||||||
IndexFile: "intel-index.json",
|
|
||||||
AutoApply: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
// Instance is an instance of a Portmaster service.
|
// Instance is an instance of a Portmaster service.
|
||||||
type Instance struct {
|
type Instance struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
@@ -121,6 +105,48 @@ type Instance struct {
|
|||||||
|
|
||||||
// New returns a new Portmaster service instance.
|
// New returns a new Portmaster service instance.
|
||||||
func New(svcCfg *ServiceConfig) (*Instance, error) { //nolint:maintidx
|
func New(svcCfg *ServiceConfig) (*Instance, error) { //nolint:maintidx
|
||||||
|
var binaryUpdateIndex registry.UpdateIndex
|
||||||
|
var intelUpdateIndex registry.UpdateIndex
|
||||||
|
if go_runtime.GOOS == "windows" {
|
||||||
|
binaryUpdateIndex = registry.UpdateIndex{
|
||||||
|
Directory: "C:/Program Files/Portmaster/binary",
|
||||||
|
DownloadDirectory: "C:/Program Files/Portmaster/new_binary",
|
||||||
|
PurgeDirectory: "C:/Program Files/Portmaster/old_binary",
|
||||||
|
Ignore: []string{"databases", "intel", "config.json"},
|
||||||
|
IndexURLs: []string{"http://192.168.88.11:8000/test-binary.json"},
|
||||||
|
IndexFile: "bin-index.json",
|
||||||
|
AutoApply: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
intelUpdateIndex = registry.UpdateIndex{
|
||||||
|
Directory: "C:/Program Files/Portmaster/intel",
|
||||||
|
DownloadDirectory: "C:/Program Files/Portmaster/new_intel",
|
||||||
|
PurgeDirectory: "C:/Program Files/Portmaster/old_intel",
|
||||||
|
IndexURLs: []string{"http://192.168.88.11:8000/test-intel.json"},
|
||||||
|
IndexFile: "intel-index.json",
|
||||||
|
AutoApply: true,
|
||||||
|
}
|
||||||
|
} else if go_runtime.GOOS == "linux" {
|
||||||
|
binaryUpdateIndex = registry.UpdateIndex{
|
||||||
|
Directory: "/usr/lib/portmaster",
|
||||||
|
DownloadDirectory: "/var/lib/portmaster/new_bin",
|
||||||
|
PurgeDirectory: "/var/lib/portmaster/old_bin",
|
||||||
|
Ignore: []string{"databases", "intel", "config.json"},
|
||||||
|
IndexURLs: []string{"http://localhost:8000/test-binary.json"},
|
||||||
|
IndexFile: "bin-index.json",
|
||||||
|
AutoApply: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
intelUpdateIndex = registry.UpdateIndex{
|
||||||
|
Directory: "/var/lib/portmaster/intel",
|
||||||
|
DownloadDirectory: "/var/lib/portmaster/new_intel",
|
||||||
|
PurgeDirectory: "/var/lib/portmaster/intel_bin",
|
||||||
|
IndexURLs: []string{"http://localhost:8000/test-intel.json"},
|
||||||
|
IndexFile: "intel-index.json",
|
||||||
|
AutoApply: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Create instance to pass it to modules.
|
// Create instance to pass it to modules.
|
||||||
instance := &Instance{}
|
instance := &Instance{}
|
||||||
instance.ctx, instance.cancelCtx = context.WithCancel(context.Background())
|
instance.ctx, instance.cancelCtx = context.WithCancel(context.Background())
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/safing/portmaster/base/log"
|
"github.com/safing/portmaster/base/log"
|
||||||
@@ -19,6 +20,8 @@ import (
|
|||||||
|
|
||||||
const MaxUnpackSize = 1 << 30 // 2^30 == 1GB
|
const MaxUnpackSize = 1 << 30 // 2^30 == 1GB
|
||||||
|
|
||||||
|
const current_platform = runtime.GOOS + "_" + runtime.GOARCH
|
||||||
|
|
||||||
type Artifact struct {
|
type Artifact struct {
|
||||||
Filename string `json:"Filename"`
|
Filename string `json:"Filename"`
|
||||||
SHA256 string `json:"SHA256"`
|
SHA256 string `json:"SHA256"`
|
||||||
@@ -107,6 +110,11 @@ func checkIfFileIsValid(filename string, artifact Artifact) (bool, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func processArtifact(client *http.Client, artifact Artifact, filePath string) error {
|
func processArtifact(client *http.Client, artifact Artifact, filePath string) error {
|
||||||
|
// Skip artifacts not meant for this machine.
|
||||||
|
if artifact.Platform != "" && artifact.Platform != current_platform {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
providedHash, err := hex.DecodeString(artifact.SHA256)
|
providedHash, err := hex.DecodeString(artifact.SHA256)
|
||||||
if err != nil || len(providedHash) != sha256.Size {
|
if err != nil || len(providedHash) != sha256.Size {
|
||||||
return fmt.Errorf("invalid provided hash %s: %w", artifact.SHA256, err)
|
return fmt.Errorf("invalid provided hash %s: %w", artifact.SHA256, err)
|
||||||
@@ -149,6 +157,7 @@ func processArtifact(client *http.Client, artifact Artifact, filePath string) er
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to write to file: %w", err)
|
return fmt.Errorf("failed to write to file: %w", err)
|
||||||
}
|
}
|
||||||
|
file.Close()
|
||||||
|
|
||||||
// Rename
|
// Rename
|
||||||
err = os.Rename(tmpFilename, filePath)
|
err = os.Rename(tmpFilename, filePath)
|
||||||
|
|||||||
@@ -125,7 +125,7 @@ func (reg *Registry) DownloadUpdates() error {
|
|||||||
// ApplyUpdates removes the current binary folder and replaces it with the downloaded one.
|
// ApplyUpdates removes the current binary folder and replaces it with the downloaded one.
|
||||||
func (reg *Registry) ApplyUpdates() error {
|
func (reg *Registry) ApplyUpdates() error {
|
||||||
// Create purge dir.
|
// Create purge dir.
|
||||||
err := os.MkdirAll(filepath.Dir(reg.updateIndex.PurgeDirectory), defaultDirMode)
|
err := os.MkdirAll(reg.updateIndex.PurgeDirectory, defaultDirMode)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to create directory: %w", err)
|
return fmt.Errorf("failed to create directory: %w", err)
|
||||||
}
|
}
|
||||||
@@ -198,7 +198,7 @@ func deleteUnfinishedDownloads(rootDir string) error {
|
|||||||
|
|
||||||
// Check if the current file has the specified extension
|
// Check if the current file has the specified extension
|
||||||
if !info.IsDir() && strings.HasSuffix(info.Name(), ".download") {
|
if !info.IsDir() && strings.HasSuffix(info.Name(), ".download") {
|
||||||
log.Warningf("updates deleting unfinished: %s\n", path)
|
log.Warningf("updates: deleting unfinished: %s\n", path)
|
||||||
err := os.Remove(path)
|
err := os.Remove(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to delete file %s: %w", path, err)
|
return fmt.Errorf("failed to delete file %s: %w", path, err)
|
||||||
|
|||||||
Reference in New Issue
Block a user