in pkg/sshd/ssh_exec.go [292:425]
func (sess *session) handleRequests(reqs <-chan *ssh.Request) {
for req := range reqs {
switch req.Type {
case "shell", "exec":
if sess.handled {
req.Reply(false, nil)
continue
}
var payload = struct{ Value string }{}
ssh.Unmarshal(req.Payload, &payload)
sess.rawCmd = payload.Value
//// If there's a session policy callback, we need to confirm before
//// accepting the session.
//if sess.sessReqCb != nil && !sess.sessReqCb(sess, req.Type) {
// sess.rawCmd = ""
// req.Reply(false, nil)
// continue
//}
sess.handled = true
req.Reply(true, nil)
go func() {
sess.srv.connectionHandler(sess)
sess.Exit(0)
}()
case "subsystem":
if sess.handled {
req.Reply(false, nil)
continue
}
var payload = struct{ Value string }{}
ssh.Unmarshal(req.Payload, &payload)
sess.subsystem = payload.Value
//// If there's a session policy callback, we need to confirm before
//// accepting the session.
//if sess.sessReqCb != nil && !sess.sessReqCb(sess, req.Type) {
// sess.rawCmd = ""
// req.Reply(false, nil)
// continue
//}
if "sftp" == payload.Value {
sess.handled = true
req.Reply(true, nil)
go func() {
sftpHandler(sess)
sess.Exit(0)
}()
} else {
req.Reply(false, nil)
continue
}
case "env":
if sess.handled {
req.Reply(false, nil)
continue
}
var kv struct{ Key, Value string }
ssh.Unmarshal(req.Payload, &kv)
sess.env = append(sess.env, fmt.Sprintf("%s=%s", kv.Key, kv.Value))
req.Reply(true, nil)
case "signal":
var payload struct{ Signal string }
ssh.Unmarshal(req.Payload, &payload)
sess.Lock()
if sess.sigCh != nil {
sess.sigCh <- Signal(payload.Signal)
} else {
if len(sess.sigBuf) < maxSigBufSize {
sess.sigBuf = append(sess.sigBuf, Signal(payload.Signal))
}
}
sess.Unlock()
case "pty-req":
if sess.handled || sess.pty != nil {
req.Reply(false, nil)
continue
}
ptyReq, ok := parsePtyRequest(req.Payload)
if !ok {
req.Reply(false, nil)
continue
}
//if sess.ptyCb != nil {
// ok := sess.ptyCb(sess.ctx, ptyReq)
// if !ok {
// req.Reply(false, nil)
// continue
// }
//}
sess.pty = &ptyReq
sess.winch = make(chan Window, 1)
sess.winch <- ptyReq.Window
defer func() {
// when reqs is closed
close(sess.winch)
}()
req.Reply(ok, nil)
case "window-change":
if sess.pty == nil {
req.Reply(false, nil)
continue
}
win, ok := parseWinchRequest(req.Payload)
if ok {
sess.pty.Window = win
sess.winch <- win
}
req.Reply(ok, nil)
//case agentRequestType:
// // TODO: option/callback to allow agent forwarding
// SetAgentRequested(sess.ctx)
// req.Reply(true, nil)
case "break":
ok := false
sess.Lock()
if sess.breakCh != nil {
sess.breakCh <- true
ok = true
}
req.Reply(ok, nil)
sess.Unlock()
default:
// TODO: debug log
req.Reply(false, nil)
}
}
}