924 lines
24 KiB
Go
924 lines
24 KiB
Go
package server
|
|
|
|
import (
|
|
"AdaptixServer/core/eventing"
|
|
"AdaptixServer/core/utils/logs"
|
|
"AdaptixServer/core/utils/safe"
|
|
"AdaptixServer/core/utils/tformat"
|
|
isvalid "AdaptixServer/core/utils/valid"
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/Adaptix-Framework/axc2"
|
|
)
|
|
|
|
func (ts *Teamserver) TsAgentList() (string, error) {
|
|
var agents []adaptix.AgentData
|
|
ts.Agents.ForEach(func(key string, value interface{}) bool {
|
|
agent, ok := value.(*Agent)
|
|
if ok {
|
|
agents = append(agents, agent.GetData())
|
|
}
|
|
return true
|
|
})
|
|
|
|
jsonAgents, err := json.Marshal(agents)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
return string(jsonAgents), nil
|
|
}
|
|
|
|
func (ts *Teamserver) TsAgentIsExists(agentId string) bool {
|
|
return ts.Agents.Contains(agentId)
|
|
}
|
|
|
|
func (ts *Teamserver) TsAgentCreate(agentCrc string, agentId string, beat []byte, listenerName string, ExternalIP string, Async bool) (adaptix.AgentData, error) {
|
|
if beat == nil {
|
|
return adaptix.AgentData{}, fmt.Errorf("agent %v does not register", agentId)
|
|
}
|
|
|
|
agentName, ok := ts.wm_agent_types[agentCrc]
|
|
if !ok {
|
|
return adaptix.AgentData{}, fmt.Errorf("agent type %v does not exists", agentCrc)
|
|
}
|
|
ok = ts.Agents.Contains(agentId)
|
|
if ok {
|
|
return adaptix.AgentData{}, fmt.Errorf("agent %v already exists", agentId)
|
|
}
|
|
|
|
agentData, handler, err := ts.Extender.ExAgentCreate(agentName, beat)
|
|
if err != nil {
|
|
return adaptix.AgentData{}, err
|
|
}
|
|
|
|
if agentData.Id == "" {
|
|
agentData.Id = agentId
|
|
}
|
|
agentData.Crc = agentCrc
|
|
agentData.Name = agentName
|
|
agentData.Listener = listenerName
|
|
agentData.ExternalIP = ExternalIP
|
|
agentData.CreateTime = time.Now().Unix()
|
|
agentData.LastTick = int(time.Now().Unix())
|
|
agentData.Async = Async
|
|
agentData.Tags = ""
|
|
agentData.Mark = ""
|
|
agentData.Color = ""
|
|
|
|
value, ok := ts.listeners.Get(listenerName)
|
|
if !ok {
|
|
return agentData, fmt.Errorf("listener %v does not exists", listenerName)
|
|
}
|
|
|
|
regName := value.(adaptix.ListenerData).RegName
|
|
value, ok = ts.listener_configs.Get(regName)
|
|
if !ok {
|
|
return agentData, fmt.Errorf("listener %v does not register", regName)
|
|
}
|
|
|
|
agent := &Agent{
|
|
Extender: handler,
|
|
HostedTasks: safe.NewSafeQueue(0x100),
|
|
HostedTunnelTasks: safe.NewSafeQueue(0x1000),
|
|
HostedTunnelData: safe.NewSafeQueue(0x1000),
|
|
RunningTasks: safe.NewMap(),
|
|
RunningJobs: safe.NewMap(),
|
|
PivotParent: nil,
|
|
PivotChilds: safe.NewSlice(),
|
|
Tick: false,
|
|
Active: true,
|
|
}
|
|
agent.SetData(agentData)
|
|
|
|
// --- PRE HOOK ---
|
|
preEvent := &eventing.EventDataAgentNew{Agent: agentData, Restore: false}
|
|
if !ts.EventManager.Emit(eventing.EventAgentNew, eventing.HookPre, preEvent) {
|
|
if preEvent.Error != nil {
|
|
return adaptix.AgentData{}, preEvent.Error
|
|
}
|
|
return adaptix.AgentData{}, fmt.Errorf("operation cancelled by hook")
|
|
}
|
|
// ----------------
|
|
|
|
ts.Agents.Put(agentData.Id, agent)
|
|
|
|
packetNew := CreateSpAgentNew(agentData)
|
|
ts.TsSyncAllClientsWithCategory(packetNew, SyncCategoryAgents)
|
|
|
|
agent.UpdateData(func(d *adaptix.AgentData) {
|
|
d.TargetId, _ = ts.TsTargetsCreateAlive(agentData)
|
|
})
|
|
|
|
err = ts.DBMS.DbAgentInsert(agent.GetData())
|
|
if err != nil {
|
|
logs.Error("", err.Error())
|
|
}
|
|
|
|
ts.TsNotifyAgent(false, agent.GetData())
|
|
|
|
// --- POST HOOK ---
|
|
postEvent := &eventing.EventDataAgentNew{Agent: agent.GetData(), Restore: false}
|
|
ts.EventManager.EmitAsync(eventing.EventAgentNew, postEvent)
|
|
// -----------------
|
|
|
|
return agent.GetData(), nil
|
|
}
|
|
|
|
func (ts *Teamserver) TsAgentCommand(agentName string, agentId string, clientName string, hookId string, handlerId string, cmdline string, ui bool, args map[string]any) error {
|
|
if !ts.agent_configs.Contains(agentName) {
|
|
return fmt.Errorf("agent %v not registered", agentName)
|
|
}
|
|
|
|
agent, err := ts.getAgent(agentId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if !agent.Active {
|
|
return fmt.Errorf("agent '%v' not active", agentId)
|
|
}
|
|
|
|
taskData, messageData, err := agent.Command(args)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if taskData.Type == adaptix.TASK_TYPE_LOCAL {
|
|
if taskData.Message != "" || taskData.ClearText != "" {
|
|
ts.TsAgentConsoleLocalCommand(agentId, clientName, cmdline, taskData.Message, taskData.ClearText)
|
|
}
|
|
} else {
|
|
taskData.HookId = hookId
|
|
taskData.HandlerId = handlerId
|
|
if taskData.Type == adaptix.TASK_TYPE_TASK && ui {
|
|
taskData.Type = adaptix.TASK_TYPE_BROWSER
|
|
}
|
|
|
|
ts.TsTaskCreate(agentId, cmdline, clientName, taskData)
|
|
|
|
if (taskData.Type != adaptix.TASK_TYPE_BROWSER) && (len(messageData.Message) > 0 || len(messageData.Text) > 0) {
|
|
ts.TsAgentConsoleOutput(agentId, messageData.Status, messageData.Message, messageData.Text, false)
|
|
}
|
|
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (ts *Teamserver) TsAgentProcessData(agentId string, bodyData []byte) error {
|
|
agent, err := ts.getAgent(agentId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
agentData := agent.GetData()
|
|
if agentData.Mark == "Inactive" {
|
|
agent.UpdateData(func(d *adaptix.AgentData) {
|
|
d.Mark = ""
|
|
})
|
|
err := ts.DBMS.DbAgentUpdate(agent.GetData())
|
|
if err != nil {
|
|
logs.Error("", err.Error())
|
|
}
|
|
|
|
updatedAgentData := agent.GetData()
|
|
|
|
//packetNew := CreateSpAgentNew(updatedAgentData)
|
|
//ts.TsSyncAgentActivated(packetNew)
|
|
|
|
// --- POST HOOK ---
|
|
postEvent := &eventing.EventDataAgentActivate{Agent: updatedAgentData}
|
|
ts.EventManager.EmitAsync(eventing.EventAgentActivate, postEvent)
|
|
// -----------------
|
|
}
|
|
|
|
if len(bodyData) > 4 {
|
|
return agent.ProcessData(bodyData)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
/// Get Tasks
|
|
|
|
func (ts *Teamserver) TsAgentGetHostedAll(agentId string, maxDataSize int) ([]byte, error) {
|
|
agent, err := ts.getAgent(agentId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
agentData := agent.GetData()
|
|
tasksCount := agent.HostedTasks.Len()
|
|
tunnelConnectCount := agent.HostedTunnelTasks.Len()
|
|
tunnelTasksCount := agent.HostedTunnelData.Len()
|
|
pivotTasksExists := false
|
|
if agent.PivotChilds.Len() > 0 {
|
|
pivotTasksExists = ts.TsTasksPivotExists(agentData.Id, true)
|
|
}
|
|
|
|
if tasksCount > 0 || tunnelConnectCount > 0 || tunnelTasksCount > 0 || pivotTasksExists {
|
|
|
|
tasks, err := ts.TsTaskGetAvailableAll(agentData.Id, maxDataSize)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
respData, err := agent.PackData(tasks)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if tasksCount > 0 {
|
|
message := fmt.Sprintf("Agent called server, sent [%v]", tformat.SizeBytesToFormat(uint64(len(respData))))
|
|
ts.TsAgentConsoleOutput(agentId, CONSOLE_OUT_INFO, message, "", false)
|
|
}
|
|
return respData, nil
|
|
}
|
|
|
|
return []byte(""), nil
|
|
}
|
|
|
|
func (ts *Teamserver) TsAgentGetHostedTasks(agentId string, maxDataSize int) ([]byte, error) {
|
|
agent, err := ts.getAgent(agentId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
agentData := agent.GetData()
|
|
tasksCount := agent.HostedTasks.Len()
|
|
if tasksCount == 0 && agent.HostedTunnelTasks.Len() == 0 {
|
|
return []byte(""), nil
|
|
}
|
|
|
|
tasks, _, err := ts.TsTaskGetAvailableTasks(agentData.Id, maxDataSize)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
respData, err := agent.PackData(tasks)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if tasksCount > 0 {
|
|
message := fmt.Sprintf("Agent called server, sent [%v]", tformat.SizeBytesToFormat(uint64(len(respData))))
|
|
ts.TsAgentConsoleOutput(agentId, CONSOLE_OUT_INFO, message, "", false)
|
|
}
|
|
|
|
return respData, nil
|
|
}
|
|
|
|
func (ts *Teamserver) TsAgentGetHostedTasksCount(agentId string, count int, maxDataSize int) ([]byte, error) {
|
|
agent, err := ts.getAgent(agentId)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
agentData := agent.GetData()
|
|
tasksCount := agent.HostedTasks.Len()
|
|
if tasksCount > 0 {
|
|
|
|
tasks, _, err := ts.TsTaskGetAvailableTasksCount(agentData.Id, count, maxDataSize)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
respData, err := agent.PackData(tasks)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
message := fmt.Sprintf("Agent called server, sent [%v]", tformat.SizeBytesToFormat(uint64(len(respData))))
|
|
ts.TsAgentConsoleOutput(agentId, CONSOLE_OUT_INFO, message, "", false)
|
|
|
|
return respData, nil
|
|
}
|
|
return []byte(""), nil
|
|
}
|
|
|
|
//func (ts *Teamserver) TsAgentGetHostedTunnels(agentId string, channelId int, maxDataSize int) ([]byte, error) {
|
|
// value, ok := ts.Agents.Get(agentId)
|
|
// if !ok {
|
|
// return nil, fmt.Errorf("agent type %v does not exists", agentId)
|
|
// }
|
|
// agent, _ := value.(*Agent)
|
|
//
|
|
// var tasks []adaptix.TaskData
|
|
// tasksSize := 0
|
|
//
|
|
// /// TUNNELS QUEUE
|
|
//
|
|
// for i := uint(0); i < agent.HostedTunnelData.Len(); i++ {
|
|
// value, ok = agent.HostedTunnelData.Get(i)
|
|
// if ok {
|
|
// taskDataTunnel := value.(adaptix.TaskDataTunnel)
|
|
// if taskDataTunnel.ChannelId == channelId {
|
|
// if tasksSize+len(taskDataTunnel.Data.Data) < maxDataSize {
|
|
// tasks = append(tasks, taskDataTunnel.Data)
|
|
// agent.HostedTunnelData.Delete(i)
|
|
// i--
|
|
// tasksSize += len(taskDataTunnel.Data.Data)
|
|
// } else {
|
|
// break
|
|
// }
|
|
// }
|
|
// } else {
|
|
// break
|
|
// }
|
|
// }
|
|
//
|
|
// if len(tasks) > 0 {
|
|
// respData, err := ts.Extender.ExAgentPackData(agent.Data, tasks)
|
|
// if err != nil {
|
|
// return nil, err
|
|
// }
|
|
// return respData, nil
|
|
// }
|
|
//
|
|
// return []byte(""), nil
|
|
//}
|
|
|
|
/// Data
|
|
|
|
type AgentUpdateFields struct {
|
|
InternalIP *string
|
|
ExternalIP *string
|
|
GmtOffset *int
|
|
ACP *int
|
|
OemCP *int
|
|
Pid *string
|
|
Tid *string
|
|
Arch *string
|
|
Elevated *bool
|
|
Process *string
|
|
Os *int
|
|
OsDesc *string
|
|
Domain *string
|
|
Computer *string
|
|
Username *string
|
|
Impersonated *string
|
|
}
|
|
|
|
func (ts *Teamserver) TsAgentUpdateData(newAgentData adaptix.AgentData) error {
|
|
value, ok := ts.Agents.Get(newAgentData.Id)
|
|
if !ok {
|
|
return errors.New("agent does not exist")
|
|
}
|
|
agent, ok := value.(*Agent)
|
|
if !ok {
|
|
return errors.New("invalid agent type")
|
|
}
|
|
|
|
agent.UpdateData(func(d *adaptix.AgentData) {
|
|
d.Sleep = newAgentData.Sleep
|
|
d.Jitter = newAgentData.Jitter
|
|
d.WorkingTime = newAgentData.WorkingTime
|
|
d.KillDate = newAgentData.KillDate
|
|
})
|
|
|
|
agentData := agent.GetData()
|
|
err := ts.DBMS.DbAgentUpdate(agentData)
|
|
if err != nil {
|
|
logs.Error("", err.Error())
|
|
}
|
|
|
|
packetNew := CreateSpAgentUpdate(agentData)
|
|
ts.TsSyncStateWithCategory(packetNew, "agent:"+agentData.Id, SyncCategoryAgents)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (ts *Teamserver) TsAgentUpdateDataPartial(agentId string, updateData interface{}) error {
|
|
value, ok := ts.Agents.Get(agentId)
|
|
if !ok {
|
|
return errors.New("agent does not exist")
|
|
}
|
|
agent, ok := value.(*Agent)
|
|
if !ok {
|
|
return errors.New("invalid agent type")
|
|
}
|
|
|
|
syncPacket := SyncPackerAgentUpdate{
|
|
SpType: TYPE_AGENT_UPDATE,
|
|
Id: agentId,
|
|
}
|
|
|
|
updated := ts.applyAgentUpdate(agent, updateData, &syncPacket)
|
|
if !updated {
|
|
return nil
|
|
}
|
|
|
|
agentData := agent.GetData()
|
|
err := ts.DBMS.DbAgentUpdate(agentData)
|
|
if err != nil {
|
|
logs.Error("", err.Error())
|
|
}
|
|
|
|
ts.TsSyncAllClients(syncPacket)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (ts *Teamserver) applyAgentUpdate(agent *Agent, updateData interface{}, syncPacket *SyncPackerAgentUpdate) bool {
|
|
updated := false
|
|
|
|
type fieldAccessor struct {
|
|
InternalIP *string `json:"internal_ip,omitempty"`
|
|
ExternalIP *string `json:"external_ip,omitempty"`
|
|
GmtOffset *int `json:"gmt_offset,omitempty"`
|
|
ACP *int `json:"acp,omitempty"`
|
|
OemCP *int `json:"oemcp,omitempty"`
|
|
Pid *string `json:"pid,omitempty"`
|
|
Tid *string `json:"tid,omitempty"`
|
|
Arch *string `json:"arch,omitempty"`
|
|
Elevated *bool `json:"elevated,omitempty"`
|
|
Process *string `json:"process,omitempty"`
|
|
Os *int `json:"os,omitempty"`
|
|
OsDesc *string `json:"os_desc,omitempty"`
|
|
Domain *string `json:"domain,omitempty"`
|
|
Computer *string `json:"computer,omitempty"`
|
|
Username *string `json:"username,omitempty"`
|
|
Impersonated *string `json:"impersonated,omitempty"`
|
|
Tags *string `json:"tags,omitempty"`
|
|
Mark *string `json:"mark,omitempty"`
|
|
Color *string `json:"color,omitempty"`
|
|
Listener *string `json:"listener,omitempty"`
|
|
CustomData *string `json:"custom_data,omitempty"`
|
|
}
|
|
|
|
jsonBytes, err := json.Marshal(updateData)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
|
|
var fields fieldAccessor
|
|
if err := json.Unmarshal(jsonBytes, &fields); err != nil {
|
|
return false
|
|
}
|
|
|
|
agent.UpdateData(func(d *adaptix.AgentData) {
|
|
if fields.InternalIP != nil {
|
|
d.InternalIP = *fields.InternalIP
|
|
syncPacket.InternalIP = fields.InternalIP
|
|
updated = true
|
|
}
|
|
if fields.ExternalIP != nil {
|
|
d.ExternalIP = *fields.ExternalIP
|
|
syncPacket.ExternalIP = fields.ExternalIP
|
|
updated = true
|
|
}
|
|
if fields.GmtOffset != nil {
|
|
d.GmtOffset = *fields.GmtOffset
|
|
syncPacket.GmtOffset = fields.GmtOffset
|
|
updated = true
|
|
}
|
|
if fields.ACP != nil {
|
|
d.ACP = *fields.ACP
|
|
syncPacket.ACP = fields.ACP
|
|
updated = true
|
|
}
|
|
if fields.OemCP != nil {
|
|
d.OemCP = *fields.OemCP
|
|
syncPacket.OemCP = fields.OemCP
|
|
updated = true
|
|
}
|
|
if fields.Pid != nil {
|
|
d.Pid = *fields.Pid
|
|
syncPacket.Pid = fields.Pid
|
|
updated = true
|
|
}
|
|
if fields.Tid != nil {
|
|
d.Tid = *fields.Tid
|
|
syncPacket.Tid = fields.Tid
|
|
updated = true
|
|
}
|
|
if fields.Arch != nil {
|
|
d.Arch = *fields.Arch
|
|
syncPacket.Arch = fields.Arch
|
|
updated = true
|
|
}
|
|
if fields.Elevated != nil {
|
|
d.Elevated = *fields.Elevated
|
|
syncPacket.Elevated = fields.Elevated
|
|
updated = true
|
|
}
|
|
if fields.Process != nil {
|
|
d.Process = *fields.Process
|
|
syncPacket.Process = fields.Process
|
|
updated = true
|
|
}
|
|
if fields.Os != nil {
|
|
d.Os = *fields.Os
|
|
syncPacket.Os = fields.Os
|
|
updated = true
|
|
}
|
|
if fields.OsDesc != nil {
|
|
d.OsDesc = *fields.OsDesc
|
|
syncPacket.OsDesc = fields.OsDesc
|
|
updated = true
|
|
}
|
|
if fields.Domain != nil {
|
|
d.Domain = *fields.Domain
|
|
syncPacket.Domain = fields.Domain
|
|
updated = true
|
|
}
|
|
if fields.Computer != nil {
|
|
d.Computer = *fields.Computer
|
|
syncPacket.Computer = fields.Computer
|
|
updated = true
|
|
}
|
|
if fields.Username != nil {
|
|
d.Username = *fields.Username
|
|
syncPacket.Username = fields.Username
|
|
updated = true
|
|
}
|
|
if fields.Impersonated != nil {
|
|
d.Impersonated = *fields.Impersonated
|
|
syncPacket.Impersonated = fields.Impersonated
|
|
updated = true
|
|
}
|
|
if fields.Tags != nil {
|
|
d.Tags = *fields.Tags
|
|
syncPacket.Tags = fields.Tags
|
|
updated = true
|
|
}
|
|
if fields.Listener != nil {
|
|
d.Listener = *fields.Listener
|
|
syncPacket.Listener = fields.Listener
|
|
updated = true
|
|
}
|
|
if fields.Mark != nil {
|
|
if d.Mark != "Terminated" && d.Mark != *fields.Mark {
|
|
d.Mark = *fields.Mark
|
|
syncPacket.Mark = fields.Mark
|
|
if *fields.Mark == "Disconnect" {
|
|
d.LastTick = int(time.Now().Unix())
|
|
}
|
|
updated = true
|
|
}
|
|
}
|
|
if fields.Color != nil {
|
|
|
|
if *fields.Color != "" {
|
|
bcolor := ""
|
|
fcolor := ""
|
|
colors := strings.Split(d.Color, "-")
|
|
if len(colors) == 2 {
|
|
bcolor = colors[0]
|
|
fcolor = colors[1]
|
|
}
|
|
|
|
newcolors := strings.Split(*fields.Color, "-")
|
|
if len(newcolors) == 2 {
|
|
if isvalid.ValidColorRGB(newcolors[0]) {
|
|
bcolor = newcolors[0]
|
|
}
|
|
if isvalid.ValidColorRGB(newcolors[1]) {
|
|
fcolor = newcolors[1]
|
|
}
|
|
}
|
|
*fields.Color = bcolor + "-" + fcolor
|
|
}
|
|
|
|
d.Color = *fields.Color
|
|
syncPacket.Color = fields.Color
|
|
updated = true
|
|
}
|
|
if fields.CustomData != nil {
|
|
d.CustomData = []byte(*fields.CustomData)
|
|
updated = true
|
|
}
|
|
})
|
|
|
|
return updated
|
|
}
|
|
|
|
func (ts *Teamserver) TsAgentTerminate(agentId string, terminateTaskId string) error {
|
|
// --- PRE HOOK ---
|
|
preEvent := &eventing.EventDataAgentTerminate{AgentId: agentId, TaskId: terminateTaskId}
|
|
if !ts.EventManager.Emit(eventing.EventAgentTerminate, eventing.HookPre, preEvent) {
|
|
if preEvent.Error != nil {
|
|
return preEvent.Error
|
|
}
|
|
return fmt.Errorf("operation cancelled by hook")
|
|
}
|
|
// ----------------
|
|
|
|
value, ok := ts.Agents.Get(agentId)
|
|
if !ok {
|
|
return errors.New("agent does not exist")
|
|
}
|
|
|
|
agent, ok := value.(*Agent)
|
|
if !ok {
|
|
return errors.New("invalid agent type")
|
|
}
|
|
agent.Active = false
|
|
agent.UpdateData(func(d *adaptix.AgentData) {
|
|
d.Mark = "Terminated"
|
|
})
|
|
|
|
/// Clear Downloads
|
|
|
|
var downloads []string
|
|
ts.downloads.ForEach(func(key string, value interface{}) bool {
|
|
downloadData := value.(adaptix.DownloadData)
|
|
if downloadData.AgentId == agentId && downloadData.State != adaptix.DOWNLOAD_STATE_FINISHED {
|
|
downloads = append(downloads, downloadData.FileId)
|
|
}
|
|
return true
|
|
})
|
|
for _, id := range downloads {
|
|
_ = ts.TsDownloadClose(id, adaptix.DOWNLOAD_STATE_CANCELED)
|
|
}
|
|
|
|
/// Clear Tunnels
|
|
|
|
var tunnelIds []string
|
|
ts.TunnelManager.ForEachTunnel(func(key string, tunnel *Tunnel) bool {
|
|
if tunnel.Data.AgentId == agentId {
|
|
tunnelIds = append(tunnelIds, tunnel.Data.TunnelId)
|
|
}
|
|
return true
|
|
})
|
|
for _, id := range tunnelIds {
|
|
_ = ts.TsTunnelStop(id)
|
|
}
|
|
|
|
/// Clear Terminals
|
|
|
|
var terminals []int
|
|
ts.terminals.ForEach(func(key string, value interface{}) bool {
|
|
term := value.(*Terminal)
|
|
if term.agent.GetData().Id == agentId {
|
|
terminals = append(terminals, term.TerminalId)
|
|
}
|
|
return true
|
|
})
|
|
for _, id := range terminals {
|
|
termId := fmt.Sprintf("%08x", id)
|
|
_ = ts.TsTerminalConnClose(termId, "agent terminated")
|
|
}
|
|
|
|
/// Clear HostedTunnelData
|
|
|
|
agent.HostedTunnelData.Clear()
|
|
|
|
/// Clear HostedTasks
|
|
for {
|
|
item, err := agent.HostedTasks.Pop()
|
|
if err != nil {
|
|
break
|
|
}
|
|
task := item.(adaptix.TaskData)
|
|
packet := CreateSpAgentTaskRemove(task)
|
|
ts.TsSyncAllClients(packet)
|
|
}
|
|
|
|
/// Clear TasksRunning
|
|
|
|
tasksRunning := agent.RunningTasks.CutMap()
|
|
for _, value = range tasksRunning {
|
|
task := value.(adaptix.TaskData)
|
|
if task.TaskId == terminateTaskId && task.Sync {
|
|
agent.RunningTasks.Put(task.TaskId, task)
|
|
} else {
|
|
packet := CreateSpAgentTaskRemove(task)
|
|
ts.TsSyncAllClients(packet)
|
|
}
|
|
|
|
if task.Type == adaptix.TASK_TYPE_JOB {
|
|
agent.RunningJobs.Delete(task.TaskId)
|
|
}
|
|
}
|
|
|
|
/// Clear Pivots
|
|
|
|
if agent.PivotParent != nil {
|
|
_ = ts.TsPivotDelete(agent.PivotParent.PivotId)
|
|
}
|
|
|
|
var pivots []string
|
|
for value := range agent.PivotChilds.Iterator() {
|
|
pivotId := value.Item.(*adaptix.PivotData).PivotId
|
|
pivots = append(pivots, pivotId)
|
|
}
|
|
for _, pivotId := range pivots {
|
|
_ = ts.TsPivotDelete(pivotId)
|
|
}
|
|
|
|
/// Update
|
|
|
|
agentData := agent.GetData()
|
|
err := ts.DBMS.DbAgentUpdate(agentData)
|
|
if err != nil {
|
|
logs.Error("", err.Error())
|
|
}
|
|
|
|
packetNew := CreateSpAgentUpdate(agentData)
|
|
ts.TsSyncStateWithCategory(packetNew, "agent:"+agentId, SyncCategoryAgents)
|
|
|
|
// --- POST HOOK ---
|
|
postEvent := &eventing.EventDataAgentTerminate{AgentId: agentId, TaskId: terminateTaskId}
|
|
ts.EventManager.EmitAsync(eventing.EventAgentTerminate, postEvent)
|
|
// -----------------
|
|
|
|
return nil
|
|
}
|
|
|
|
func (ts *Teamserver) TsAgentConsoleRemove(agentId string) error {
|
|
_, ok := ts.Agents.Get(agentId)
|
|
if !ok {
|
|
return fmt.Errorf("agent '%v' does not exist", agentId)
|
|
}
|
|
_ = ts.DBMS.DbConsoleDelete(agentId)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (ts *Teamserver) TsAgentRemove(agentId string) error {
|
|
// --- PRE HOOK ---
|
|
preEvent := &eventing.EventDataAgentRemove{}
|
|
if value, ok := ts.Agents.Get(agentId); ok {
|
|
if agent, ok := value.(*Agent); ok {
|
|
preEvent.Agent = agent.GetData()
|
|
}
|
|
}
|
|
if !ts.EventManager.Emit(eventing.EventAgentRemove, eventing.HookPre, preEvent) {
|
|
if preEvent.Error != nil {
|
|
return preEvent.Error
|
|
}
|
|
return fmt.Errorf("operation cancelled by hook")
|
|
}
|
|
// ----------------
|
|
|
|
value, ok := ts.Agents.GetDelete(agentId)
|
|
if !ok {
|
|
return fmt.Errorf("agent '%v' does not exist", agentId)
|
|
}
|
|
agent, ok := value.(*Agent)
|
|
if !ok {
|
|
return fmt.Errorf("invalid agent type for '%v'", agentId)
|
|
}
|
|
|
|
/// Clear Downloads
|
|
|
|
var downloads []string
|
|
ts.downloads.ForEach(func(key string, value interface{}) bool {
|
|
downloadData := value.(adaptix.DownloadData)
|
|
if downloadData.AgentId == agentId && downloadData.State != adaptix.DOWNLOAD_STATE_FINISHED {
|
|
downloads = append(downloads, downloadData.FileId)
|
|
}
|
|
return true
|
|
})
|
|
for _, id := range downloads {
|
|
_ = ts.TsDownloadClose(id, adaptix.DOWNLOAD_STATE_CANCELED)
|
|
}
|
|
|
|
/// Clear Tunnels
|
|
|
|
var tunnelIds2 []string
|
|
ts.TunnelManager.ForEachTunnel(func(key string, tunnel *Tunnel) bool {
|
|
if tunnel.Data.AgentId == agentId {
|
|
tunnelIds2 = append(tunnelIds2, tunnel.Data.TunnelId)
|
|
}
|
|
return true
|
|
})
|
|
for _, id := range tunnelIds2 {
|
|
_ = ts.TsTunnelStop(id)
|
|
}
|
|
|
|
/// Clear Pivots
|
|
|
|
if agent.PivotParent != nil {
|
|
_ = ts.TsPivotDelete(agent.PivotParent.PivotId)
|
|
}
|
|
|
|
var pivots []string
|
|
for value := range agent.PivotChilds.Iterator() {
|
|
pivotId := value.Item.(*adaptix.PivotData).PivotId
|
|
pivots = append(pivots, pivotId)
|
|
}
|
|
for _, pivotId := range pivots {
|
|
_ = ts.TsPivotDelete(pivotId)
|
|
}
|
|
|
|
err := ts.DBMS.DbAgentDelete(agentId)
|
|
if err != nil {
|
|
logs.Error("", err.Error())
|
|
} else {
|
|
_ = ts.DBMS.DbTaskDelete("", agentId)
|
|
_ = ts.DBMS.DbConsoleDelete(agentId)
|
|
}
|
|
|
|
packet := CreateSpAgentRemove(agentId)
|
|
ts.TsSyncAllClientsWithCategory(packet, SyncCategoryAgents)
|
|
|
|
// --- POST HOOK ---
|
|
postEvent := &eventing.EventDataAgentRemove{Agent: agent.GetData()}
|
|
ts.EventManager.EmitAsync(eventing.EventAgentRemove, postEvent)
|
|
// -----------------
|
|
|
|
return nil
|
|
}
|
|
|
|
func (ts *Teamserver) TsAgentSetTick(agentId string, listenerName string) error {
|
|
value, ok := ts.Agents.Get(agentId)
|
|
if !ok {
|
|
return fmt.Errorf("agent type %v does not exists", agentId)
|
|
}
|
|
agent, ok := value.(*Agent)
|
|
if !ok {
|
|
return fmt.Errorf("invalid agent type for '%v'", agentId)
|
|
}
|
|
|
|
agentData := agent.GetData()
|
|
|
|
listenerChanged := (listenerName != "") && (agentData.Listener != listenerName)
|
|
|
|
if agentData.Async {
|
|
if listenerChanged {
|
|
agent.UpdateData(func(d *adaptix.AgentData) {
|
|
d.LastTick = int(time.Now().Unix())
|
|
d.Listener = listenerName
|
|
})
|
|
updatedAgentData := agent.GetData()
|
|
packet := CreateSpAgentUpdate(updatedAgentData)
|
|
ts.TsSyncStateWithCategory(packet, "agent:"+agentId, SyncCategoryAgents)
|
|
_ = ts.DBMS.DbAgentUpdate(updatedAgentData)
|
|
} else {
|
|
agent.UpdateData(func(d *adaptix.AgentData) {
|
|
d.LastTick = int(time.Now().Unix())
|
|
})
|
|
_ = ts.DBMS.DbAgentTick(agent.GetData())
|
|
}
|
|
agent.Tick = true
|
|
} else if listenerChanged {
|
|
agent.UpdateData(func(d *adaptix.AgentData) {
|
|
d.Listener = listenerName
|
|
})
|
|
updatedAgentData := agent.GetData()
|
|
packet := CreateSpAgentUpdate(updatedAgentData)
|
|
ts.TsSyncStateWithCategory(packet, "agent:"+agentId, SyncCategoryAgents)
|
|
_ = ts.DBMS.DbAgentUpdate(updatedAgentData)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
/// Sync
|
|
|
|
func (ts *Teamserver) TsAgentTickUpdate() {
|
|
for {
|
|
var agentSlice []string
|
|
ts.Agents.ForEach(func(key string, value interface{}) bool {
|
|
agent, ok := value.(*Agent)
|
|
if !ok {
|
|
return true
|
|
}
|
|
agentData := agent.GetData()
|
|
if agentData.Async {
|
|
if agent.Tick {
|
|
agent.Tick = false
|
|
agentSlice = append(agentSlice, agentData.Id)
|
|
}
|
|
}
|
|
return true
|
|
})
|
|
|
|
if len(agentSlice) > 0 {
|
|
packetTick := CreateSpAgentTick(agentSlice)
|
|
ts.TsSyncStateWithCategory(packetTick, "tick", SyncCategoryAgents)
|
|
}
|
|
|
|
time.Sleep(800 * time.Millisecond)
|
|
}
|
|
}
|
|
|
|
/// Console
|
|
|
|
func (ts *Teamserver) TsAgentConsoleOutput(agentId string, messageType int, message string, clearText string, store bool) {
|
|
packet := CreateSpAgentConsoleOutput(agentId, messageType, message, clearText)
|
|
ts.TsSyncConsole(packet, "")
|
|
|
|
if store {
|
|
_ = ts.DBMS.DbConsoleInsert(agentId, packet)
|
|
}
|
|
}
|
|
|
|
func (ts *Teamserver) TsAgentConsoleOutputClient(agentId string, client string, messageType int, message string, clearText string) {
|
|
packet := CreateSpAgentConsoleOutput(agentId, messageType, message, clearText)
|
|
ts.TsSyncConsole(packet, client)
|
|
}
|
|
|
|
func (ts *Teamserver) TsAgentConsoleErrorCommand(agentId string, client string, cmdline string, message string, HookId string, HandlerId string) {
|
|
packet := CreateSpAgentErrorCommand(agentId, cmdline, message, HookId, HandlerId)
|
|
ts.TsSyncConsole(packet, client)
|
|
}
|
|
|
|
func (ts *Teamserver) TsAgentConsoleLocalCommand(agentId string, client string, cmdline string, message string, text string) {
|
|
packet := CreateSpAgentLocalCommand(agentId, cmdline, message, text)
|
|
ts.TsSyncConsole(packet, client)
|
|
}
|