diff --git a/_example/example.js b/_example/example.js index cd9e9ebf..2ca86409 100644 --- a/_example/example.js +++ b/_example/example.js @@ -4,10 +4,6 @@ require("functions") log("session script loaded, fake AP is " + fakeESSID); -// enable the graph module so we can extract more historical info -// for each device we see -run('graph on') - // create an empty ticker so we can run commands every few seconds // this will inject decoy wifi client probes used to detect KARMA // attacks and in general rogue access points @@ -35,8 +31,5 @@ onEvent('wifi.client.handshake', onHandshake); // register for wifi.ap.new events (used to detect rogue APs) onEvent('wifi.ap.new', onNewAP); -// register for new nodes in the graph -onEvent('graph.node.new', onNewNode); - // register for gateway changes onEvent('gateway.change', onGatewayChange) \ No newline at end of file diff --git a/_example/functions.js b/_example/functions.js index e48ed21f..63e2474f 100644 --- a/_example/functions.js +++ b/_example/functions.js @@ -1,19 +1,9 @@ var fakeESSID = random.String(16, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'); var fakeBSSID = random.Mac() -// uses graph.to_dot and graphviz to generate a png graph -function createGraph(who, where) { - // generates a .dot file with the graph for this mac - run('graph.to_dot ' + who); - // uses graphviz to make a png of it - run('!dot -Tpng bettergraph.dot > ' + where); -} - function onDeauthentication(event) { var data = event.data; - createGraph(data.address1, '/tmp/graph_deauth.png'); - var message = '🚨 Detected deauthentication frame:\n\n' + // 'Time: ' + event.time + "\n" + // 'GPS: lat=' + session.GPS.Latitude + " lon=" + session.GPS.Longitude + " updated_at=" + @@ -28,14 +18,11 @@ function onDeauthentication(event) { // send to telegram bot sendMessage(message); - sendPhoto("/tmp/graph_deauth.png"); } function onNewAP(event){ var ap = event.data; if(ap.hostname == fakeESSID) { - createGraph(ap.mac, '/tmp/graph_ap.png'); - var message = '🦠 Detected rogue AP:\n\n' + // 'Time: ' + event.time + "\n" + // 'GPS: lat=' + session.GPS.Latitude + " lon=" + session.GPS.Longitude + " updated_at=" + @@ -44,7 +31,6 @@ function onNewAP(event){ // send to telegram bot sendMessage(message); - sendPhoto("/tmp/graph_ap.png"); } } @@ -52,8 +38,6 @@ function onHandshake(event){ var data = event.data; var what = 'handshake'; - createGraph(data.station, '/tmp/graph_handshake.png'); - if(data.pmkid != null) { what = "RSN PMKID"; } else if(data.full) { @@ -71,23 +55,6 @@ function onHandshake(event){ // send to telegram bot sendMessage(message); - sendPhoto("/tmp/graph_handshake.png"); -} - -function onNewNode(event) { - var node = event.data; - - if(node.type != 'ssid' && node.type != 'ble_server' && graph.IsConnected(node.type, node.id)) { - createGraph(node.id, '/tmp/graph_node.png'); - - var message = '🖥️ Detected previously unknown ' + node.type + ':\n\n' + - 'Type: ' + node.type + "\n" + - 'MAC: ' + node.id; - - // send to telegram bot - sendMessage(message); - sendPhoto("/tmp/graph_node.png"); - } } function onGatewayChange(event) { diff --git a/graphpage.html b/graphpage.html deleted file mode 100644 index 8fe6210a..00000000 --- a/graphpage.html +++ /dev/null @@ -1,195 +0,0 @@ -
- - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/modules/events_stream/events_view.go b/modules/events_stream/events_view.go index ed0a5ec1..ce9479f2 100644 --- a/modules/events_stream/events_view.go +++ b/modules/events_stream/events_view.go @@ -127,8 +127,6 @@ func (mod *EventsStream) Render(output io.Writer, e session.Event) { mod.viewSynScanEvent(output, e) } else if e.Tag == "update.available" { mod.viewUpdateEvent(output, e) - } else if strings.HasPrefix(e.Tag, "graph.") { - mod.viewGraphEvent(output, e) } else if e.Tag == "gateway.change" { mod.viewGatewayEvent(output, e) } else if e.Tag != "tick" { diff --git a/modules/events_stream/events_view_graph.go b/modules/events_stream/events_view_graph.go deleted file mode 100644 index 6fc2cc7c..00000000 --- a/modules/events_stream/events_view_graph.go +++ /dev/null @@ -1,35 +0,0 @@ -package events_stream - -import ( - "fmt" - "io" - - "github.com/bettercap/bettercap/session" - "github.com/bettercap/bettercap/modules/graph" - - "github.com/evilsocket/islazy/tui" -) - -func (mod *EventsStream) viewGraphEvent(output io.Writer, e session.Event) { - if e.Tag == "graph.node.new" { - node := e.Data.(*graph.Node) - - fmt.Fprintf(output, "[%s] [%s] %s %s\n", - e.Time.Format(mod.timeFormat), - tui.Green(e.Tag), - tui.Yellow(string(node.Type)), - node.ID) - } else if e.Tag == "graph.edge.new" { - data := e.Data.(graph.EdgeEvent) - fmt.Fprintf(output, "[%s] [%s] %s %s %s %s %s\n", - e.Time.Format(mod.timeFormat), - tui.Green(e.Tag), - tui.Dim(string(data.Left.Type)), - data.Left.ID, - tui.Bold(string(data.Edge.Type)), - tui.Dim(string(data.Right.Type)), - data.Right.ID) - }else { - fmt.Fprintf(output, "[%s] [%s] %v\n", e.Time.Format(mod.timeFormat), tui.Green(e.Tag), e) - } -} diff --git a/modules/graph/create.go b/modules/graph/create.go deleted file mode 100644 index f4779df8..00000000 --- a/modules/graph/create.go +++ /dev/null @@ -1,184 +0,0 @@ -package graph - -import ( - "fmt" - "github.com/bettercap/bettercap/network" -) - -func (mod *Module) createIPGraph(endpoint *network.Endpoint) (*Node, bool, error) { - node, err := mod.db.FindNode(Endpoint, endpoint.HwAddress) - isNew := node == nil - if err != nil { - return nil, false, err - } else if isNew { - if node, err = mod.db.CreateNode(Endpoint, endpoint.HwAddress, endpoint, ""); err != nil { - return nil, false, err - } - } else { - if err = mod.db.UpdateNode(node); err != nil { - return nil, false, err - } - } - - // create relations if needed - if manages, err := mod.db.FindLastRecentEdgeOfType(mod.gw, node, Manages, edgeStaleTime); err != nil { - return nil, false, err - } else if manages == nil { - if manages, err = mod.db.CreateEdge(mod.gw, node, Manages); err != nil { - return nil, false, err - } - } - - if connects_to, err := mod.db.FindLastRecentEdgeOfType(node, mod.gw, ConnectsTo, edgeStaleTime); err != nil { - return nil, false, err - } else if connects_to == nil { - if connects_to, err = mod.db.CreateEdge(node, mod.gw, ConnectsTo); err != nil { - return nil, false, err - } - } - - return node, isNew, nil -} - -func (mod *Module) createDot11ApGraph(ap *network.AccessPoint) (*Node, bool, error) { - node, err := mod.db.FindNode(AccessPoint, ap.HwAddress) - isNew := node == nil - if err != nil { - return nil, false, err - } else if isNew { - if node, err = mod.db.CreateNode(AccessPoint, ap.HwAddress, ap, ""); err != nil { - return nil, false, err - } - } else if err = mod.db.UpdateNode(node); err != nil { - return nil, false, err - } - return node, isNew, nil -} - -func (mod *Module) createDot11SSIDGraph(hex string, ssid string) (*Node, bool, error) { - node, err := mod.db.FindNode(SSID, hex) - isNew := node == nil - if err != nil { - return nil, false, err - } else if isNew { - if node, err = mod.db.CreateNode(SSID, hex, ssid, ""); err != nil { - return nil, false, err - } - } else if err = mod.db.UpdateNode(node); err != nil { - return nil, false, err - } - return node, isNew, nil -} - -func (mod *Module) createDot11StaGraph(station *network.Station) (*Node, bool, error) { - node, err := mod.db.FindNode(Station, station.HwAddress) - isNew := node == nil - if err != nil { - return nil, false, err - } else if isNew { - if node, err = mod.db.CreateNode(Station, station.HwAddress, station, ""); err != nil { - return nil, false, err - } - } else if err = mod.db.UpdateNode(node); err != nil { - return nil, false, err - } - return node, isNew, nil -} - -func (mod *Module) createDot11Graph(ap *network.AccessPoint, station *network.Station) (*Node, bool, *Node, bool, error) { - apNode, apIsNew, err := mod.createDot11ApGraph(ap) - if err != nil { - return nil, false, nil, false, err - } - - staNode, staIsNew, err := mod.createDot11StaGraph(station) - if err != nil { - return nil, false, nil, false, err - } - - // create relations if needed - if manages, err := mod.db.FindLastRecentEdgeOfType(apNode, staNode, Manages, edgeStaleTime); err != nil { - return nil, false, nil, false, err - } else if manages == nil { - if manages, err = mod.db.CreateEdge(apNode, staNode, Manages); err != nil { - return nil, false, nil, false, err - } - } - - if connects_to, err := mod.db.FindLastRecentEdgeOfType(staNode, apNode, ConnectsTo, edgeStaleTime); err != nil { - return nil, false, nil, false, err - } else if connects_to == nil { - if connects_to, err = mod.db.CreateEdge(staNode, apNode, ConnectsTo); err != nil { - return nil, false, nil, false, err - } - } - - return apNode, apIsNew, staNode, staIsNew, nil -} - -func (mod *Module) createDot11ProbeGraph(ssid string, station *network.Station) (*Node, bool, *Node, bool, error) { - ssidNode, ssidIsNew, err := mod.createDot11SSIDGraph(fmt.Sprintf("%x", ssid), ssid) - if err != nil { - return nil, false, nil, false, err - } - - staNode, staIsNew, err := mod.createDot11StaGraph(station) - if err != nil { - return nil, false, nil, false, err - } - - // create relations if needed - if probes_for, err := mod.db.FindLastRecentEdgeOfType(staNode, ssidNode, ProbesFor, edgeStaleTime); err != nil { - return nil, false, nil, false, err - } else if probes_for == nil { - if probes_for, err = mod.db.CreateEdge(staNode, ssidNode, ProbesFor); err != nil { - return nil, false, nil, false, err - } - } - - if probed_by, err := mod.db.FindLastRecentEdgeOfType(ssidNode, staNode, ProbedBy, edgeStaleTime); err != nil { - return nil, false, nil, false, err - } else if probed_by == nil { - if probed_by, err = mod.db.CreateEdge(ssidNode, staNode, ProbedBy); err != nil { - return nil, false, nil, false, err - } - } - - return ssidNode, ssidIsNew, staNode, staIsNew, nil -} - -func (mod *Module) createBLEServerGraph(dev *network.BLEDevice) (*Node, bool, error) { - mac := network.NormalizeMac(dev.Device.ID()) - node, err := mod.db.FindNode(BLEServer, mac) - isNew := node == nil - if err != nil { - return nil, false, err - } else if isNew { - if node, err = mod.db.CreateNode(BLEServer, mac, dev, ""); err != nil { - return nil, false, err - } - } else if err = mod.db.UpdateNode(node); err != nil { - return nil, false, err - } - return node, isNew, nil -} - -func (mod *Module) connectAsSame(a, b *Node) error { - if aIsB, err := mod.db.FindLastEdgeOfType(a, b, Is); err != nil { - return err - } else if aIsB == nil { - if aIsB, err = mod.db.CreateEdge(a, b, Is); err != nil { - return err - } - } - - if bIsA, err := mod.db.FindLastEdgeOfType(b, a, Is); err != nil { - return err - } else if bIsA == nil { - if bIsA, err = mod.db.CreateEdge(b, a, Is); err != nil { - return err - } - } - - return nil -} diff --git a/modules/graph/edge.go b/modules/graph/edge.go deleted file mode 100644 index 4c6eff93..00000000 --- a/modules/graph/edge.go +++ /dev/null @@ -1,42 +0,0 @@ -package graph - -import ( - "fmt" - "github.com/bettercap/bettercap/session" - "time" -) - -type EdgeType string - -const ( - Is EdgeType = "is" - ProbesFor EdgeType = "probes_for" - ProbedBy EdgeType = "probed_by" - ConnectsTo EdgeType = "connects_to" - Manages EdgeType = "manages" -) - -type EdgeEvent struct { - Left *Node - Edge *Edge - Right *Node -} - -type Edge struct { - Type EdgeType `json:"type"` - CreatedAt time.Time `json:"created_at"` - Position *session.GPS `json:"position,omitempty"` -} - -func (e Edge) Dot(left, right *Node, width float64) string { - edgeLen := 1.0 - if e.Type == Is { - edgeLen = 0.3 - } - return fmt.Sprintf("\"%s\" -> \"%s\" [label=\"%s\", len=%.2f, penwidth=%.2f];", - left.String(), - right.String(), - e.Type, - edgeLen, - width) -} diff --git a/modules/graph/edges.go b/modules/graph/edges.go deleted file mode 100644 index eae8ac02..00000000 --- a/modules/graph/edges.go +++ /dev/null @@ -1,158 +0,0 @@ -package graph - -import ( - "encoding/json" - "github.com/evilsocket/islazy/fs" - "io/ioutil" - "os" - "path" - "sort" - "sync" - "time" -) - -const edgesIndexName = "edges.json" - -type EdgesTo map[string][]Edge - -type EdgesCallback func(string, []Edge, string) error - -type Edges struct { - sync.RWMutex - timestamp time.Time - fileName string - size int - from map[string]EdgesTo -} - -type edgesJSON struct { - Timestamp time.Time `json:"timestamp"` - Size int `json:"size"` - Edges map[string]EdgesTo `json:"edges"` -} - -func LoadEdges(basePath string) (*Edges, error) { - edges := Edges{ - fileName: path.Join(basePath, edgesIndexName), - from: make(map[string]EdgesTo), - } - - if fs.Exists(edges.fileName) { - var js edgesJSON - - if raw, err := ioutil.ReadFile(edges.fileName); err != nil { - return nil, err - } else if err = json.Unmarshal(raw, &js); err != nil { - return nil, err - } - - edges.timestamp = js.Timestamp - edges.from = js.Edges - edges.size = js.Size - } - - return &edges, nil -} - -func (e *Edges) flush() error { - e.timestamp = time.Now() - js := edgesJSON{ - Timestamp: e.timestamp, - Size: e.size, - Edges: e.from, - } - - if raw, err := json.Marshal(js); err != nil { - return err - } else if err = ioutil.WriteFile(e.fileName, raw, os.ModePerm); err != nil { - return err - } - - return nil -} - -func (e *Edges) Flush() error { - e.RLock() - defer e.RUnlock() - return e.flush() -} - -func (e *Edges) ForEachEdge(cb EdgesCallback) error { - e.RLock() - defer e.RUnlock() - - for from, edgesTo := range e.from { - for to, edges := range edgesTo { - if err := cb(from, edges, to); err != nil { - return err - } - } - } - - return nil -} - -func (e *Edges) ForEachEdgeFrom(nodeID string, cb EdgesCallback) error { - e.RLock() - defer e.RUnlock() - - if edgesTo, found := e.from[nodeID]; found { - for to, edges := range edgesTo { - if err := cb(nodeID, edges, to); err != nil { - return err - } - } - } - - return nil -} - -func (e *Edges) IsConnected(nodeID string) bool { - e.RLock() - defer e.RUnlock() - - if edgesTo, found := e.from[nodeID]; found { - return len(edgesTo) > 0 - } - - return false -} - -func (e *Edges) FindEdges(fromID, toID string, doSort bool) []Edge { - e.RLock() - defer e.RUnlock() - - if edgesTo, foundFrom := e.from[fromID]; foundFrom { - if edges, foundTo := edgesTo[toID]; foundTo { - if doSort { - // sort edges from oldest to newer - sort.Slice(edges, func(i, j int) bool { - return edges[i].CreatedAt.Before(edges[j].CreatedAt) - }) - } - return edges - } - } - - return nil -} - -func (e *Edges) Connect(fromID, toID string, edge Edge) error { - e.Lock() - defer e.Unlock() - - if edgesTo, foundFrom := e.from[fromID]; foundFrom { - edges := edgesTo[toID] - edges = append(edges, edge) - e.from[fromID][toID] = edges - } else { - // create the entire path - e.from[fromID] = EdgesTo{ - toID: {edge}, - } - } - - e.size++ - - return e.flush() -} diff --git a/modules/graph/graph.go b/modules/graph/graph.go deleted file mode 100644 index 1a32e017..00000000 --- a/modules/graph/graph.go +++ /dev/null @@ -1,425 +0,0 @@ -package graph - -import ( - "encoding/json" - "fmt" - "github.com/bettercap/bettercap/session" - "github.com/evilsocket/islazy/fs" - "path" - "sync" - "time" -) - -var Loaded = (* Graph)(nil) - -type NodeCallback func(*Node) -type EdgeCallback func(*Node, []Edge, *Node) - -type Graph struct { - sync.Mutex - - path string - edges *Edges -} - -func NewGraph(path string) (*Graph, error) { - if edges, err := LoadEdges(path); err != nil { - return nil, err - } else { - Loaded = &Graph{ - path: path, - edges: edges, - } - return Loaded, nil - } -} - -func (g *Graph) EachNode(cb NodeCallback) error { - g.Lock() - defer g.Unlock() - - for _, nodeType := range NodeTypes { - err := fs.Glob(g.path, fmt.Sprintf("%s_*.json", nodeType), func(fileName string) error { - if node, err := ReadNode(fileName); err != nil { - return err - } else { - cb(node) - } - return nil - }) - if err != nil { - return err - } - } - return nil -} - -func (g *Graph) EachEdge(cb EdgeCallback) error { - g.Lock() - defer g.Unlock() - - return g.edges.ForEachEdge(func(fromID string, edges []Edge, toID string) error { - var left, right *Node - var err error - - leftFileName := path.Join(g.path, fromID+".json") - rightFileName := path.Join(g.path, toID+".json") - - if left, err = ReadNode(leftFileName); err != nil { - return err - } else if right, err = ReadNode(rightFileName); err != nil { - return err - } - - cb(left, edges, right) - - return nil - }) -} - -func (g *Graph) Traverse(root string, onNode NodeCallback, onEdge EdgeCallback) error { - if root == "" { - // traverse the entire graph - if err := g.EachNode(onNode); err != nil { - return err - } else if err = g.EachEdge(onEdge); err != nil { - return err - } - } else { - // start by a specific node - roots, err := g.FindOtherTypes("", root) - if err != nil { - return err - } - - stack := NewStack() - for _, root := range roots { - stack.Push(root) - } - - type edgeBucket struct { - left *Node - edges []Edge - right *Node - } - - allEdges := make([]edgeBucket, 0) - visited := make(map[string]bool) - - for { - if last := stack.Pop(); last == nil { - break - } else { - node := last.(*Node) - nodeID := node.String() - if _, found := visited[nodeID]; found { - continue - } else { - visited[nodeID] = true - } - - onNode(node) - - // collect all edges starting from this node - err = g.edges.ForEachEdgeFrom(nodeID, func(_ string, edges []Edge, toID string) error { - rightFileName := path.Join(g.path, toID+".json") - if right, err := ReadNode(rightFileName); err != nil { - return err - } else { - // collect new node - if _, found := visited[toID]; !found { - stack.Push(right) - } - // collect all edges, we'll emit this later - allEdges = append(allEdges, edgeBucket{ - left: node, - edges: edges, - right: right, - }) - } - return nil - }) - } - } - - for _, edge := range allEdges { - onEdge(edge.left, edge.edges, edge.right) - } - } - - return nil -} - -func (g *Graph) IsConnected(nodeType string, nodeID string) bool { - return g.edges.IsConnected(fmt.Sprintf("%s_%s", nodeType, nodeID)) -} - -func (g *Graph) Dot(filter, layout, name string, disconnected bool) (string, int, int, error) { - size := 0 - discarded := 0 - - data := fmt.Sprintf("digraph %s {\n", name) - data += fmt.Sprintf(" layout=%s\n", layout) - - typeMap := make(map[NodeType]bool) - - type typeCount struct { - edge Edge - count int - } - - if err := g.Traverse(filter, func(node *Node) { - include := false - if disconnected { - include = true - } else { - include = g.edges.IsConnected(node.String()) - } - - if include { - size++ - typeMap[node.Type] = true - data += fmt.Sprintf(" %s\n", node.Dot(filter == node.ID)) - } else { - discarded++ - } - }, func(left *Node, edges []Edge, right *Node) { - // collect counters by edge type in order to calculate proportional widths - byType := make(map[string]typeCount) - tot := len(edges) - - for _, edge := range edges { - if c, found := byType[string(edge.Type)]; found { - c.count++ - } else { - byType[string(edge.Type)] = typeCount{ - edge: edge, - count: 1, - } - } - } - - max := 2.0 - for _, c := range byType { - w := max * float64(c.count/tot) - if w < 0.5 { - w = 0.5 - } - data += fmt.Sprintf(" %s\n", c.edge.Dot(left, right, w)) - } - }); err != nil { - return "", 0, 0, err - } - - /* - data += "\n" - data += "node [style=filled height=0.55 fontname=\"Verdana\" fontsize=10];\n" - data += "subgraph legend {\n" + - "graph[style=dotted];\n" + - "label = \"Legend\";\n" - - var types []NodeType - for nodeType, _ := range typeMap { - types = append(types, nodeType) - node := Node{ - Type: nodeType, - Annotations: nodeTypeDescs[nodeType], - Dummy: true, - } - data += fmt.Sprintf(" %s\n", node.Dot(false)) - } - - ntypes := len(types) - for i := 0; i < ntypes - 1; i++ { - data += fmt.Sprintf(" \"%s\" -> \"%s\" [style=invis];\n", types[i], types[i + 1]) - } - data += "}\n" - */ - - data += "\n" - data += " overlap=false\n" - data += "}" - - return data, size, discarded, nil -} - -func (g *Graph) JSON(filter string, disconnected bool) (string, int, int, error) { - size := 0 - discarded := 0 - - type link struct { - Source string `json:"source"` - Target string `json:"target"` - Edge interface{} `json:"edge"` - } - - type data struct { - Nodes []map[string]interface{} `json:"nodes"` - Links []link `json:"links"` - } - - jsData := data{ - Nodes: make([]map[string]interface{}, 0), - Links: make([]link, 0), - } - - if err := g.Traverse(filter, func(node *Node) { - include := false - if disconnected { - include = true - } else { - include = g.edges.IsConnected(node.String()) - } - - if include { - size++ - - if nm, err := node.ToMap(); err != nil { - panic(err) - } else { - // patch id - nm["id"] = node.String() - jsData.Nodes = append(jsData.Nodes, nm) - } - } else { - discarded++ - } - }, func(left *Node, edges []Edge, right *Node) { - for _, edge := range edges { - jsData.Links = append(jsData.Links, link{ - Source: left.String(), - Target: right.String(), - Edge: edge, - }) - } - }); err != nil { - return "", 0, 0, err - } - - if raw, err := json.Marshal(jsData); err != nil { - return "", 0, 0, err - } else { - return string(raw), size, discarded, nil - } -} - -func (g *Graph) FindNode(t NodeType, id string) (*Node, error) { - g.Lock() - defer g.Unlock() - - nodeFileName := path.Join(g.path, fmt.Sprintf("%s_%s.json", t, id)) - if fs.Exists(nodeFileName) { - return ReadNode(nodeFileName) - } - - return nil, nil -} - -func (g *Graph) FindOtherTypes(t NodeType, id string) ([]*Node, error) { - g.Lock() - defer g.Unlock() - - var otherNodes []*Node - - for _, otherType := range NodeTypes { - if otherType != t { - if nodeFileName := path.Join(g.path, fmt.Sprintf("%s_%s.json", otherType, id)); fs.Exists(nodeFileName) { - if node, err := ReadNode(nodeFileName); err != nil { - return nil, err - } else { - otherNodes = append(otherNodes, node) - } - } - } - } - - return otherNodes, nil -} - -func (g *Graph) CreateNode(t NodeType, id string, entity interface{}, annotations string) (*Node, error) { - g.Lock() - defer g.Unlock() - - node := &Node{ - Type: t, - ID: id, - Entity: entity, - Annotations: annotations, - } - - nodeFileName := path.Join(g.path, fmt.Sprintf("%s.json", node.String())) - if err := CreateNode(nodeFileName, node); err != nil { - return nil, err - } - - session.I.Events.Add("graph.node.new", node) - - return node, nil -} - -func (g *Graph) UpdateNode(node *Node) error { - g.Lock() - defer g.Unlock() - - nodeFileName := path.Join(g.path, fmt.Sprintf("%s.json", node.String())) - if err := UpdateNode(nodeFileName, node); err != nil { - return err - } - - return nil -} - -func (g *Graph) FindLastEdgeOfType(from, to *Node, edgeType EdgeType) (*Edge, error) { - edges := g.edges.FindEdges(from.String(), to.String(), true) - num := len(edges) - for i := range edges { - // loop backwards - idx := num - 1 - i - edge := edges[idx] - if edge.Type == edgeType { - return &edge, nil - } - } - return nil, nil -} - -func (g *Graph) FindLastRecentEdgeOfType(from, to *Node, edgeType EdgeType, staleTime time.Duration) (*Edge, error) { - edges := g.edges.FindEdges(from.String(), to.String(), true) - num := len(edges) - for i := range edges { - // loop backwards - idx := num - 1 - i - edge := edges[idx] - if edge.Type == edgeType { - if time.Since(edge.CreatedAt) >= staleTime { - return nil, nil - } - return &edge, nil - } - } - - return nil, nil -} - -func (g *Graph) CreateEdge(from, to *Node, edgeType EdgeType) (*Edge, error) { - edge := Edge{ - Type: edgeType, - CreatedAt: time.Now(), - } - - if session.I.GPS.Updated.IsZero() == false { - edge.Position = &session.I.GPS - } - - if err := g.edges.Connect(from.String(), to.String(), edge); err != nil { - return nil, err - } - - session.I.Events.Add("graph.edge.new", EdgeEvent{ - Left: from, - Edge: &edge, - Right: to, - }) - - return &edge, nil -} diff --git a/modules/graph/js_builtin.go b/modules/graph/js_builtin.go deleted file mode 100644 index 49252d47..00000000 --- a/modules/graph/js_builtin.go +++ /dev/null @@ -1,15 +0,0 @@ -package graph - -import ( - "github.com/bettercap/bettercap/log" -) - -type graphPackage struct{} - -func (g graphPackage) IsConnected(nodeType, nodeID string) bool { - if Loaded == nil { - log.Error("graph.IsConnected: graph not loaded") - return false - } - return Loaded.IsConnected(nodeType, nodeID) -} diff --git a/modules/graph/module.go b/modules/graph/module.go deleted file mode 100644 index 211d24ca..00000000 --- a/modules/graph/module.go +++ /dev/null @@ -1,348 +0,0 @@ -package graph - -import ( - "github.com/bettercap/bettercap/caplets" - "github.com/bettercap/bettercap/modules/wifi" - "github.com/bettercap/bettercap/network" - "github.com/bettercap/bettercap/session" - "github.com/evilsocket/islazy/fs" - "github.com/evilsocket/islazy/plugin" - "github.com/evilsocket/islazy/str" - "os" - "path/filepath" - "regexp" - "sync" - "time" -) - -const ( - ifaceAnnotation = "