@@ -47,6 +47,9 @@ type Session interface {
47
47
// RawCommand returns the exact command that was provided by the user.
48
48
RawCommand () string
49
49
50
+ // Subsystem returns the subsystem requested by the user.
51
+ Subsystem () string
52
+
50
53
// PublicKey returns the PublicKey used to authenticate. If a public key was not
51
54
// used it will return nil.
52
55
PublicKey () PublicKey
@@ -87,32 +90,35 @@ func DefaultSessionHandler(srv *Server, conn *gossh.ServerConn, newChan gossh.Ne
87
90
return
88
91
}
89
92
sess := & session {
90
- Channel : ch ,
91
- conn : conn ,
92
- handler : srv .Handler ,
93
- ptyCb : srv .PtyCallback ,
94
- sessReqCb : srv .SessionRequestCallback ,
95
- ctx : ctx ,
93
+ Channel : ch ,
94
+ conn : conn ,
95
+ handler : srv .Handler ,
96
+ ptyCb : srv .PtyCallback ,
97
+ sessReqCb : srv .SessionRequestCallback ,
98
+ subsystemHandlers : srv .SubsystemHandlers ,
99
+ ctx : ctx ,
96
100
}
97
101
sess .handleRequests (reqs )
98
102
}
99
103
100
104
type session struct {
101
105
sync.Mutex
102
106
gossh.Channel
103
- conn * gossh.ServerConn
104
- handler Handler
105
- handled bool
106
- exited bool
107
- pty * Pty
108
- winch chan Window
109
- env []string
110
- ptyCb PtyCallback
111
- sessReqCb SessionRequestCallback
112
- rawCmd string
113
- ctx Context
114
- sigCh chan <- Signal
115
- sigBuf []Signal
107
+ conn * gossh.ServerConn
108
+ handler Handler
109
+ subsystemHandlers map [string ]SubsystemHandler
110
+ handled bool
111
+ exited bool
112
+ pty * Pty
113
+ winch chan Window
114
+ env []string
115
+ ptyCb PtyCallback
116
+ sessReqCb SessionRequestCallback
117
+ rawCmd string
118
+ subsystem string
119
+ ctx Context
120
+ sigCh chan <- Signal
121
+ sigBuf []Signal
116
122
}
117
123
118
124
func (sess * session ) Write (p []byte ) (n int , err error ) {
@@ -191,6 +197,10 @@ func (sess *session) Command() []string {
191
197
return append ([]string (nil ), cmd ... )
192
198
}
193
199
200
+ func (sess * session ) Subsystem () string {
201
+ return sess .subsystem
202
+ }
203
+
194
204
func (sess * session ) Pty () (Pty , <- chan Window , bool ) {
195
205
if sess .pty != nil {
196
206
return * sess .pty , sess .winch , true
@@ -239,6 +249,40 @@ func (sess *session) handleRequests(reqs <-chan *gossh.Request) {
239
249
sess .handler (sess )
240
250
sess .Exit (0 )
241
251
}()
252
+ case "subsystem" :
253
+ if sess .handled {
254
+ req .Reply (false , nil )
255
+ continue
256
+ }
257
+
258
+ var payload = struct { Value string }{}
259
+ gossh .Unmarshal (req .Payload , & payload )
260
+ sess .subsystem = payload .Value
261
+
262
+ // If there's a session policy callback, we need to confirm before
263
+ // accepting the session.
264
+ if sess .sessReqCb != nil && ! sess .sessReqCb (sess , req .Type ) {
265
+ sess .rawCmd = ""
266
+ req .Reply (false , nil )
267
+ continue
268
+ }
269
+
270
+ handler := sess .subsystemHandlers [payload .Value ]
271
+ if handler == nil {
272
+ handler = sess .subsystemHandlers ["default" ]
273
+ }
274
+ if handler == nil {
275
+ req .Reply (false , nil )
276
+ continue
277
+ }
278
+
279
+ sess .handled = true
280
+ req .Reply (true , nil )
281
+
282
+ go func () {
283
+ handler (sess )
284
+ sess .Exit (0 )
285
+ }()
242
286
case "env" :
243
287
if sess .handled {
244
288
req .Reply (false , nil )
0 commit comments