From 86784190267c901d22244e56c2749ea6ca4852f6 Mon Sep 17 00:00:00 2001 From: Bruce Leidl Date: Wed, 24 Feb 2016 01:26:31 +0000 Subject: [PATCH] Initial commit of settings dialog --- fw-settings/builder.go | 114 ++++++++++++++ fw-settings/config.go | 57 +++++++ fw-settings/dbus.go | 65 ++++++++ fw-settings/definitions/Dialog.xml | 187 ++++++++++++++++++++++ fw-settings/definitions/Makefile | 8 + fw-settings/definitions/RuleEdit.xml | 201 ++++++++++++++++++++++++ fw-settings/definitions/RuleItem.xml | 89 +++++++++++ fw-settings/definitions/dialog.go | 200 ++++++++++++++++++++++++ fw-settings/definitions/generate.rb | 47 ++++++ fw-settings/definitions/management.go | 25 +++ fw-settings/definitions/rule_edit.go | 214 ++++++++++++++++++++++++++ fw-settings/definitions/rule_item.go | 101 ++++++++++++ fw-settings/main.go | 60 ++++++++ fw-settings/rule_edit.go | 161 +++++++++++++++++++ fw-settings/rules.go | 147 ++++++++++++++++++ 15 files changed, 1676 insertions(+) create mode 100644 fw-settings/builder.go create mode 100644 fw-settings/config.go create mode 100644 fw-settings/dbus.go create mode 100644 fw-settings/definitions/Dialog.xml create mode 100644 fw-settings/definitions/Makefile create mode 100644 fw-settings/definitions/RuleEdit.xml create mode 100644 fw-settings/definitions/RuleItem.xml create mode 100644 fw-settings/definitions/dialog.go create mode 100644 fw-settings/definitions/generate.rb create mode 100644 fw-settings/definitions/management.go create mode 100644 fw-settings/definitions/rule_edit.go create mode 100644 fw-settings/definitions/rule_item.go create mode 100644 fw-settings/main.go create mode 100644 fw-settings/rule_edit.go create mode 100644 fw-settings/rules.go diff --git a/fw-settings/builder.go b/fw-settings/builder.go new file mode 100644 index 0000000..05a321d --- /dev/null +++ b/fw-settings/builder.go @@ -0,0 +1,114 @@ +package main + +import ( + "bufio" + "fmt" + "log" + "os" + "path/filepath" + "reflect" + + "github.com/gotk3/gotk3/glib" + "github.com/gotk3/gotk3/gtk" + "github.com/subgraph/fw-daemon/fw-settings/definitions" +) + +const ( + defsFolder = "definitions" + xmlExtension = ".xml" +) + +func getDefinitionWithFileFallback(uiName string) string { + // this makes sure a missing definition wont break only when the app is released + uiDef := getDefinition(uiName) + + fileName := filepath.Join(defsFolder, uiName+xmlExtension) + if fileNotFound(fileName) { + log.Printf("gui: loading compiled definition %q\n", uiName) + return uiDef.String() + } + + return readFile(fileName) +} + +// This must be called from the UI thread - otherwise bad things will happen sooner or later +func builderForDefinition(uiName string) *gtk.Builder { + // assertInUIThread() + + template := getDefinitionWithFileFallback(uiName) + + builder, err := gtk.BuilderNew() + if err != nil { + //We cant recover from this + panic(err) + } + + err = builder.AddFromString(template) + if err != nil { + //This is a programming error + panic(fmt.Sprintf("gui: failed load %s: %s\n", uiName, err.Error())) + } + + return builder +} + +func fileNotFound(fileName string) bool { + _, fnf := os.Stat(fileName) + return os.IsNotExist(fnf) +} + +func readFile(fileName string) string { + file, _ := os.Open(fileName) + reader := bufio.NewScanner(file) + var content string + for reader.Scan() { + content = content + reader.Text() + } + file.Close() + return content +} + +func getDefinition(uiName string) fmt.Stringer { + def, ok := definitions.Get(uiName) + if !ok { + panic(fmt.Sprintf("No definition found for %s", uiName)) + } + + return def +} + +type builder struct { + *gtk.Builder +} + +func newBuilder(uiName string) *builder { + return &builder{builderForDefinition(uiName)} +} + +func (b *builder) getItem(name string, target interface{}) { + v := reflect.ValueOf(target) + if v.Kind() != reflect.Ptr { + panic("builder.getItem() target argument must be a pointer") + } + elem := v.Elem() + elem.Set(reflect.ValueOf(b.get(name))) +} + +func (b *builder) getItems(args ...interface{}) { + for len(args) >= 2 { + name, ok := args[0].(string) + if !ok { + panic("string argument expected in builder.getItems()") + } + b.getItem(name, args[1]) + args = args[2:] + } +} + +func (b *builder) get(name string) glib.IObject { + obj, err := b.GetObject(name) + if err != nil { + panic("builder.GetObject() failed: " + err.Error()) + } + return obj +} diff --git a/fw-settings/config.go b/fw-settings/config.go new file mode 100644 index 0000000..6aa2542 --- /dev/null +++ b/fw-settings/config.go @@ -0,0 +1,57 @@ +package main + +import ( + "github.com/gotk3/gotk3/gtk" + "github.com/op/go-logging" +) + +var levelToId = map[int32]string{ + int32(logging.ERROR): "error", + int32(logging.WARNING): "warning", + int32(logging.NOTICE): "notice", + int32(logging.INFO): "info", + int32(logging.DEBUG): "debug", +} + +var idToLevel = func() map[string]int32 { + m := make(map[string]int32) + for k, v := range levelToId { + m[v] = k + } + return m +}() + +func loadConfig(win *gtk.Window, b *builder, dbus *dbusObject) { + var levelCombo *gtk.ComboBoxText + var redactCheck *gtk.CheckButton + + b.getItems( + "level_combo", &levelCombo, + "redact_checkbox", &redactCheck, + ) + + conf, err := dbus.getConfig() + if err != nil { + failDialog(win, "Failed to load config from fw daemon: %v", err) + } + + if lvl, ok := conf["loglevel"].(int32); ok { + if id, ok := levelToId[lvl]; ok { + levelCombo.SetActiveID(id) + } + } + if v, ok := conf["logredact"].(bool); ok { + redactCheck.SetActive(v) + } + b.ConnectSignals(map[string]interface{}{ + "on_level_combo_changed": func() { + if lvl, ok := idToLevel[levelCombo.GetActiveID()]; ok { + dbus.setConfig("loglevel", lvl) + } + }, + "on_redact_checkbox_toggled": func() { + dbus.setConfig("logredact", redactCheck.GetActive()) + }, + }) + +} diff --git a/fw-settings/dbus.go b/fw-settings/dbus.go new file mode 100644 index 0000000..5010ce7 --- /dev/null +++ b/fw-settings/dbus.go @@ -0,0 +1,65 @@ +package main + +import ( + "github.com/godbus/dbus" +) + +type dbusObject struct { + dbus.BusObject +} + +type dbusRule struct { + Id uint32 + App string + Path string + Verb uint32 + Target string +} + +func newDbusObject() (*dbusObject, error) { + conn, err := dbus.SystemBus() + if err != nil { + return nil, err + } + return &dbusObject{conn.Object("com.subgraph.Firewall", "/com/subgraph/Firewall")}, nil +} + +func (ob *dbusObject) isEnabled() (bool, error) { + var flag bool + if err := ob.Call("com.subgraph.Firewall.IsEnabled", 0).Store(&flag); err != nil { + return false, err + } + return flag, nil +} + +func (ob *dbusObject) listRules() ([]dbusRule, error) { + rules := []dbusRule{} + if err := ob.Call("com.subgraph.Firewall.ListRules", 0).Store(&rules); err != nil { + return nil, err + } + return rules, nil +} + +func (ob *dbusObject) deleteRule(id uint32) { + ob.Call("com.subgraph.Firewall.DeleteRule", 0, id) +} + +func (ob *dbusObject) updateRule(rule *dbusRule) { + ob.Call("com.subgraph.Firewall.UpdateRule", 0, rule) +} + +func (ob *dbusObject) getConfig() (map[string]interface{}, error) { + res := make(map[string]dbus.Variant) + if err := ob.Call("com.subgraph.Firewall.GetConfig", 0).Store(&res); err != nil { + return nil, err + } + config := make(map[string]interface{}) + for k, v := range res { + config[k] = v.Value() + } + return config, nil +} + +func (ob *dbusObject) setConfig(key string, val interface{}) { + ob.Call("com.subgraph.Firewall.SetConfig", 0, key, dbus.MakeVariant(val)) +} diff --git a/fw-settings/definitions/Dialog.xml b/fw-settings/definitions/Dialog.xml new file mode 100644 index 0000000..867b072 --- /dev/null +++ b/fw-settings/definitions/Dialog.xml @@ -0,0 +1,187 @@ + + + + + + False + True + Firewall Settings + 600 + 400 + dialog + + + True + True + 5 + + + True + False + 12 + 12 + 12 + 12 + + + True + False + Firewall Rules + 0 + + + + + + 0 + 0 + + + + + True + False + 12 + 12 + 8 + True + True + + + True + True + True + True + never + in + + + 0 + 0 + + + + + 0 + 1 + + + + + 1 + + + + + True + False + Rules + + + 1 + False + + + + + True + False + 12 + 12 + + + True + False + 12 + 8 + 6 + 6 + + + True + False + start + Log Level: + + + 0 + 0 + + + + + True + False + 0 + + Error + Warning + Notice + Info + Debug + + + + + 1 + 0 + + + + + Remove host names and addresses from logs + True + True + False + 0 + True + + + + 0 + 1 + 2 + + + + + 0 + 1 + + + + + True + False + Logging + start + 0 + + + + + + 0 + 0 + + + + + 1 + + + + + True + False + Options + + + 1 + False + + + + + + diff --git a/fw-settings/definitions/Makefile b/fw-settings/definitions/Makefile new file mode 100644 index 0000000..ae97f5d --- /dev/null +++ b/fw-settings/definitions/Makefile @@ -0,0 +1,8 @@ +generate: + ruby ./generate.rb + +touch: + ls *.xml | xargs -n1 touch + +doctor: touch generate + git diff --exit-code . \ No newline at end of file diff --git a/fw-settings/definitions/RuleEdit.xml b/fw-settings/definitions/RuleEdit.xml new file mode 100644 index 0000000..2ad8738 --- /dev/null +++ b/fw-settings/definitions/RuleEdit.xml @@ -0,0 +1,201 @@ + + + + + + False + Edit Rule + dialog + + + False + vertical + 2 + + + False + end + + + Cancel + True + True + True + + + True + True + 0 + + + + + Ok + True + True + True + 0.60000002384185791 + + + True + True + 1 + + + + + False + False + 0 + + + + + True + False + 12 + 12 + 12 + 24 + 24 + + + True + False + Enter changes for firewall rule below. The character <b>*</b> can entered alone into either the <b>host</b> or <b>port</b> fields to match any value. + + True + True + 40 + + + 0 + 0 + 2 + + + + + True + False + True + 0 + + + 1 + 1 + + + + + True + False + 12 + 10 + + + True + False + 0 + + Allow + Deny + + + + 0 + 0 + + + + + True + False + Connections to <b>host:</b> + True + + + 1 + 0 + + + + + True + True + 34 + hostname or ip address + + + + 2 + 0 + + + + + True + False + on <b>port:</b> + True + + + 3 + 0 + + + + + True + True + 5 + 4 + 5 + Port + + + + + 4 + 0 + + + + + 0 + 2 + 2 + + + + + True + False + 12 + 10 + Path: + 1 + + + + + + 0 + 1 + + + + + False + True + 1 + + + + + + cancel_button + ok_button + + + diff --git a/fw-settings/definitions/RuleItem.xml b/fw-settings/definitions/RuleItem.xml new file mode 100644 index 0000000..7fdbd75 --- /dev/null +++ b/fw-settings/definitions/RuleItem.xml @@ -0,0 +1,89 @@ + + + + + + True + False + True + + + True + False + start + 8 + 10 + 0 + + + 0 + 0 + + + + + True + False + 10 + 1 + + + 1 + 0 + + + + + True + False + start + True + 0 + + + 2 + 0 + + + + + True + True + True + none + + + + True + False + document-properties-symbolic + + + + + 3 + 0 + + + + + True + True + True + none + + + + True + False + edit-delete-symbolic + + + + + 4 + 0 + + + + diff --git a/fw-settings/definitions/dialog.go b/fw-settings/definitions/dialog.go new file mode 100644 index 0000000..546f865 --- /dev/null +++ b/fw-settings/definitions/dialog.go @@ -0,0 +1,200 @@ +package definitions + +func init() { + add(`Dialog`, &defDialog{}) +} + +type defDialog struct{} + +func (*defDialog) String() string { + return ` + + + + + + False + True + Firewall Settings + 600 + 400 + dialog + + + True + True + 5 + + + True + False + 12 + 12 + 12 + 12 + + + True + False + Firewall Rules + 0 + + + + + + 0 + 0 + + + + + True + False + 12 + 12 + 8 + True + True + + + True + True + True + True + never + in + + + 0 + 0 + + + + + 0 + 1 + + + + + 1 + + + + + True + False + Rules + + + 1 + False + + + + + True + False + 12 + 12 + + + True + False + 12 + 8 + 6 + 6 + + + True + False + start + Log Level: + + + 0 + 0 + + + + + True + False + 0 + + Error + Warning + Notice + Info + Debug + + + + + 1 + 0 + + + + + Remove host names and addresses from logs + True + True + False + 0 + True + + + + 0 + 1 + 2 + + + + + 0 + 1 + + + + + True + False + Logging + start + 0 + + + + + + 0 + 0 + + + + + 1 + + + + + True + False + Options + + + 1 + False + + + + + + + +` +} diff --git a/fw-settings/definitions/generate.rb b/fw-settings/definitions/generate.rb new file mode 100644 index 0000000..12857fe --- /dev/null +++ b/fw-settings/definitions/generate.rb @@ -0,0 +1,47 @@ +#!/usr/bin/env ruby + +require 'fileutils' + +def parse_go_name(file_name) + File.basename(file_name, ".xml"). + gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2'). + gsub(/([a-z\d])([A-Z])/,'\1_\2'). + tr("-", "_"). + gsub(/\/_/, '/'). + downcase + ".go" +end + +def gen_go_file(xml_file, go_file) + xml_definition = File.read(xml_file) + ui_name = File.basename(xml_file, '.xml') + File.open(go_file, 'w+') do |target| + target.puts <