TsTerminal API upgrade

This commit is contained in:
Ralf
2025-12-26 22:16:05 +03:00
parent f0a074bac0
commit 9b34a5d26f
10 changed files with 134 additions and 61 deletions
+1 -1
View File
@@ -64,7 +64,7 @@ func (ex *AdaptixExtender) ExAgentTunnelCallbacks(agentData adaptix.AgentData, t
return module.AgentTunnelCallbacks()
}
func (ex *AdaptixExtender) ExAgentTerminalCallbacks(agentData adaptix.AgentData) (func(int, string, int, int) (adaptix.TaskData, error), func(int, []byte) (adaptix.TaskData, error), func(int) (adaptix.TaskData, error), error) {
func (ex *AdaptixExtender) ExAgentTerminalCallbacks(agentData adaptix.AgentData) (func(int, string, int, int, int) (adaptix.TaskData, error), func(int, int, []byte) (adaptix.TaskData, error), func(int) (adaptix.TaskData, error), error) {
module, ok := ex.agentModules[agentData.Name]
if !ok {
+1 -1
View File
@@ -64,7 +64,7 @@ type ExtAgent interface {
AgentPivotPackData(pivotId string, data []byte) (adaptix.TaskData, error)
AgentTunnelCallbacks() (func(int, int, int, string, int) adaptix.TaskData, func(int, int, int, string, int) adaptix.TaskData, func(int, []byte) adaptix.TaskData, func(int, []byte) adaptix.TaskData, func(int) adaptix.TaskData, func(int, int) adaptix.TaskData, error)
AgentTerminalCallbacks() (func(int, string, int, int) (adaptix.TaskData, error), func(int, []byte) (adaptix.TaskData, error), func(int) (adaptix.TaskData, error), error)
AgentTerminalCallbacks() (func(int, string, int, int, int) (adaptix.TaskData, error), func(int, int, []byte) (adaptix.TaskData, error), func(int) (adaptix.TaskData, error), error)
}
type AdaptixExtender struct {
+91 -36
View File
@@ -1,6 +1,7 @@
package server
import (
"context"
"encoding/base64"
"errors"
"fmt"
@@ -80,7 +81,7 @@ func (ts *Teamserver) TsAgentTerminalCreateChannel(terminalData string, wsconn *
return err
}
taskData, err := terminal.handlerStart(terminal.TerminalId, program, sizeH, sizeW)
taskData, err := terminal.handlerStart(terminal.TerminalId, program, sizeH, sizeW, OemCP)
if err != nil {
return err
}
@@ -115,7 +116,7 @@ func (ts *Teamserver) TsTerminalGetPipe(AgentId string, terminalId string) (*io.
return terminal.prSrv, terminal.pwTun, nil
}
func (ts *Teamserver) TsTerminalConnResume(agentId string, terminalId string) {
func (ts *Teamserver) TsTerminalConnResume(agentId string, terminalId string, ioDirect bool) {
agent, err := ts.getAgent(agentId)
if err != nil {
return
@@ -130,7 +131,26 @@ func (ts *Teamserver) TsTerminalConnResume(agentId string, terminalId string) {
return
}
relayWebsocketToTerminal(ts, agent, terminal, terminalId)
relayWebsocketToTerminal(ts, agent, terminal, terminalId, ioDirect)
}
func (ts *Teamserver) TsTerminalConnData(terminalId string, data []byte) {
value, ok := ts.terminals.Get(terminalId)
if !ok {
return
}
terminal, ok := value.(*Terminal)
if !ok {
return
}
terminal.mu.Lock()
defer terminal.mu.Unlock()
if terminal.closed || terminal.pwTun == nil {
return
}
_, _ = terminal.pwTun.Write(data)
}
func (ts *Teamserver) TsTerminalConnClose(terminalId string, status string) error {
@@ -151,31 +171,41 @@ func closeTerminalResources(terminal *Terminal) {
if terminal == nil {
return
}
terminal.mu.Lock()
if terminal.closed {
terminal.mu.Unlock()
return
}
terminal.closed = true
terminal.mu.Unlock()
if terminal.wsconn != nil {
_ = terminal.wsconn.Close()
}
if terminal.prSrv != nil {
_ = terminal.prSrv.Close()
}
if terminal.pwSrv != nil {
_ = terminal.pwSrv.Close()
if terminal.pwTun != nil {
_ = terminal.pwTun.Close()
}
if terminal.prTun != nil {
_ = terminal.prTun.Close()
}
if terminal.pwTun != nil {
_ = terminal.pwTun.Close()
if terminal.pwSrv != nil {
_ = terminal.pwSrv.Close()
}
if terminal.prSrv != nil {
_ = terminal.prSrv.Close()
}
}
///
func relayWebsocketToTerminal(ts *Teamserver, agent *Agent, terminal *Terminal, terminalId string) {
var closeOnce sync.Once
func relayWebsocketToTerminal(ts *Teamserver, agent *Agent, terminal *Terminal, terminalId string, direct bool) {
ctx, cancel := context.WithCancel(context.Background())
var once sync.Once
var wsWriteMu sync.Mutex
closeAll := func() {
closeOnce.Do(func() {
finish := func() {
once.Do(func() {
cancel()
ts.terminals.Delete(terminalId)
closeTerminalResources(terminal)
@@ -187,42 +217,67 @@ func relayWebsocketToTerminal(ts *Teamserver, agent *Agent, terminal *Terminal,
}
go func() {
defer closeAll()
defer finish()
if terminal.wsconn == nil || terminal.pwSrv == nil {
return
}
for {
_, msg, err := terminal.wsconn.ReadMessage()
if err != nil {
return
break
}
if terminal.pwSrv == nil {
return
}
if _, err = terminal.pwSrv.Write(msg); err != nil {
return
if _, err := terminal.pwSrv.Write(msg); err != nil {
break
}
}
_ = terminal.pwSrv.Close()
}()
go func() {
defer closeAll()
defer finish()
if terminal.wsconn == nil || terminal.prTun == nil {
return
}
buf := ts.TunnelManager.GetBuffer()
defer ts.TunnelManager.PutBuffer(buf)
for {
if terminal.prTun == nil {
return
}
n, err := terminal.prTun.Read(buf)
if err != nil {
return
if n > 0 {
wsWriteMu.Lock()
writeErr := terminal.wsconn.WriteMessage(websocket.BinaryMessage, buf[:n])
wsWriteMu.Unlock()
if writeErr != nil {
break
}
}
wsWriteMu.Lock()
writeErr := terminal.wsconn.WriteMessage(websocket.BinaryMessage, buf[:n])
wsWriteMu.Unlock()
if writeErr != nil {
return
if err != nil {
break
}
}
}()
if !direct {
go func() {
buf := ts.TunnelManager.GetBuffer()
defer ts.TunnelManager.PutBuffer(buf)
for {
select {
case <-ctx.Done():
return
default:
n, err := terminal.prSrv.Read(buf)
if n > 0 {
taskData, writeErr := terminal.handlerWrite(terminal.TerminalId, terminal.CodePage, buf[:n])
if writeErr == nil {
tunnelManageTask(agent, taskData)
}
relayPipeToTaskData(agent, terminal.TerminalId, taskData)
}
if err != nil {
return
}
}
}
}()
}
}
+5 -3
View File
@@ -159,7 +159,9 @@ type Terminal struct {
TerminalId int
CodePage int
agent *Agent
agent *Agent
mu sync.Mutex
closed bool
wsconn *websocket.Conn
@@ -169,8 +171,8 @@ type Terminal struct {
pwTun *io.PipeWriter
prTun *io.PipeReader
handlerStart func(terminalId int, program string, sizeH int, sizeW int) (adaptix.TaskData, error)
handlerWrite func(terminalId int, data []byte) (adaptix.TaskData, error)
handlerStart func(terminalId int, program string, sizeH int, sizeW int, oemCP int) (adaptix.TaskData, error)
handlerWrite func(terminalId int, oemCP int, data []byte) (adaptix.TaskData, error)
handlerClose func(terminalId int) (adaptix.TaskData, error)
}
@@ -2004,14 +2004,23 @@ func TunnelReverse(tunnelId int, port int) ([]byte, error) {
/// TERMINAL
func TerminalStart(terminalId int, program string, sizeH int, sizeW int) ([]byte, error) {
return nil, errors.New("Function Remote Terminal not supported")
func TerminalStart(terminalId int, program string, sizeH int, sizeW int, oemCP int) ([]byte, error) {
programArgs := ModuleObject.ts.TsConvertUTF8toCp(program, oemCP)
array := []interface{}{COMMAND_SHELL_START, terminalId, programArgs}
return PackArray(array)
}
func TerminalWrite(terminalId int, data []byte) ([]byte, error) {
return nil, errors.New("Function Remote Terminal not supported")
func TerminalWrite(terminalId int, oemCP int, data []byte) ([]byte, error) {
dataEncode := ModuleObject.ts.TsConvertUTF8toCp(string(data), oemCP)
if oemCP > 0 {
dataEncode = strings.ReplaceAll(dataEncode, "\n", "\r\n")
}
array := []interface{}{COMMAND_SHELL_WRITE, terminalId, len(dataEncode), []byte(dataEncode)}
return PackArray(array)
}
func TerminalClose(terminalId int) ([]byte, error) {
return nil, errors.New("Function Remote Terminal not supported")
array := []interface{}{COMMAND_JOBS_KILL, terminalId}
return PackArray(array)
}
@@ -3,6 +3,7 @@ package main
import (
"encoding/hex"
"encoding/json"
"io"
"math/rand"
"time"
@@ -99,6 +100,12 @@ type Teamserver interface {
TsTunnelConnectionData(channelId int, data []byte)
TsTunnelConnectionAccept(tunnelId int, channelId int)
TsTerminalConnExists(terminalId string) bool
TsTerminalGetPipe(AgentId string, terminalId string) (*io.PipeReader, *io.PipeWriter, error)
TsTerminalConnResume(agentId string, terminalId string, ioDirect bool)
TsTerminalConnData(terminalId string, data []byte)
TsTerminalConnClose(terminalId string, status string) error
TsConvertCpToUTF8(input string, codePage int) string
TsConvertUTF8toCp(input string, codePage int) string
TsWin32Error(errorCode uint) string
@@ -318,12 +325,12 @@ func TunnelMessageReverse(tunnelId int, port int) adaptix.TaskData {
/// TERMINAL
func (m *ModuleExtender) AgentTerminalCallbacks() (func(int, string, int, int) (adaptix.TaskData, error), func(int, []byte) (adaptix.TaskData, error), func(int) (adaptix.TaskData, error), error) {
func (m *ModuleExtender) AgentTerminalCallbacks() (func(int, string, int, int, int) (adaptix.TaskData, error), func(int, int, []byte) (adaptix.TaskData, error), func(int) (adaptix.TaskData, error), error) {
return TerminalMessageStart, TerminalMessageWrite, TerminalMessageClose, nil
}
func TerminalMessageStart(terminalId int, program string, sizeH int, sizeW int) (adaptix.TaskData, error) {
packData, err := TerminalStart(terminalId, program, sizeH, sizeW)
func TerminalMessageStart(terminalId int, program string, sizeH int, sizeW int, oemCP int) (adaptix.TaskData, error) {
packData, err := TerminalStart(terminalId, program, sizeH, sizeW, oemCP)
if err != nil {
return adaptix.TaskData{}, err
}
@@ -337,8 +344,8 @@ func TerminalMessageStart(terminalId int, program string, sizeH int, sizeW int)
return taskData, nil
}
func TerminalMessageWrite(channelId int, data []byte) (adaptix.TaskData, error) {
packData, err := TerminalWrite(channelId, data)
func TerminalMessageWrite(terminalId int, oemCP int, data []byte) (adaptix.TaskData, error) {
packData, err := TerminalWrite(terminalId, oemCP, data)
if err != nil {
return adaptix.TaskData{}, err
}
@@ -1545,14 +1545,14 @@ func TunnelReverse(tunnelId int, port int) ([]byte, error) {
/// TERMINAL
func TerminalStart(terminalId int, program string, sizeH int, sizeW int) ([]byte, error) {
func TerminalStart(terminalId int, program string, sizeH int, sizeW int, oemCP int) ([]byte, error) {
packerData, _ := msgpack.Marshal(ParamsTerminalStart{TermId: terminalId, Program: program, Height: sizeH, Width: sizeW})
cmd := Command{Code: COMMAND_TERMINAL_START, Data: packerData}
return msgpack.Marshal(cmd)
}
func TerminalWrite(terminalId int, data []byte) ([]byte, error) {
return nil, nil
func TerminalWrite(terminalId int, oemCP int, data []byte) ([]byte, error) {
return data, nil
}
func TerminalClose(terminalId int) ([]byte, error) {
@@ -331,12 +331,12 @@ func TunnelMessageReverse(tunnelId int, port int) adaptix.TaskData {
/// TERMINAL
func (m *ModuleExtender) AgentTerminalCallbacks() (func(int, string, int, int) (adaptix.TaskData, error), func(int, []byte) (adaptix.TaskData, error), func(int) (adaptix.TaskData, error), error) {
func (m *ModuleExtender) AgentTerminalCallbacks() (func(int, string, int, int, int) (adaptix.TaskData, error), func(int, int, []byte) (adaptix.TaskData, error), func(int) (adaptix.TaskData, error), error) {
return TerminalMessageStart, TerminalMessageWrite, TerminalMessageClose, nil
}
func TerminalMessageStart(terminalId int, program string, sizeH int, sizeW int) (adaptix.TaskData, error) {
packData, err := TerminalStart(terminalId, program, sizeH, sizeW)
func TerminalMessageStart(terminalId int, program string, sizeH int, sizeW int, oemCP int) (adaptix.TaskData, error) {
packData, err := TerminalStart(terminalId, program, sizeH, sizeW, oemCP)
if err != nil {
return adaptix.TaskData{}, err
}
@@ -350,8 +350,8 @@ func TerminalMessageStart(terminalId int, program string, sizeH int, sizeW int)
return taskData, nil
}
func TerminalMessageWrite(channelId int, data []byte) (adaptix.TaskData, error) {
packData, err := TerminalWrite(channelId, data)
func TerminalMessageWrite(terminalId int, oemCP int, data []byte) (adaptix.TaskData, error) {
packData, err := TerminalWrite(terminalId, oemCP, data)
if err != nil {
return adaptix.TaskData{}, err
}
@@ -41,7 +41,7 @@ type Teamserver interface {
TsAgentTerminalCloseChannel(terminalId string, status string) error
TsTerminalConnExists(terminalId string) bool
TsTerminalConnResume(agentId string, terminalId string)
TsTerminalConnResume(agentId string, terminalId string, ioDirect bool)
TsTerminalGetPipe(AgentId string, terminalId string) (*io.PipeReader, *io.PipeWriter, error)
TsTunnelGetPipe(AgentId string, channelId int) (*io.PipeReader, *io.PipeWriter, error)
@@ -401,7 +401,7 @@ func (handler *TCP) handleConnection(conn net.Conn, ts Teamserver) {
return
}
ts.TsTerminalConnResume(agentId, terminalId)
ts.TsTerminalConnResume(agentId, terminalId, true)
pr, pw, err := ModuleObject.ts.TsTerminalGetPipe(agentId, terminalId)
if err != nil {