You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
fw-daemon/fw-settings/prompt.go

902 lines
21 KiB

package main
import (
"errors"
"fmt"
"log"
spath "path"
"strings"
"strconv"
"sync"
"time"
"github.com/subgraph/fw-daemon/sgfw"
"github.com/gotk3/gotk3/gdk"
"github.com/gotk3/gotk3/glib"
"github.com/gotk3/gotk3/gtk"
)
type Prompt struct {
app *fwApp
tv *gtk.TreeView
ts *gtk.TreeStore
stack *gtk.Stack
pecols []*gtk.TreeViewColumn
pncol *gtk.TreeViewColumn
promptLock *sync.Mutex
recentLock *sync.Mutex
config *sgfw.FirewallConfigs
recentlyRemoved []string
}
const (
COL_NO_NREFS = iota
COL_NO_ICON_PIXBUF
COL_NO_GUID
COL_NO_PATH
COL_NO_SANDBOX
COL_NO_ICON
COL_NO_PROTO
COL_NO_PID
COL_NO_DSTIP
COL_NO_HOSTNAME
COL_NO_PORT
COL_NO_UID
COL_NO_GID
COL_NO_ORIGIN
COL_NO_TIMESTAMP
COL_NO_IS_SOCKS
COL_NO_OPTSTRING
COL_NO_ACTION
COL_NO_FILLER
COL_NO_LAST
)
type ruleColumns struct {
nrefs int
Path string
Sandbox string
GUID string
Icon string
Proto string
Pid int
Target string
Hostname string
Port int
UID int
GID int
Uname string
Gname string
Origin string
Timestamp string
IsSocks bool
ForceTLS bool
Scope int
}
func createPromptView(app *fwApp, sw *gtk.ScrolledWindow) (*Prompt, error) {
var err error
p := &Prompt{}
p.app = app
p.promptLock = &sync.Mutex{}
p.recentLock = &sync.Mutex{}
p.tv, err = gtk.TreeViewNew()
if err != nil {
return nil, err
}
p.tv.SetSizeRequest(300, 300)
p.tv.SetHeadersClickable(true)
p.tv.SetEnableSearch(false)
p.tv.AppendColumn(createColumnText("#", COL_NO_NREFS))
p.tv.AppendColumn(createColumnImg("", COL_NO_ICON_PIXBUF))
guidcol := createColumnText("GUID", COL_NO_GUID)
guidcol.SetVisible(false)
p.tv.AppendColumn(guidcol)
p.tv.AppendColumn(createColumnText("Path", COL_NO_PATH))
sbcol := createColumnText("Realm", COL_NO_SANDBOX)
//sbcol.SetVisible(true)
p.tv.AppendColumn(sbcol)
icol := createColumnText("Icon", COL_NO_ICON)
icol.SetVisible(false)
p.tv.AppendColumn(icol)
var pecol *gtk.TreeViewColumn
p.tv.AppendColumn(createColumnText("Protocol", COL_NO_PROTO))
pecol = createColumnText("PID", COL_NO_PID)
p.tv.AppendColumn(pecol)
p.pecols = append(p.pecols, pecol)
p.tv.AppendColumn(createColumnText("IP Address", COL_NO_DSTIP))
pecol = createColumnText("Hostname", COL_NO_HOSTNAME)
pecol.SetMinWidth(64)
p.tv.AppendColumn(pecol)
p.tv.AppendColumn(createColumnText("Port", COL_NO_PORT))
pecol = createColumnText("UID", COL_NO_UID)
p.tv.AppendColumn(pecol)
p.pecols = append(p.pecols, pecol)
pecol = createColumnText("GID", COL_NO_GID)
p.tv.AppendColumn(pecol)
p.pecols = append(p.pecols, pecol)
pecol = createColumnText("Origin", COL_NO_ORIGIN)
p.tv.AppendColumn(pecol)
p.pecols = append(p.pecols, pecol)
pecol = createColumnText("Timestamp", COL_NO_TIMESTAMP)
p.tv.AppendColumn(pecol)
p.pecols = append(p.pecols, pecol)
scol := createColumnText("Is SOCKS", COL_NO_IS_SOCKS)
scol.SetVisible(false)
p.tv.AppendColumn(scol)
pecol = createColumnText("Details", COL_NO_OPTSTRING)
p.tv.AppendColumn(pecol)
p.pecols = append(p.pecols, pecol)
acol := createColumnText("Scope", COL_NO_ACTION)
acol.SetVisible(false)
p.tv.AppendColumn(acol)
pncol := createColumnImg("", COL_NO_FILLER)
pncol.SetVisible(false)
pncol.SetSortIndicator(false)
p.tv.AppendColumn(pncol)
p.pncol = pncol
p.togglePECols()
p.ts = createTreeStore(true)
p.tv.SetModel(p.ts)
p.tv.Connect("row-activated", func() {
p.promptLock.Lock()
seldata, _, _, err := p.getSelectedRule()
p.promptLock.Unlock()
if err != nil {
warnDialog(&p.app.win.Window, "Unexpected error reading selected rule: " + err.Error() + "\n" + fmt.Sprintf("%+v", seldata))
return
}
rl := &ruleList{app: p.app}
target := seldata.Hostname
if target == "" {
target = seldata.Target
}
rr := &ruleRow{ rl: rl, rule: &sgfw.DbusRule{
Path: seldata.Path,
Sandbox: seldata.Sandbox,
Pid: uint32(seldata.Pid),
UID: int32(seldata.UID),
GID: int32(seldata.GID),
Target: strings.Join([]string{target, strconv.Itoa(seldata.Port)}, ":"),
Proto: seldata.Proto,
Origin: seldata.Origin,
IsSocks: seldata.IsSocks,
}}
redit := newRuleAdd(rr, DIALOG_MODE_PROMPT)
redit.update()
redit.run(seldata.GUID, p.buttonAction)
return
})
p.app.appendConfigCallback(p.togglePECols)
sw.SetSizeRequest(600, 400)
p.createShortcuts()
sw.Add(p.tv)
return p, nil
}
func (p *Prompt) HasItems() bool {
return p.ts.IterNChildren(nil) > 0
}
func (p *Prompt) togglePECols() {
v := p.app.Config.PromptExpanded
for _, pc := range p.pecols {
pc.SetVisible(v)
}
p.pncol.SetVisible(!v)
}
func (p *Prompt) createShortcuts() {
// We register here since the shortcuts are bound in an ephemeral window
p.app.RegisterShortcutHelp("<Alt>a", "prompt", "Allow")
p.app.RegisterShortcutHelp("<Alt>d Escape", "prompt", "Deny")
p.app.RegisterShortcutHelp("<Alt>c", "prompt", "Cancel")
p.app.RegisterShortcutHelp("<Alt>h", "prompt", "Select the hostname/IP entry")
p.app.RegisterShortcutHelp("<Alt>p", "prompt", "Select the port entry")
p.app.RegisterShortcutHelp("<Alt>o", "prompt", "Select protocol")
p.app.RegisterShortcutHelp("<Alt>t", "prompt", "Toggle allow TLS only")
p.app.RegisterShortcutHelp("<Alt>s", "prompt", "Select scope")
p.app.RegisterShortcutHelp("<Alt>u", "prompt", "Toggle apply UID")
p.app.RegisterShortcutHelp("<Alt>g", "prompt", "Toggle apply GID")
p.app.ConnectShortcut("<Primary><Alt>space", "", "", p.app.win.Window, func (win gtk.Window) {
vis := p.app.tlStack.GetVisibleChildName()
iter, found := p.ts.GetIterFirst()
if iter == nil || found == false && vis != "prompt" {
return
}
if vis != "prompt" {
p.app.tlStack.SetVisibleChildFull("prompt", gtk.STACK_TRANSITION_TYPE_SLIDE_LEFT_RIGHT)
p.app.onStackChanged()
}
pi, _ := p.ts.GetPath(iter)
if pi != nil {
p.tv.SetCursor(pi, nil, false)
p.tv.Emit("row-activated")
}
})
}
func createColumnImg(title string, id int) *gtk.TreeViewColumn {
cellRenderer, err := gtk.CellRendererPixbufNew()
if err != nil {
log.Fatal("Unable to create image cell renderer:", err)
}
column, err := gtk.TreeViewColumnNewWithAttribute(title, cellRenderer, "pixbuf", id)
if err != nil {
log.Fatal("Unable to create cell column:", err)
}
return column
}
func createColumnText(title string, id int) *gtk.TreeViewColumn {
cellRenderer, err := gtk.CellRendererTextNew()
if err != nil {
log.Fatal("Unable to create text cell renderer:", err)
}
column, err := gtk.TreeViewColumnNewWithAttribute(title, cellRenderer, "text", id)
if err != nil {
log.Fatal("Unable to create cell column:", err)
}
column.SetSortColumnID(id)
column.SetResizable(true)
return column
}
func createTreeStore(general bool) *gtk.TreeStore {
colData := []glib.Type{glib.TYPE_INT, glib.TYPE_OBJECT, glib.TYPE_STRING, glib.TYPE_STRING, glib.TYPE_STRING, glib.TYPE_STRING, glib.TYPE_STRING, glib.TYPE_INT, glib.TYPE_STRING,
glib.TYPE_STRING, glib.TYPE_INT, glib.TYPE_INT, glib.TYPE_INT, glib.TYPE_STRING, glib.TYPE_STRING, glib.TYPE_INT, glib.TYPE_STRING, glib.TYPE_INT, glib.TYPE_OBJECT}
treeStore, err := gtk.TreeStoreNew(colData...)
if err != nil {
log.Fatal("Unable to create list store:", err)
}
return treeStore
}
func (p *Prompt) addRequestInc(guid, path, icon, proto string, pid int, ipaddr, hostname string, port, uid, gid int,
origin, timestamp string, is_socks bool, optstring string, sandbox string, action int) bool {
duplicated := false
p.promptLock.Lock()
defer p.promptLock.Unlock()
for ridx := 0; ridx < p.ts.IterNChildren(nil); ridx++ {
rule, iter, err := p.getRuleByIdx(ridx, -1)
if err != nil {
break
// XXX: not compared: optstring/sandbox
} else if (rule.Path == path) && (rule.Proto == proto) && (rule.Pid == pid) && (rule.Target == ipaddr) && (rule.Hostname == hostname) &&
(rule.Port == port) && (rule.UID == uid) && (rule.GID == gid) && (rule.Origin == origin) && (rule.IsSocks == is_socks) {
rule.nrefs++
err := p.ts.SetValue(iter, 0, rule.nrefs)
if err != nil {
fmt.Println("Error creating duplicate firewall prompt entry:", err)
break
}
duplicated = true
subiter := p.ts.Append(iter)
p.storeNewEntry(subiter, guid, path, sandbox, icon, proto, pid, ipaddr, hostname, port, uid, gid, origin, timestamp, is_socks, optstring, action)
break
}
}
return duplicated
}
func (p *Prompt) AddRequest(guid, path, icon, proto string, pid int, ipaddr, hostname string, port, uid, gid int,
origin, timestamp string, is_socks bool, optstring string, sandbox string, action int) bool {
if p.ts == nil {
waitTimes := []int{1, 2, 5, 10}
if p.ts == nil {
fmt.Println("SGFW prompter was not ready to receive firewall request... waiting")
for _, wtime := range waitTimes {
time.Sleep(time.Duration(wtime) * time.Second)
if p.ts != nil {
break
}
fmt.Println("SGFW prompter is still waiting...")
}
}
}
if p.ts == nil {
log.Fatal("SGFW prompter GUI failed to load for unknown reasons")
}
if p.addRequestInc(guid, path, icon, proto, pid, ipaddr, hostname, port, uid, gid, origin, timestamp, is_socks, optstring, sandbox, action) {
fmt.Println("Request was duplicate: ", guid)
p.promptLock.Lock()
p.toggleHover()
p.promptLock.Unlock()
return true
}
p.promptLock.Lock()
defer p.promptLock.Unlock()
iter := p.ts.Append(nil)
p.storeNewEntry(iter, guid, path, sandbox, icon, proto, pid, ipaddr, hostname, port, uid, gid, origin, timestamp, is_socks, optstring, action)
p.toggleHover()
return true
}
// Needs to be locked by caller
func (p *Prompt)storeNewEntry(iter *gtk.TreeIter, guid, path, sandbox, icon, proto string, pid int, ipaddr, hostname string, port, uid, gid int, origin,
timestamp string, is_socks bool, optstring string, action int) {
var colVals = [COL_NO_LAST]interface{}{}
if is_socks {
if (optstring != "") && (strings.Index(optstring, "SOCKS") == -1) {
optstring = "SOCKS5 / " + optstring
} else if optstring == "" {
optstring = "SOCKS5"
}
}
colVals[COL_NO_NREFS] = 1
colVals[COL_NO_ICON_PIXBUF] = nil
colVals[COL_NO_GUID] = guid
colVals[COL_NO_PATH] = path
colVals[COL_NO_SANDBOX] = sandbox
colVals[COL_NO_ICON] = icon
colVals[COL_NO_PROTO] = proto
colVals[COL_NO_PID] = pid
if ipaddr == "" {
colVals[COL_NO_DSTIP] = "---"
} else {
colVals[COL_NO_DSTIP] = ipaddr
}
colVals[COL_NO_HOSTNAME] = hostname
colVals[COL_NO_PORT] = port
colVals[COL_NO_UID] = uid
colVals[COL_NO_GID] = gid
colVals[COL_NO_ORIGIN] = origin
colVals[COL_NO_TIMESTAMP] = timestamp
colVals[COL_NO_IS_SOCKS] = 0
if is_socks {
colVals[COL_NO_IS_SOCKS] = 1
}
colVals[COL_NO_OPTSTRING] = optstring
colVals[COL_NO_ACTION] = action
colVals[COL_NO_FILLER] = nil
itheme, err := gtk.IconThemeGetDefault()
if err != nil {
log.Fatal("Could not load default icon theme:", err)
}
in := []string{spath.Base(path)}
if sandbox != "" {
in = append([]string{sandbox}, in...)
}
if icon != "" {
in = append(in, icon)
}
in = append(in, "terminal")
if path == "[unknown]" {
in = []string{"image-missing"}
}
for _, ia := range in {
pb, _ := itheme.LoadIcon(ia, int(gtk.ICON_SIZE_BUTTON), gtk.ICON_LOOKUP_GENERIC_FALLBACK)
if pb != nil {
colVals[COL_NO_ICON_PIXBUF] = pb
break
}
}
pb, err := gdk.PixbufNew(gdk.COLORSPACE_RGB, true, 8, 24, 24)
if err != nil {
log.Println("Error creating blank icon:", err)
} else {
colVals[COL_NO_FILLER] = pb
img, err := gtk.ImageNewFromPixbuf(pb)
if err != nil {
log.Println("Error creating image from pixbuf:", err)
} else {
img.Clear()
pb = img.GetPixbuf()
colVals[COL_NO_FILLER] = pb
}
}
for n := 0; n < len(colVals); n++ {
err := p.ts.SetValue(iter, n, colVals[n])
if err != nil {
log.Fatal("Unable to add row:", err)
}
}
return
}
func (p *Prompt) getRuleByIdx(idx, subidx int) (ruleColumns, *gtk.TreeIter, error) {
rule := ruleColumns{}
tpath := fmt.Sprintf("%d", idx)
if subidx != -1 {
tpath = fmt.Sprintf("%d:%d", idx, subidx)
}
path, err := gtk.TreePathNewFromString(tpath)
if err != nil {
return rule, nil, err
}
iter, err := p.ts.GetIter(path)
if err != nil {
return rule, nil, err
}
rule.nrefs, err = p.lsGetInt(iter, COL_NO_NREFS)
if err != nil {
return rule, nil, err
}
rule.GUID, err = p.lsGetStr(iter, COL_NO_GUID)
if err != nil {
return rule, nil, err
}
rule.Path, err = p.lsGetStr(iter, COL_NO_PATH)
if err != nil {
return rule, nil, err
}
rule.Sandbox, err = p.lsGetStr(iter, COL_NO_SANDBOX)
if err != nil {
return rule, nil, err
}
rule.Icon, err = p.lsGetStr(iter, COL_NO_ICON)
if err != nil {
return rule, nil, err
}
rule.Proto, err = p.lsGetStr(iter, COL_NO_PROTO)
if err != nil {
return rule, nil, err
}
rule.Pid, err = p.lsGetInt(iter, COL_NO_PID)
if err != nil {
return rule, nil, err
}
rule.Target, err = p.lsGetStr(iter, COL_NO_DSTIP)
if err != nil {
return rule, nil, err
}
rule.Hostname, err = p.lsGetStr(iter, COL_NO_HOSTNAME)
if err != nil {
return rule, nil, err
}
rule.Port, err = p.lsGetInt(iter, COL_NO_PORT)
if err != nil {
return rule, nil, err
}
rule.UID, err = p.lsGetInt(iter, COL_NO_UID)
if err != nil {
return rule, nil, err
}
rule.GID, err = p.lsGetInt(iter, COL_NO_GID)
if err != nil {
return rule, nil, err
}
rule.Origin, err = p.lsGetStr(iter, COL_NO_ORIGIN)
if err != nil {
return rule, nil, err
}
rule.Timestamp, err = p.lsGetStr(iter, COL_NO_TIMESTAMP)
if err != nil {
return rule, nil, err
}
rule.IsSocks = false
is_socks, err := p.lsGetInt(iter, COL_NO_IS_SOCKS)
if err != nil {
return rule, nil, err
}
if is_socks != 0 {
rule.IsSocks = true
}
rule.Scope, err = p.lsGetInt(iter, COL_NO_ACTION)
if err != nil {
return rule, nil, err
}
return rule, iter, nil
}
func (p *Prompt) lsGetInt(iter *gtk.TreeIter, idx int) (int, error) {
val, err := p.ts.GetValue(iter, idx)
if err != nil {
return 0, err
}
ival, err := val.GoValue()
if err != nil {
return 0, err
}
return ival.(int), nil
}
func (p *Prompt) lsGetStr(iter *gtk.TreeIter, idx int) (string, error) {
val, err := p.ts.GetValue(iter, idx)
if err != nil {
return "", err
}
sval, err := val.GetString()
if err != nil {
return "", err
}
return sval, nil
}
func (p *Prompt) toggleHover() {
nitems := p.ts.IterNChildren(nil)
stack := p.app.tlStack.GetChildByName("prompt")
if nitems > 0 {
if p.app.Settings.GetToplevelPrompt() {
//p.win.SetModal(true)
p.app.win.Deiconify()
p.app.win.SetKeepAbove(true)
p.app.win.Stick()
}
p.app.win.SetUrgencyHint(true)
p.app.win.Present()
if p.app.tlStack.GetVisibleChildName() != "prompt" {
err := p.app.tlStack.ChildSetProperty(stack, "needs-attention", true)
if err != nil {
fmt.Println("Error setting stack attention")
}
}
} else {
//p.win.SetModal(false)
p.app.win.SetUrgencyHint(false)
if p.app.Settings.GetToplevelPrompt() {
p.app.win.SetKeepAbove(false)
p.app.win.Unstick()
}
p.app.tlStack.ChildSetProperty(stack, "needs-attention", false)
}
}
// Needs to be locked by the caller
func (p *Prompt) getSelectedRule() (ruleColumns, int, int, error) {
rule := ruleColumns{}
sel, err := p.tv.GetSelection()
if err != nil {
return rule, -1, -1, err
}
rows := sel.GetSelectedRows(p.ts)
if rows.Length() <= 0 {
return rule, -1, -1, errors.New("no selection was made")
}
rdata := rows.NthData(0)
tpath := rdata.(*gtk.TreePath).String()
subidx := -1
ptoks := strings.Split(tpath, ":")
if len(ptoks) > 2 {
return rule, -1, -1, errors.New("internal error parsing selected item tree path")
} else if len(ptoks) == 2 {
subidx, err = strconv.Atoi(ptoks[1])
if err != nil {
return rule, -1, -1, err
}
tpath = ptoks[0]
}
lIndex, err := strconv.Atoi(tpath)
if err != nil {
return rule, -1, -1, err
}
// fmt.Printf("lindex = %d : %d\n", lIndex, subidx)
rule, _, err = p.getRuleByIdx(lIndex, subidx)
if err != nil {
return rule, -1, -1, err
}
return rule, lIndex, subidx, nil
}
// Needs to be locked by the caller
func (p *Prompt) numSelections() int {
sel, err := p.tv.GetSelection()
if err != nil {
return -1
}
rows := sel.GetSelectedRows(p.ts)
return int(rows.Length())
}
func (p *Prompt) removeSelectedRule(idx, subidx int) error {
fmt.Printf("XXX: attempting to remove idx = %v, %v\n", idx, subidx)
ppathstr := fmt.Sprintf("%d", idx)
pathstr := ppathstr
if subidx > -1 {
pathstr = fmt.Sprintf("%d:%d", idx, subidx)
}
iter, err := p.ts.GetIterFromString(pathstr)
if err != nil {
return err
}
nchildren := p.ts.IterNChildren(iter)
if nchildren >= 1 {
firstpath := fmt.Sprintf("%d:0", idx)
citer, err := p.ts.GetIterFromString(firstpath)
if err != nil {
return err
}
gnrefs, err := p.ts.GetValue(iter, COL_NO_NREFS)
if err != nil {
return err
}
vnrefs, err := gnrefs.GoValue()
if err != nil {
return err
}
nrefs := vnrefs.(int) - 1
for n := 0; n < COL_NO_LAST; n++ {
val, err := p.ts.GetValue(citer, n)
if err != nil {
return err
}
if n == COL_NO_NREFS {
err = p.ts.SetValue(iter, n, nrefs)
} else {
err = p.ts.SetValue(iter, n, val)
}
if err != nil {
return err
}
}
p.ts.Remove(citer)
return nil
}
p.ts.Remove(iter)
if subidx > -1 {
ppath, err := gtk.TreePathNewFromString(ppathstr)
if err != nil {
return err
}
piter, err := p.ts.GetIter(ppath)
if err != nil {
return err
}
nrefs, err := p.lsGetInt(piter, COL_NO_NREFS)
if err != nil {
return err
}
err = p.ts.SetValue(piter, COL_NO_NREFS, nrefs-1)
if err != nil {
return err
}
}
p.toggleHover()
return nil
}
func (p *Prompt) addRecentlyRemoved(guid string) {
p.recentLock.Lock()
defer p.recentLock.Unlock()
fmt.Println("RECENTLY REMOVED: ", guid)
p.recentlyRemoved = append(p.recentlyRemoved, guid)
}
func (p *Prompt) wasRecentlyRemoved(guid string) bool {
p.recentLock.Lock()
defer p.recentLock.Unlock()
for gind, g := range p.recentlyRemoved {
if g == guid {
p.recentlyRemoved = append(p.recentlyRemoved[:gind], p.recentlyRemoved[gind+1:]...)
return true
}
}
return false
}
func (p *Prompt) RemoveRequest(guid string) {
if p.wasRecentlyRemoved(guid) {
fmt.Printf("Entry for %s was recently removed; deleting from cache\n", guid)
return
}
removed := false
if p.ts == nil {
return
}
p.promptLock.Lock()
defer p.promptLock.Unlock()
remove_outer:
for ridx := 0; ridx < p.ts.IterNChildren(nil); ridx++ {
nchildren := 0
this_iter, err := p.ts.GetIterFromString(fmt.Sprintf("%d", ridx))
if err != nil {
log.Println("Strange condition; couldn't get iter of known tree index:", err)
} else {
nchildren = p.ts.IterNChildren(this_iter)
}
for cidx := 0; cidx < nchildren-1; cidx++ {
sidx := cidx
if cidx == nchildren {
cidx = -1
}
rule, _, err := p.getRuleByIdx(ridx, sidx)
if err != nil {
break remove_outer
} else if rule.GUID == guid {
p.removeSelectedRule(ridx, sidx)
removed = true
break
}
}
}
if !removed {
fmt.Printf("Unexpected condition: SGFW requested prompt removal for non-existent GUID %v\n", guid)
}
}
func (p *Prompt) RemoveAll() {
p.promptLock.Lock()
defer p.promptLock.Unlock()
p.recentLock.Lock()
defer p.recentLock.Unlock()
p.recentlyRemoved = p.recentlyRemoved[:0]
for {
iter, found := p.ts.GetIterFirst()
if iter == nil || found == false {
break
}
pi, _ := p.ts.GetPath(iter)
if pi == nil {
break
}
p.tv.SetCursor(pi, nil, false)
_, idx, subidx, err := p.getSelectedRule()
if err != nil {
break
}
p.removeSelectedRule(idx, subidx)
}
}
func (p *Prompt) makeDecision(rule string, scope int, guid string) error {
return p.app.Dbus.answerPrompt(uint32(scope), rule, guid)
}
func (p *Prompt) buttonAction(guid string, rr *sgfw.DbusRule) {
p.promptLock.Lock()
rule, idx, subidx, err := p.getSelectedRule()
if err != nil {
p.promptLock.Unlock()
warnDialog(&p.app.win.Window, "Error occurred processing request: %s", err.Error())
return
}
tk := strings.Split(rr.Target, ":")
// Overlay the rules
rule.Scope = int(rr.Mode)
//rule.Path = urule.Path
rule.Port, _ = strconv.Atoi(tk[1])
rule.Target = tk[0]
rule.Proto = rr.Proto
rule.UID = int(rr.UID)
rule.GID = int(rr.GID)
// rule.Uname = urule.Uname
// rule.Gname = urule.Gname
fmt.Println("rule = ", rule)
action := sgfw.RuleActionString[sgfw.RuleAction(rr.Verb)]
rulestr := action
proto := rule.Proto
if proto == "any" || proto == "" {
proto = "*"
}
rulestr += "|" + proto + ":" + rule.Target + ":" + strconv.Itoa(rule.Port)
rulestr += "|" + sgfw.RuleModeString[sgfw.RuleMode(rule.Scope)]
rulestr += "|" + strconv.Itoa(rule.UID) + ":" + strconv.Itoa(rule.GID)
if rule.Sandbox != "" {
rulestr += "|" + rule.Sandbox
}
fmt.Println("RULESTR = ", rulestr)
p.makeDecision(rulestr, int(rule.Scope), guid)
err = p.removeSelectedRule(idx, subidx)
p.addRecentlyRemoved(guid)
p.promptLock.Unlock()
if err != nil {
warnDialog(&p.app.win.Window, "Error setting new rule: %s", err.Error())
}
}