mirror of
https://github.com/bytedream/docker4ssh.git
synced 2025-05-09 12:15:11 +02:00
80 lines
1.9 KiB
Go
80 lines
1.9 KiB
Go
package ssh
|
|
|
|
import (
|
|
"docker4ssh/docker"
|
|
"fmt"
|
|
"go.uber.org/zap"
|
|
"golang.org/x/crypto/ssh"
|
|
)
|
|
|
|
type RequestType string
|
|
|
|
const (
|
|
RequestPtyReq RequestType = "pty-req"
|
|
RequestWindowChange RequestType = "window-change"
|
|
)
|
|
|
|
type PtyReqPayload struct {
|
|
Term string
|
|
|
|
Width, Height uint32
|
|
PixelWidth, PixelHeight uint32
|
|
|
|
Modes []byte
|
|
}
|
|
|
|
func handleChannels(chans <-chan ssh.NewChannel, client *docker.Client, user *User) {
|
|
for channel := range chans {
|
|
go handleChannel(channel, client, user)
|
|
}
|
|
}
|
|
|
|
func handleChannel(channel ssh.NewChannel, client *docker.Client, user *User) {
|
|
if t := channel.ChannelType(); t != "session" {
|
|
channel.Reject(ssh.UnknownChannelType, fmt.Sprintf("unknown channel type: %s", t))
|
|
return
|
|
}
|
|
|
|
conn, requests, err := channel.Accept()
|
|
if err != nil {
|
|
zap.S().Warnf("Failed to accept channel for user %s", user.ID)
|
|
return
|
|
}
|
|
defer conn.Close()
|
|
user.Terminal.ReadWriter = conn
|
|
|
|
// handle all other request besides the normal user input.
|
|
// currently, only 'pty-req' is implemented which determines a terminal size change
|
|
go handleRequest(requests, user)
|
|
|
|
// this handles the actual user terminal connection.
|
|
// blocks until the session has finished
|
|
connection(client, user)
|
|
|
|
zap.S().Debugf("Session for user %s ended", user.ID)
|
|
}
|
|
|
|
func handleRequest(requests <-chan *ssh.Request, user *User) {
|
|
for request := range requests {
|
|
switch RequestType(request.Type) {
|
|
case RequestPtyReq:
|
|
// this could spam the logs when the user resizes his window constantly
|
|
// log()
|
|
|
|
var ptyReq PtyReqPayload
|
|
ssh.Unmarshal(request.Payload, &ptyReq)
|
|
|
|
user.Terminal.Width = ptyReq.Width
|
|
user.Terminal.Height = ptyReq.Height
|
|
case RequestWindowChange:
|
|
// prevent from logging
|
|
default:
|
|
zap.S().Debugf("New request from user %s - Type: %s, Want Reply: %t, Payload: '%s'", user.ID, request.Type, request.WantReply, request.Payload)
|
|
}
|
|
|
|
if request.WantReply {
|
|
request.Reply(true, nil)
|
|
}
|
|
}
|
|
}
|