mirror of
https://github.com/bettercap/bettercap
synced 2025-08-19 21:13:18 -07:00
new: implemented api.rest.record and api.rest.replay
This commit is contained in:
parent
4713d25ea7
commit
0a31ac8167
76 changed files with 7610 additions and 48 deletions
|
@ -36,7 +36,7 @@ func (mod *RestAPI) setAuthFailed(w http.ResponseWriter, r *http.Request) {
|
|||
func (mod *RestAPI) toJSON(w http.ResponseWriter, o interface{}) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
if err := json.NewEncoder(w).Encode(o); err != nil {
|
||||
mod.Error("error while encoding object to JSON: %v", err)
|
||||
fmt.Printf("error while encoding object to JSON: %v\n", err)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,8 +64,68 @@ func (mod *RestAPI) checkAuth(r *http.Request) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
func (mod *RestAPI) patchFrame(buf []byte) (frame map[string]interface{}, err error) {
|
||||
// this is ugly but necessary: since we're replaying, the
|
||||
// api.rest state object is filled with *old* values (the
|
||||
// recorded ones), but the UI needs updated values at least
|
||||
// of that in order to understand that a replay is going on
|
||||
// and where we are at it. So we need to parse the record
|
||||
// back into a session object and update only the api.rest.state
|
||||
frame = make(map[string]interface{})
|
||||
|
||||
if err = json.Unmarshal(buf, &frame); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, i := range frame["modules"].([]interface{}) {
|
||||
m := i.(map[string]interface{})
|
||||
if m["name"] == "api.rest" {
|
||||
state := m["state"].(map[string]interface{})
|
||||
mod.State.Range(func(key interface{}, value interface{}) bool {
|
||||
state[key.(string)] = value
|
||||
return true
|
||||
})
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func (mod *RestAPI) showSession(w http.ResponseWriter, r *http.Request) {
|
||||
mod.toJSON(w, session.I)
|
||||
if mod.replaying {
|
||||
if !mod.record.Session.Over() {
|
||||
from := mod.record.Session.CurFrame() - 1
|
||||
q := r.URL.Query()
|
||||
vals := q["from"]
|
||||
if len(vals) > 0 {
|
||||
if n, err := strconv.Atoi(vals[0]); err == nil {
|
||||
from = n
|
||||
}
|
||||
}
|
||||
mod.record.Session.SetFrom(from)
|
||||
|
||||
mod.Debug("replaying session %d of %d from %s",
|
||||
mod.record.Session.CurFrame(),
|
||||
mod.record.Session.Frames(),
|
||||
mod.recordFileName)
|
||||
|
||||
mod.State.Store("rec_frames", mod.record.Session.Frames())
|
||||
mod.State.Store("rec_cur_frame", mod.record.Session.CurFrame())
|
||||
|
||||
buf := mod.record.Session.Next()
|
||||
if frame, err := mod.patchFrame(buf); err != nil {
|
||||
mod.Error("%v", err)
|
||||
} else {
|
||||
mod.toJSON(w, frame)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
mod.stopReplay()
|
||||
}
|
||||
}
|
||||
|
||||
mod.toJSON(w, mod.Session)
|
||||
}
|
||||
|
||||
func (mod *RestAPI) showBLE(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -73,8 +133,8 @@ func (mod *RestAPI) showBLE(w http.ResponseWriter, r *http.Request) {
|
|||
mac := strings.ToLower(params["mac"])
|
||||
|
||||
if mac == "" {
|
||||
mod.toJSON(w, session.I.BLE)
|
||||
} else if dev, found := session.I.BLE.Get(mac); found {
|
||||
mod.toJSON(w, mod.Session.BLE)
|
||||
} else if dev, found := mod.Session.BLE.Get(mac); found {
|
||||
mod.toJSON(w, dev)
|
||||
} else {
|
||||
http.Error(w, "Not Found", 404)
|
||||
|
@ -86,8 +146,8 @@ func (mod *RestAPI) showHID(w http.ResponseWriter, r *http.Request) {
|
|||
mac := strings.ToLower(params["mac"])
|
||||
|
||||
if mac == "" {
|
||||
mod.toJSON(w, session.I.HID)
|
||||
} else if dev, found := session.I.HID.Get(mac); found {
|
||||
mod.toJSON(w, mod.Session.HID)
|
||||
} else if dev, found := mod.Session.HID.Get(mac); found {
|
||||
mod.toJSON(w, dev)
|
||||
} else {
|
||||
http.Error(w, "Not Found", 404)
|
||||
|
@ -95,19 +155,19 @@ func (mod *RestAPI) showHID(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func (mod *RestAPI) showEnv(w http.ResponseWriter, r *http.Request) {
|
||||
mod.toJSON(w, session.I.Env)
|
||||
mod.toJSON(w, mod.Session.Env)
|
||||
}
|
||||
|
||||
func (mod *RestAPI) showGateway(w http.ResponseWriter, r *http.Request) {
|
||||
mod.toJSON(w, session.I.Gateway)
|
||||
mod.toJSON(w, mod.Session.Gateway)
|
||||
}
|
||||
|
||||
func (mod *RestAPI) showInterface(w http.ResponseWriter, r *http.Request) {
|
||||
mod.toJSON(w, session.I.Interface)
|
||||
mod.toJSON(w, mod.Session.Interface)
|
||||
}
|
||||
|
||||
func (mod *RestAPI) showModules(w http.ResponseWriter, r *http.Request) {
|
||||
mod.toJSON(w, session.I.Modules)
|
||||
mod.toJSON(w, mod.Session.Modules)
|
||||
}
|
||||
|
||||
func (mod *RestAPI) showLAN(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -115,8 +175,8 @@ func (mod *RestAPI) showLAN(w http.ResponseWriter, r *http.Request) {
|
|||
mac := strings.ToLower(params["mac"])
|
||||
|
||||
if mac == "" {
|
||||
mod.toJSON(w, session.I.Lan)
|
||||
} else if host, found := session.I.Lan.Get(mac); found {
|
||||
mod.toJSON(w, mod.Session.Lan)
|
||||
} else if host, found := mod.Session.Lan.Get(mac); found {
|
||||
mod.toJSON(w, host)
|
||||
} else {
|
||||
http.Error(w, "Not Found", 404)
|
||||
|
@ -124,15 +184,15 @@ func (mod *RestAPI) showLAN(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func (mod *RestAPI) showOptions(w http.ResponseWriter, r *http.Request) {
|
||||
mod.toJSON(w, session.I.Options)
|
||||
mod.toJSON(w, mod.Session.Options)
|
||||
}
|
||||
|
||||
func (mod *RestAPI) showPackets(w http.ResponseWriter, r *http.Request) {
|
||||
mod.toJSON(w, session.I.Queue)
|
||||
mod.toJSON(w, mod.Session.Queue)
|
||||
}
|
||||
|
||||
func (mod *RestAPI) showStartedAt(w http.ResponseWriter, r *http.Request) {
|
||||
mod.toJSON(w, session.I.StartedAt)
|
||||
mod.toJSON(w, mod.Session.StartedAt)
|
||||
}
|
||||
|
||||
func (mod *RestAPI) showWiFi(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -140,10 +200,10 @@ func (mod *RestAPI) showWiFi(w http.ResponseWriter, r *http.Request) {
|
|||
mac := strings.ToLower(params["mac"])
|
||||
|
||||
if mac == "" {
|
||||
mod.toJSON(w, session.I.WiFi)
|
||||
} else if station, found := session.I.WiFi.Get(mac); found {
|
||||
mod.toJSON(w, mod.Session.WiFi)
|
||||
} else if station, found := mod.Session.WiFi.Get(mac); found {
|
||||
mod.toJSON(w, station)
|
||||
} else if client, found := session.I.WiFi.GetClient(mac); found {
|
||||
} else if client, found := mod.Session.WiFi.GetClient(mac); found {
|
||||
mod.toJSON(w, client)
|
||||
} else {
|
||||
http.Error(w, "Not Found", 404)
|
||||
|
@ -170,42 +230,72 @@ func (mod *RestAPI) runSessionCommand(w http.ResponseWriter, r *http.Request) {
|
|||
mod.toJSON(w, APIResponse{Success: true})
|
||||
}
|
||||
|
||||
func (mod *RestAPI) getEvents(limit int) []session.Event {
|
||||
events := make([]session.Event, 0)
|
||||
for _, e := range mod.Session.Events.Sorted() {
|
||||
if mod.Session.EventsIgnoreList.Ignored(e) == false {
|
||||
events = append(events, e)
|
||||
}
|
||||
}
|
||||
|
||||
nevents := len(events)
|
||||
nmax := nevents
|
||||
n := nmax
|
||||
|
||||
if limit > 0 && limit < nmax {
|
||||
n = limit
|
||||
}
|
||||
|
||||
return events[nevents-n:]
|
||||
}
|
||||
|
||||
func (mod *RestAPI) showEvents(w http.ResponseWriter, r *http.Request) {
|
||||
var err error
|
||||
q := r.URL.Query()
|
||||
|
||||
if mod.replaying {
|
||||
if !mod.record.Events.Over() {
|
||||
from := mod.record.Events.CurFrame() - 1
|
||||
vals := q["from"]
|
||||
if len(vals) > 0 {
|
||||
if n, err := strconv.Atoi(vals[0]); err == nil {
|
||||
from = n
|
||||
}
|
||||
}
|
||||
mod.record.Events.SetFrom(from)
|
||||
|
||||
mod.Debug("replaying events %d of %d from %s",
|
||||
mod.record.Events.CurFrame(),
|
||||
mod.record.Events.Frames(),
|
||||
mod.recordFileName)
|
||||
|
||||
buf := mod.record.Events.Next()
|
||||
if _, err := w.Write(buf); err != nil {
|
||||
mod.Error("%v", err)
|
||||
} else {
|
||||
return
|
||||
}
|
||||
} else {
|
||||
mod.stopReplay()
|
||||
}
|
||||
}
|
||||
|
||||
if mod.useWebsocket {
|
||||
mod.startStreamingEvents(w, r)
|
||||
} else {
|
||||
events := make([]session.Event, 0)
|
||||
for _, e := range session.I.Events.Sorted() {
|
||||
if mod.Session.EventsIgnoreList.Ignored(e) == false {
|
||||
events = append(events, e)
|
||||
}
|
||||
}
|
||||
|
||||
nevents := len(events)
|
||||
nmax := nevents
|
||||
n := nmax
|
||||
|
||||
q := r.URL.Query()
|
||||
vals := q["n"]
|
||||
limit := 0
|
||||
if len(vals) > 0 {
|
||||
n, err = strconv.Atoi(q["n"][0])
|
||||
if err == nil {
|
||||
if n > nmax {
|
||||
n = nmax
|
||||
}
|
||||
} else {
|
||||
n = nmax
|
||||
if n, err := strconv.Atoi(q["n"][0]); err == nil {
|
||||
limit = n
|
||||
}
|
||||
}
|
||||
|
||||
mod.toJSON(w, events[nevents-n:])
|
||||
mod.toJSON(w, mod.getEvents(limit))
|
||||
}
|
||||
}
|
||||
|
||||
func (mod *RestAPI) clearEvents(w http.ResponseWriter, r *http.Request) {
|
||||
session.I.Events.Clear()
|
||||
mod.Session.Events.Clear()
|
||||
}
|
||||
|
||||
func (mod *RestAPI) corsRoute(w http.ResponseWriter, r *http.Request) {
|
||||
|
@ -227,10 +317,10 @@ func (mod *RestAPI) sessionRoute(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
session.I.Lock()
|
||||
defer session.I.Unlock()
|
||||
mod.Session.Lock()
|
||||
defer mod.Session.Unlock()
|
||||
|
||||
path := r.URL.String()
|
||||
path := r.URL.Path
|
||||
switch {
|
||||
case path == "/api/session":
|
||||
mod.showSession(w, r)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue