385 lines
9.6 KiB
Go
385 lines
9.6 KiB
Go
package server
|
|
|
|
import (
|
|
"AdaptixServer/core/eventing"
|
|
"AdaptixServer/core/utils/krypt"
|
|
"AdaptixServer/core/utils/logs"
|
|
"fmt"
|
|
"time"
|
|
|
|
"github.com/Adaptix-Framework/axc2"
|
|
)
|
|
|
|
type TaskHandler interface {
|
|
Create(tm *TaskManager, agent *Agent, taskData *adaptix.TaskData)
|
|
Update(tm *TaskManager, agent *Agent, task *adaptix.TaskData, updateData *adaptix.TaskData)
|
|
PostHook(tm *TaskManager, agent *Agent, task *adaptix.TaskData, hookData *adaptix.TaskData, jobIndex int) error
|
|
OnClientDisconnect(tm *TaskManager, agent *Agent, task *adaptix.TaskData, clientName string)
|
|
}
|
|
|
|
type TaskManager struct {
|
|
ts *Teamserver
|
|
handlers map[int]TaskHandler
|
|
}
|
|
|
|
func NewTaskManager(ts *Teamserver) *TaskManager {
|
|
tm := &TaskManager{
|
|
ts: ts,
|
|
handlers: make(map[int]TaskHandler),
|
|
}
|
|
|
|
taskHandler := &TaskTaskHandler{}
|
|
tm.handlers[adaptix.TASK_TYPE_TASK] = taskHandler
|
|
tm.handlers[adaptix.TASK_TYPE_BROWSER] = taskHandler
|
|
tm.handlers[adaptix.TASK_TYPE_JOB] = &JobTaskHandler{}
|
|
tm.handlers[adaptix.TASK_TYPE_TUNNEL] = &TunnelTaskHandler{}
|
|
|
|
return tm
|
|
}
|
|
|
|
func (tm *TaskManager) getAgent(agentId string) (*Agent, error) {
|
|
value, ok := tm.ts.Agents.Get(agentId)
|
|
if !ok {
|
|
return nil, fmt.Errorf("agent %v not found", agentId)
|
|
}
|
|
agent, ok := value.(*Agent)
|
|
if !ok {
|
|
return nil, fmt.Errorf("invalid agent type for %v", agentId)
|
|
}
|
|
return agent, nil
|
|
}
|
|
|
|
func (tm *TaskManager) prepareTaskData(agent *Agent, cmdline string, client string, taskData *adaptix.TaskData) {
|
|
agentData := agent.GetData()
|
|
|
|
if taskData.TaskId == "" {
|
|
taskData.TaskId, _ = krypt.GenerateUID(8)
|
|
}
|
|
taskData.AgentId = agentData.Id
|
|
taskData.CommandLine = cmdline
|
|
taskData.Client = client
|
|
taskData.Computer = agentData.Computer
|
|
taskData.StartDate = time.Now().Unix()
|
|
|
|
if taskData.Completed {
|
|
taskData.FinishDate = taskData.StartDate
|
|
}
|
|
|
|
taskData.User = agentData.Username
|
|
if agentData.Impersonated != "" {
|
|
taskData.User += fmt.Sprintf(" [%s]", agentData.Impersonated)
|
|
}
|
|
}
|
|
|
|
func (tm *TaskManager) syncTaskCreate(agentId string, agent *Agent, taskData *adaptix.TaskData) {
|
|
packet_task := CreateSpAgentTaskSync(*taskData)
|
|
tm.ts.TsSyncAllClientsWithCategory(packet_task, SyncCategoryTasksManager)
|
|
|
|
if taskData.Type != adaptix.TASK_TYPE_BROWSER {
|
|
packet_console := CreateSpAgentConsoleTaskSync(*taskData)
|
|
tm.ts.TsSyncConsole(packet_console, taskData.Client)
|
|
|
|
_ = tm.ts.DBMS.DbConsoleInsert(agentId, packet_console)
|
|
}
|
|
}
|
|
|
|
func (tm *TaskManager) syncTaskUpdate(agentId string, agent *Agent, taskData *adaptix.TaskData) {
|
|
|
|
packet_task := CreateSpAgentTaskUpdate(*taskData)
|
|
if taskData.HandlerId == "" {
|
|
tm.ts.TsSyncAllClientsWithCategory(packet_task, SyncCategoryTasksManager)
|
|
} else {
|
|
handlerClient := taskData.Client
|
|
tm.ts.TsSyncExcludeClientWithCategory(handlerClient, packet_task, SyncCategoryTasksManager)
|
|
packet_task.HandlerId = taskData.HandlerId
|
|
tm.ts.TsSyncClient(handlerClient, packet_task)
|
|
}
|
|
|
|
if taskData.Type != adaptix.TASK_TYPE_BROWSER {
|
|
packet_console := CreateSpAgentConsoleTaskUpd(*taskData)
|
|
tm.ts.TsSyncConsole(packet_console, taskData.Client)
|
|
|
|
_ = tm.ts.DBMS.DbConsoleInsert(agentId, packet_console)
|
|
}
|
|
}
|
|
|
|
func (tm *TaskManager) completeTask(agent *Agent, taskData *adaptix.TaskData) {
|
|
_ = tm.ts.DBMS.DbTaskInsert(*taskData)
|
|
|
|
// --- POST HOOK ---
|
|
postEvent := &eventing.EventDataTaskComplete{
|
|
AgentId: taskData.AgentId,
|
|
Task: *taskData,
|
|
}
|
|
tm.ts.EventManager.EmitAsync(eventing.EventTaskComplete, postEvent)
|
|
// -----------------
|
|
}
|
|
|
|
func (tm *TaskManager) executeServerHandler(taskData *adaptix.TaskData) {
|
|
if taskData.HandlerId == "" {
|
|
return
|
|
}
|
|
if !tm.ts.TsAxScriptIsServerHook(taskData.HandlerId) {
|
|
return
|
|
}
|
|
handlerData := map[string]interface{}{
|
|
"agent": taskData.AgentId,
|
|
"task_id": taskData.TaskId,
|
|
"cmdline": taskData.CommandLine,
|
|
"message": taskData.Message,
|
|
"text": taskData.ClearText,
|
|
"type": taskData.MessageType,
|
|
}
|
|
_ = tm.ts.TsAxScriptExecHandler(taskData.HandlerId, handlerData)
|
|
taskData.HandlerId = ""
|
|
}
|
|
|
|
func (tm *TaskManager) Create(agentId string, cmdline string, client string, taskData adaptix.TaskData) {
|
|
agent, err := tm.getAgent(agentId)
|
|
if err != nil {
|
|
logs.Error("", "TsTaskCreate: %v", err)
|
|
return
|
|
}
|
|
|
|
if !agent.Active {
|
|
return
|
|
}
|
|
|
|
tm.prepareTaskData(agent, cmdline, client, &taskData)
|
|
|
|
// --- PRE HOOK ---
|
|
preEvent := &eventing.EventDataTaskCreate{
|
|
AgentId: agentId,
|
|
Task: taskData,
|
|
Cmdline: cmdline,
|
|
Client: client,
|
|
}
|
|
if !tm.ts.EventManager.Emit(eventing.EventTaskCreate, eventing.HookPre, preEvent) {
|
|
return
|
|
}
|
|
// ----------------
|
|
|
|
handler, ok := tm.handlers[taskData.Type]
|
|
if !ok {
|
|
logs.Debug("", "Unknown task type: %d", taskData.Type)
|
|
return
|
|
}
|
|
|
|
handler.Create(tm, agent, &taskData)
|
|
|
|
// --- POST HOOK ---
|
|
postEvent := &eventing.EventDataTaskCreate{
|
|
AgentId: agentId,
|
|
Task: taskData,
|
|
Cmdline: cmdline,
|
|
Client: client,
|
|
}
|
|
tm.ts.EventManager.EmitAsync(eventing.EventTaskCreate, postEvent)
|
|
// -----------------
|
|
}
|
|
|
|
func (tm *TaskManager) Update(agentId string, updateData adaptix.TaskData) {
|
|
agent, err := tm.getAgent(agentId)
|
|
if err != nil {
|
|
logs.Error("", "TsTaskUpdate: %v", err)
|
|
return
|
|
}
|
|
|
|
value, ok := agent.RunningTasks.Get(updateData.TaskId)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
task, ok := value.(adaptix.TaskData)
|
|
if !ok {
|
|
logs.Error("", "TsTaskUpdate: invalid task type for %v", updateData.TaskId)
|
|
return
|
|
}
|
|
|
|
task.Data = []byte("")
|
|
|
|
handler, ok := tm.handlers[task.Type]
|
|
if !ok {
|
|
logs.Debug("", "Unknown task type: %d", task.Type)
|
|
return
|
|
}
|
|
|
|
handler.Update(tm, agent, &task, &updateData)
|
|
}
|
|
|
|
func (tm *TaskManager) PostHook(hookData adaptix.TaskData, jobIndex int) error {
|
|
agent, err := tm.getAgent(hookData.AgentId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
value, ok := agent.RunningTasks.Get(hookData.TaskId)
|
|
if !ok {
|
|
return fmt.Errorf("task %v not found", hookData.TaskId)
|
|
}
|
|
|
|
task, ok := value.(adaptix.TaskData)
|
|
if !ok {
|
|
return fmt.Errorf("invalid task type for %v", hookData.TaskId)
|
|
}
|
|
|
|
if task.HookId == "" || task.HookId != hookData.HookId || task.Client != hookData.Client || !tm.ts.TsClientConnected(task.Client) {
|
|
return fmt.Errorf("operation not available")
|
|
}
|
|
|
|
handler, ok := tm.handlers[task.Type]
|
|
if !ok {
|
|
return fmt.Errorf("unknown task type: %d", task.Type)
|
|
}
|
|
|
|
return handler.PostHook(tm, agent, &task, &hookData, jobIndex)
|
|
}
|
|
|
|
func (tm *TaskManager) Cancel(agentId string, taskId string) error {
|
|
agent, err := tm.getAgent(agentId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
found, retTask := agent.HostedTasks.RemoveIf(func(v interface{}) bool {
|
|
task, ok := v.(adaptix.TaskData)
|
|
return ok && task.TaskId == taskId
|
|
})
|
|
|
|
if found {
|
|
task, ok := retTask.(adaptix.TaskData)
|
|
if ok {
|
|
if task.HookId != "" && tm.ts.TsAxScriptIsServerHook(task.HookId) {
|
|
tm.ts.TsAxScriptRemovePostHook(task.HookId)
|
|
}
|
|
if task.HandlerId != "" && tm.ts.TsAxScriptIsServerHook(task.HandlerId) {
|
|
tm.ts.TsAxScriptRemoveHandler(task.HandlerId)
|
|
}
|
|
packet := CreateSpAgentTaskRemove(task)
|
|
tm.ts.TsSyncAllClients(packet)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (tm *TaskManager) Delete(agentId string, taskId string) error {
|
|
agent, err := tm.getAgent(agentId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
found, _ := agent.HostedTasks.FindIf(func(v interface{}) bool {
|
|
task, ok := v.(adaptix.TaskData)
|
|
return ok && task.TaskId == taskId
|
|
})
|
|
if found {
|
|
return fmt.Errorf("task %v in process", taskId)
|
|
}
|
|
|
|
_, ok := agent.RunningTasks.Get(taskId)
|
|
if ok {
|
|
return fmt.Errorf("task %v in process", taskId)
|
|
}
|
|
|
|
task, err := tm.ts.DBMS.DbTaskGet(taskId)
|
|
if err != nil {
|
|
return fmt.Errorf("task %v not found", taskId)
|
|
}
|
|
|
|
_ = tm.ts.DBMS.DbTaskDelete(task.TaskId, "")
|
|
|
|
packet := CreateSpAgentTaskRemove(task)
|
|
tm.ts.TsSyncAllClients(packet)
|
|
return nil
|
|
}
|
|
|
|
func (tm *TaskManager) Save(taskData adaptix.TaskData) error {
|
|
agent, err := tm.getAgent(taskData.AgentId)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
agentData := agent.GetData()
|
|
taskData.Type = adaptix.TASK_TYPE_TASK
|
|
taskData.TaskId, _ = krypt.GenerateUID(8)
|
|
taskData.Computer = agentData.Computer
|
|
taskData.User = agentData.Username
|
|
taskData.StartDate = time.Now().Unix()
|
|
taskData.FinishDate = taskData.StartDate
|
|
taskData.Sync = true
|
|
taskData.Completed = true
|
|
|
|
packet_task := CreateSpAgentTaskSync(taskData)
|
|
tm.ts.TsSyncAllClients(packet_task)
|
|
|
|
_ = tm.ts.DBMS.DbTaskInsert(taskData)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (tm *TaskManager) ProcessDisconnectedClient(clientName string) {
|
|
tm.ts.Agents.ForEach(func(agentId string, agentValue interface{}) bool {
|
|
agent, ok := agentValue.(*Agent)
|
|
if !ok {
|
|
return true
|
|
}
|
|
|
|
var tasksToProcess []string
|
|
agent.RunningTasks.ForEach(func(taskId string, taskValue interface{}) bool {
|
|
task, ok := taskValue.(adaptix.TaskData)
|
|
if !ok {
|
|
return true
|
|
}
|
|
|
|
if task.HookId != "" && task.Client == clientName {
|
|
tasksToProcess = append(tasksToProcess, taskId)
|
|
return true
|
|
}
|
|
|
|
if task.Type == adaptix.TASK_TYPE_TUNNEL && task.Client == clientName {
|
|
clientHostedTunnel := false
|
|
tm.ts.TunnelManager.ForEachTunnel(func(_ string, tunnel *Tunnel) bool {
|
|
if tunnel != nil && tunnel.TaskId == task.TaskId && tunnel.Data.Client == clientName {
|
|
clientHostedTunnel = true
|
|
return false
|
|
}
|
|
return true
|
|
})
|
|
|
|
if clientHostedTunnel {
|
|
tasksToProcess = append(tasksToProcess, taskId)
|
|
}
|
|
}
|
|
return true
|
|
})
|
|
|
|
for _, taskId := range tasksToProcess {
|
|
value, ok := agent.RunningTasks.Get(taskId)
|
|
if !ok {
|
|
continue
|
|
}
|
|
task, ok := value.(adaptix.TaskData)
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
handler, ok := tm.handlers[task.Type]
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
handler.OnClientDisconnect(tm, agent, &task, clientName)
|
|
}
|
|
|
|
return true
|
|
})
|
|
}
|
|
|
|
func (tm *TaskManager) RunningExists(agentId string, taskId string) bool {
|
|
agent, err := tm.getAgent(agentId)
|
|
if err != nil {
|
|
return false
|
|
}
|
|
return agent.RunningTasks.Contains(taskId)
|
|
}
|