Lots of assorted cleanup.

Much better code for detecting if a rule being edited is valid.
fw-prompt window now forces itself to be on top if a rule is pending approval.
Matching by user/uid and group/gid options now visible but not functional.
shw_dev
shw 7 years ago
parent aba795fa97
commit 3319802a80

@ -1,3 +1,33 @@
To get this to work, first edit /usr/share/gnome-shell/modes/subgraph.json To get this to work, first edit /usr/share/gnome-shell/modes/subgraph.json
Remove the entry for "firewall@subgraph.com", hit CTRL+F2 and then issue the reload "r" command. Remove the entry for "firewall@subgraph.com", hit CTRL+F2 and then issue the reload "r" command.
Reset these changes to revert back to the old gnome-shell prompt. Reset these changes to revert back to the old gnome-shell prompt.
Changes for getting this working in ubuntu:
(this is the crux of, but not all of the steps necessary to get this running)
apt-get install libnetfilter-queue-dev
#apt-get install all dependencies: gtk3/cairo/pango/glib etc.
mkdir /etc/sgfw
cat >> /etc/sgfw/sgfw.conf << EOF
log_level="NOTICE"
log_redact=false
prompt_expanded=true
prompt_expert=true
default_action="SESSION"
EOF
cp ./src/github.com/subgraph/fw-daemon/sources/etc/dbus-1/system.d/com.subgraph.Firewall.conf /etc/dbus-1/system.d/com.subgraph.Firewall.conf
iptables -t mangle -I PREROUTING 1 -m conntrack --ctstate NEW --proto tcp -j NFQUEUE --queue-num 0 --queue-bypass; iptables -I FORWARD 1 -m mark --mark 0x1 -j REJECT --reject-with icmp-host-prohibited
go install github.com/subgraph/fw-daemon
go install github.com/subgraph/fw-daemon/fw-settings
go install github.com/subgraph/fw-daemon/fw-prompt
GODEBUG=cgocheck=0 ./fw-daemon
Then launch ./fw-prompt

