forked from jaksi/sshesame
/
channel.go
117 lines (111 loc) · 2.93 KB
/
channel.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
package channel
import (
"fmt"
log "github.com/sirupsen/logrus"
"github.com/longkeyy/sshesame/request"
"golang.org/x/crypto/ssh"
"golang.org/x/crypto/ssh/terminal"
"io"
"net"
"strconv"
)
// RFC 4254
type x11 struct {
SourceAddress string
SourcePort uint32
}
func (payload x11) String() string {
return net.JoinHostPort(payload.SourceAddress, strconv.Itoa(int(payload.SourcePort)))
}
type tcpip struct {
DestinationAddress string
DestinationPort uint32
SourceAddress string
SourcePort uint32
}
func (payload tcpip) String() string {
return fmt.Sprintf("%v -> %v",
net.JoinHostPort(payload.SourceAddress, strconv.Itoa(int(payload.SourcePort))),
net.JoinHostPort(payload.DestinationAddress, strconv.Itoa(int(payload.DestinationPort))))
}
func Handle(remoteAddr net.Addr, newChannel ssh.NewChannel) {
var payload interface{} = newChannel.ExtraData()
switch newChannel.ChannelType() {
case "x11":
parsedPayload := x11{}
err := ssh.Unmarshal(newChannel.ExtraData(), &parsedPayload)
if err != nil {
log.Warning("Failed to parse payload:", err.Error())
break
}
payload = parsedPayload
case "forwarded-tcpip":
// Server initiated forwarding
fallthrough
case "direct-tcpip":
// Client initiated forwarding
parsedPayload := tcpip{}
err := ssh.Unmarshal(newChannel.ExtraData(), &parsedPayload)
if err != nil {
log.Warning("Failed to parse payload:", err.Error())
break
}
payload = parsedPayload
}
log.WithFields(log.Fields{
"client": remoteAddr,
"channel": newChannel.ChannelType(),
"payload": payload,
}).Info("Channel requested")
channel, channelRequests, err := newChannel.Accept()
if err != nil {
log.Warning("Failed to accept channel:", err.Error())
return
}
defer channel.Close()
go request.Handle(remoteAddr, newChannel.ChannelType(), channelRequests)
if newChannel.ChannelType() == "session" {
terminal := terminal.NewTerminal(channel, "$ ")
for {
line, err := terminal.ReadLine()
if err != nil {
if err == io.EOF {
log.WithFields(log.Fields{
"client": remoteAddr,
"channel": newChannel.ChannelType(),
}).Info("Terminal closed")
request.SendExitStatus(channel)
} else {
log.Warning("Failed to read from terminal:", err.Error())
}
break
}
log.WithFields(log.Fields{
"client": remoteAddr,
"channel": newChannel.ChannelType(),
"line": line,
}).Info("Channel input received")
}
} else {
data := make([]byte, 256)
for {
length, err := channel.Read(data)
if err != nil {
if err == io.EOF {
log.WithFields(log.Fields{
"client": remoteAddr,
"channel": newChannel.ChannelType(),
}).Info("Channel closed")
} else {
log.Warning("Failed to read from channel:", err.Error())
}
break
}
log.WithFields(log.Fields{
"client": remoteAddr,
"channel": newChannel.ChannelType(),
"data": string(data[:length]),
}).Info("Channel input received")
}
}
}