diff --git a/TODO b/TODO new file mode 100644 index 0000000..59791c2 --- /dev/null +++ b/TODO @@ -0,0 +1,6 @@ +fw-prompt: + This function needs to be updated because it no longer works: + func toggleHover() { mainWin.SetKeepAbove(len(decisionWaiters) > 0) } + +new go-procsnitch vendor package changes should be pushed into main project + diff --git a/fw-prompt/dbus.go b/fw-prompt/dbus.go index d9ca0fe..8a300a8 100644 --- a/fw-prompt/dbus.go +++ b/fw-prompt/dbus.go @@ -55,7 +55,7 @@ func newDbusServer() (*dbusServer, error) { func (ds *dbusServer) RequestPrompt(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) (int32, string, *dbus.Error) { log.Printf("request prompt: app = %s, icon = %s, path = %s, address = %s / ip = %s, is_socks = %v, action = %v\n", application, icon, path, address, ip, is_socks, action) - decision := addRequest(nil, guid, path, icon, proto, int(pid), ip, address, int(port), int(uid), int(gid), origin, is_socks, optstring, sandbox) + decision := addRequest(nil, guid, path, icon, proto, int(pid), ip, address, int(port), int(uid), int(gid), origin, is_socks, optstring, sandbox, int(action)) log.Print("Waiting on decision...") decision.Cond.L.Lock() for !decision.Ready { @@ -69,7 +69,7 @@ func (ds *dbusServer) RequestPrompt(guid, application, icon, path, address strin 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) + addRequestAsync(nil, guid, path, icon, proto, int(pid), ip, address, int(port), int(uid), int(gid), origin, is_socks, optstring, sandbox, int(action)) return true, nil } diff --git a/fw-prompt/fw-prompt.go b/fw-prompt/fw-prompt.go index 786371d..8c97b17 100644 --- a/fw-prompt/fw-prompt.go +++ b/fw-prompt/fw-prompt.go @@ -314,8 +314,8 @@ func createColumn(title string, id int) *gtk.TreeViewColumn { } func createListStore(general bool) *gtk.ListStore { - colData := []glib.Type{glib.TYPE_INT, 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_INT, glib.TYPE_STRING} + colData := []glib.Type{glib.TYPE_INT, 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_INT, glib.TYPE_STRING, glib.TYPE_INT} listStore, err := gtk.ListStoreNew(colData...) if err != nil { @@ -350,7 +350,8 @@ func removeRequest(listStore *gtk.ListStore, guid string) { } -func addRequestInc(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 { +func addRequestInc(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, action int) bool { duplicated := false globalPromptLock.Lock() @@ -383,7 +384,8 @@ func addRequestInc(listStore *gtk.ListStore, guid, path, icon, proto string, pid return duplicated } -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 { +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, action int) bool { if listStore == nil { listStore = globalLS waitTimes := []int{1, 2, 5, 10} @@ -410,7 +412,7 @@ func addRequestAsync(listStore *gtk.ListStore, guid, path, icon, proto string, p 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) { + if addRequestInc(listStore, guid, path, icon, proto, pid, ipaddr, hostname, port, uid, gid, origin, is_socks, optstring, sandbox, action) { fmt.Println("REQUEST WAS DUPLICATE") return false } else { @@ -428,7 +430,7 @@ func addRequestAsync(listStore *gtk.ListStore, guid, path, icon, proto string, p } } - colVals := make([]interface{}, 14) + colVals := make([]interface{}, 15) colVals[0] = 1 colVals[1] = guid colVals[2] = path @@ -454,6 +456,7 @@ func addRequestAsync(listStore *gtk.ListStore, guid, path, icon, proto string, p } colVals[13] = optstring + colVals[14] = action colNums := make([]int, len(colVals)) @@ -472,7 +475,8 @@ func addRequestAsync(listStore *gtk.ListStore, guid, path, icon, proto string, p 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 { +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, action int) *decisionWaiter { if listStore == nil { listStore = globalLS waitTimes := []int{1, 2, 5, 10} @@ -499,7 +503,7 @@ func addRequest(listStore *gtk.ListStore, guid, path, icon, proto string, pid in 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) { + if addRequestInc(listStore, guid, path, icon, proto, pid, ipaddr, hostname, port, uid, gid, origin, is_socks, optstring, sandbox, action) { fmt.Println("REQUEST WAS DUPLICATE") decision := addDecision() toggleHover() @@ -519,7 +523,7 @@ func addRequest(listStore *gtk.ListStore, guid, path, icon, proto string, pid in } } - colVals := make([]interface{}, 14) + colVals := make([]interface{}, 15) colVals[0] = 1 colVals[1] = guid colVals[2] = path @@ -545,6 +549,7 @@ func addRequest(listStore *gtk.ListStore, guid, path, icon, proto string, pid in } colVals[13] = optstring + colVals[14] = action colNums := make([]int, len(colVals)) @@ -774,6 +779,7 @@ func createCurrentRule() (ruleColumns, error) { rule.Uname, rule.Gname = "", "" rule.ForceTLS = chkTLS.GetActive() + /* Pid int Origin string */ @@ -915,6 +921,11 @@ func getRuleByIdx(idx int) (ruleColumns, *gtk.TreeIter, error) { rule.IsSocks = true } + rule.Scope, err = lsGetInt(globalLS, iter, 14) + if err != nil { + return rule, nil, err + } + return rule, iter, nil } @@ -953,7 +964,7 @@ func addPendingPrompts(rules []string) { for _, rule := range rules { fields := strings.Split(rule, "|") - if len(fields) != 17 { + if len(fields) != 18 { log.Printf("Got saved prompt message with strange data: \"%s\"", rule) continue } @@ -1001,7 +1012,13 @@ func addPendingPrompts(rules []string) { optstring := fields[16] - addRequestAsync(nil, guid, path, icon, proto, int(pid), ip, address, int(port), int(uid), int(gid), origin, is_socks, optstring, sandbox) + action, err := strconv.Atoi(fields[17]) + if err != nil { + log.Println("Error converting action in pending prompt message to integer:", err) + continue + } + + addRequestAsync(nil, guid, path, icon, proto, int(pid), ip, address, int(port), int(uid), int(gid), origin, is_socks, optstring, sandbox, action) } } @@ -1206,6 +1223,10 @@ func main() { tv.AppendColumn(createColumn("Details", 13)) + acol := createColumn("Scope", 14) + acol.SetVisible(false) + tv.AppendColumn(acol) + listStore := createListStore(true) globalLS = listStore @@ -1322,12 +1343,12 @@ func main() { } editPort.SetText(strconv.Itoa(seldata.Port)) - radioOnce.SetActive(true) - radioProcess.SetActive(false) + radioOnce.SetActive(seldata.Scope == int(sgfw.APPLY_ONCE)) radioProcess.SetSensitive(seldata.Pid > 0) radioParent.SetActive(false) - radioSession.SetActive(false) - radioPermanent.SetActive(false) + radioSession.SetActive(seldata.Scope == int(sgfw.APPLY_SESSION)) + radioPermanent.SetActive(seldata.Scope == int(sgfw.APPLY_FOREVER)) + comboProto.SetActiveID(seldata.Proto) chkTLS.SetActive(seldata.IsSocks) diff --git a/sgfw/dbus.go b/sgfw/dbus.go index 9abfa99..a853d5e 100644 --- a/sgfw/dbus.go +++ b/sgfw/dbus.go @@ -241,7 +241,8 @@ func (ds *dbusServer) GetPendingRequests(policy string) ([]string, *dbus.Error) pstr += strconv.FormatInt(int64(pc.procInfo().Pid), 10) + "|" pstr += pc.sandbox() + "|" pstr += strconv.FormatBool(pc.socks()) + "|" - pstr += pc.getOptString() + pstr += pc.getOptString() + "|" + pstr += strconv.FormatUint(uint64(FirewallConfig.DefaultActionID), 10) pending_data = append(pending_data, pstr) } @@ -334,10 +335,10 @@ func (ds *dbusServer) SetConfig(key string, val dbus.Variant) *dbus.Error { return nil } -func (ds *dbusServer) prompt(p *Policy) { +/*func (ds *dbusServer) prompt(p *Policy) { log.Info("prompting...") ds.prompter.prompt(p) -} +} */ func (ob *dbusObjectP) alertRule(data string) { ob.Call("com.subgraph.fwprompt.EventNotifier.Alert", 0, data) diff --git a/sgfw/policy.go b/sgfw/policy.go index 2f9858d..03ab932 100644 --- a/sgfw/policy.go +++ b/sgfw/policy.go @@ -50,8 +50,8 @@ type pendingConnection interface { drop() setPrompting(bool) getPrompting() bool - setPrompter(*dbusObjectP) - getPrompter() *dbusObjectP + setPrompter(*prompter) + getPrompter() *prompter getGUID() string print() string } @@ -63,7 +63,7 @@ type pendingPkt struct { pinfo *procsnitch.Info optstring string prompting bool - prompter *dbusObjectP + prompter *prompter guid string } @@ -183,11 +183,11 @@ func (pp *pendingPkt) drop() { pp.pkt.Accept() } -func (pp *pendingPkt) setPrompter(val *dbusObjectP) { +func (pp *pendingPkt) setPrompter(val *prompter) { pp.prompter = val } -func (pp *pendingPkt) getPrompter() *dbusObjectP { +func (pp *pendingPkt) getPrompter() *prompter { return pp.prompter } @@ -320,32 +320,24 @@ func (p *Policy) processPromptResult(pc pendingConnection) { //if DoMultiPrompt || (!DoMultiPrompt && !p.promptInProgress) { // if !p.promptInProgress { p.promptInProgress = true - go p.fw.dbus.prompt(p) + go p.fw.dbus.prompter.prompt(p) // } } func (p *Policy) nextPending() (pendingConnection, bool) { p.lock.Lock() 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, true } - // 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 } } - // } return nil, false } @@ -421,7 +413,7 @@ func (p *Policy) filterPending(rule *Rule) { if prompter == nil { fmt.Println("-------- prompter = NULL") } else { - call := prompter.Call("com.subgraph.FirewallPrompt.RemovePrompt", 0, pc.getGUID()) + call := prompter.dbusObj.Call("com.subgraph.FirewallPrompt.RemovePrompt", 0, pc.getGUID()) fmt.Println("CAAAAAAAAAAAAAAALL = ", call) } diff --git a/sgfw/prompt.go b/sgfw/prompt.go index ee72a13..2705e38 100644 --- a/sgfw/prompt.go +++ b/sgfw/prompt.go @@ -3,10 +3,12 @@ package sgfw import ( "fmt" "net" + "os" "os/user" "strconv" "strings" "sync" + "syscall" "time" "github.com/godbus/dbus" @@ -35,6 +37,7 @@ func (p *prompter) prompt(policy *Policy) { defer p.lock.Unlock() _, ok := p.policyMap[policy.sandbox+"|"+policy.path] if ok { + p.cond.Signal() return } p.policyMap[policy.sandbox+"|"+policy.path] = policy @@ -44,21 +47,23 @@ func (p *prompter) prompt(policy *Policy) { } func (p *prompter) promptLoop() { - p.lock.Lock() + // p.lock.Lock() for { // fmt.Println("XXX: promptLoop() outer") + p.lock.Lock() for p.processNextPacket() { // fmt.Println("XXX: promptLoop() inner") } + p.lock.Unlock() // fmt.Println("promptLoop() wait") - p.cond.Wait() + // p.cond.Wait() } } func (p *prompter) processNextPacket() bool { var pc pendingConnection = nil - if 1 == 2 { + /* if 1 == 2 { // if !DoMultiPrompt { pc, _ = p.nextConnection() if pc == nil { @@ -68,12 +73,12 @@ func (p *prompter) processNextPacket() bool { defer p.lock.Lock() p.processConnection(pc) return true - } + } */ empty := true for { pc, empty = p.nextConnection() - // fmt.Println("XXX: processNextPacket() loop; empty = ", empty, " / pc = ", pc) + fmt.Println("XXX: processNextPacket() loop; empty = ", empty, " / pc = ", pc) if pc == nil && empty { return false } else if pc == nil { @@ -85,27 +90,145 @@ func (p *prompter) processNextPacket() bool { p.lock.Unlock() defer p.lock.Lock() // fmt.Println("XXX: Waiting for prompt lock go...") - for { - - if pc.getPrompting() { - log.Debugf("Skipping over already prompted connection") - continue - } - - break + if pc.getPrompting() { + log.Debugf("Skipping over already prompted connection") } + pc.setPrompting(true) go p.processConnection(pc) return true } +type PC2FDMapping struct { + guid string + inode uint64 + fd int + fdpath string + prompter *prompter +} + +var PC2FDMap = map[string]PC2FDMapping{} +var PC2FDMapLock = &sync.Mutex{} +var PC2FDMapRunning = false + +func monitorPromptFDs(pc pendingConnection) { + guid := pc.getGUID() + pid := pc.procInfo().Pid + inode := pc.procInfo().Inode + fd := pc.procInfo().FD + prompter := pc.getPrompter() + + fmt.Printf("ADD TO MONITOR: %v | %v / %v / %v\n", pc.policy().application, guid, pid, fd) + + if pid == -1 || fd == -1 || prompter == nil { + log.Warning("Unexpected error condition occurred while adding socket fd to monitor") + return + } + + PC2FDMapLock.Lock() + defer PC2FDMapLock.Unlock() + + fdpath := fmt.Sprintf("/proc/%d/fd/%d", pid, fd) + PC2FDMap[guid] = PC2FDMapping{guid: guid, inode: inode, fd: fd, fdpath: fdpath, prompter: prompter} + return +} + +func monitorPromptFDLoop() { + fmt.Println("++++++++++= monitorPromptFDLoop()") + + for true { + delete_guids := []string{} + PC2FDMapLock.Lock() + fmt.Println("++++ nentries = ", len(PC2FDMap)) + + for guid, fdmon := range PC2FDMap { + fmt.Println("ENTRY:", fdmon) + + lsb, err := os.Stat(fdmon.fdpath) + if err != nil { + log.Warningf("Error looking up socket \"%s\": %v\n", fdmon.fdpath, err) + delete_guids = append(delete_guids, guid) + continue + } + + sb, ok := lsb.Sys().(*syscall.Stat_t) + if !ok { + log.Warning("Not a syscall.Stat_t") + delete_guids = append(delete_guids, guid) + continue + } + + inode := sb.Ino + fmt.Println("+++ INODE = ", inode) + + if inode != fdmon.inode { + fmt.Printf("inode mismatch: %v vs %v\n", inode, fdmon.inode) + delete_guids = append(delete_guids, guid) + } + + } + + fmt.Println("guids to delete: ", delete_guids) + saved_mappings := []PC2FDMapping{} + for _, guid := range delete_guids { + saved_mappings = append(saved_mappings, PC2FDMap[guid]) + delete(PC2FDMap, guid) + } + + PC2FDMapLock.Unlock() + + for _, mapping := range saved_mappings { + call := mapping.prompter.dbusObj.Call("com.subgraph.FirewallPrompt.RemovePrompt", 0, mapping.guid) + fmt.Println("DISPOSING CALL = ", call) + prompter := mapping.prompter + + prompter.lock.Lock() + + for _, policy := range prompter.policyQueue { + policy.lock.Lock() + pcind := 0 + + for pcind < len(policy.pendingQueue) { + + if policy.pendingQueue[pcind].getGUID() == mapping.guid { + fmt.Println("-------------- found guid to remove") + policy.pendingQueue = append(policy.pendingQueue[:pcind], policy.pendingQueue[pcind+1:]...) + } else { + pcind++ + } + + } + + policy.lock.Unlock() + } + + prompter.lock.Unlock() + } + + fmt.Println("++++++++++= monitorPromptFDLoop WAIT") + time.Sleep(5 * time.Second) + } + +} + func (p *prompter) processConnection(pc pendingConnection) { var scope int32 var dres bool var rule string + if !PC2FDMapRunning { + PC2FDMapLock.Lock() + + if !PC2FDMapRunning { + PC2FDMapRunning = true + PC2FDMapLock.Unlock() + go monitorPromptFDLoop() + } + + } + if pc.getPrompter() == nil { - pc.setPrompter(&dbusObjectP{p.dbusObj}) + pc.setPrompter(p) } addr := pc.hostname() @@ -127,6 +250,7 @@ func (p *prompter) processConnection(pc pendingConnection) { // fmt.Println("# outstanding prompt chans = ", len(outstandingPromptChans)) // fmt.Println("ABOUT TO CALL ASYNC PROMPT") + monitorPromptFDs(pc) call := p.dbusObj.Call("com.subgraph.FirewallPrompt.RequestPromptAsync", 0, pc.getGUID(), policy.application, @@ -300,15 +424,23 @@ func (p *prompter) processConnection(pc pendingConnection) { } func (p *prompter) nextConnection() (pendingConnection, bool) { - for { - if len(p.policyQueue) == 0 { - return nil, true - } - policy := p.policyQueue[0] + pind := 0 + + if len(p.policyQueue) == 0 { + return nil, true + } + fmt.Println("policy queue len = ", len(p.policyQueue)) + + for pind < len(p.policyQueue) { + fmt.Printf("pind = %v of %v\n", pind, len(p.policyQueue)) + policy := p.policyQueue[pind] pc, qempty := policy.nextPending() + if pc == nil && qempty { p.removePolicy(policy) + continue } else { + pind++ // if pc == nil && !qempty { if len(policy.rulesPending) > 0 { @@ -360,17 +492,24 @@ func (p *prompter) nextConnection() (pendingConnection, bool) { 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) - } + if pc == nil && !qempty { + // log.Errorf("FIX ME: I NEED TO SLEEP ON A WAKEABLE CONDITION PROPERLY!!") + time.Sleep(time.Millisecond * 300) + continue + } + if pc != nil && pc.getPrompting() { + fmt.Println("SKIPPING PROMPTED") + continue } + return pc, qempty } } + + return nil, true } func (p *prompter) removePolicy(policy *Policy) { diff --git a/sgfw/rules.go b/sgfw/rules.go index adeb3f7..f5795f8 100644 --- a/sgfw/rules.go +++ b/sgfw/rules.go @@ -479,7 +479,10 @@ func (fw *Firewall) loadRules() { if err != nil { if !os.IsNotExist(err) { log.Warningf("Failed to open %s for reading: %v", p, err) + } else { + log.Warningf("Did not find a rules file at %s: SGFW loaded with no rules\n", p) } + return } var policy *Policy @@ -497,7 +500,13 @@ func (fw *Firewall) loadRules() { func (fw *Firewall) processPathLine(line string) *Policy { pathLine := line[1 : len(line)-1] + toks := strings.Split(pathLine, "|") + if len(toks) != 2 { + log.Warning("Error parsing rules directive:", line) + return nil + } + policy := fw.policyForPathAndSandbox(toks[1], toks[0]) policy.lock.Lock() defer policy.lock.Unlock() diff --git a/sgfw/socks_server_chain.go b/sgfw/socks_server_chain.go index 9a2a2dd..85ee570 100644 --- a/sgfw/socks_server_chain.go +++ b/sgfw/socks_server_chain.go @@ -56,7 +56,7 @@ type pendingSocksConnection struct { pinfo *procsnitch.Info verdict chan int prompting bool - prompter *dbusObjectP + prompter *prompter guid string optstr string } @@ -124,9 +124,9 @@ func (sc *pendingSocksConnection) acceptTLSOnly() { sc.deliverVerdict(socksVerdi func (sc *pendingSocksConnection) drop() { sc.deliverVerdict(socksVerdictDrop) } -func (sc *pendingSocksConnection) setPrompter(val *dbusObjectP) { sc.prompter = val } +func (sc *pendingSocksConnection) setPrompter(val *prompter) { sc.prompter = val } -func (sc *pendingSocksConnection) getPrompter() *dbusObjectP { return sc.prompter } +func (sc *pendingSocksConnection) getPrompter() *prompter { return sc.prompter } func (sc *pendingSocksConnection) getGUID() string { if sc.guid == "" { diff --git a/vendor/github.com/subgraph/go-procsnitch/proc.go b/vendor/github.com/subgraph/go-procsnitch/proc.go index 823850e..fe23232 100644 --- a/vendor/github.com/subgraph/go-procsnitch/proc.go +++ b/vendor/github.com/subgraph/go-procsnitch/proc.go @@ -1,8 +1,8 @@ package procsnitch import ( - "encoding/hex" "encoding/binary" + "encoding/hex" "errors" "fmt" "github.com/op/go-logging" @@ -169,7 +169,7 @@ func ParseIP(ip string) (net.IP, error) { } if isLittleEndian > 0 { - for i := 0; i < len(dst) / 4; i++ { + for i := 0; i < len(dst)/4; i++ { start, end := i*4, (i+1)*4 word := dst[start:end] lval := binary.LittleEndian.Uint32(word) @@ -177,13 +177,13 @@ func ParseIP(ip string) (net.IP, error) { } } -/* if len(dst) == 16 { - dst2 := []byte{dst[3], dst[2], dst[1], dst[0], dst[7], dst[6], dst[5], dst[4], dst[11], dst[10], dst[9], dst[8], dst[15], dst[14], dst[13], dst[12]} - return net.IP(dst2), nil - } - for i, j := 0, len(dst)-1; i < j; i, j = i+1, j-1 { - dst[i], dst[j] = dst[j], dst[i] - } */ + /* if len(dst) == 16 { + dst2 := []byte{dst[3], dst[2], dst[1], dst[0], dst[7], dst[6], dst[5], dst[4], dst[11], dst[10], dst[9], dst[8], dst[15], dst[14], dst[13], dst[12]} + return net.IP(dst2), nil + } + for i, j := 0, len(dst)-1; i < j; i, j = i+1, j-1 { + dst[i], dst[j] = dst[j], dst[i] + } */ return net.IP(dst), nil } @@ -312,6 +312,7 @@ func stripLabel(s string) string { // stolen from github.com/virtao/GoEndian const INT_SIZE int = int(unsafe.Sizeof(0)) + func setEndian() { var i int = 0x1 bs := (*[INT_SIZE]byte)(unsafe.Pointer(&i)) diff --git a/vendor/github.com/subgraph/go-procsnitch/proc_pid.go b/vendor/github.com/subgraph/go-procsnitch/proc_pid.go index a34c9b1..549ea37 100644 --- a/vendor/github.com/subgraph/go-procsnitch/proc_pid.go +++ b/vendor/github.com/subgraph/go-procsnitch/proc_pid.go @@ -23,7 +23,9 @@ type Info struct { FirstArg string ParentCmdLine string ParentExePath string - Sandbox string + Sandbox string + Inode uint64 + FD int } type pidCache struct { @@ -51,10 +53,12 @@ func loadCache() map[uint64]*Info { for _, n := range readdir("/proc") { pid := toPid(n) if pid != 0 { - pinfo := &Info{Pid: pid} - for _, inode := range inodesFromPid(pid) { + inodes, fds := inodesFromPid(pid) + for iind, inode := range inodes { + pinfo := &Info{Inode: inode, Pid: pid, FD: fds[iind]} cmap[inode] = pinfo } + } } return cmap @@ -76,8 +80,9 @@ func toPid(name string) int { return (int)(pid) } -func inodesFromPid(pid int) []uint64 { +func inodesFromPid(pid int) ([]uint64, []int) { var inodes []uint64 + var fds []int fdpath := fmt.Sprintf("/proc/%d/fd", pid) for _, n := range readdir(fdpath) { if link, err := os.Readlink(path.Join(fdpath, n)); err != nil { @@ -85,12 +90,19 @@ func inodesFromPid(pid int) []uint64 { log.Warningf("Error reading link %s: %v", n, err) } } else { + fd, err := strconv.Atoi(n) + if err != nil { + log.Warningf("Error retrieving fd associated with pid %v: %v", pid, err) + fd = -1 + } + if inode := extractSocket(link); inode > 0 { inodes = append(inodes, inode) + fds = append(fds, fd) } } } - return inodes + return inodes, fds } func extractSocket(name string) uint64 { diff --git a/vendor/github.com/subgraph/go-procsnitch/socket.go b/vendor/github.com/subgraph/go-procsnitch/socket.go index f137ed0..f6d40c0 100644 --- a/vendor/github.com/subgraph/go-procsnitch/socket.go +++ b/vendor/github.com/subgraph/go-procsnitch/socket.go @@ -117,21 +117,21 @@ func findUDPSocketAll(srcAddr net.IP, srcPort uint16, dstAddr net.IP, dstPort ui }) } else if strictness == MATCH_LOOSE { return findSocket(proto, func(ss socketStatus) bool { - /* - fmt.Println("Match loose") - fmt.Printf("sock dst = %v pkt dst = %v\n", ss.remote.ip, dstAddr) - fmt.Printf("sock port = %d pkt port = %d\n", ss.local.port, srcPort) - fmt.Printf("local ip: %v\n source ip: %v\n", ss.local.ip, srcAddr) + /* + fmt.Println("Match loose") + fmt.Printf("sock dst = %v pkt dst = %v\n", ss.remote.ip, dstAddr) + fmt.Printf("sock port = %d pkt port = %d\n", ss.local.port, srcPort) + fmt.Printf("local ip: %v\n source ip: %v\n", ss.local.ip, srcAddr) */ - if (ss.local.port == srcPort && (ss.local.ip.Equal(net.IPv4(0,0,0,0)) && ss.remote.ip.Equal(net.IPv4(0,0,0,0)))) { - fmt.Printf("Matching for UDP socket bound to *:%d\n",ss.local.port) + if ss.local.port == srcPort && (ss.local.ip.Equal(net.IPv4(0, 0, 0, 0)) && ss.remote.ip.Equal(net.IPv4(0, 0, 0, 0))) { + fmt.Printf("Matching for UDP socket bound to *:%d\n", ss.local.port) return true - } else if (ss.remote.ip.Equal(dstAddr) && ss.local.port == srcPort && ss.local.ip.Equal(srcAddr)) { + } else if ss.remote.ip.Equal(dstAddr) && ss.local.port == srcPort && ss.local.ip.Equal(srcAddr) { return true } - // Finally, loop through all interfaces if src port matches + // Finally, loop through all interfaces if src port matches if ss.local.port == srcPort { ifs, err := net.Interfaces() @@ -148,13 +148,13 @@ func findUDPSocketAll(srcAddr net.IP, srcPort uint16, dstAddr net.IP, dstPort ui for _, addr := range addrs { var ifip net.IP switch x := addr.(type) { - case *net.IPNet: - ifip = x.IP - case *net.IPAddr: - ifip = x.IP + case *net.IPNet: + ifip = x.IP + case *net.IPAddr: + ifip = x.IP } if ss.local.ip.Equal(ifip) { - fmt.Printf("Matched on UDP socket bound to %v:%d\n",ifip,srcPort) + fmt.Printf("Matched on UDP socket bound to %v:%d\n", ifip, srcPort) return true } } @@ -163,8 +163,8 @@ func findUDPSocketAll(srcAddr net.IP, srcPort uint16, dstAddr net.IP, dstPort ui return false //return (ss.remote.ip.Equal(dstAddr) || ss.remote.ip.Equal(net.IPv4(0,0,0,0))) && ss.local.port == srcPort && (ss.local.ip.Equal(srcAddr) || ss.local.ip.Equal(net.IPv4(0,0,0,0))) /* - return (ss.remote.ip.Equal(dstAddr) || addrMatchesAny(ss.remote.ip)) && ss.local.port == srcPort && ss.local.ip.Equal(srcAddr) || - (ss.local.ip.Equal(dstAddr) || addrMatchesAny(ss.local.ip)) && ss.remote.port == srcPort && ss.remote.ip.Equal(srcAddr) */ + return (ss.remote.ip.Equal(dstAddr) || addrMatchesAny(ss.remote.ip)) && ss.local.port == srcPort && ss.local.ip.Equal(srcAddr) || + (ss.local.ip.Equal(dstAddr) || addrMatchesAny(ss.local.ip)) && ss.remote.port == srcPort && ss.remote.ip.Equal(srcAddr) */ }) } return findSocket(proto, func(ss socketStatus) bool { @@ -367,11 +367,11 @@ func getSocketLines(proto string) []string { } func addrMatchesAny(addr net.IP) bool { - wildcard := net.IP{0,0,0,0} + wildcard := net.IP{0, 0, 0, 0} if addr.To4() == nil { - wildcard = net.IP{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0} + wildcard = net.IP{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0} } - return wildcard.Equal(addr) + return wildcard.Equal(addr) }