Very noisy, experimental support for asynchronous multi-rule firewall prompting.

Fixed prompted rule removal bug in fw-prompt.
shw_dev
shw 7 years ago
parent 3319802a80
commit 5f5042fed4

@ -570,8 +570,9 @@ func clearEditor() {
chkGroup.SetActive(false)
}
func removeSelectedRule(idx int) error {
func removeSelectedRule(idx int, rmdecision bool) error {
fmt.Println("XXX: attempting to remove idx = ", idx)
path, err := gtk.TreePathNewFromString(fmt.Sprintf("%d", idx))
if err != nil {
return err
@ -582,14 +583,12 @@ func removeSelectedRule(idx int) error {
return err
}
ok := globalLS.Remove(iter)
globalLS.Remove(iter)
// XXX: hmmm? why does this work? shouldn't it be the opposite?
if ok {
return errors.New("Unexpected error removing rule from list")
if rmdecision {
decisionWaiters = append(decisionWaiters[:idx], decisionWaiters[idx+1:]...)
}
decisionWaiters = append(decisionWaiters[:idx], decisionWaiters[idx+1:]...)
toggleHover()
return nil
}
@ -879,7 +878,7 @@ func main() {
fmt.Println("RULESTR = ", rulestr)
makeDecision(idx, rulestr, int(rule.Scope))
fmt.Println("Decision made.")
err = removeSelectedRule(idx)
err = removeSelectedRule(idx, true)
if err == nil {
clearEditor()
} else {
@ -905,7 +904,7 @@ func main() {
fmt.Println("RULESTR = ", rulestr)
makeDecision(idx, rulestr, int(rule.Scope))
fmt.Println("Decision made.")
err = removeSelectedRule(idx)
err = removeSelectedRule(idx, true)
if err == nil {
clearEditor()
} else {
@ -922,7 +921,7 @@ func main() {
makeDecision(idx, "", 0)
fmt.Println("Decision made.")
err = removeSelectedRule(idx)
err = removeSelectedRule(idx, true)
if err == nil {
clearEditor()
} else {

@ -93,7 +93,7 @@ const FirewallPromptHandler = new Lang.Class({
RequestPromptAsync: function(params, invocation) {
let [app, icon, path, address, port, ip, origin, proto, uid, gid, user, group, pid, optstring, expanded, expert, action] = params;
this._closeDialog();
// this._closeDialog();
this._dialog = new Dialog.PromptDialog(invocation);
this._invocation = invocation;
this._dialog.update(app, icon, path, address, port, ip, origin, uid, gid, user, group, pid, proto, optstring, expanded, expert, action);

@ -24,7 +24,7 @@ var _interpreters = []string{
"bash",
}
type sandboxRule struct {
/*type sandboxRule struct {
SrcIf net.IP
DstIP net.IP
DstPort uint16
@ -33,7 +33,7 @@ type sandboxRule struct {
var sandboxRules = []sandboxRule {
// { net.IP{172,16,1,42}, net.IP{140,211,166,134}, 21, false },
}
} */
type pendingConnection interface {
policy() *Policy
@ -47,6 +47,8 @@ type pendingConnection interface {
dstPort() uint16
accept()
drop()
setPrompting(bool)
getPrompting() bool
print() string
}
@ -56,6 +58,7 @@ type pendingPkt struct {
pkt *nfqueue.NFQPacket
pinfo *procsnitch.Info
optstring string
prompting bool
}
func getEmptyPInfo() *procsnitch.Info {
@ -152,6 +155,14 @@ func (pp *pendingPkt) drop() {
pp.pkt.Accept()
}
func (pp *pendingPkt) getPrompting() bool {
return pp.prompting
}
func (pp *pendingPkt) setPrompting(val bool) {
pp.prompting = val
}
func (pp *pendingPkt) print() string {
return printPacket(pp.pkt, pp.name, pp.pinfo)
}
@ -216,7 +227,7 @@ func (p *Policy) processPacket(pkt *nfqueue.NFQPacket, pinfo *procsnitch.Info, o
case FILTER_ALLOW:
pkt.Accept()
case FILTER_PROMPT:
p.processPromptResult(&pendingPkt{pol: p, name: name, pkt: pkt, pinfo: pinfo, optstring: optstr})
p.processPromptResult(&pendingPkt{pol: p, name: name, pkt: pkt, pinfo: pinfo, optstring: optstr, prompting: false})
default:
log.Warningf("Unexpected filter result: %d", result)
}
@ -224,19 +235,41 @@ func (p *Policy) processPacket(pkt *nfqueue.NFQPacket, pinfo *procsnitch.Info, o
func (p *Policy) processPromptResult(pc pendingConnection) {
p.pendingQueue = append(p.pendingQueue, pc)
if !p.promptInProgress {
fmt.Println("processPromptResult(): p.promptInProgress = ", p.promptInProgress)
if DoMultiPrompt || (!DoMultiPrompt && !p.promptInProgress) {
p.promptInProgress = true
go p.fw.dbus.prompt(p)
}
}
func (p *Policy) nextPending() pendingConnection {
func (p *Policy) nextPending() (pendingConnection, bool) {
p.lock.Lock()
fmt.Println("nextPending(): len = ", len(p.pendingQueue))
defer p.lock.Unlock()
if !DoMultiPrompt {
if len(p.pendingQueue) == 0 {
return nil, true
}
return p.pendingQueue[0], false
}
if len(p.pendingQueue) == 0 {
return nil
return nil, true
}
return p.pendingQueue[0]
// for len(p.pendingQueue) != 0 {
fmt.Println("nextPending() loop: len = ", len(p.pendingQueue))
for i := 0; i < len(p.pendingQueue); i++ {
fmt.Printf("pendingqueue %v: %v\n", i, p.pendingQueue[i].getPrompting())
if !p.pendingQueue[i].getPrompting() {
return p.pendingQueue[i], false
}
}
// }
fmt.Println("nextPending() returning")
return nil, false
}
func (p *Policy) removePending(pc pendingConnection) {

@ -10,6 +10,12 @@ import (
"github.com/godbus/dbus"
)
var DoMultiPrompt = true
const MAX_PROMPTS = 3
var outstandingPrompts = 0
var promptLock = &sync.Mutex{}
func newPrompter(conn *dbus.Conn) *prompter {
p := new(prompter)
p.cond = sync.NewCond(&p.lock)
@ -42,27 +48,86 @@ func (p *prompter) prompt(policy *Policy) {
func (p *prompter) promptLoop() {
p.lock.Lock()
for {
fmt.Println("promptLoop() outer")
for p.processNextPacket() {
fmt.Println("promptLoop() inner")
}
fmt.Println("promptLoop() wait")
p.cond.Wait()
}
}
func (p *prompter) processNextPacket() bool {
pc := p.nextConnection()
if pc == nil {
return false
var pc pendingConnection = nil
if !DoMultiPrompt {
pc, _ = p.nextConnection()
if pc == nil {
return false
}
p.lock.Unlock()
defer p.lock.Lock()
p.processConnection(pc)
return true
}
empty := true
for {
pc, empty = p.nextConnection()
fmt.Println("processNextPacket() loop; empty = ", empty, " / pc = ", pc)
if pc == nil && empty {
return false
} else if pc == nil {
continue
} else if pc != nil {
break
}
}
p.lock.Unlock()
defer p.lock.Lock()
p.processConnection(pc)
fmt.Println("Waiting for prompt lock go...")
for {
promptLock.Lock()
if outstandingPrompts >= MAX_PROMPTS {
promptLock.Unlock()
continue
}
if pc.getPrompting() {
fmt.Println("Skipping over already prompted connection")
promptLock.Unlock()
continue
}
break
}
fmt.Println("Passed prompt lock!")
outstandingPrompts++
fmt.Println("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("Return decremented outstanding to ", outstandingPrompts)
promptLock.Unlock()
pc.setPrompting(false)
}
func (p *prompter) processConnection(pc pendingConnection) {
var scope int32
var rule string
if DoMultiPrompt {
defer processReturn(pc)
}
addr := pc.hostname()
if addr == "" {
addr = pc.dst().String()
@ -124,23 +189,35 @@ func (p *prompter) processConnection(pc pendingConnection) {
dbusp.alertRule("sgfw prompt added new rule")
}
func (p *prompter) nextConnection() pendingConnection {
func (p *prompter) nextConnection() (pendingConnection, bool) {
fmt.Println("nextConnection()")
for {
if len(p.policyQueue) == 0 {
return nil
return nil, true
}
policy := p.policyQueue[0]
pc := policy.nextPending()
if pc == nil {
pc, qempty := policy.nextPending()
if pc == nil && qempty {
p.removePolicy(policy)
} else {
return pc
return pc, qempty
}
}
}
func (p *prompter) removePolicy(policy *Policy) {
newQueue := make([]*Policy, 0, len(p.policyQueue)-1)
var newQueue []*Policy = nil
if DoMultiPrompt {
if len(p.policyQueue) == 0 {
fmt.Println("Skipping over zero length policy queue")
newQueue = make([]*Policy, 0, 0)
}
}
if !DoMultiPrompt || newQueue == nil {
newQueue = make([]*Policy, 0, len(p.policyQueue)-1)
}
for _, pol := range p.policyQueue {
if pol != policy {
newQueue = append(newQueue, pol)

@ -51,6 +51,7 @@ type pendingSocksConnection struct {
destPort uint16
pinfo *procsnitch.Info
verdict chan int
prompting bool
}
func (sc *pendingSocksConnection) policy() *Policy {
@ -95,6 +96,10 @@ func (sc *pendingSocksConnection) accept() { sc.deliverVerdict(socksVerdictAccep
func (sc *pendingSocksConnection) drop() { sc.deliverVerdict(socksVerdictDrop) }
func (sc *pendingSocksConnection) getPrompting() bool { return sc.prompting }
func (sc *pendingSocksConnection) setPrompting(val bool) { sc.prompting = val }
func (sc *pendingSocksConnection) print() string { return "socks connection" }
func NewSocksChain(cfg *socksChainConfig, wg *sync.WaitGroup, fw *Firewall) *socksChain {
@ -247,6 +252,7 @@ func (c *socksChainSession) filterConnect() bool {
destPort: port,
pinfo: pinfo,
verdict: make(chan int),
prompting: false,
}
policy.processPromptResult(pending)
v := <-pending.verdict

Loading…
Cancel
Save