diff --git a/fw-settings/dbus.go b/fw-settings/dbus.go index 6d167f7..9f07830 100644 --- a/fw-settings/dbus.go +++ b/fw-settings/dbus.go @@ -1,15 +1,26 @@ package main import ( + "errors" + "fmt" "github.com/subgraph/fw-daemon/sgfw" - "github.com/godbus/dbus" ) + type dbusObject struct { dbus.BusObject } +type dbusObjectP struct { + dbus.BusObject +} + +type dbusServer struct { + conn *dbus.Conn + run bool +} + func newDbusObject() (*dbusObject, error) { conn, err := dbus.SystemBus() if err != nil { @@ -18,6 +29,14 @@ func newDbusObject() (*dbusObject, error) { return &dbusObject{conn.Object("com.subgraph.Firewall", "/com/subgraph/Firewall")}, nil } +func newDbusObjectPrompt() (*dbusObjectP, error) { + conn, err := dbus.SystemBus() + if err != nil { + return nil, err + } + return &dbusObjectP{conn.Object("com.subgraph.fwprompt.EventNotifier", "/com/subgraph/fwprompt/EventNotifier")}, nil +} + func (ob *dbusObject) isEnabled() (bool, error) { var flag bool if err := ob.Call("com.subgraph.Firewall.IsEnabled", 0).Store(&flag); err != nil { @@ -58,3 +77,41 @@ func (ob *dbusObject) getConfig() (map[string]interface{}, error) { func (ob *dbusObject) setConfig(key string, val interface{}) { ob.Call("com.subgraph.Firewall.SetConfig", 0, key, dbus.MakeVariant(val)) } + +func newDbusServer() (*dbusServer, error) { + conn, err := dbus.SystemBus() + + if err != nil { + return nil, err + } + + reply, err := conn.RequestName("com.subgraph.fwprompt.EventNotifier", dbus.NameFlagDoNotQueue) + + if err != nil { + return nil, err + } + + if reply != dbus.RequestNameReplyPrimaryOwner { + return nil, errors.New("Bus name is already owned") + } + + ds := &dbusServer{} + + if err := conn.Export(ds, "/com/subgraph/fwprompt/EventNotifier", "com.subgraph.fwprompt.EventNotifier"); err != nil { + return nil, err + } + + ds.conn = conn + ds.run = true + return ds, nil +} + +func (ds *dbusServer) Alert(data string) *dbus.Error { + fmt.Println("Received Dbus update alert: ", data) + repopulateWin() + return nil +} + +func (ob *dbusObjectP) alertRule(data string) { + ob.Call("com.subgraph.fwprompt.EventNotifier.Alert", 0, data) +} diff --git a/fw-settings/main.go b/fw-settings/main.go index 429c8ec..9e1136f 100644 --- a/fw-settings/main.go +++ b/fw-settings/main.go @@ -3,6 +3,7 @@ package main import ( "fmt" "os" + "sync" "github.com/subgraph/fw-daemon/sgfw" @@ -10,6 +11,12 @@ import ( "github.com/gotk3/gotk3/gtk" ) +var fwswin *gtk.Window = nil +var fwsbuilder *builder = nil +var swRulesPermanent *gtk.ScrolledWindow = nil +var swRulesSession *gtk.ScrolledWindow = nil +var swRulesSystem *gtk.ScrolledWindow = nil + func failDialog(parent *gtk.Window, format string, args ...interface{}) { d := gtk.MessageDialogNew(parent, 0, gtk.MESSAGE_ERROR, gtk.BUTTONS_CLOSE, format, args...) @@ -23,12 +30,76 @@ func activate(app *gtk.Application) { win.Present() return } + populateWin(app, win) +} + +var repopMutex = &sync.Mutex{} + +func repopulateWin() { + fmt.Println("Refreshing firewall rule list.") + repopMutex.Lock() + win := fwswin + + dbus, err := newDbusObject() + if err != nil { + failDialog(win, "Failed to connect to dbus system bus: %v", err) + } + + child, err := swRulesPermanent.GetChild() + if err != nil { + failDialog(win, "Unable to clear out permanent rules list display: %v", err) + } + swRulesPermanent.Remove(child) + + child, err = swRulesSession.GetChild() + if err != nil { + failDialog(win, "Unable to clear out session rules list display: %v", err) + } + swRulesSession.Remove(child) + + child, err = swRulesSystem.GetChild() + if err != nil { + failDialog(win, "Unable to clear out session rules list display: %v", err) + } + swRulesSystem.Remove(child) + + boxPermanent, _ := gtk.ListBoxNew() + swRulesPermanent.Add(boxPermanent) + + boxSession, _ := gtk.ListBoxNew() + swRulesSession.Add(boxSession) + + boxSystem, _ := gtk.ListBoxNew() + swRulesSystem.Add(boxSystem) + + + rlPermanent := newRuleList(dbus, win, boxPermanent) + if _, err := dbus.isEnabled(); err != nil { + failDialog(win, "Unable is connect to firewall daemon. Is it running?") + } + rlPermanent.loadRules(sgfw.RULE_MODE_PERMANENT) + + rlSession := newRuleList(dbus, win, boxSession) + if _, err := dbus.isEnabled(); err != nil { + failDialog(win, "Unable is connect to firewall daemon. Is it running?") + } + rlSession.loadRules(sgfw.RULE_MODE_SESSION) - var swRulesPermanent *gtk.ScrolledWindow - var swRulesSession *gtk.ScrolledWindow - var swRulesSystem *gtk.ScrolledWindow + rlSystem := newRuleList(dbus, win, boxSystem) + if _, err := dbus.isEnabled(); err != nil { + failDialog(win, "Unable is connect to firewall daemon. Is it running?") + } + rlSystem.loadRules(sgfw.RULE_MODE_SYSTEM) + loadConfig(win, fwsbuilder, dbus) +// app.AddWindow(win) + win.ShowAll() + repopMutex.Unlock() +} + +func populateWin(app *gtk.Application, win *gtk.Window) { b := newBuilder("Dialog") + fwsbuilder = b b.getItems( "window", &win, "swRulesPermanent", &swRulesPermanent, @@ -72,6 +143,7 @@ func activate(app *gtk.Application) { loadConfig(win, b, dbus) app.AddWindow(win) + fwswin = win win.ShowAll() } @@ -81,5 +153,12 @@ func main() { panic(fmt.Sprintf("gtk.ApplicationNew() failed: %v", err)) } app.Connect("activate", activate) + + _, err = newDbusServer(); + + if err != nil { + panic(fmt.Sprintf("Error initializing Dbus server: %v", err)) + } + app.Run(os.Args) } diff --git a/sgfw/dbus.go b/sgfw/dbus.go index 7052ada..e4f7b17 100644 --- a/sgfw/dbus.go +++ b/sgfw/dbus.go @@ -49,6 +49,19 @@ const busName = "com.subgraph.Firewall" const objectPath = "/com/subgraph/Firewall" const interfaceName = "com.subgraph.Firewall" +type dbusObjectP struct { + dbus.BusObject +} + +func newDbusObjectPrompt() (*dbusObjectP, error) { + conn, err := dbus.SystemBus() + if err != nil { + return nil, err + } + return &dbusObjectP{conn.Object("com.subgraph.fwprompt.EventNotifier", "/com/subgraph/fwprompt/EventNotifier")}, nil +} + + type dbusServer struct { fw *Firewall conn *dbus.Conn @@ -226,3 +239,7 @@ func (ds *dbusServer) prompt(p *Policy) { log.Info("prompting...") ds.prompter.prompt(p) } + +func (ob *dbusObjectP) alertRule(data string) { + ob.Call("com.subgraph.fwprompt.EventNotifier.Alert", 0, data) +} diff --git a/sgfw/prompt.go b/sgfw/prompt.go index e1ee8ae..d53129e 100644 --- a/sgfw/prompt.go +++ b/sgfw/prompt.go @@ -120,6 +120,7 @@ func (p *prompter) processConnection(pc pendingConnection) { if fscope == APPLY_FOREVER { policy.fw.saveRules() } + dbusp.alertRule("sgfw prompt added new rule") } func (p *prompter) nextConnection() pendingConnection { diff --git a/sgfw/sgfw.go b/sgfw/sgfw.go index e38fb84..86261a1 100644 --- a/sgfw/sgfw.go +++ b/sgfw/sgfw.go @@ -10,6 +10,7 @@ import ( "bufio" "encoding/json" "strings" + "fmt" "github.com/op/go-logging" nfqueue "github.com/subgraph/go-nfnetlink/nfqueue" @@ -17,6 +18,8 @@ import ( "github.com/subgraph/go-procsnitch" ) +var dbusp *dbusObjectP = nil + type Firewall struct { dbus *dbusServer dns *dnsCache @@ -229,6 +232,13 @@ func Main() { log.Notice("Did not find SOCKS5 configuration file at", defaultSocksCfgPath, "; ignoring subsystem...") } + dbusp, err = newDbusObjectPrompt() + if err != nil { + panic(fmt.Sprintf("Failed to connect to dbus system bus for sgfw prompt events: %v", err)) + } + + dbusp.alertRule("fw-daemon initialization") + go OzReceiver(fw) fw.runFilter() diff --git a/sources/etc/dbus-1/system.d/com.Subgraph.fwprompt.EventNotifier.conf b/sources/etc/dbus-1/system.d/com.Subgraph.fwprompt.EventNotifier.conf new file mode 100644 index 0000000..04ffad0 --- /dev/null +++ b/sources/etc/dbus-1/system.d/com.Subgraph.fwprompt.EventNotifier.conf @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + +