ADDED: System rules

ADDED: Persistant configs
ADDED: Prompt configurations (default action, advanced options, auto expand)
FIXED: Default focus on prompt
FIXED: Bug in display of *:<port> rule
FIXED: Updated ui to gnome >= 3.20
socks-filter
xSmurf 8 years ago
parent 3798b30a2c
commit 95c5e486ba

@ -0,0 +1,79 @@
// TODO: Check permissions on file
// TODO: Create dir if needed
// TODO: Dont' fail hard on failed read
package main
import (
"bufio"
"io/ioutil"
"os"
"github.com/naoina/toml"
"github.com/op/go-logging"
)
const (
configDefaultPath string = "/etc/sgfw/sgfw.conf"
)
type FirewallConfigs struct {
LogLevel string
LoggingLevel logging.Level `toml:"-"`
LogRedact bool
PromptExpanded bool
PromptExpert bool
DefaultAction string
DefaultActionId int32 `toml:"-"`
}
var FirewallConfig FirewallConfigs
func readConfig() {
f, err := os.Open(configDefaultPath)
if err != nil {
log.Error(err.Error())
os.Exit(1)
}
defer f.Close()
buf, err := ioutil.ReadAll(f)
if err != nil {
log.Error(err.Error())
os.Exit(1)
}
FirewallConfig = FirewallConfigs{
LogLevel: "NOTICE",
LoggingLevel: logging.NOTICE,
LogRedact: false,
PromptExpanded: false,
PromptExpert: false,
DefaultAction: "SESSION",
DefaultActionId: 1,
}
if err := toml.Unmarshal(buf, &FirewallConfig); err != nil {
log.Error(err.Error())
os.Exit(1)
}
FirewallConfig.LoggingLevel, _ = logging.LogLevel(FirewallConfig.LogLevel)
FirewallConfig.DefaultActionId = valueScope(FirewallConfig.DefaultAction)
}
func writeConfig() {
FirewallConfig.LogLevel = FirewallConfig.LoggingLevel.String()
FirewallConfig.DefaultAction = printScope(FirewallConfig.DefaultActionId)
f, err := os.Create(configDefaultPath)
if err != nil {
log.Error(err.Error())
os.Exit(1)
}
defer f.Close()
w := bufio.NewWriter(f)
cw := toml.NewEncoder(w)
if err := cw.Encode(FirewallConfig); err != nil {
log.Error(err.Error())
os.Exit(1)
}
w.Flush()
}

