@@ -7,20 +7,17 @@ import (
7
7
"errors"
8
8
"flag"
9
9
"fmt"
10
- "io"
11
10
"io/ioutil"
12
11
"log"
13
12
"net"
14
13
"os"
15
14
"os/exec"
16
15
"path/filepath"
17
16
"strings"
18
- "sync"
19
17
"syscall"
20
18
21
- "code.google.com/p/go.crypto/ssh"
22
19
"github.com/flynn/go-shlex"
23
- "github.com/kr/pty "
20
+ "golang.org/x/crypto/ssh "
24
21
)
25
22
26
23
var host = flag .String ("h" , "" , "host ip to listen on" )
@@ -50,27 +47,6 @@ func exitStatus(err error) (exitStatusMsg, error) {
50
47
return exitStatusMsg {0 }, nil
51
48
}
52
49
53
- func attachShell (cmd * exec.Cmd , stdout io.Writer , stdin io.Reader ) (* os.File , * sync.WaitGroup , error ) {
54
- var wg sync.WaitGroup
55
- wg .Add (2 )
56
-
57
- // Note that pty merges stdout and stderr.
58
- cmdPty , err := pty .Start (cmd )
59
- if err != nil {
60
- return nil , nil , err
61
- }
62
- go func () {
63
- io .Copy (stdout , cmdPty )
64
- wg .Done ()
65
- }()
66
- go func () {
67
- io .Copy (cmdPty , stdin )
68
- wg .Done ()
69
- }()
70
-
71
- return cmdPty , & wg , nil
72
- }
73
-
74
50
func addKey (conf * ssh.ServerConfig , block * pem.Block ) (err error ) {
75
51
var key interface {}
76
52
switch block .Type {
@@ -223,135 +199,3 @@ func handleConn(conn net.Conn, conf *ssh.ServerConfig, execHandler []string) {
223
199
go handleChannel (sshConn , ch , execHandler )
224
200
}
225
201
}
226
-
227
- func handleChannel (conn * ssh.ServerConn , newChan ssh.NewChannel , execHandler []string ) {
228
- ch , reqs , err := newChan .Accept ()
229
- if err != nil {
230
- log .Println ("newChan.Accept failed:" , err )
231
- return
232
- }
233
-
234
- assert := func (at string , err error ) bool {
235
- if err != nil {
236
- log .Printf ("%s failed: %s" , at , err )
237
- ch .Stderr ().Write ([]byte ("Internal error.\n " ))
238
- return true
239
- }
240
- return false
241
- }
242
-
243
- var stdout , stderr io.Writer
244
- if * debug {
245
- stdout = io .MultiWriter (ch , os .Stdout )
246
- stderr = io .MultiWriter (ch .Stderr (), os .Stdout )
247
- } else {
248
- stdout = ch
249
- stderr = ch .Stderr ()
250
- }
251
-
252
- var ptyShell * os.File
253
-
254
- for req := range reqs {
255
- switch req .Type {
256
- case "exec" :
257
- if req .WantReply {
258
- req .Reply (true , nil )
259
- }
260
-
261
- cmdline := string (req .Payload [4 :])
262
- var cmd * exec.Cmd
263
- if * shell {
264
- shellcmd := flag .Arg (1 ) + " " + cmdline
265
- cmd = exec .Command (os .Getenv ("SHELL" ), "-c" , shellcmd )
266
- } else {
267
- cmdargs , err := shlex .Split (cmdline )
268
- if assert ("shlex.Split" , err ) {
269
- ch .Close ()
270
- return
271
- }
272
- cmd = exec .Command (execHandler [0 ], append (execHandler [1 :], cmdargs ... )... )
273
- }
274
- if * env {
275
- cmd .Env = os .Environ ()
276
- } else {
277
- cmd .Env = []string {}
278
- }
279
- if conn .Permissions != nil {
280
- // Using Permissions.Extensions as a way to get state from PublicKeyCallback
281
- if conn .Permissions .Extensions ["environ" ] != "" {
282
- cmd .Env = append (cmd .Env , strings .Split (conn .Permissions .Extensions ["environ" ], "\n " )... )
283
- }
284
- cmd .Env = append (cmd .Env , "USER=" + conn .Permissions .Extensions ["user" ])
285
- }
286
- cmd .Env = append (cmd .Env , "SSH_ORIGINAL_COMMAND=" + cmdline )
287
-
288
- // cmd.Wait closes the stdin when it's done, so we need to proxy it through a pipe
289
- stdinPipe , err := cmd .StdinPipe ()
290
- if assert ("cmd.StdinPipe" , err ) {
291
- ch .Close ()
292
- return
293
- }
294
- go io .Copy (stdinPipe , ch )
295
-
296
- cmd .Stdout = stdout
297
- cmd .Stderr = stderr
298
-
299
- go func () {
300
- status , err := exitStatus (cmd .Run ())
301
- if ! assert ("exec run" , err ) {
302
- _ , err := ch .SendRequest ("exit-status" , false , ssh .Marshal (& status ))
303
- assert ("exec exit" , err )
304
- }
305
- ch .Close ()
306
- }()
307
- case "pty-req" :
308
- width , height , okSize := parsePtyRequest (req .Payload )
309
-
310
- var cmd * exec.Cmd
311
- if * shell {
312
- cmd = exec .Command (os .Getenv ("SHELL" ))
313
- } else {
314
- cmd = exec .Command (execHandler [0 ], execHandler [1 :]... )
315
- }
316
- if * env {
317
- cmd .Env = os .Environ ()
318
- } else {
319
- cmd .Env = []string {}
320
- }
321
- if conn .Permissions != nil {
322
- // Using Permissions.Extensions as a way to get state from PublicKeyCallback
323
- if conn .Permissions .Extensions ["environ" ] != "" {
324
- cmd .Env = append (cmd .Env , strings .Split (conn .Permissions .Extensions ["environ" ], "\n " )... )
325
- }
326
- cmd .Env = append (cmd .Env , "USER=" + conn .Permissions .Extensions ["user" ])
327
- }
328
- ptyShell , _ , err := attachShell (cmd , stdout , ch )
329
- if assert ("attachShell" , err ) {
330
- ch .Close ()
331
- return
332
- }
333
- if okSize {
334
- setWinsize (ptyShell .Fd (), width , height )
335
- req .Reply (true , nil )
336
- }
337
-
338
- go func () {
339
- status , err := exitStatus (cmd .Wait ())
340
- if ! assert ("pty run" , err ) {
341
- _ , err := ch .SendRequest ("exit-status" , false , ssh .Marshal (& status ))
342
- assert ("pty exit" , err )
343
- }
344
- ch .Close ()
345
- }()
346
- case "window-change" :
347
- width , height , okSize := parsePtyRequest (req .Payload )
348
- if okSize {
349
- setWinsize (ptyShell .Fd (), width , height )
350
- }
351
- }
352
-
353
- if req .WantReply {
354
- req .Reply (true , nil )
355
- }
356
- }
357
- }
0 commit comments