docker4ssh/server/ssh/handle.go
2021-12-19 17:30:51 +01:00

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)
}
}
}