@ -14,11 +14,19 @@ import (
"github.com/subgraph/fw-daemon/proc-coroner"
"github.com/subgraph/fw-daemon/proc-coroner"
)
)
var gPrompter * prompter = nil
func newPrompter ( conn * dbus . Conn ) * prompter {
func newPrompter ( conn * dbus . Conn ) * prompter {
p := new ( prompter )
p := new ( prompter )
p . cond = sync . NewCond ( & p . lock )
p . cond = sync . NewCond ( & p . lock )
p . dbusObj = conn . Object ( "com.subgraph.FirewallPrompt" , "/com/subgraph/FirewallPrompt" )
p . dbusObj = conn . Object ( "com.subgraph.FirewallPrompt" , "/com/subgraph/FirewallPrompt" )
p . policyMap = make ( map [ string ] * Policy )
p . policyMap = make ( map [ string ] * Policy )
if gPrompter != nil {
fmt . Println ( "Unexpected: global prompter variable was already set!" )
}
gPrompter = p
go p . promptLoop ( )
go p . promptLoop ( )
return p
return p
}
}
@ -62,12 +70,14 @@ func (p *prompter) processNextPacket() bool {
pc , empty = p . nextConnection ( )
pc , empty = p . nextConnection ( )
p . lock . Unlock ( )
p . lock . Unlock ( )
if pc != nil {
if pc != nil {
fmt . Println ( "G OT NON NIL ")
fmt . Println ( "G ot next pending connection... ")
}
}
//fmt.Println("XXX: processNextPacket() loop; empty = ", empty, " / pc = ", pc)
//fmt.Println("XXX: processNextPacket() loop; empty = ", empty, " / pc = ", pc)
if pc == nil && empty {
if pc == nil && empty {
time . Sleep ( 100 * time . Millisecond )
return false
return false
} else if pc == nil {
} else if pc == nil {
time . Sleep ( 100 * time . Millisecond )
continue
continue
} else if pc != nil {
} else if pc != nil {
break
break
@ -80,7 +90,6 @@ func (p *prompter) processNextPacket() bool {
}
}
pc . setPrompting ( true )
pc . setPrompting ( true )
fmt . Println ( "processConnection" )
go p . processConnection ( pc )
go p . processConnection ( pc )
return true
return true
}
}
@ -93,9 +102,48 @@ type PC2FDMapping struct {
prompter * prompter
prompter * prompter
}
}
func dumpPendingQueues ( ) string {
result := ""
pctotal := 0
if gPrompter == nil {
return "Cannot query pending connections; no prompts have been issued yet!"
}
all_policies := make ( [ ] * Policy , 0 )
gPrompter . lock . Lock ( )
defer gPrompter . lock . Unlock ( )
for _ , policy := range gPrompter . policyMap {
all_policies = append ( all_policies , policy )
}
result += fmt . Sprintf ( "Total policies: %d\n" , len ( all_policies ) )
for pind , policy := range all_policies {
policy . lock . Lock ( )
if len ( policy . pendingQueue ) > 0 {
result += fmt . Sprintf ( " Policy %d of %d (%s): #pc = %d\n" , pind + 1 ,
len ( all_policies ) , policy . application , len ( policy . pendingQueue ) )
for pcind , pc := range policy . pendingQueue {
result += fmt . Sprintf ( " %d: %s\n" , pcind + 1 , pc . print ( ) )
pctotal ++
}
}
policy . lock . Unlock ( )
}
result += "-----------------------------------\n"
result = fmt . Sprintf ( "Pending Queues / total pending connections = %d\n" , pctotal ) + result
return result
}
var PC2FDMap = map [ string ] PC2FDMapping { }
var PC2FDMap = map [ string ] PC2FDMapping { }
var PC2FDMapLock = & sync . Mutex { }
var PC2FDMapLock = & sync . Mutex { }
var PC2FDMapRunning = false
func monitorPromptFDs ( pc pendingConnection ) {
func monitorPromptFDs ( pc pendingConnection ) {
guid := pc . getGUID ( )
guid := pc . getGUID ( )
@ -104,7 +152,7 @@ func monitorPromptFDs(pc pendingConnection) {
fd := pc . procInfo ( ) . FD
fd := pc . procInfo ( ) . FD
prompter := pc . getPrompter ( )
prompter := pc . getPrompter ( )
fmt . Printf ( "ADD TO MONITOR: %v | %v / %v / %v\n" , pc . policy ( ) . application , guid , pid , fd )
//fmt.Printf("ADD TO MONITOR: %v | %v / %v / %v\n", pc.policy().application, guid, pid, fd)
if pid == - 1 || fd == - 1 || prompter == nil {
if pid == - 1 || fd == - 1 || prompter == nil {
log . Warning ( "Unexpected error condition occurred while adding socket fd to monitor" )
log . Warning ( "Unexpected error condition occurred while adding socket fd to monitor" )
@ -119,16 +167,28 @@ func monitorPromptFDs(pc pendingConnection) {
return
return
}
}
func dumpMonitoredFDs ( ) string {
PC2FDMapLock . Lock ( )
defer PC2FDMapLock . Unlock ( )
cnt := 1
result := fmt . Sprintf ( "Monitored FDs: %v total\n" , len ( PC2FDMap ) )
for guid , fdmon := range PC2FDMap {
result += fmt . Sprintf ( "%d: %s -> [inode=%v, fd=%d, fdpath=%s]\n" , cnt , guid , fdmon . inode , fdmon . fd , fdmon . fdpath )
cnt ++
}
result += "-----------------------------------\n"
return result
}
func monitorPromptFDLoop ( ) {
func monitorPromptFDLoop ( ) {
fmt . Println ( "++++++++++= monitorPromptFDLoop()" )
for true {
for true {
delete_guids := [ ] string { }
delete_guids := [ ] string { }
PC2FDMapLock . Lock ( )
PC2FDMapLock . Lock ( )
fmt . Println ( "++++ nentries = " , len ( PC2FDMap ) )
for guid , fdmon := range PC2FDMap {
for guid , fdmon := range PC2FDMap {
fmt . Println ( "ENTRY:" , fdmon )
lsb , err := os . Stat ( fdmon . fdpath )
lsb , err := os . Stat ( fdmon . fdpath )
if err != nil {
if err != nil {
@ -154,7 +214,10 @@ func monitorPromptFDLoop() {
}
}
fmt . Println ( "guids to delete: " , delete_guids )
if len ( delete_guids ) > 0 {
fmt . Println ( "guids to delete: " , delete_guids )
}
saved_mappings := [ ] PC2FDMapping { }
saved_mappings := [ ] PC2FDMapping { }
for _ , guid := range delete_guids {
for _ , guid := range delete_guids {
saved_mappings = append ( saved_mappings , PC2FDMap [ guid ] )
saved_mappings = append ( saved_mappings , PC2FDMap [ guid ] )
@ -164,9 +227,10 @@ func monitorPromptFDLoop() {
PC2FDMapLock . Unlock ( )
PC2FDMapLock . Unlock ( )
for _ , mapping := range saved_mappings {
for _ , mapping := range saved_mappings {
call : = mapping . prompter . dbusObj . Call ( "com.subgraph.FirewallPrompt.RemovePrompt" , 0 , mapping . guid )
_ = mapping . prompter . dbusObj . Call ( "com.subgraph.FirewallPrompt.RemovePrompt" , 0 , mapping . guid )
fmt . Println ( "DISPOSING CALL = " , call )
// fmt.Println("DISPOSING CALL = ", call)
prompter := mapping . prompter
prompter := mapping . prompter
found := false
prompter . lock . Lock ( )
prompter . lock . Lock ( )
@ -177,8 +241,9 @@ func monitorPromptFDLoop() {
for pcind < len ( policy . pendingQueue ) {
for pcind < len ( policy . pendingQueue ) {
if policy . pendingQueue [ pcind ] . getGUID ( ) == mapping . guid {
if policy . pendingQueue [ pcind ] . getGUID ( ) == mapping . guid {
fmt . Println ( "-------------- found guid to remove" )
// fmt.Println("-------------- found guid to remove")
policy . pendingQueue = append ( policy . pendingQueue [ : pcind ] , policy . pendingQueue [ pcind + 1 : ] ... )
policy . pendingQueue = append ( policy . pendingQueue [ : pcind ] , policy . pendingQueue [ pcind + 1 : ] ... )
found = true
} else {
} else {
pcind ++
pcind ++
}
}
@ -188,33 +253,27 @@ func monitorPromptFDLoop() {
policy . lock . Unlock ( )
policy . lock . Unlock ( )
}
}
if ! found {
fmt . Println ( "Warning: FD monitor could not find pending connection to map to removed GUID: %s" , mapping . guid )
}
prompter . lock . Unlock ( )
prompter . lock . Unlock ( )
}
}
fmt . Println ( "++++++++++= monitorPromptFDLoop WAIT" )
time . Sleep ( 5 * time . Second )
time . Sleep ( 5 * time . Second )
}
}
}
}
func init ( ) {
go monitorPromptFDLoop ( )
}
func ( p * prompter ) processConnection ( pc pendingConnection ) {
func ( p * prompter ) processConnection ( pc pendingConnection ) {
var scope int32
var scope int32
var dres bool
var dres bool
var rule string
var rule string
if ! PC2FDMapRunning {
PC2FDMapLock . Lock ( )
if ! PC2FDMapRunning {
PC2FDMapRunning = true
PC2FDMapLock . Unlock ( )
go monitorPromptFDLoop ( )
} else {
PC2FDMapLock . Unlock ( )
}
}
if pc . getPrompter ( ) == nil {
if pc . getPrompter ( ) == nil {
pc . setPrompter ( p )
pc . setPrompter ( p )
}
}
@ -338,10 +397,10 @@ func (p *prompter) nextConnection() (pendingConnection, bool) {
if len ( p . policyQueue ) == 0 {
if len ( p . policyQueue ) == 0 {
return nil , true
return nil , true
}
}
fmt . Println ( "policy queue len = " , len ( p . policyQueue ) )
//fmt.Println("policy queue len = ", len(p.policyQueue))
for pind < len ( p . policyQueue ) {
for pind < len ( p . policyQueue ) {
fmt . Printf ( "policy loop %d of %d\n" , pind , len ( p . policyQueue ) )
//fmt.Printf("policy loop %d of %d\n", pind, len(p.policyQueue))
//fmt.Printf("XXX: pind = %v of %v\n", pind, len(p.policyQueue))
//fmt.Printf("XXX: pind = %v of %v\n", pind, len(p.policyQueue))
policy := p . policyQueue [ pind ]
policy := p . policyQueue [ pind ]
pc , qempty := policy . nextPending ( )
pc , qempty := policy . nextPending ( )
@ -362,7 +421,11 @@ func (p *prompter) nextConnection() (pendingConnection, bool) {
pendingOther = append ( pendingOther , r )
pendingOther = append ( pendingOther , r )
}
}
}
}
fmt . Printf ( "# pending once = %d, other = %d, pc = %p / policy = %p\n" , len ( pendingOnce ) , len ( pendingOther ) , pc , policy )
if len ( pendingOnce ) > 0 || len ( pendingOther ) > 0 {
fmt . Printf ( "# pending once = %d, other = %d, pc = %p / policy = %p\n" , len ( pendingOnce ) , len ( pendingOther ) , pc , policy )
}
policy . rulesPending = pendingOther
policy . rulesPending = pendingOther
// One time filters are all applied right here, at once.
// One time filters are all applied right here, at once.