Skip to content

Commit fb97a24

Browse files
committed
Add SessionPolicyCallback
Closes #7
1 parent d3a6756 commit fb97a24

File tree

4 files changed

+41
-21
lines changed

4 files changed

+41
-21
lines changed

context.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"context"
55
"encoding/hex"
66
"net"
7+
"sync"
78

89
gossh "golang.org/x/crypto/ssh"
910
)
@@ -59,9 +60,11 @@ var (
5960
// Context is a package specific context interface. It exposes connection
6061
// metadata and allows new values to be easily written to it. It's used in
6162
// authentication handlers and callbacks, and its underlying context.Context is
62-
// exposed on Session in the session Handler.
63+
// exposed on Session in the session Handler. This also embeds a sync.Locker so
64+
// values can safely be set between different sessions.
6365
type Context interface {
6466
context.Context
67+
sync.Locker
6568

6669
// User returns the username used when establishing the SSH connection.
6770
User() string
@@ -90,11 +93,12 @@ type Context interface {
9093

9194
type sshContext struct {
9295
context.Context
96+
sync.Mutex
9397
}
9498

9599
func newContext(srv *Server) (*sshContext, context.CancelFunc) {
96100
innerCtx, cancel := context.WithCancel(context.Background())
97-
ctx := &sshContext{innerCtx}
101+
ctx := &sshContext{innerCtx, sync.Mutex{}}
98102
ctx.SetValue(ContextKeyServer, srv)
99103
perms := &Permissions{&gossh.Permissions{}}
100104
ctx.SetValue(ContextKeyPermissions, perms)

server.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ type Server struct {
2929
PtyCallback PtyCallback // callback for allowing PTY sessions, allows all if nil
3030
ConnCallback ConnCallback // optional callback for wrapping net.Conn before handling
3131
LocalPortForwardingCallback LocalPortForwardingCallback // callback for allowing local port forwarding, denies all if nil
32+
SessionPolicyCallback SessionPolicyCallback
3233

3334
IdleTimeout time.Duration // connection timeout when no activity, none if empty
3435
MaxTimeout time.Duration // absolute connection timeout, none if empty

session.go

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -84,30 +84,32 @@ func sessionHandler(srv *Server, conn *gossh.ServerConn, newChan gossh.NewChanne
8484
return
8585
}
8686
sess := &session{
87-
Channel: ch,
88-
conn: conn,
89-
handler: srv.Handler,
90-
ptyCb: srv.PtyCallback,
91-
ctx: ctx,
87+
Channel: ch,
88+
conn: conn,
89+
handler: srv.Handler,
90+
ptyCb: srv.PtyCallback,
91+
sessPolCb: srv.SessionPolicyCallback,
92+
ctx: ctx,
9293
}
9394
sess.handleRequests(reqs)
9495
}
9596

9697
type session struct {
9798
sync.Mutex
9899
gossh.Channel
99-
conn *gossh.ServerConn
100-
handler Handler
101-
handled bool
102-
exited bool
103-
pty *Pty
104-
winch chan Window
105-
env []string
106-
ptyCb PtyCallback
107-
cmd []string
108-
ctx Context
109-
sigCh chan<- Signal
110-
sigBuf []Signal
100+
conn *gossh.ServerConn
101+
handler Handler
102+
handled bool
103+
exited bool
104+
pty *Pty
105+
winch chan Window
106+
env []string
107+
ptyCb PtyCallback
108+
sessPolCb SessionPolicyCallback
109+
cmd []string
110+
ctx Context
111+
sigCh chan<- Signal
112+
sigBuf []Signal
111113
}
112114

113115
func (sess *session) Write(p []byte) (n int, err error) {
@@ -209,12 +211,22 @@ func (sess *session) handleRequests(reqs <-chan *gossh.Request) {
209211
req.Reply(false, nil)
210212
continue
211213
}
212-
sess.handled = true
213-
req.Reply(true, nil)
214214

215215
var payload = struct{ Value string }{}
216216
gossh.Unmarshal(req.Payload, &payload)
217217
sess.cmd, _ = shlex.Split(payload.Value, true)
218+
219+
// If there's a session policy callback, we need to confirm before
220+
// accepting the session.
221+
if sess.sessPolCb != nil && !sess.sessPolCb(sess, req.Type) {
222+
sess.cmd = nil
223+
req.Reply(false, nil)
224+
continue
225+
}
226+
227+
sess.handled = true
228+
req.Reply(true, nil)
229+
218230
go func() {
219231
sess.handler(sess)
220232
sess.Exit(0)

ssh.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ type PasswordHandler func(ctx Context, password string) bool
4242
// PtyCallback is a hook for allowing PTY sessions.
4343
type PtyCallback func(ctx Context, pty Pty) bool
4444

45+
// SessionPolicyCallback is a callback for allowing SSH sessions.
46+
type SessionPolicyCallback func(sess Session, requestType string) bool
47+
4548
// ConnCallback is a hook for new connections before handling.
4649
// It allows wrapping for timeouts and limiting by returning
4750
// the net.Conn that will be used as the underlying connection.

0 commit comments

Comments
 (0)