@ -6,6 +6,7 @@ import (
"github.com/gotk3/gotk3/glib" "github.com/gotk3/gotk3/glib"
"log" "log"
"fmt" "fmt"
"strings"
"strconv" "strconv"
"os" "os"
"io/ioutil" "io/ioutil"
@ -42,7 +43,10 @@ type ruleColumns struct {
Port int Port int
UID int UID int
GID int GID int
Uname string
Gname string
Origin string Origin string
Scope int
} }
@ -53,14 +57,17 @@ var globalLS *gtk.ListStore
var globalTV *gtk.TreeView var globalTV *gtk.TreeView
var decisionWaiters []*decisionWaiter var decisionWaiters []*decisionWaiter
var editApp, editTarget, editPort *gtk.Entry var editApp, editTarget, editPort, editUser, editGroup *gtk.Entry
var comboProto *gtk.ComboBoxText var comboProto *gtk.ComboBoxText
var radioOnce, radioProcess, radioParent, radioSession, radioPermanent *gtk.RadioButton
var btnApprove, btnDeny, btnIgnore *gtk.Button
var chkUser, chkGroup *gtk.CheckButton
func dumpDecisions() { func dumpDecisions() {
fmt.Println("Total of decisions pending: ", len(decisionWaiters)) fmt.Println("XXX Total of decisions pending: ", len(decisionWaiters))
for i := 0; i < len(decisionWaiters); i++ { for i := 0; i < len(decisionWaiters); i++ {
fmt.Printf("%d ready = %v, rule = %v\n", i+1, decisionWaiters[i].Ready, decisionWaiters[i].Rule) fmt.Printf("XXX %d ready = %v, rule = %v\n", i+1, decisionWaiters[i].Ready, decisionWaiters[i].Rule)
} }
} }
@ -174,7 +181,6 @@ func loadPreferences() bool {
} }
prefPath := usr.HomeDir + "/.fwprompt.json" prefPath := usr.HomeDir + "/.fwprompt.json"
fmt.Println("xxxxxxxxxxxxxxxxxxxxxx preferences path = ", prefPath)
jfile, err := ioutil.ReadFile(prefPath) jfile, err := ioutil.ReadFile(prefPath)
@ -214,6 +220,17 @@ func get_vbox() *gtk.Box {
return vbox return vbox
} }
func get_checkbox(text string, activated bool) *gtk.CheckButton {
cb, err := gtk.CheckButtonNewWithLabel(text)
if err != nil {
log.Fatal("Unable to create new checkbox:", err)
}
cb.SetActive(activated)
return cb
}
func get_combobox() *gtk.ComboBoxText { func get_combobox() *gtk.ComboBoxText {
combo, err := gtk.ComboBoxTextNew() combo, err := gtk.ComboBoxTextNew()
@ -336,6 +353,7 @@ func addRequest(listStore *gtk.ListStore, path, proto string, pid int, ipaddr, h
decision := addDecision() decision := addDecision()
dumpDecisions() dumpDecisions()
toggleHover()
return decision return decision
} }
@ -359,7 +377,7 @@ func setup_settings() {
} }
scrollbox.Add(box) scrollbox.Add(box)
scrollbox.SetSizeRequest(600, 800) scrollbox.SetSizeRequest(600, 400)
tv, err := gtk.TreeViewNew() tv, err := gtk.TreeViewNew()
@ -438,10 +456,74 @@ func makeDecision(idx int, rule string, scope int) {
decisionWaiters[idx].Cond.L.Unlock() decisionWaiters[idx].Cond.L.Unlock()
} }
func toggleHover() {
mainWin.SetKeepAbove(len(decisionWaiters) > 0)
}
func toggleValidRuleState() {
ok := true
if numSelections() <= 0 {
ok = false
}
str, err := editApp.GetText()
if err != nil || strings.Trim(str, "\t ") == "" {
ok = false
}
str, err = editTarget.GetText()
if err != nil || strings.Trim(str, "\t ") == "" {
ok = false
}
str, err = editPort.GetText()
if err != nil || strings.Trim(str, "\t ") == "" {
ok = false
} else {
pval, err := strconv.Atoi(str)
if err != nil || pval < 0 || pval > 65535 {
ok = false
}
}
if chkUser.GetActive() {
str, err = editUser.GetText()
if err != nil || strings.Trim(str, "\t ") == "" {
ok = false
}
}
if chkGroup.GetActive() {
str, err = editGroup.GetText()
if err != nil || strings.Trim(str, "\t ") == "" {
ok = false
}
}
btnApprove.SetSensitive(ok)
btnDeny.SetSensitive(ok)
btnIgnore.SetSensitive(ok)
}
func createCurrentRule() (ruleColumns, error) { func createCurrentRule() (ruleColumns, error) {
rule := ruleColumns{} rule := ruleColumns{Scope: int(sgfw.APPLY_ONCE)}
var err error = nil var err error = nil
if radioProcess.GetActive() {
return rule, errors.New("Process scope is unsupported at the moment")
} else if radioParent.GetActive() {
return rule, errors.New("Parent process scope is unsupported at the moment")
} else if radioSession.GetActive() {
rule.Scope = int(sgfw.APPLY_SESSION)
} else if radioPermanent.GetActive() {
rule.Scope = int(sgfw.APPLY_FOREVER)
} else {
rule.Scope = int(sgfw.APPLY_ONCE)
}
rule.Path, err = editApp.GetText() rule.Path, err = editApp.GetText()
if err != nil { if err != nil {
return rule, err return rule, err
@ -465,6 +547,7 @@ func createCurrentRule() (ruleColumns, error) {
rule.Proto = comboProto.GetActiveID() rule.Proto = comboProto.GetActiveID()
rule.UID, rule.GID = 0, 0 rule.UID, rule.GID = 0, 0
rule.Uname, rule.Gname = "", ""
/* Pid int /* Pid int
Origin string */ Origin string */
@ -475,12 +558,16 @@ func clearEditor() {
editApp.SetText("") editApp.SetText("")
editTarget.SetText("") editTarget.SetText("")
editPort.SetText("") editPort.SetText("")
editUser.SetText("")
editGroup.SetText("")
comboProto.SetActive(0) comboProto.SetActive(0)
/* ronce.SetActive(true) radioOnce.SetActive(true)
rprocess.SetActive(false) radioProcess.SetActive(false)
rparent.SetActive(false) radioParent.SetActive(false)
rsession.SetActive(false) radioSession.SetActive(false)
rpermanent.SetActive(false) */ radioPermanent.SetActive(false)
chkUser.SetActive(false)
chkGroup.SetActive(false)
} }
func removeSelectedRule(idx int) error { func removeSelectedRule(idx int) error {
@ -503,9 +590,20 @@ func removeSelectedRule(idx int) error {
} }
decisionWaiters = append(decisionWaiters[:idx], decisionWaiters[idx+1:]...) decisionWaiters = append(decisionWaiters[:idx], decisionWaiters[idx+1:]...)
toggleHover()
return nil return nil
} }
func numSelections() int {
sel, err := globalTV.GetSelection()
if err != nil {
return -1
}
rows := sel.GetSelectedRows(globalLS)
return int(rows.Length())
}
func getSelectedRule() (ruleColumns, int, error) { func getSelectedRule() (ruleColumns, int, error) {
rule := ruleColumns{} rule := ruleColumns{}
@ -568,7 +666,15 @@ func getSelectedRule() (ruleColumns, int, error) {
return rule, -1, err return rule, -1, err
} }
rule.UID, rule.GID = 0, 0 rule.UID, err = lsGetInt(globalLS, iter, 7)
if err != nil {
return rule, -1, err
}
rule.GID, err = lsGetInt(globalLS, iter, 8)
if err != nil {
return rule, -1, err
}
rule.Origin, err = lsGetStr(globalLS, iter, 9) rule.Origin, err = lsGetStr(globalLS, iter, 9)
if err != nil { if err != nil {
@ -619,7 +725,7 @@ func main() {
log.Fatal("Unable to create new notebook:", err) log.Fatal("Unable to create new notebook:", err)
} }
loglevel := "Pending Approval" loglevel := "Firewall Traffic Pending Approval"
nbLabel, err := gtk.LabelNew(loglevel) nbLabel, err := gtk.LabelNew(loglevel)
@ -652,41 +758,48 @@ func main() {
tv.SetSizeRequest(300, 300) tv.SetSizeRequest(300, 300)
tv.SetHeadersClickable(true) tv.SetHeadersClickable(true)
ab, err := gtk.ButtonNewWithLabel("Approve") btnApprove, err = gtk.ButtonNewWithLabel("Approve")
if err != nil { if err != nil {
log.Fatal("Unable to create button:", err) log.Fatal("Unable to create button:", err)
} }
db, err := gtk.ButtonNewWithLabel("Deny") btnDeny, err = gtk.ButtonNewWithLabel("Deny")
if err != nil { if err != nil {
log.Fatal("Unable to create button:", err) log.Fatal("Unable to create button:", err)
} }
ib, err := gtk.ButtonNewWithLabel("Ignore") btnIgnore, err = gtk.ButtonNewWithLabel("Ignore")
if err != nil { if err != nil {
log.Fatal("Unable to create button:", err) log.Fatal("Unable to create button:", err)
} }
btnApprove.SetSensitive(false)
btnDeny.SetSensitive(false)
btnIgnore.SetSensitive(false)
bb := get_hbox() bb := get_hbox()
bb.PackStart(ab, false, false, 5) bb.PackStart(btnApprove, false, false, 5)
bb.PackStart(db, false, false, 5) bb.PackStart(btnDeny, false, false, 5)
bb.PackStart(ib, false, false, 5) bb.PackStart(btnIgnore, false, false, 5)
editbox := get_vbox() editbox := get_vbox()
hbox := get_hbox() hbox := get_hbox()
lbl := get_label("Application path:") lbl := get_label("Application path:")
editApp = get_entry("") editApp = get_entry("")
editApp.Connect("changed", toggleValidRuleState)
hbox.PackStart(lbl, false, false, 10) hbox.PackStart(lbl, false, false, 10)
hbox.PackStart(editApp, false, false, 5) hbox.PackStart(editApp, true, true, 50)
editbox.PackStart(hbox, false, false, 5) editbox.PackStart(hbox, false, false, 5)
hbox = get_hbox() hbox = get_hbox()
lbl = get_label("Target host/IP:") lbl = get_label("Target host/IP:")
editTarget = get_entry("") editTarget = get_entry("")
editTarget.Connect("changed", toggleValidRuleState)
hbox.PackStart(lbl, false, false, 10) hbox.PackStart(lbl, false, false, 10)
hbox.PackStart(editTarget, false, false, 5) hbox.PackStart(editTarget, false, false, 5)
lbl = get_label("Port:") lbl = get_label("Port:")
editPort = get_entry("") editPort = get_entry("")
editPort.Connect("changed", toggleValidRuleState)
hbox.PackStart(lbl, false, false, 5) hbox.PackStart(lbl, false, false, 5)
hbox.PackStart(editPort, false, false, 5) hbox.PackStart(editPort, false, false, 5)
lbl = get_label("Protocol:") lbl = get_label("Protocol:")
@ -697,17 +810,34 @@ func main() {
hbox = get_hbox() hbox = get_hbox()
lbl = get_label("Apply rule:") lbl = get_label("Apply rule:")
ronce := get_radiobutton(nil, "Once", true) radioOnce = get_radiobutton(nil, "Once", true)
rprocess := get_radiobutton(ronce, "This Process", false) radioProcess = get_radiobutton(radioOnce, "This Process", false)
rparent := get_radiobutton(ronce, "Parent Process", false) radioParent = get_radiobutton(radioOnce, "Parent Process", false)
rsession := get_radiobutton(ronce, "Session", false) radioSession = get_radiobutton(radioOnce, "Session", false)
rpermanent := get_radiobutton(ronce, "Permanent", false) radioPermanent = get_radiobutton(radioOnce, "Permanent", false)
radioProcess.SetSensitive(false)
radioParent.SetSensitive(false)
hbox.PackStart(lbl, false, false, 10) hbox.PackStart(lbl, false, false, 10)
hbox.PackStart(ronce, false, false, 5) hbox.PackStart(radioOnce, false, false, 5)
hbox.PackStart(rprocess, false, false, 5) hbox.PackStart(radioProcess, false, false, 5)
hbox.PackStart(rparent, false, false, 5) hbox.PackStart(radioParent, false, false, 5)
hbox.PackStart(rsession, false, false, 5) hbox.PackStart(radioSession, false, false, 5)
hbox.PackStart(rpermanent, false, false, 5) hbox.PackStart(radioPermanent, false, false, 5)
editbox.PackStart(hbox, false, false, 5)
hbox = get_hbox()
chkUser = get_checkbox("Apply to UID/username", false)
chkUser.Connect("toggled", toggleValidRuleState)
editUser = get_entry("")
editUser.Connect("changed", toggleValidRuleState)
hbox.PackStart(chkUser, false, false, 10)
hbox.PackStart(editUser, false, false, 10)
chkGroup = get_checkbox("Apply to GID/group:", false)
chkGroup.Connect("toggled", toggleValidRuleState)
editGroup = get_entry("")
editGroup.Connect("changed", toggleValidRuleState)
hbox.PackStart(chkGroup, false, false, 10)
hbox.PackStart(editGroup, false, false, 10)
editbox.PackStart(hbox, false, false, 5) editbox.PackStart(hbox, false, false, 5)
box.PackStart(bb, false, false, 5) box.PackStart(bb, false, false, 5)
@ -731,7 +861,7 @@ func main() {
tv.SetModel(listStore) tv.SetModel(listStore)
ab.Connect("clicked", func() { btnApprove.Connect("clicked", func() {
rule, idx, err := getSelectedRule() rule, idx, err := getSelectedRule()
if err != nil { if err != nil {
promptError("Error occurred processing request: "+err.Error()) promptError("Error occurred processing request: "+err.Error())
@ -747,7 +877,7 @@ func main() {
fmt.Println("rule = ", rule) fmt.Println("rule = ", rule)
rulestr := "ALLOW|" + rule.Proto + ":" + rule.Target + ":" + strconv.Itoa(rule.Port) rulestr := "ALLOW|" + rule.Proto + ":" + rule.Target + ":" + strconv.Itoa(rule.Port)
fmt.Println("RULESTR = ", rulestr) fmt.Println("RULESTR = ", rulestr)
makeDecision(idx, rulestr, int(sgfw.APPLY_ONCE)) makeDecision(idx, rulestr, int(rule.Scope))
fmt.Println("Decision made.") fmt.Println("Decision made.")
err = removeSelectedRule(idx) err = removeSelectedRule(idx)
if err == nil { if err == nil {
@ -757,7 +887,7 @@ func main() {
} }
}) })
db.Connect("clicked", func() { btnDeny.Connect("clicked", func() {
rule, idx, err := getSelectedRule() rule, idx, err := getSelectedRule()
if err != nil { if err != nil {
promptError("Error occurred processing request: "+err.Error()) promptError("Error occurred processing request: "+err.Error())
@ -773,7 +903,7 @@ func main() {
fmt.Println("rule = ", rule) fmt.Println("rule = ", rule)
rulestr := "DENY|" + rule.Proto + ":" + rule.Target + ":" + strconv.Itoa(rule.Port) rulestr := "DENY|" + rule.Proto + ":" + rule.Target + ":" + strconv.Itoa(rule.Port)
fmt.Println("RULESTR = ", rulestr) fmt.Println("RULESTR = ", rulestr)
makeDecision(idx, rulestr, int(sgfw.APPLY_ONCE)) makeDecision(idx, rulestr, int(rule.Scope))
fmt.Println("Decision made.") fmt.Println("Decision made.")
err = removeSelectedRule(idx) err = removeSelectedRule(idx)
if err == nil { if err == nil {
@ -783,21 +913,24 @@ func main() {
} }
}) })
ib.Connect("clicked", func() { btnIgnore.Connect("clicked", func() {
promptError("Ignoring firewall request.") _, idx, err := getSelectedRule()
return if err != nil {
/* promptError("Ignoring firewall request.") promptError("Error occurred processing request: "+err.Error())
fmt.Println("LOCKING") return
decisionWaiters[0].Cond.L.Lock() }
decisionWaiters[0].Ready = true
decisionWaiters[0].Rule = "bloop done" makeDecision(idx, "", 0)
fmt.Println("SIGNALING") fmt.Println("Decision made.")
decisionWaiters[0].Cond.Signal() err = removeSelectedRule(idx)
fmt.Println("SIGNALED") if err == nil {
fmt.Println("UNLOCKING") clearEditor()
decisionWaiters[0].Cond.L.Unlock() */ } else {
promptError("Error setting new rule: "+err.Error())
}
}) })
// tv.SetActivateOnSingleClick(true)
tv.Connect("row-activated", func() { tv.Connect("row-activated", func() {
seldata, _, err := getSelectedRule() seldata, _, err := getSelectedRule()
if err != nil { if err != nil {
@ -814,28 +947,45 @@ func main() {
} }
editPort.SetText(strconv.Itoa(seldata.Port)) editPort.SetText(strconv.Itoa(seldata.Port))
ronce.SetActive(true) radioOnce.SetActive(true)
rprocess.SetActive(false) radioProcess.SetActive(false)
rparent.SetActive(false) radioParent.SetActive(false)
rsession.SetActive(false) radioSession.SetActive(false)
rpermanent.SetActive(false) radioPermanent.SetActive(false)
comboProto.SetActiveID(seldata.Proto) comboProto.SetActiveID(seldata.Proto)
if seldata.Uname != "" {
editUser.SetText(seldata.Uname)
} else if seldata.UID != -1 {
editUser.SetText(strconv.Itoa(seldata.UID))
} else {
editUser.SetText("")
}
if seldata.Gname != "" {
editGroup.SetText(seldata.Gname)
} else if seldata.GID != -1 {
editGroup.SetText(strconv.Itoa(seldata.GID))
} else {
editGroup.SetText("")
}
chkUser.SetActive(false)
chkGroup.SetActive(false)
return return
// promptInfo(sval)
}) })
scrollbox.SetSizeRequest(600, 800) scrollbox.SetSizeRequest(600, 400)
Notebook.AppendPage(scrollbox, nbLabel) Notebook.AppendPage(scrollbox, nbLabel)
setup_settings() // setup_settings()
mainWin.Add(Notebook) mainWin.Add(Notebook)
if userPrefs.Winheight > 0 && userPrefs.Winwidth > 0 { if userPrefs.Winheight > 0 && userPrefs.Winwidth > 0 {
fmt.Printf("height was %d, width was %d\n", userPrefs.Winheight, userPrefs.Winwidth) // fmt.Printf("height was %d, width was %d\n", userPrefs.Winheight, userPrefs.Winwidth)
mainWin.Resize(int(userPrefs.Winwidth), int(userPrefs.Winheight)) mainWin.Resize(int(userPrefs.Winwidth), int(userPrefs.Winheight))
} else { } else {
mainWin.SetDefaultSize(800, 600) mainWin.SetDefaultSize(850, 450)
} }
if userPrefs.Wintop > 0 && userPrefs.Winleft > 0 { if userPrefs.Wintop > 0 && userPrefs.Winleft > 0 {
@ -843,6 +993,6 @@ func main() {
} }
mainWin.ShowAll() mainWin.ShowAll()
mainWin.SetKeepAbove(true) // mainWin.SetKeepAbove(true)
gtk.Main() gtk.Main()
} }

Loading…
Cancel
Save