@ -60,6 +60,7 @@ type DbusRule struct {
Path string
Verb uint32
Target string
Mode uint16
}
func newDbusServer() (*dbusServer, error) {
@ -107,6 +108,7 @@ func createDbusRule(r *Rule) DbusRule {
Path: r.policy.path,
Verb: uint32(r.rtype),
Target: r.AddrString(false),
Mode: uint16(r.mode),
}
}
@ -126,10 +128,14 @@ func (ds *dbusServer) DeleteRule(id uint32) *dbus.Error {
ds.fw.lock.Lock()
r := ds.fw.rulesById[uint(id)]
ds.fw.lock.Unlock()
if r.mode == RULE_MODE_SYSTEM {
log.Warningf("Cannot delete system rule: %s", r.String())
return nil
}
if r != nil {
r.policy.removeRule(r)
}
if !r.sessionOnly {
if r.mode != RULE_MODE_SESSION {
ds.fw.saveRules()
}
return nil
@ -141,6 +147,10 @@ func (ds *dbusServer) UpdateRule(rule DbusRule) *dbus.Error {
r := ds.fw.rulesById[uint(rule.Id)]
ds.fw.lock.Unlock()
if r != nil {
if r.mode == RULE_MODE_SYSTEM {
log.Warningf("Cannot modify system rule: %s", r.String())
return nil
}
tmp := new(Rule)
tmp.addr = noAddress
if !tmp.parseTarget(rule.Target) {
@ -154,8 +164,9 @@ func (ds *dbusServer) UpdateRule(rule DbusRule) *dbus.Error {
r.hostname = tmp.hostname
r.addr = tmp.addr
r.port = tmp.port
r.mode = RuleMode(rule.Mode)
r.policy.lock.Unlock()
if !r.sessionOnly {
if r.mode != RULE_MODE_SESSION {
ds.fw.saveRules()
}
}
@ -164,21 +175,35 @@ func (ds *dbusServer) UpdateRule(rule DbusRule) *dbus.Error {
func (ds *dbusServer) GetConfig() (map[string]dbus.Variant, *dbus.Error) {
conf := make(map[string]dbus.Variant)
conf["loglevel"] = dbus.MakeVariant(int32(ds.fw.logBackend.GetLevel("sgfw")))
conf["logredact"] = dbus.MakeVariant(logRedact)
conf["log_level"] = dbus.MakeVariant(int32(ds.fw.logBackend.GetLevel("sgfw")))
conf["log_redact"] = dbus.MakeVariant(FirewallConfig.LogRedact)
conf["prompt_expanded"] = dbus.MakeVariant(FirewallConfig.PromptExpanded)
conf["prompt_expert"] = dbus.MakeVariant(FirewallConfig.PromptExpert)
conf["default_action"] = dbus.MakeVariant(int32(FirewallConfig.DefaultActionId))
return conf, nil
}
func (ds *dbusServer) SetConfig(key string, val dbus.Variant) *dbus.Error {
switch key {
case "loglevel":
case "log_level":
l := val.Value().(int32)
lvl := logging.Level(l)
ds.fw.logBackend.SetLevel(lvl, "sgfw")
case "logredact":
FirewallConfig.LoggingLevel = lvl
case "log_redact":
flag := val.Value().(bool)
logRedact = flag
FirewallConfig.LogRedact = flag
case "prompt_expanded":
flag := val.Value().(bool)
FirewallConfig.PromptExpanded = flag
case "prompt_expert":
flag := val.Value().(bool)
FirewallConfig.PromptExpert = flag
case "default_action":
l := val.Value().(int32)
FirewallConfig.DefaultActionId = l
}
writeConfig()
return nil
}

@ -54,7 +54,7 @@ func (dc *dnsCache) processRecordA(name string, answers []dnsRR) {
name = name[:len(name)-1]
}
dc.ipMap[ip] = name
if !logRedact {
if !FirewallConfig.LogRedact {
log.Infof("Adding %s: %s", name, ip)
}
default:

@ -21,13 +21,33 @@ var idToLevel = func() map[string]int32 {
return m
}()
var actionToId = map[int32]string{
0: "ONCE",
1: "SESSION",
3: "FOREVER",
}
var idToAction = func() map[string]int32 {
m := make(map[string]int32)
for k, v := range actionToId {
m[v] = k
}
return m
}()
func loadConfig(win *gtk.Window, b *builder, dbus *dbusObject) {
var levelCombo *gtk.ComboBoxText
var redactCheck *gtk.CheckButton
var expandedCheck *gtk.CheckButton
var expertCheck *gtk.CheckButton
var actionCombo *gtk.ComboBoxText
b.getItems(
"level_combo", &levelCombo,
"redact_checkbox", &redactCheck,
"expanded_checkbox", &expandedCheck,
"expert_checkbox", &expertCheck,
"action_combo", &actionCombo,
)
conf, err := dbus.getConfig()
@ -35,22 +55,44 @@ func loadConfig(win *gtk.Window, b *builder, dbus *dbusObject) {
failDialog(win, "Failed to load config from fw daemon: %v", err)
}
if lvl, ok := conf["loglevel"].(int32); ok {
if lvl, ok := conf["log_level"].(int32); ok {
if id, ok := levelToId[lvl]; ok {
levelCombo.SetActiveID(id)
}
}
if v, ok := conf["logredact"].(bool); ok {
if v, ok := conf["log_redact"].(bool); ok {
redactCheck.SetActive(v)
}
if v, ok := conf["prompt_expanded"].(bool); ok {
expandedCheck.SetActive(v)
}
if v, ok := conf["prompt_expert"].(bool); ok {
expertCheck.SetActive(v)
}
if av, ok := conf["default_action"].(int32); ok {
if id, ok := actionToId[av]; ok {
actionCombo.SetActiveID(id)
}
}
b.ConnectSignals(map[string]interface{}{
"on_level_combo_changed": func() {
if lvl, ok := idToLevel[levelCombo.GetActiveID()]; ok {
dbus.setConfig("loglevel", lvl)
dbus.setConfig("log_level", lvl)
}
},
"on_redact_checkbox_toggled": func() {
dbus.setConfig("logredact", redactCheck.GetActive())
dbus.setConfig("log_redact", redactCheck.GetActive())
},
"on_expanded_checkbox_toggled": func() {
dbus.setConfig("prompt_expanded", expandedCheck.GetActive())
},
"on_expert_checkbox_toggled": func() {
dbus.setConfig("prompt_expert", expertCheck.GetActive())
},
"on_action_combo_changed": func() {
if al, ok := idToAction[actionCombo.GetActiveID()]; ok {
dbus.setConfig("default_action", al)
}
},
})

@ -8,12 +8,21 @@ type dbusObject struct {
dbus.BusObject
}
//type RuleMode uint16
const (
RULE_MODE_SESSION uint16 = iota
RULE_MODE_PERMANENT
RULE_MODE_SYSTEM
)
type dbusRule struct {
Id uint32
App string
Path string
Verb uint32
Target string
Mode uint16
}
func newDbusObject() (*dbusObject, error) {

@ -1,53 +1,56 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.19.0 -->
<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.16"/>
<requires lib="gtk+" version="3.20"/>
<object class="GtkWindow" id="window">
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="title" translatable="yes">Firewall Settings</property>
<property name="title">Subgraph Firewall</property>
<property name="window_position">center</property>
<property name="default_width">600</property>
<property name="default_height">400</property>
<property name="type_hint">dialog</property>
<child>
<object class="GtkNotebook" id="notebook">
<property name="visible">True</property>
<property name="can_focus">True</property>
<object class="GtkBox" id="box1">
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkStack" id="toplevel_stack">
<property name="can_focus">False</property>
<property name="margin_bottom">5</property>
<property name="transition_duration">1000</property>
<child>
<object class="GtkGrid" id="grid3">
<object class="GtkNotebook" id="rulesnotebook">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_right">12</property>
<property name="margin_top">12</property>
<property name="margin_bottom">12</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<child>
<object class="GtkLabel" id="label4">
<object class="GtkScrolledWindow" id="swRulesPermanent">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Firewall Rules</property>
<property name="xalign">0</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="hscrollbar_policy">never</property>
<property name="shadow_type">in</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="tab_expand">True</property>
</packing>
</child>
<child>
<object class="GtkGrid" id="grid4">
<child type="tab">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_right">12</property>
<property name="margin_top">8</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="label" translatable="yes">Permanent</property>
</object>
<packing>
<property name="tab_expand">True</property>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow">
<object class="GtkScrolledWindow" id="swRulesSession">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
@ -56,62 +59,121 @@
<property name="shadow_type">in</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="position">1</property>
<property name="tab_expand">True</property>
</packing>
</child>
<child type="tab">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Session</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="position">1</property>
<property name="tab_expand">True</property>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="swRulesSystem">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="hscrollbar_policy">never</property>
<property name="shadow_type">in</property>
</object>
<packing>
<property name="position">1</property>
<property name="position">2</property>
<property name="tab_expand">True</property>
</packing>
</child>
<child type="tab">
<object class="GtkLabel" id="label2">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Rules</property>
<property name="label" translatable="yes">System</property>
</object>
<packing>
<property name="position">1</property>
<property name="position">2</property>
<property name="tab_expand">True</property>
<property name="tab_fill">False</property>
</packing>
</child>
</object>
<packing>
<property name="name">page0</property>
<property name="title" translatable="yes">Rules</property>
</packing>
</child>
<child>
<object class="GtkGrid" id="grid1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_top">12</property>
<property name="margin_left">10</property>
<property name="margin_right">10</property>
<property name="margin_top">10</property>
<property name="margin_bottom">10</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="row_spacing">5</property>
<property name="column_homogeneous">True</property>
<child>
<object class="GtkGrid" id="grid2">
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_top">8</property>
<property name="row_spacing">6</property>
<property name="column_spacing">6</property>
<property name="halign">start</property>
<property name="margin_top">10</property>
<property name="margin_bottom">5</property>
<property name="label" translatable="yes">Prompt</property>
<property name="ellipsize">start</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label3">
<object class="GtkLabel" id="label5">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Log Level:</property>
<property name="margin_bottom">5</property>
<property name="label" translatable="yes">Logging</property>
<property name="ellipsize">start</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="margin_left">10</property>
<property name="label" translatable="yes">Daemon Log Level:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="level_combo">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="active">0</property>
<items>
<item id="error" translatable="yes">Error</item>
@ -124,7 +186,7 @@
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
@ -133,55 +195,111 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="margin_left">10</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_redact_checkbox_toggled" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="top_attach">2</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="expanded_checkbox">
<property name="label" translatable="yes">Always expand event prompt</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="halign">start</property>
<property name="margin_left">10</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_expanded_checkbox_toggled" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="top_attach">4</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label5">
<object class="GtkCheckButton" id="expert_checkbox">
<property name="label" translatable="yes">Show expert options in event prompt</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Logging</property>
<property name="ellipsize">start</property>
<property name="xalign">0</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="halign">start</property>
<property name="margin_left">10</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_expert_checkbox_toggled" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="top_attach">5</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="margin_left">10</property>
<property name="label" translatable="yes">Default Scope:</property>
</object>
<packing>
<property name="position">1</property>
<property name="left_attach">0</property>
<property name="top_attach">6</property>
</packing>
</child>
<child type="tab">
<object class="GtkLabel" id="label1">
<child>
<object class="GtkComboBoxText" id="action_combo">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Options</property>
<property name="hexpand">True</property>
<property name="active">0</property>
<items>
<item id="FOREVER" translatable="yes">Forever</item>
<item id="SESSION" translatable="yes">Session</item>
<item id="ONCE" translatable="yes">Once</item>
</items>
<signal name="changed" handler="on_action_combo_changed" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">6</property>
</packing>
</child>
</object>
<packing>
<property name="name">page1</property>
<property name="title" translatable="yes">Options</property>
<property name="position">1</property>
<property name="tab_fill">False</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
</child>
<child type="titlebar">
<object class="GtkHeaderBar" id="headerbar">
<property name="can_focus">False</property>
<property name="show_close_button">True</property>
<property name="decoration_layout">:minimize,maximize,close</property>
<child type="title">
<object class="GtkStackSwitcher" id="stack_switcher">
<property name="can_focus">False</property>
<property name="icon_size">2</property>
<property name="stack">toplevel_stack</property>
</object>
</child>
</object>
</child>
</object>
</interface>

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.19.0 -->
<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.16"/>
<object class="GtkDialog" id="dialog">
@ -34,7 +34,6 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="yalign">0.60000002384185791</property>
</object>
<packing>
<property name="expand">True</property>
@ -78,8 +77,8 @@
<object class="GtkLabel" id="path_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="hexpand">True</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">1</property>
@ -171,10 +170,11 @@
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="margin_left">12</property>
<property name="margin_right">10</property>
<property name="hexpand">False</property>
<property name="label" translatable="yes">Path:</property>
<property name="xalign">1</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.19.0 -->
<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.16"/>
<object class="GtkGrid" id="grid">
@ -13,7 +13,6 @@
<property name="halign">start</property>
<property name="margin_left">8</property>
<property name="margin_right">10</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
@ -24,8 +23,8 @@
<object class="GtkLabel" id="verb_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="margin_right">10</property>
<property name="xalign">1</property>
</object>
<packing>
<property name="left_attach">1</property>
@ -38,7 +37,6 @@
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="hexpand">True</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">2</property>
@ -50,11 +48,11 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Edit Firewall rule</property>
<property name="tooltip_text" translatable="yes">Edit firewall rule</property>
<property name="relief">none</property>
<signal name="clicked" handler="on_edit_rule" swapped="no"/>
<child>
<object class="GtkImage" id="image2">
<object class="GtkImage" id="img_edit_button">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">document-properties-symbolic</property>
@ -71,7 +69,7 @@
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Delete Firewall rule</property>
<property name="tooltip_text" translatable="yes">Delete firewall rule</property>
<property name="relief">none</property>
<signal name="clicked" handler="on_delete_rule" swapped="no"/>
<child>
@ -82,6 +80,28 @@
</object>
</child>
</object>
<packing>
<property name="left_attach">5</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="save_button">
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="no_show_all">True</property>
<property name="tooltip_text" translatable="yes">Save as new permanent firewall rule</property>
<property name="relief">none</property>
<signal name="clicked" handler="on_save_rule" swapped="no"/>
<child>
<object class="GtkImage" id="img_save_button">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">document-new-symbolic</property>
</object>
</child>
</object>
<packing>
<property name="left_attach">4</property>
<property name="top_attach">0</property>

@ -9,55 +9,58 @@ type defDialog struct{}
func (*defDialog) String() string {
return `
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.19.0 -->
<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.16"/>
<requires lib="gtk+" version="3.20"/>
<object class="GtkWindow" id="window">
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="title" translatable="yes">Firewall Settings</property>
<property name="title">Subgraph Firewall</property>
<property name="window_position">center</property>
<property name="default_width">600</property>
<property name="default_height">400</property>
<property name="type_hint">dialog</property>
<child>
<object class="GtkNotebook" id="notebook">
<property name="visible">True</property>
<property name="can_focus">True</property>
<object class="GtkBox" id="box1">
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkStack" id="toplevel_stack">
<property name="can_focus">False</property>
<property name="margin_bottom">5</property>
<property name="transition_duration">1000</property>
<child>
<object class="GtkGrid" id="grid3">
<object class="GtkNotebook" id="rulesnotebook">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_right">12</property>
<property name="margin_top">12</property>
<property name="margin_bottom">12</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<child>
<object class="GtkLabel" id="label4">
<object class="GtkScrolledWindow" id="swRulesPermanent">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Firewall Rules</property>
<property name="xalign">0</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="hscrollbar_policy">never</property>
<property name="shadow_type">in</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="tab_expand">True</property>
</packing>
</child>
<child>
<object class="GtkGrid" id="grid4">
<child type="tab">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_right">12</property>
<property name="margin_top">8</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="label" translatable="yes">Permanent</property>
</object>
<packing>
<property name="tab_expand">True</property>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="scrolledwindow">
<object class="GtkScrolledWindow" id="swRulesSession">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
@ -66,62 +69,121 @@ func (*defDialog) String() string {
<property name="shadow_type">in</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="position">1</property>
<property name="tab_expand">True</property>
</packing>
</child>
<child type="tab">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Session</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="position">1</property>
<property name="tab_expand">True</property>
<property name="tab_fill">False</property>
</packing>
</child>
<child>
<object class="GtkScrolledWindow" id="swRulesSystem">
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="hscrollbar_policy">never</property>
<property name="shadow_type">in</property>
</object>
<packing>
<property name="position">1</property>
<property name="position">2</property>
<property name="tab_expand">True</property>
</packing>
</child>
<child type="tab">
<object class="GtkLabel" id="label2">
<object class="GtkLabel">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Rules</property>
<property name="label" translatable="yes">System</property>
</object>
<packing>
<property name="position">1</property>
<property name="position">2</property>
<property name="tab_expand">True</property>
<property name="tab_fill">False</property>
</packing>
</child>
</object>
<packing>
<property name="name">page0</property>
<property name="title" translatable="yes">Rules</property>
</packing>
</child>
<child>
<object class="GtkGrid" id="grid1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_top">12</property>
<property name="margin_left">10</property>
<property name="margin_right">10</property>
<property name="margin_top">10</property>
<property name="margin_bottom">10</property>
<property name="hexpand">True</property>
<property name="vexpand">True</property>
<property name="row_spacing">5</property>
<property name="column_homogeneous">True</property>
<child>
<object class="GtkGrid" id="grid2">
<object class="GtkLabel" id="label1">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="margin_left">12</property>
<property name="margin_top">8</property>
<property name="row_spacing">6</property>
<property name="column_spacing">6</property>
<property name="halign">start</property>
<property name="margin_top">10</property>
<property name="margin_bottom">5</property>
<property name="label" translatable="yes">Prompt</property>
<property name="ellipsize">start</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">3</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label3">
<object class="GtkLabel" id="label5">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="label" translatable="yes">Log Level:</property>
<property name="margin_bottom">5</property>
<property name="label" translatable="yes">Logging</property>
<property name="ellipsize">start</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label3">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="margin_left">10</property>
<property name="label" translatable="yes">Daemon Log Level:</property>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
<object class="GtkComboBoxText" id="level_combo">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="hexpand">True</property>
<property name="active">0</property>
<items>
<item id="error" translatable="yes">Error</item>
@ -134,7 +196,7 @@ func (*defDialog) String() string {
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">0</property>
<property name="top_attach">1</property>
</packing>
</child>
<child>
@ -143,55 +205,111 @@ func (*defDialog) String() string {
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="xalign">0</property>
<property name="halign">start</property>
<property name="margin_left">10</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_redact_checkbox_toggled" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="top_attach">2</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkCheckButton" id="expanded_checkbox">
<property name="label" translatable="yes">Always expand event prompt</property>
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="halign">start</property>
<property name="margin_left">10</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_expanded_checkbox_toggled" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">1</property>
<property name="top_attach">4</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label5">
<object class="GtkCheckButton" id="expert_checkbox">
<property name="label" translatable="yes">Show expert options in event prompt</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Logging</property>
<property name="ellipsize">start</property>
<property name="xalign">0</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>
<property name="can_focus">True</property>
<property name="receives_default">False</property>
<property name="halign">start</property>
<property name="margin_left">10</property>
<property name="draw_indicator">True</property>
<signal name="toggled" handler="on_expert_checkbox_toggled" swapped="no"/>
</object>
<packing>
<property name="left_attach">0</property>
<property name="top_attach">0</property>
<property name="top_attach">5</property>
<property name="width">2</property>
</packing>
</child>
<child>
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="margin_left">10</property>
<property name="label" translatable="yes">Default Scope:</property>
</object>
<packing>
<property name="position">1</property>
<property name="left_attach">0</property>
<property name="top_attach">6</property>
</packing>
</child>
<child type="tab">
<object class="GtkLabel" id="label1">
<child>
<object class="GtkComboBoxText" id="action_combo">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="label" translatable="yes">Options</property>
<property name="hexpand">True</property>
<property name="active">0</property>
<items>
<item id="FOREVER" translatable="yes">Forever</item>
<item id="SESSION" translatable="yes">Session</item>
<item id="ONCE" translatable="yes">Once</item>
</items>
<signal name="changed" handler="on_action_combo_changed" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
<property name="top_attach">6</property>
</packing>
</child>
</object>
<packing>
<property name="name">page1</property>
<property name="title" translatable="yes">Options</property>
<property name="position">1</property>
<property name="tab_fill">False</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
</object>
</child>
<child type="titlebar">
<object class="GtkHeaderBar" id="headerbar">
<property name="can_focus">False</property>
<property name="show_close_button">True</property>
<property name="decoration_layout">:minimize,maximize,close</property>
<child type="title">
<object class="GtkStackSwitcher" id="stack_switcher">
<property name="can_focus">False</property>
<property name="icon_size">2</property>
<property name="stack">toplevel_stack</property>
</object>
</child>
</object>
</child>
</object>
</interface>

@ -9,7 +9,7 @@ type defRuleEdit struct{}
func (*defRuleEdit) String() string {
return `
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.19.0 -->
<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.16"/>
<object class="GtkDialog" id="dialog">
@ -44,7 +44,6 @@ func (*defRuleEdit) String() string {
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="yalign">0.60000002384185791</property>
</object>
<packing>
<property name="expand">True</property>
@ -88,8 +87,8 @@ func (*defRuleEdit) String() string {
<object class="GtkLabel" id="path_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="hexpand">True</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">1</property>
@ -181,10 +180,11 @@ func (*defRuleEdit) String() string {
<object class="GtkLabel" id="label2">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="margin_left">12</property>
<property name="margin_right">10</property>
<property name="hexpand">False</property>
<property name="label" translatable="yes">Path:</property>
<property name="xalign">1</property>
<attributes>
<attribute name="weight" value="bold"/>
</attributes>

@ -9,7 +9,7 @@ type defRuleItem struct{}
func (*defRuleItem) String() string {
return `
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated with glade 3.19.0 -->
<!-- Generated with glade 3.20.0 -->
<interface>
<requires lib="gtk+" version="3.16"/>
<object class="GtkGrid" id="grid">
@ -23,7 +23,6 @@ func (*defRuleItem) String() string {
<property name="halign">start</property>
<property name="margin_left">8</property>
<property name="margin_right">10</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">0</property>
@ -34,8 +33,8 @@ func (*defRuleItem) String() string {
<object class="GtkLabel" id="verb_label">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="margin_right">10</property>
<property name="xalign">1</property>
</object>
<packing>
<property name="left_attach">1</property>
@ -48,7 +47,6 @@ func (*defRuleItem) String() string {
<property name="can_focus">False</property>
<property name="halign">start</property>
<property name="hexpand">True</property>
<property name="xalign">0</property>
</object>
<packing>
<property name="left_attach">2</property>
@ -60,11 +58,11 @@ func (*defRuleItem) String() string {
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Edit Firewall rule</property>
<property name="tooltip_text" translatable="yes">Edit firewall rule</property>
<property name="relief">none</property>
<signal name="clicked" handler="on_edit_rule" swapped="no"/>
<child>
<object class="GtkImage" id="image2">
<object class="GtkImage" id="img_edit_button">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">document-properties-symbolic</property>
@ -81,7 +79,7 @@ func (*defRuleItem) String() string {
<property name="visible">True</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="tooltip_text" translatable="yes">Delete Firewall rule</property>
<property name="tooltip_text" translatable="yes">Delete firewall rule</property>
<property name="relief">none</property>
<signal name="clicked" handler="on_delete_rule" swapped="no"/>
<child>
@ -92,6 +90,28 @@ func (*defRuleItem) String() string {
</object>
</child>
</object>
<packing>
<property name="left_attach">5</property>
<property name="top_attach">0</property>
</packing>
</child>
<child>
<object class="GtkButton" id="save_button">
<property name="sensitive">False</property>
<property name="can_focus">True</property>
<property name="receives_default">True</property>
<property name="no_show_all">True</property>
<property name="tooltip_text" translatable="yes">Save as new permanent firewall rule</property>
<property name="relief">none</property>
<signal name="clicked" handler="on_save_rule" swapped="no"/>
<child>
<object class="GtkImage" id="img_save_button">
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="icon_name">document-new-symbolic</property>
</object>
</child>
</object>
<packing>
<property name="left_attach">4</property>
<property name="top_attach">0</property>

@ -22,29 +22,52 @@ func activate(app *gtk.Application) {
return
}
var scrolled *gtk.ScrolledWindow
var swRulesPermanent *gtk.ScrolledWindow
var swRulesSession *gtk.ScrolledWindow
var swRulesSystem *gtk.ScrolledWindow
b := newBuilder("Dialog")
b.getItems(
"window", &win,
"scrolledwindow", &scrolled,
"swRulesPermanent", &swRulesPermanent,
"swRulesSession", &swRulesSession,
"swRulesSystem", &swRulesSystem,
)
win.SetIconName("security-high-symbolic")
//win.SetIconName("security-high-symbolic")
win.SetIconName("security-medium")
box, _ := gtk.ListBoxNew()
scrolled.Add(box)
boxPermanent, _ := gtk.ListBoxNew()
swRulesPermanent.Add(boxPermanent)
boxSession, _ := gtk.ListBoxNew()
swRulesSession.Add(boxSession)
boxSystem, _ := gtk.ListBoxNew()
swRulesSystem.Add(boxSystem)
dbus, err := newDbusObject()
if err != nil {
failDialog(win, "Failed to connect to dbus system bus: %v", err)
}
rl := NewRuleList(dbus, win, box)
rlPermanent := NewRuleList(dbus, win, boxPermanent)
if _, err := dbus.isEnabled(); err != nil {
failDialog(win, "Unable is connect to firewall daemon. Is it running?")
}
rlPermanent.loadRules(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(RULE_MODE_SESSION)
rlSystem := NewRuleList(dbus, win, boxSystem)
if _, err := dbus.isEnabled(); err != nil {
failDialog(win, "Unable is connect to firewall daemon. Is it running?")
}
rl.loadRules()
rlSystem.loadRules(RULE_MODE_SYSTEM)
loadConfig(win, b, dbus)
app.AddWindow(win)
win.ShowAll()

@ -2,11 +2,12 @@ package main
import (
"fmt"
"github.com/gotk3/gotk3/gtk"
"net"
"strconv"
"strings"
"unicode"
"github.com/gotk3/gotk3/gtk"
)
const (
@ -24,7 +25,7 @@ type ruleEdit struct {
ok *gtk.Button
}
func newRuleEdit(rr *ruleRow) *ruleEdit {
func newRuleEdit(rr *ruleRow, saveasnew bool) *ruleEdit {
redit := &ruleEdit{row: rr}
b := newBuilder("RuleEdit")
b.getItems(
@ -40,6 +41,9 @@ func newRuleEdit(rr *ruleRow) *ruleEdit {
"on_port_changed": redit.onChanged,
"on_host_changed": redit.onChanged,
})
if saveasnew {
redit.ok.SetLabel("Save As New")
}
return redit
}
@ -124,19 +128,25 @@ func (re *ruleEdit) updateRow() {
re.row.update()
}
func (re *ruleEdit) run() {
func (re *ruleEdit) run(saveasnew bool) {
re.dialog.SetTransientFor(re.row.rl.win)
if re.dialog.Run() == editDialogOk {
if saveasnew {
re.row.rule.Mode = RULE_MODE_PERMANENT
}
re.updateRow()
re.row.rl.dbus.updateRule(re.row.rule)
if saveasnew {
re.row.widget.Hide()
}
}
re.dialog.Destroy()
}
func (rr *ruleRow) runEditor() {
redit := newRuleEdit(rr)
func (rr *ruleRow) runEditor(saveasnew bool) {
redit := newRuleEdit(rr, saveasnew)
redit.updateDialogFields()
redit.run()
redit.run(saveasnew)
}
func (re *ruleEdit) onPortInsertText(entry *gtk.Entry, text string) {

@ -22,27 +22,34 @@ type ruleRow struct {
app_label *gtk.Label
verb_label *gtk.Label
target_label *gtk.Label
edit_button *gtk.Button
save_button *gtk.Button
delete_button *gtk.Button
}
func NewRuleList(dbus *dbusObject, win *gtk.Window, list *gtk.ListBox) *ruleList {
rl := &ruleList{dbus: dbus, win: win, list: list}
rl.list.SetSelectionMode(gtk.SELECTION_NONE)
rl.col1, _ = gtk.SizeGroupNew(gtk.SIZE_GROUP_HORIZONTAL)
rl.col2, _ = gtk.SizeGroupNew(gtk.SIZE_GROUP_HORIZONTAL)
rl.col3, _ = gtk.SizeGroupNew(gtk.SIZE_GROUP_HORIZONTAL)
return rl
}
func (rl *ruleList) loadRules() error {
func (rl *ruleList) loadRules(mode uint16) error {
rules, err := rl.dbus.listRules()
if err != nil {
return err
}
rl.addRules(rules)
rl.addRules(rules, mode)
return nil
}
func (rl *ruleList) addRules(rules []dbusRule) {
func (rl *ruleList) addRules(rules []dbusRule, mode uint16) {
for i := 0; i < len(rules); i++ {
if rules[i].Mode != mode {
continue
}
row := createWidget(&rules[i])
row.rl = rl
rl.col1.AddWidget(row.app_label)
@ -65,9 +72,26 @@ func createWidget(rule *dbusRule) *ruleRow {
"app_label", &row.app_label,
"verb_label", &row.verb_label,
"target_label", &row.target_label,
"edit_button", &row.edit_button,
"save_button", &row.save_button,
"delete_button", &row.delete_button,
)
switch rule.Mode {
case RULE_MODE_SYSTEM:
row.edit_button.SetVisible(false)
row.edit_button.SetNoShowAll(true)
row.delete_button.SetSensitive(false)
row.delete_button.SetTooltipText("Cannot delete system rules")
break
case RULE_MODE_SESSION:
row.save_button.SetSensitive(true)
row.save_button.SetNoShowAll(false)
break
}
builder.ConnectSignals(map[string]interface{}{
"on_edit_rule": row.onEdit,
"on_save_rule": row.onSaveAsNew,
"on_delete_rule": row.onDelete,
})
row.widget, _ = gtk.ListBoxRowNew()
@ -104,14 +128,18 @@ func getTargetText(rule *dbusRule) string {
return fmt.Sprintf("Connections to All hosts on port %s", items[1])
}
if items[1] == "*" {
return fmt.Sprintf("All connections to host %s")
return fmt.Sprintf("All connections to host %s", items[0])
}
return fmt.Sprintf("Connections to %s on port %s", items[0], items[1])
}
func (rr *ruleRow) onSaveAsNew() {
rr.runEditor(true)
}
func (rr *ruleRow) onEdit() {
rr.runEditor()
rr.runEditor(false)
}
func (rr *ruleRow) onDelete() {

@ -73,7 +73,15 @@ const OptionListItem = new Lang.Class({
},
setText: function(text) {
if (text) {
this._label.text = text;
this._label.show();
this.actor.show();
} else {
this._label.text = "";
this._label.hide();
this.actor.hide();
}
},
setSelected: function(isSelected) {
@ -155,6 +163,20 @@ const OptionList = new Lang.Class({
log("unexpected scope value "+ this.buttonGroup._selected);
return RuleScope.APPLY_SESSION;
}
},
scopeToIdx: function(scope) {
switch (scope) {
case RuleScope.APPLY_ONCE:
return 2;
case RuleScope.APPLY_SESSION:
return 1;
case RuleScope.APPLY_FOREVER:
return 0;
default:
log("unexpected scope value "+ scope);
return 1;
}
}
});
@ -379,13 +401,15 @@ const PromptDialog = new Lang.Class({
box.add_child(this.optionList.actor);
this.optionList.addOptions([
"Only PORT AND ADDRESS",
"Only ADDRESS",
"Only PORT",
"Any Connection"]);
this._initialKeyFocusDestroyId = 1;
this.setButtons([
{ label: "Allow", action: Lang.bind(this, this.onAllow) },
{ label: "Deny", action: Lang.bind(this, this.onDeny) }]);
{ label: "Deny", action: Lang.bind(this, this.onDeny) }
]);
},
onAllow: function() {
@ -417,20 +441,27 @@ const PromptDialog = new Lang.Class({
case 0:
return this._address + ":" + this._port;
case 1:
return this._address + ":*";
case 2:
return "*:" + this._port;
case 3:
return "*:*";
}
},
update: function(application, icon, path, address, port, ip, user, pid) {
update: function(application, icon, path, address, port, ip, user, pid, proto, expanded, expert, action) {
this._address = address;
this._port = port;
let port_str = "TCP Port "+ port;
let port_str = (proto+"").toUpperCase() + " Port "+ port;
this.header.setTitle(application);
this.header.setMessage("Wants to connect to "+ address + " on " + port_str);
if (expanded) {
this.details.isOpen = false;
this.details.activate()
}
if(icon) {
this.header.setIcon(icon);
} else {
@ -438,6 +469,15 @@ const PromptDialog = new Lang.Class({
}
this.optionList.setOptionText(0, "Only "+ address + " on "+ port_str);
if (expert) {
this.optionList.setOptionText(1, "Only "+ address + " on any port");
this.optionList.setOptionText(2, "Only "+ port_str);
} else {
this.optionList.setOptionText(1, false);
this.optionList.setOptionText(2, false);
}
this.optionList.buttonGroup._setChecked(this.optionList.scopeToIdx(action))
this.info.setDetails(ip, path, pid, user);
},
});

@ -52,6 +52,9 @@ const FirewallPromptInterface = '<node> \
<arg type="s" direction="in" name="ip" /> \
<arg type="s" direction="in" name="user" /> \
<arg type="i" direction="in" name="pid" /> \
<arg type="b" direction="in" name="expanded" /> \
<arg type="b" direction="in" name="expert" /> \
<arg type="i" direction="in" name="action" /> \
<arg type="i" direction="out" name="scope" /> \
<arg type="s" direction="out" name="rule" /> \
</method> \
@ -83,13 +86,12 @@ const FirewallPromptHandler = new Lang.Class({
},
RequestPromptAsync: function(params, invocation) {
let [app, icon, path, address, port, ip, user, pid] = params;
let [app, icon, path, address, port, ip, user, pid, expanded, expert, action] = params;
this._closeDialog();
this._dialog = new Dialog.PromptDialog(invocation);
this._invocation = invocation;
this._dialog.update(app, icon, path, address, port, ip, user, pid);
this._dialog.update(app, icon, path, address, port, ip, user, pid, "TCP", expanded, expert, action);
this._dialog.open();
},
CloseAsync: function(params, invocation) {
@ -99,7 +101,7 @@ const FirewallPromptHandler = new Lang.Class({
TestPrompt: function(params, invocation) {
this._closeDialog();
this._dialog = new Dialog.PromptDialog(nil);
this._dialog.update("Firefox", "firefox", "/usr/bin/firefox", "242.12.111.18", "443", "linux", "2342");
this._dialog.update("Firefox", "firefox", "/usr/bin/firefox-esr", "242.12.111.18", "443", "linux", "2342", "TCP", true, true);
this._dialog.open();
}
});

@ -9,9 +9,12 @@ import (
const iptablesRule = "OUTPUT -t mangle -m conntrack --ctstate NEW -j NFQUEUE --queue-num 0 --queue-bypass"
const dnsRule = "INPUT --protocol udp --sport 53 -j NFQUEUE --queue-num 0 --queue-bypass"
//const logRule = "OUTPUT --protocol tcp -m mark --mark 1 -j LOG"
const blockRule = "OUTPUT --protocol tcp -m mark --mark 1 -j REJECT"
func setupIPTables() {
// addIPTRules(iptablesRule, dnsRule, logRule, blockRule)
addIPTRules(iptablesRule, dnsRule, blockRule)
}

@ -13,9 +13,10 @@ import (
"time"
"unsafe"
"github.com/op/go-logging"
"github.com/subgraph/fw-daemon/nfqueue"
"github.com/subgraph/go-procsnitch"
"github.com/op/go-logging"
)
var log = logging.MustGetLogger("sgfw")
@ -35,7 +36,7 @@ func isTerminal(fd int) bool {
return err == 0
}
func setupLoggerBackend() logging.LeveledBackend {
func setupLoggerBackend(lvl logging.Level) logging.LeveledBackend {
format := logFormat
if isTerminal(int(os.Stderr.Fd())) {
format = ttyFormat
@ -43,12 +44,10 @@ func setupLoggerBackend() logging.LeveledBackend {
backend := logging.NewLogBackend(os.Stderr, "", 0)
formatter := logging.NewBackendFormatter(backend, format)
leveler := logging.AddModuleLevel(formatter)
leveler.SetLevel(logging.NOTICE, "sgfw")
leveler.SetLevel(lvl, "sgfw")
return leveler
}
var logRedact bool
type Firewall struct {
dbus *dbusServer
dns *dnsCache
@ -187,8 +186,8 @@ func getSocksChainConfig(config *SocksJsonConfig) *socksChainConfig {
}
func main() {
logBackend := setupLoggerBackend()
readConfig()
logBackend := setupLoggerBackend(FirewallConfig.LoggingLevel)
log.SetBackend(logBackend)
procsnitch.SetLogger(log)

@ -2,6 +2,7 @@ package main
import (
"fmt"
"strings"
"sync"
"github.com/subgraph/fw-daemon/nfqueue"
@ -9,6 +10,12 @@ import (
"net"
)
var _interpreters = []string{
"python",
"ruby",
"bash",
}
type pendingConnection interface {
policy() *Policy
procInfo() *procsnitch.Info
@ -98,7 +105,7 @@ func (p *Policy) processPacket(pkt *nfqueue.Packet, pinfo *procsnitch.Info) {
p.lock.Lock()
defer p.lock.Unlock()
name := p.fw.dns.Lookup(pkt.Dst)
if !logRedact {
if !FirewallConfig.LogRedact {
log.Infof("Lookup(%s): %s", pkt.Dst.String(), name)
}
result := p.rules.filterPacket(pkt, pinfo, name)
@ -165,6 +172,7 @@ func (p *Policy) processNewRule(r *Rule, scope int32) bool {
func (p *Policy) parseRule(s string, add bool) (*Rule, error) {
r := new(Rule)
r.mode = RULE_MODE_PERMANENT
r.policy = p
if !r.parse(s) {
return nil, parseError(s)
@ -195,7 +203,7 @@ func (p *Policy) filterPending(rule *Rule) {
remaining := []pendingConnection{}
for _, pc := range p.pendingQueue {
if rule.match(pc.dst(), pc.dstPort(), pc.hostname()) {
log.Infof("Also applying %s to %s", rule.getString(logRedact), pc.print())
log.Infof("Also applying %s to %s", rule.getString(FirewallConfig.LogRedact), pc.print())
if rule.rtype == RULE_ALLOW {
pc.accept()
} else {
@ -212,7 +220,7 @@ func (p *Policy) filterPending(rule *Rule) {
func (p *Policy) hasPersistentRules() bool {
for _, r := range p.rules {
if !r.sessionOnly {
if r.mode != RULE_MODE_SESSION {
return true
}
}
@ -231,7 +239,7 @@ func printPacket(pkt *nfqueue.Packet, hostname string) string {
}
}()
if logRedact {
if FirewallConfig.LogRedact {
hostname = "[redacted]"
}
name := hostname
@ -253,12 +261,23 @@ func (fw *Firewall) filterPacket(pkt *nfqueue.Packet) {
pkt.Accept()
return
}
log.Debugf("filterPacket [%s] %s", pinfo.ExePath, printPacket(pkt, fw.dns.Lookup(pkt.Dst)))
ppath := pinfo.ExePath
cf := strings.Fields(pinfo.CmdLine)
if len(cf) > 1 && strings.HasPrefix(cf[1], "/") {
for _, intp := range _interpreters {
if strings.Contains(pinfo.ExePath, intp) {
ppath = cf[1]
break
}
}
}
//log.Debugf("pinfo: [%d] %s > %s", pinfo.ParentPid, pinfo.CmdLine, pinfo.ParentExePath)
log.Debugf("filterPacket [%s] %s", ppath, printPacket(pkt, fw.dns.Lookup(pkt.Dst)))
if basicAllowPacket(pkt) {
pkt.Accept()
return
}
policy := fw.PolicyForPath(pinfo.ExePath)
policy := fw.PolicyForPath(ppath)
policy.processPacket(pkt, pinfo)
}

@ -5,6 +5,7 @@ import (
"github.com/godbus/dbus"
"os/user"
"strconv"
"strings"
"sync"
)
@ -65,14 +66,28 @@ func (p *prompter) processNextPacket() bool {
func printScope(scope int32) string {
switch scope {
case APPLY_FOREVER:
return "APPLY_FOREVER"
case APPLY_SESSION:
return "APPLY_SESSION"
return "SESSION"
case APPLY_ONCE:
return "APPLY_ONCE"
return "ONCE"
case APPLY_FOREVER:
return "FOREVER"
default:
return "SESSION"
}
}
func valueScope(scope string) int32 {
scope = strings.ToUpper(scope)
switch scope {
case "SESSION":
return APPLY_SESSION
case "ONCE":
return APPLY_ONCE
case "FOREVER":
return APPLY_FOREVER
default:
return fmt.Sprintf("Unknown (%d)", scope)
return APPLY_SESSION
}
}
@ -94,7 +109,10 @@ func (p *prompter) processConnection(pc pendingConnection) {
int32(pc.dstPort()),
pc.dst().String(),
uidToUser(pc.procInfo().UID),
int32(pc.procInfo().Pid))
int32(pc.procInfo().Pid),
FirewallConfig.PromptExpanded,
FirewallConfig.PromptExpert,
FirewallConfig.DefaultActionId)
err := call.Store(&scope, &rule)
if err != nil {
log.Warningf("Error sending dbus RequestPrompt message: %v", err)
@ -111,7 +129,7 @@ func (p *prompter) processConnection(pc pendingConnection) {
return
}
if scope == APPLY_SESSION {
r.sessionOnly = true
r.mode = RULE_MODE_SESSION
}
if !policy.processNewRule(r, scope) {
p.lock.Lock()

@ -23,10 +23,18 @@ const (
const matchAny = 0
const noAddress = uint32(0xffffffff)
type RuleMode uint16
const (
RULE_MODE_SESSION RuleMode = iota
RULE_MODE_PERMANENT
RULE_MODE_SYSTEM
)
type Rule struct {
id uint
policy *Policy
sessionOnly bool
mode RuleMode
rtype int
hostname string
addr uint32
@ -42,8 +50,12 @@ func (r *Rule) getString(redact bool) string {
if r.rtype == RULE_ALLOW {
rtype = "ALLOW"
}
rmode := ""
if r.mode == RULE_MODE_SYSTEM {
rmode = "|SYSTEM"
}
return fmt.Sprintf("%s|%s", rtype, r.AddrString(redact))
return fmt.Sprintf("%s|%s%s", rtype, r.AddrString(redact), rmode)
}
func (r *Rule) AddrString(redact bool) string {
@ -103,10 +115,10 @@ func (rl *RuleList) filter(dst net.IP, dstPort uint16, hostname string, pinfo *p
for _, r := range *rl {
if r.match(dst, dstPort, hostname) {
dstStr := dst.String()
if logRedact {
if FirewallConfig.LogRedact {
dstStr = "[redacted]"
}
log.Infof("%s (%s -> %s:%d)", r.getString(logRedact), pinfo.ExePath, dstStr, dstPort)
log.Infof("%s (%s -> %s:%d)", r.getString(FirewallConfig.LogRedact), pinfo.ExePath, dstStr, dstPort)
if r.rtype == RULE_DENY {
return FILTER_DENY
} else if r.rtype == RULE_ALLOW {
@ -124,9 +136,12 @@ func parseError(s string) error {
func (r *Rule) parse(s string) bool {
r.addr = noAddress
parts := strings.Split(s, "|")
if len(parts) != 2 {
if len(parts) < 2 {
return false
}
if len(parts) >= 3 && parts[2] == "SYSTEM" {
r.mode = RULE_MODE_SYSTEM
}
return r.parseVerb(parts[0]) && r.parseTarget(parts[1])
}
@ -231,7 +246,7 @@ func savePolicy(f *os.File, p *Policy) {
return
}
for _, r := range p.rules {
if !r.sessionOnly {
if r.mode != RULE_MODE_SESSION {
if !writeLine(f, r.String()) {
return
}

Loading…
Cancel
Save