*Very experimental*/under-dev release of new fully asynchronous multi-prompter.

New Dbus method "RequestPromptAsync" to handle "return-less" prompter invocations in fw-prompt.
Proper GUI locking in fw-prompt eliminates old race/crash conditions.
New DBus method "GetPendingRequests" in SGFW allows prompter to retrieve pending connections.
Policies now maintain rulesPending list of unapplied asynchronously submitted FW rules from the prompter.
Fixed reentrance/crash bug in UID and GID to name lookups.
shw_dev
Stephen Watt 7 years ago
parent 2f5e10d53d
commit 2eac4c7dc5

@ -6,11 +6,23 @@ import (
"log"
)
type dbusObject struct {
dbus.BusObject
}
type dbusServer struct {
conn *dbus.Conn
run bool
}
func newDbusObjectAdd() (*dbusObject, error) {
conn, err := dbus.SystemBus()
if err != nil {
return nil, err
}
return &dbusObject{conn.Object("com.subgraph.Firewall", "/com/subgraph/Firewall")}, nil
}
func newDbusServer() (*dbusServer, error) {
conn, err := dbus.SystemBus()
@ -54,6 +66,13 @@ func (ds *dbusServer) RequestPrompt(guid, application, icon, path, address strin
return int32(decision.Scope), decision.Rule, nil
}
func (ds *dbusServer) RequestPromptAsync(guid, application, icon, path, address string, port int32, ip, origin, proto string, uid, gid int32, username, groupname string, pid int32, sandbox string,
is_socks bool, optstring string, expanded, expert bool, action int32) (bool, *dbus.Error) {
log.Printf("ASYNC request prompt: guid = %s, app = %s, icon = %s, path = %s, address = %s / ip = %s, is_socks = %v, action = %v\n", guid, application, icon, path, address, ip, is_socks, action)
addRequestAsync(nil, guid, path, icon, proto, int(pid), ip, address, int(port), int(uid), int(gid), origin, is_socks, optstring, sandbox)
return true, nil
}
func (ds *dbusServer) RemovePrompt(guid string) *dbus.Error {
log.Printf("++++++++ Cancelling prompt: %s\n", guid)
removeRequest(nil, guid)

@ -53,6 +53,7 @@ type ruleColumns struct {
Scope int
}
var dbuso *dbusObject
var userPrefs fpPreferences
var mainWin *gtk.Window
var Notebook *gtk.Notebook
@ -327,6 +328,7 @@ func createListStore(general bool) *gtk.ListStore {
func removeRequest(listStore *gtk.ListStore, guid string) {
removed := false
globalPromptLock.Lock()
defer globalPromptLock.Unlock()
/* XXX: This is horrible. Figure out how to do this properly. */
for ridx := 0; ridx < 2000; ridx++ {
@ -342,8 +344,6 @@ func removeRequest(listStore *gtk.ListStore, guid string) {
}
globalPromptLock.Unlock()
if !removed {
log.Printf("Unexpected condition: SGFW requested prompt removal for non-existent GUID %v\n", guid)
}
@ -354,6 +354,7 @@ func addRequestInc(listStore *gtk.ListStore, guid, path, icon, proto string, pid
duplicated := false
globalPromptLock.Lock()
defer globalPromptLock.Unlock()
for ridx := 0; ridx < 2000; ridx++ {
@ -368,7 +369,7 @@ func addRequestInc(listStore *gtk.ListStore, guid, path, icon, proto string, pid
err := globalLS.SetValue(iter, 0, rule.nrefs)
if err != nil {
log.Print("Error creating duplicate firewall prompt entry:", err)
log.Println("Error creating duplicate firewall prompt entry:", err)
break
}
@ -379,28 +380,117 @@ func addRequestInc(listStore *gtk.ListStore, guid, path, icon, proto string, pid
}
globalPromptLock.Unlock()
return duplicated
}
func addRequest(listStore *gtk.ListStore, guid, path, icon, proto string, pid int, ipaddr, hostname string, port, uid, gid int, origin string, is_socks bool, optstring string, sandbox string) *decisionWaiter {
func addRequestAsync(listStore *gtk.ListStore, guid, path, icon, proto string, pid int, ipaddr, hostname string, port, uid, gid int, origin string, is_socks bool, optstring string, sandbox string) bool {
if listStore == nil {
listStore = globalLS
waitTimes := []int{1, 2, 5, 10}
if listStore == nil {
log.Print("SGFW prompter was not ready to receive firewall request... waiting")
log.Println("SGFW prompter was not ready to receive firewall request... waiting")
for _, wtime := range waitTimes {
time.Sleep(time.Duration(wtime) * time.Second)
listStore = globalLS
if listStore != nil {
break
}
log.Println("SGFW prompter is still waiting...")
}
}
for _, wtime := range waitTimes {
time.Sleep(time.Duration(wtime) * time.Second)
listStore = globalLS
}
if listStore != nil {
break
if listStore == nil {
log.Fatal("SGFW prompter GUI failed to load for unknown reasons")
}
if addRequestInc(listStore, guid, path, icon, proto, pid, ipaddr, hostname, port, uid, gid, origin, is_socks, optstring, sandbox) {
fmt.Println("REQUEST WAS DUPLICATE")
return false
} else {
fmt.Println("NOT DUPLICATE")
}
globalPromptLock.Lock()
iter := listStore.Append()
if is_socks {
if (optstring != "") && (strings.Index(optstring, "SOCKS") == -1) {
optstring = "SOCKS5 / " + optstring
} else if optstring == "" {
optstring = "SOCKS5"
}
}
colVals := make([]interface{}, 14)
colVals[0] = 1
colVals[1] = guid
colVals[2] = path
colVals[3] = icon
colVals[4] = proto
colVals[5] = pid
if ipaddr == "" {
colVals[6] = "---"
} else {
colVals[6] = ipaddr
}
colVals[7] = hostname
colVals[8] = port
colVals[9] = uid
colVals[10] = gid
colVals[11] = origin
colVals[12] = 0
if is_socks {
colVals[12] = 1
}
colVals[13] = optstring
colNums := make([]int, len(colVals))
for n := 0; n < len(colVals); n++ {
colNums[n] = n
}
err := listStore.Set(iter, colNums, colVals)
globalPromptLock.Unlock()
if err != nil {
log.Fatal("Unable to add row:", err)
}
toggleHover()
return true
}
func addRequest(listStore *gtk.ListStore, guid, path, icon, proto string, pid int, ipaddr, hostname string, port, uid, gid int, origin string, is_socks bool, optstring string, sandbox string) *decisionWaiter {
if listStore == nil {
listStore = globalLS
waitTimes := []int{1, 2, 5, 10}
if listStore == nil {
log.Println("SGFW prompter was not ready to receive firewall request... waiting")
for _, wtime := range waitTimes {
time.Sleep(time.Duration(wtime) * time.Second)
listStore = globalLS
if listStore != nil {
break
}
log.Println("SGFW prompter is still waiting...")
}
log.Print("SGFW prompter is still waiting...")
}
}
@ -565,13 +655,26 @@ func lsGetInt(ls *gtk.ListStore, iter *gtk.TreeIter, idx int) (int, error) {
return ival.(int), nil
}
func makeDecision(idx int, rule string, scope int) {
func makeDecision(idx int, rule string, scope int) error {
var dres bool
call := dbuso.Call("AddRuleAsync", 0, uint32(scope), rule, "*")
err := call.Store(&dres)
if err != nil {
log.Println("Error notifying SGFW of asynchronous rule addition:", err)
return err
}
fmt.Println("makeDecision remote result:", dres)
return nil
decisionWaiters[idx].Cond.L.Lock()
decisionWaiters[idx].Rule = rule
decisionWaiters[idx].Scope = scope
decisionWaiters[idx].Ready = true
decisionWaiters[idx].Cond.Signal()
decisionWaiters[idx].Cond.L.Unlock()
return nil
}
func toggleHover() {
@ -581,7 +684,9 @@ func toggleHover() {
func toggleValidRuleState() {
ok := true
globalPromptLock.Lock()
// Unfortunately, this can cause deadlock since it's a part ofi the item removal cascade
// globalPromptLock.Lock()
// defer globalPromptLock.Unlock()
if numSelections() <= 0 {
ok = false
@ -625,7 +730,6 @@ func toggleValidRuleState() {
btnApprove.SetSensitive(ok)
btnDeny.SetSensitive(ok)
btnIgnore.SetSensitive(ok)
globalPromptLock.Unlock()
}
func createCurrentRule() (ruleColumns, error) {
@ -710,7 +814,7 @@ func removeSelectedRule(idx int, rmdecision bool) error {
globalLS.Remove(iter)
if rmdecision {
decisionWaiters = append(decisionWaiters[:idx], decisionWaiters[idx+1:]...)
// decisionWaiters = append(decisionWaiters[:idx], decisionWaiters[idx+1:]...)
}
toggleHover()
@ -844,6 +948,64 @@ func getSelectedRule() (ruleColumns, int, error) {
return rule, lIndex, nil
}
func addPendingPrompts(rules []string) {
for _, rule := range rules {
fields := strings.Split(rule, "|")
if len(fields) != 17 {
log.Printf("Got saved prompt message with strange data: \"%s\"", rule)
continue
}
guid := fields[0]
icon := fields[2]
path := fields[3]
address := fields[4]
port, err := strconv.Atoi(fields[5])
if err != nil {
log.Println("Error converting port in pending prompt message to integer:", err)
continue
}
ip := fields[6]
origin := fields[7]
proto := fields[8]
uid, err := strconv.Atoi(fields[9])
if err != nil {
log.Println("Error converting UID in pending prompt message to integer:", err)
continue
}
gid, err := strconv.Atoi(fields[10])
if err != nil {
log.Println("Error converting GID in pending prompt message to integer:", err)
continue
}
pid, err := strconv.Atoi(fields[13])
if err != nil {
log.Println("Error converting pid in pending prompt message to integer:", err)
continue
}
sandbox := fields[14]
is_socks, err := strconv.ParseBool(fields[15])
if err != nil {
log.Println("Error converting SOCKS flag in pending prompt message to boolean:", err)
continue
}
optstring := fields[16]
addRequestAsync(nil, guid, path, icon, proto, int(pid), ip, address, int(port), int(uid), int(gid), origin, is_socks, optstring, sandbox)
}
}
func main() {
decisionWaiters = make([]*decisionWaiter, 0)
_, err := newDbusServer()
@ -852,6 +1014,11 @@ func main() {
return
}
dbuso, err = newDbusObjectAdd()
if err != nil {
log.Fatal("Failed to connect to dbus system bus: %v", err)
}
loadPreferences()
gtk.Init(nil)
@ -1045,17 +1212,17 @@ func main() {
tv.SetModel(listStore)
btnApprove.Connect("clicked", func() {
// globalPromptLock.Lock()
globalPromptLock.Lock()
rule, idx, err := getSelectedRule()
if err != nil {
// globalPromptLock.Unlock()
globalPromptLock.Unlock()
promptError("Error occurred processing request: " + err.Error())
return
}
rule, err = createCurrentRule()
if err != nil {
// globalPromptLock.Unlock()
globalPromptLock.Unlock()
promptError("Error occurred constructing new rule: " + err.Error())
return
}
@ -1071,7 +1238,7 @@ func main() {
fmt.Println("RULESTR = ", rulestr)
makeDecision(idx, rulestr, int(rule.Scope))
fmt.Println("Decision made.")
// globalPromptLock.Unlock()
globalPromptLock.Unlock()
err = removeSelectedRule(idx, true)
if err == nil {
clearEditor()
@ -1081,17 +1248,17 @@ func main() {
})
btnDeny.Connect("clicked", func() {
// globalPromptLock.Lock()
globalPromptLock.Lock()
rule, idx, err := getSelectedRule()
if err != nil {
// globalPromptLock.Unlock()
globalPromptLock.Unlock()
promptError("Error occurred processing request: " + err.Error())
return
}
rule, err = createCurrentRule()
if err != nil {
// globalPromptLock.Unlock()
globalPromptLock.Unlock()
promptError("Error occurred constructing new rule: " + err.Error())
return
}
@ -1101,7 +1268,7 @@ func main() {
fmt.Println("RULESTR = ", rulestr)
makeDecision(idx, rulestr, int(rule.Scope))
fmt.Println("Decision made.")
// globalPromptLock.Unlock()
globalPromptLock.Unlock()
err = removeSelectedRule(idx, true)
if err == nil {
clearEditor()
@ -1111,17 +1278,17 @@ func main() {
})
btnIgnore.Connect("clicked", func() {
// globalPromptLock.Lock()
globalPromptLock.Lock()
_, idx, err := getSelectedRule()
if err != nil {
// globalPromptLock.Unlock()
globalPromptLock.Unlock()
promptError("Error occurred processing request: " + err.Error())
return
}
makeDecision(idx, "", 0)
fmt.Println("Decision made.")
// globalPromptLock.Unlock()
globalPromptLock.Unlock()
err = removeSelectedRule(idx, true)
if err == nil {
clearEditor()
@ -1132,10 +1299,10 @@ func main() {
// tv.SetActivateOnSingleClick(true)
tv.Connect("row-activated", func() {
// globalPromptLock.Lock()
globalPromptLock.Lock()
seldata, _, err := getSelectedRule()
globalPromptLock.Unlock()
if err != nil {
// globalPromptLock.Unlock()
promptError("Unexpected error reading selected rule: " + err.Error())
return
}
@ -1182,8 +1349,6 @@ func main() {
chkUser.SetActive(false)
chkGroup.SetActive(false)
// globalPromptLock.Unlock()
return
})
@ -1206,5 +1371,16 @@ func main() {
mainWin.ShowAll()
// mainWin.SetKeepAbove(true)
var dres = []string{}
call := dbuso.Call("GetPendingRequests", 0, "*")
err = call.Store(&dres)
if err != nil {
errmsg := "Could not query running SGFW instance (maybe it's not running?): " + err.Error()
promptError(errmsg)
} else {
addPendingPrompts(dres)
}
gtk.Main()
}

@ -199,6 +199,72 @@ func (ds *dbusServer) DeleteRule(id uint32) *dbus.Error {
return nil
}
func (ds *dbusServer) GetPendingRequests(policy string) ([]string, *dbus.Error) {
log.Debug("+++ GetPendingRequests()")
ds.fw.lock.Lock()
defer ds.fw.lock.Unlock()
pending_data := make([]string, 0)
for pname := range ds.fw.policyMap {
policy := ds.fw.policyMap[pname]
pqueue := policy.pendingQueue
for _, pc := range pqueue {
addr := pc.hostname()
if addr == "" {
addr = pc.dst().String()
}
dststr := ""
if pc.dst() != nil {
dststr = pc.dst().String()
} else {
dststr = addr + " (via proxy resolver)"
}
pstr := ""
pstr += pc.getGUID() + "|"
pstr += policy.application + "|"
pstr += policy.icon + "|"
pstr += policy.path + "|"
pstr += addr + "|"
pstr += strconv.FormatUint(uint64(pc.dstPort()), 10) + "|"
pstr += dststr + "|"
pstr += pc.src().String() + "|"
pstr += pc.proto() + "|"
pstr += strconv.FormatInt(int64(pc.procInfo().UID), 10) + "|"
pstr += strconv.FormatInt(int64(pc.procInfo().GID), 10) + "|"
pstr += uidToUser(pc.procInfo().UID) + "|"
pstr += gidToGroup(pc.procInfo().GID) + "|"
pstr += strconv.FormatInt(int64(pc.procInfo().Pid), 10) + "|"
pstr += pc.sandbox() + "|"
pstr += strconv.FormatBool(pc.socks()) + "|"
pstr += pc.getOptString()
pending_data = append(pending_data, pstr)
}
}
return pending_data, nil
}
func (ds *dbusServer) AddRuleAsync(scope uint32, rule string, policy string) (bool, *dbus.Error) {
log.Debugf("AddRuleAsync %v, %v / %v\n", scope, rule, policy)
ds.fw.lock.Lock()
defer ds.fw.lock.Unlock()
prule := PendingRule{rule: rule, scope: int(scope), policy: policy}
for pname := range ds.fw.policyMap {
log.Debug("+++ Adding prule to policy")
ds.fw.policyMap[pname].rulesPending = append(ds.fw.policyMap[pname].rulesPending, prule)
}
return true, nil
}
func (ds *dbusServer) UpdateRule(rule DbusRule) *dbus.Error {
log.Debugf("UpdateRule %v", rule)
ds.fw.lock.Lock()

@ -6,8 +6,6 @@ import (
"strings"
"sync"
// "encoding/binary"
// nfnetlink "github.com/subgraph/go-nfnetlink"
"github.com/google/gopacket/layers"
nfqueue "github.com/subgraph/go-nfnetlink/nfqueue"
@ -213,6 +211,12 @@ func (pp *pendingPkt) print() string {
return printPacket(pp.pkt, pp.name, pp.pinfo)
}
type PendingRule struct {
rule string
scope int
policy string
}
type Policy struct {
fw *Firewall
path string
@ -223,6 +227,7 @@ type Policy struct {
pendingQueue []pendingConnection
promptInProgress bool
lock sync.Mutex
rulesPending []PendingRule
}
func (fw *Firewall) PolicyForPath(path string) *Policy {
@ -312,21 +317,22 @@ func (p *Policy) processPacket(pkt *nfqueue.NFQPacket, pinfo *procsnitch.Info, o
func (p *Policy) processPromptResult(pc pendingConnection) {
p.pendingQueue = append(p.pendingQueue, pc)
//fmt.Println("processPromptResult(): p.promptInProgress = ", p.promptInProgress)
if DoMultiPrompt || (!DoMultiPrompt && !p.promptInProgress) {
p.promptInProgress = true
go p.fw.dbus.prompt(p)
}
//if DoMultiPrompt || (!DoMultiPrompt && !p.promptInProgress) {
// if !p.promptInProgress {
p.promptInProgress = true
go p.fw.dbus.prompt(p)
// }
}
func (p *Policy) nextPending() (pendingConnection, bool) {
p.lock.Lock()
defer p.lock.Unlock()
if !DoMultiPrompt {
/* if !DoMultiPrompt {
if len(p.pendingQueue) == 0 {
return nil, true
}
return p.pendingQueue[0], false
}
}*/
if len(p.pendingQueue) == 0 {
return nil, true
@ -334,6 +340,7 @@ func (p *Policy) nextPending() (pendingConnection, bool) {
// for len(p.pendingQueue) != 0 {
for i := 0; i < len(p.pendingQueue); i++ {
fmt.Printf("pendingQueue %v of %v: %v\n", i, len(p.pendingQueue), p.pendingQueue[i])
if !p.pendingQueue[i].getPrompting() {
return p.pendingQueue[i], false
}
@ -414,8 +421,6 @@ func (p *Policy) filterPending(rule *Rule) {
if prompter == nil {
fmt.Println("-------- prompter = NULL")
} else {
fmt.Println("---------- could send prompter")
call := prompter.Call("com.subgraph.FirewallPrompt.RemovePrompt", 0, pc.getGUID())
fmt.Println("CAAAAAAAAAAAAAAALL = ", call)
}

@ -13,15 +13,6 @@ import (
"github.com/subgraph/fw-daemon/proc-coroner"
)
var DoMultiPrompt = true
const MAX_PROMPTS = 5
var outstandingPrompts = 0
var outstandingPromptChans [](chan *dbus.Call)
var promptLock = &sync.Mutex{}
var promptChanLock = &sync.Mutex{}
func newPrompter(conn *dbus.Conn) *prompter {
p := new(prompter)
p.cond = sync.NewCond(&p.lock)
@ -39,30 +30,6 @@ type prompter struct {
policyQueue []*Policy
}
func saveChannel(ch chan *dbus.Call, add bool, do_close bool) {
promptChanLock.Lock()
if add {
outstandingPromptChans = append(outstandingPromptChans, ch)
} else {
for idx, och := range outstandingPromptChans {
if och == ch {
outstandingPromptChans = append(outstandingPromptChans[:idx], outstandingPromptChans[idx+1:]...)
break
}
}
}
if !add && do_close {
close(ch)
}
promptChanLock.Unlock()
return
}
func (p *prompter) prompt(policy *Policy) {
p.lock.Lock()
defer p.lock.Unlock()
@ -91,7 +58,8 @@ func (p *prompter) promptLoop() {
func (p *prompter) processNextPacket() bool {
var pc pendingConnection = nil
if !DoMultiPrompt {
if 1 == 2 {
// if !DoMultiPrompt {
pc, _ = p.nextConnection()
if pc == nil {
return false
@ -118,66 +86,28 @@ func (p *prompter) processNextPacket() bool {
defer p.lock.Lock()
// fmt.Println("XXX: Waiting for prompt lock go...")
for {
promptLock.Lock()
if outstandingPrompts >= MAX_PROMPTS {
promptLock.Unlock()
continue
}
if pc.getPrompting() {
log.Debugf("Skipping over already prompted connection")
promptLock.Unlock()
continue
}
break
}
// fmt.Println("XXX: Passed prompt lock!")
outstandingPrompts++
// fmt.Println("XXX: Incremented outstanding to ", outstandingPrompts)
promptLock.Unlock()
// if !pc.getPrompting() {
pc.setPrompting(true)
go p.processConnection(pc)
// }
return true
}
func processReturn(pc pendingConnection) {
promptLock.Lock()
outstandingPrompts--
// fmt.Println("XXX: Return decremented outstanding to ", outstandingPrompts)
promptLock.Unlock()
pc.setPrompting(false)
}
func alertChannel(chidx int, scope int32, rule string) {
defer func() {
if r := recover(); r != nil {
log.Warning("SGFW recovered from panic while delivering out of band rule:", r)
}
}()
promptData := make([]interface{}, 3)
promptData[0] = scope
promptData[1] = rule
promptData[2] = 666
outstandingPromptChans[chidx] <- &dbus.Call{Body: promptData}
}
func (p *prompter) processConnection(pc pendingConnection) {
var scope int32
var dres bool
var rule string
if pc.getPrompter() == nil {
pc.setPrompter(&dbusObjectP{p.dbusObj})
}
if DoMultiPrompt {
defer processReturn(pc)
}
addr := pc.hostname()
if addr == "" {
addr = pc.dst().String()
@ -192,10 +122,12 @@ func (p *prompter) processConnection(pc pendingConnection) {
dststr = addr + " (via proxy resolver)"
}
callChan := make(chan *dbus.Call, 10)
saveChannel(callChan, true, false)
fmt.Println("# outstanding prompt chans = ", len(outstandingPromptChans))
p.dbusObj.Go("com.subgraph.FirewallPrompt.RequestPrompt", 0, callChan,
// callChan := make(chan *dbus.Call, 10)
// saveChannel(callChan, true, false)
// fmt.Println("# outstanding prompt chans = ", len(outstandingPromptChans))
// fmt.Println("ABOUT TO CALL ASYNC PROMPT")
call := p.dbusObj.Call("com.subgraph.FirewallPrompt.RequestPromptAsync", 0,
pc.getGUID(),
policy.application,
policy.icon,
@ -217,52 +149,88 @@ func (p *prompter) processConnection(pc pendingConnection) {
FirewallConfig.PromptExpert,
int32(FirewallConfig.DefaultActionID))
select {
case call := <-callChan:
err := call.Store(&dres)
if err != nil {
log.Warningf("Error sending dbus async RequestPrompt message: %v", err)
policy.removePending(pc)
pc.drop()
return
}
if call.Err != nil {
fmt.Println("Error reading DBus channel (accepting packet): ", call.Err)
policy.removePending(pc)
pc.accept()
saveChannel(callChan, false, true)
time.Sleep(1 * time.Second)
return
}
if !dres {
fmt.Println("Unexpected: fw-prompt async RequestPrompt message returned:", dres)
}
if len(call.Body) != 2 {
log.Warning("SGFW got back response in unrecognized format, len = ", len(call.Body))
saveChannel(callChan, false, true)
return
if (len(call.Body) == 3) && (call.Body[2] == 666) {
fmt.Printf("+++++++++ AWESOME: %v | %v | %v\n", call.Body[0], call.Body[1], call.Body[2])
scope = call.Body[0].(int32)
rule = call.Body[1].(string)
/* p.dbusObj.Go("com.subgraph.FirewallPrompt.RequestPrompt", 0, callChan,
pc.getGUID(),
policy.application,
policy.icon,
policy.path,
addr,
int32(pc.dstPort()),
dststr,
pc.src().String(),
pc.proto(),
int32(pc.procInfo().UID),
int32(pc.procInfo().GID),
uidToUser(pc.procInfo().UID),
gidToGroup(pc.procInfo().GID),
int32(pc.procInfo().Pid),
pc.sandbox(),
pc.socks(),
pc.getOptString(),
FirewallConfig.PromptExpanded,
FirewallConfig.PromptExpert,
int32(FirewallConfig.DefaultActionID))
select {
case call := <-callChan:
if call.Err != nil {
fmt.Println("Error reading DBus channel (accepting packet): ", call.Err)
policy.removePending(pc)
pc.accept()
saveChannel(callChan, false, true)
time.Sleep(1 * time.Second)
return
}
return
}
if len(call.Body) != 2 {
log.Warning("SGFW got back response in unrecognized format, len = ", len(call.Body))
saveChannel(callChan, false, true)
fmt.Printf("DBUS GOT BACK: %v, %v\n", call.Body[0], call.Body[1])
scope = call.Body[0].(int32)
rule = call.Body[1].(string)
}
if (len(call.Body) == 3) && (call.Body[2] == 666) {
fmt.Printf("+++++++++ AWESOME: %v | %v | %v\n", call.Body[0], call.Body[1], call.Body[2])
scope = call.Body[0].(int32)
rule = call.Body[1].(string)
}
saveChannel(callChan, false, true)
return
}
// Try alerting every other channel
promptData := make([]interface{}, 3)
promptData[0] = scope
promptData[1] = rule
promptData[2] = 666
promptChanLock.Lock()
fmt.Println("# channels to alert: ", len(outstandingPromptChans))
fmt.Printf("DBUS GOT BACK: %v, %v\n", call.Body[0], call.Body[1])
scope = call.Body[0].(int32)
rule = call.Body[1].(string)
}
for chidx, _ := range outstandingPromptChans {
alertChannel(chidx, scope, rule)
// ch <- &dbus.Call{Body: promptData}
}
saveChannel(callChan, false, true)
promptChanLock.Unlock()
// Try alerting every other channel
promptData := make([]interface{}, 3)
promptData[0] = scope
promptData[1] = rule
promptData[2] = 666
promptChanLock.Lock()
fmt.Println("# channels to alert: ", len(outstandingPromptChans))
for chidx, _ := range outstandingPromptChans {
alertChannel(chidx, scope, rule)
// ch <- &dbus.Call{Body: promptData}
}
promptChanLock.Unlock() */
/* err := call.Store(&scope, &rule)
if err != nil {
@ -341,9 +309,64 @@ func (p *prompter) nextConnection() (pendingConnection, bool) {
if pc == nil && qempty {
p.removePolicy(policy)
} else {
if pc == nil && !qempty {
log.Errorf("FIX ME: I NEED TO SLEEP ON A WAKEABLE CONDITION PROPERLY!!")
time.Sleep(time.Millisecond * 300)
// if pc == nil && !qempty {
if len(policy.rulesPending) > 0 {
fmt.Println("policy rules pending = ", len(policy.rulesPending))
prule := policy.rulesPending[0]
policy.rulesPending = append(policy.rulesPending[:0], policy.rulesPending[1:]...)
toks := strings.Split(prule.rule, "|")
sandbox := ""
if len(toks) > 2 {
sandbox = toks[2]
}
tempRule := fmt.Sprintf("%s|%s", toks[0], toks[1])
/* if pc.src() != nil && !pc.src().Equal(net.ParseIP("127.0.0.1")) && sandbox != "" {
tempRule += "||-1:-1|" + sandbox + "|" + pc.src().String()
} else {*/
tempRule += "||-1:-1|" + sandbox + "|"
// }
r, err := policy.parseRule(tempRule, false)
if err != nil {
log.Warningf("Error parsing rule string returned from dbus RequestPrompt: %v", err)
// policy.removePending(pc)
// pc.drop()
// return
} else {
fscope := FilterScope(prule.scope)
if fscope == APPLY_SESSION {
r.mode = RULE_MODE_SESSION
} else if fscope == APPLY_PROCESS {
r.mode = RULE_MODE_PROCESS
// r.pid = pc.procInfo().Pid
// pcoroner.MonitorProcess(r.pid)
}
if !policy.processNewRule(r, fscope) {
// p.lock.Lock()
// defer p.lock.Unlock()
// p.removePolicy(pc.policy())
}
if fscope == APPLY_FOREVER {
r.mode = RULE_MODE_PERMANENT
policy.fw.saveRules()
}
log.Warningf("Prompt returning rule: %v", tempRule)
dbusp.alertRule("sgfw prompt added new rule")
}
// }
if pc == nil && !qempty {
log.Errorf("FIX ME: I NEED TO SLEEP ON A WAKEABLE CONDITION PROPERLY!!")
time.Sleep(time.Millisecond * 300)
}
}
return pc, qempty
}
@ -353,14 +376,15 @@ func (p *prompter) nextConnection() (pendingConnection, bool) {
func (p *prompter) removePolicy(policy *Policy) {
var newQueue []*Policy = nil
if DoMultiPrompt {
if len(p.policyQueue) == 0 {
log.Debugf("Skipping over zero length policy queue")
newQueue = make([]*Policy, 0, 0)
}
// if DoMultiPrompt {
if len(p.policyQueue) == 0 {
log.Debugf("Skipping over zero length policy queue")
newQueue = make([]*Policy, 0, 0)
}
// }
if !DoMultiPrompt || newQueue == nil {
// if !DoMultiPrompt || newQueue == nil {
if newQueue == nil {
newQueue = make([]*Policy, 0, len(p.policyQueue)-1)
}
for _, pol := range p.policyQueue {
@ -374,11 +398,17 @@ func (p *prompter) removePolicy(policy *Policy) {
var userMap = make(map[int]string)
var groupMap = make(map[int]string)
var userMapLock = &sync.Mutex{}
var groupMapLock = &sync.Mutex{}
func lookupUser(uid int) string {
if uid == -1 {
return "[unknown]"
}
userMapLock.Lock()
defer userMapLock.Unlock()
u, err := user.LookupId(strconv.Itoa(uid))
if err != nil {
return fmt.Sprintf("%d", uid)
@ -390,6 +420,10 @@ func lookupGroup(gid int) string {
if gid == -1 {
return "[unknown]"
}
groupMapLock.Lock()
defer groupMapLock.Unlock()
g, err := user.LookupGroupId(strconv.Itoa(gid))
if err != nil {
return fmt.Sprintf("%d", gid)

Loading…
Cancel
Save