197 lines
5.1 KiB
Go
197 lines
5.1 KiB
Go
|
|
package starssh
|
||
|
|
|
||
|
|
import (
|
||
|
|
"bufio"
|
||
|
|
"context"
|
||
|
|
"io"
|
||
|
|
"net"
|
||
|
|
"sync"
|
||
|
|
"time"
|
||
|
|
|
||
|
|
"github.com/pkg/sftp"
|
||
|
|
"golang.org/x/crypto/ssh"
|
||
|
|
)
|
||
|
|
|
||
|
|
const (
|
||
|
|
defaultSSHPort = 22
|
||
|
|
defaultLoginTimeout = 5 * time.Second
|
||
|
|
defaultKeepAliveTimeout = 3 * time.Second
|
||
|
|
defaultShellPollInterval = 120 * time.Millisecond
|
||
|
|
defaultShellSetupDelay = 200 * time.Millisecond
|
||
|
|
defaultShellSetupTimeout = 3 * time.Second
|
||
|
|
defaultShellWaitTimeout = 30 * time.Second
|
||
|
|
defaultShellPromptToken = "__STARSSH_PROMPT__>"
|
||
|
|
defaultPTYTerm = "xterm"
|
||
|
|
defaultPTYRows = 500
|
||
|
|
defaultPTYColumns = 250
|
||
|
|
|
||
|
|
defaultTransferBufferSize = 1024 * 1024
|
||
|
|
|
||
|
|
defaultExecStreamMaxPendingChunks = 256
|
||
|
|
defaultExecStreamMaxPendingBytes = 4 * 1024 * 1024
|
||
|
|
)
|
||
|
|
|
||
|
|
type DialContextFunc func(ctx context.Context, network, address string) (net.Conn, error)
|
||
|
|
|
||
|
|
type ProxyType string
|
||
|
|
|
||
|
|
const (
|
||
|
|
ProxyTypeSOCKS5 ProxyType = "socks5"
|
||
|
|
ProxyTypeHTTPConnect ProxyType = "http_connect"
|
||
|
|
)
|
||
|
|
|
||
|
|
type ProxyConfig struct {
|
||
|
|
Type ProxyType
|
||
|
|
Addr string
|
||
|
|
Username string
|
||
|
|
Password string
|
||
|
|
Timeout time.Duration
|
||
|
|
}
|
||
|
|
|
||
|
|
type AuthMethodKind string
|
||
|
|
|
||
|
|
const (
|
||
|
|
AuthMethodPrivateKey AuthMethodKind = "private_key"
|
||
|
|
AuthMethodPassword AuthMethodKind = "password"
|
||
|
|
AuthMethodKeyboardInteractive AuthMethodKind = "keyboard_interactive"
|
||
|
|
AuthMethodSSHAgent AuthMethodKind = "ssh_agent"
|
||
|
|
)
|
||
|
|
|
||
|
|
type StarSSH struct {
|
||
|
|
stateMu sync.RWMutex
|
||
|
|
Client *ssh.Client
|
||
|
|
PublicKey ssh.PublicKey
|
||
|
|
PubkeyBase64 string
|
||
|
|
Hostname string
|
||
|
|
RemoteAddr net.Addr
|
||
|
|
Banner string
|
||
|
|
LoginInfo LoginInput
|
||
|
|
online bool
|
||
|
|
upstream *StarSSH
|
||
|
|
sftpClient *sftp.Client
|
||
|
|
sftpMu sync.Mutex
|
||
|
|
keepaliveMu sync.Mutex
|
||
|
|
keepaliveStop chan struct{}
|
||
|
|
keepaliveDone chan struct{}
|
||
|
|
}
|
||
|
|
|
||
|
|
type LoginInput struct {
|
||
|
|
KeyExchanges []string
|
||
|
|
Ciphers []string
|
||
|
|
MACs []string
|
||
|
|
User string
|
||
|
|
Password string
|
||
|
|
PasswordCallback func() (string, error)
|
||
|
|
KeyboardInteractiveCallback ssh.KeyboardInteractiveChallenge
|
||
|
|
Prikey string
|
||
|
|
PrikeyPwd string
|
||
|
|
DisableSSHAgent bool
|
||
|
|
AuthOrder []AuthMethodKind
|
||
|
|
Addr string
|
||
|
|
Port int
|
||
|
|
Timeout time.Duration
|
||
|
|
DialContext DialContextFunc
|
||
|
|
Proxy *ProxyConfig
|
||
|
|
Jump *LoginInput
|
||
|
|
KeepAliveInterval time.Duration
|
||
|
|
KeepAliveTimeout time.Duration
|
||
|
|
HostKeyCallback func(string, net.Addr, ssh.PublicKey) error
|
||
|
|
BannerCallback func(string) error
|
||
|
|
}
|
||
|
|
|
||
|
|
// StarShell keeps the legacy prompt-driven helper for POSIX-style scripted shell interactions.
|
||
|
|
// It is not a generic cross-shell abstraction; for product-grade interactive terminals, prefer TerminalSession.
|
||
|
|
type StarShell struct {
|
||
|
|
Keyword string
|
||
|
|
UseWaitDefault bool
|
||
|
|
WaitTimeout time.Duration
|
||
|
|
Session *ssh.Session
|
||
|
|
in io.Writer
|
||
|
|
out *bufio.Reader
|
||
|
|
er *bufio.Reader
|
||
|
|
outbyte []byte
|
||
|
|
errbyte []byte
|
||
|
|
lastout int64
|
||
|
|
errors error
|
||
|
|
isprint bool
|
||
|
|
isfuncs bool
|
||
|
|
iscolor bool
|
||
|
|
isecho bool
|
||
|
|
rw sync.RWMutex
|
||
|
|
funcs func(string)
|
||
|
|
writeMu sync.Mutex
|
||
|
|
commandMu sync.Mutex
|
||
|
|
closeOnce sync.Once
|
||
|
|
promptToken string
|
||
|
|
}
|
||
|
|
|
||
|
|
type TerminalConfig struct {
|
||
|
|
Term string
|
||
|
|
Rows int
|
||
|
|
Columns int
|
||
|
|
Modes ssh.TerminalModes
|
||
|
|
}
|
||
|
|
|
||
|
|
type TerminalControl byte
|
||
|
|
|
||
|
|
const (
|
||
|
|
TerminalControlInterrupt TerminalControl = 0x03
|
||
|
|
TerminalControlEOF TerminalControl = 0x04
|
||
|
|
TerminalControlBell TerminalControl = 0x07
|
||
|
|
TerminalControlBackspace TerminalControl = 0x08
|
||
|
|
TerminalControlLineKill TerminalControl = 0x15
|
||
|
|
TerminalControlQuit TerminalControl = 0x1c
|
||
|
|
TerminalControlSuspend TerminalControl = 0x1a
|
||
|
|
TerminalControlPauseOutput TerminalControl = 0x13
|
||
|
|
TerminalControlResumeOutput TerminalControl = 0x11
|
||
|
|
)
|
||
|
|
|
||
|
|
type TerminalCloseReason string
|
||
|
|
|
||
|
|
const (
|
||
|
|
TerminalCloseReasonUnknown TerminalCloseReason = ""
|
||
|
|
TerminalCloseReasonExit TerminalCloseReason = "exit"
|
||
|
|
TerminalCloseReasonSignal TerminalCloseReason = "signal"
|
||
|
|
TerminalCloseReasonClosed TerminalCloseReason = "closed"
|
||
|
|
TerminalCloseReasonContextCanceled TerminalCloseReason = "context_canceled"
|
||
|
|
TerminalCloseReasonDeadlineExceeded TerminalCloseReason = "deadline_exceeded"
|
||
|
|
TerminalCloseReasonTransportError TerminalCloseReason = "transport_error"
|
||
|
|
)
|
||
|
|
|
||
|
|
type TerminalExitInfo struct {
|
||
|
|
ExitCode int
|
||
|
|
ExitSignal string
|
||
|
|
ExitMessage string
|
||
|
|
Reason TerminalCloseReason
|
||
|
|
}
|
||
|
|
|
||
|
|
type TerminalSession struct {
|
||
|
|
Session *ssh.Session
|
||
|
|
ID string
|
||
|
|
Label string
|
||
|
|
Metadata map[string]string
|
||
|
|
stdin io.WriteCloser
|
||
|
|
stdout io.Reader
|
||
|
|
stderr io.Reader
|
||
|
|
|
||
|
|
attachMu sync.RWMutex
|
||
|
|
in io.Reader
|
||
|
|
out io.Writer
|
||
|
|
errOut io.Writer
|
||
|
|
|
||
|
|
runOnce sync.Once
|
||
|
|
runDone chan struct{}
|
||
|
|
runErr error
|
||
|
|
|
||
|
|
waitOnce sync.Once
|
||
|
|
waitDone chan struct{}
|
||
|
|
|
||
|
|
stateMu sync.RWMutex
|
||
|
|
waitErr error
|
||
|
|
exitInfo TerminalExitInfo
|
||
|
|
closeReason TerminalCloseReason
|
||
|
|
closeErr error
|
||
|
|
|
||
|
|
closeOnce sync.Once
|
||
|
|
}
|