LEFT | RIGHT |
1 // Copyright 2011 The Go Authors. All rights reserved. | 1 // Copyright 2011 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 package ssh | 5 package ssh |
6 | 6 |
7 // Session tests. | 7 // Session tests. |
8 | 8 |
9 import ( | 9 import ( |
10 "bytes" | 10 "bytes" |
11 crypto_rand "crypto/rand" | 11 crypto_rand "crypto/rand" |
12 "io" | 12 "io" |
13 "io/ioutil" | 13 "io/ioutil" |
14 "math/rand" | 14 "math/rand" |
15 "net" | 15 "net" |
16 "testing" | 16 "testing" |
17 | 17 |
18 "code.google.com/p/go.crypto/ssh/terminal" | 18 "code.google.com/p/go.crypto/ssh/terminal" |
19 ) | 19 ) |
20 | 20 |
21 type serverType func(Channel, *testing.T) | 21 type serverType func(*channel, *testing.T) |
22 | 22 |
23 // dial constructs a new test server and returns a *ClientConn. | 23 // dial constructs a new test server and returns a *ClientConn. |
24 func dial(handler serverType, t *testing.T) *ClientConn { | 24 func dial(handler serverType, t *testing.T) *ClientConn { |
25 l, err := Listen("tcp", "127.0.0.1:0", serverConfig) | 25 l, err := Listen("tcp", "127.0.0.1:0", serverConfig) |
26 if err != nil { | 26 if err != nil { |
27 t.Fatalf("unable to listen: %v", err) | 27 t.Fatalf("unable to listen: %v", err) |
28 } | 28 } |
29 go func() { | 29 go func() { |
30 defer l.Close() | 30 defer l.Close() |
31 conn, err := l.Accept() | 31 conn, err := l.Accept() |
(...skipping 18 matching lines...) Expand all Loading... |
50 } | 50 } |
51 if err != nil { | 51 if err != nil { |
52 t.Errorf("Unable to accept incoming channel requ
est: %v", err) | 52 t.Errorf("Unable to accept incoming channel requ
est: %v", err) |
53 return | 53 return |
54 } | 54 } |
55 if ch.ChannelType() != "session" { | 55 if ch.ChannelType() != "session" { |
56 ch.Reject(UnknownChannelType, "unknown channel t
ype") | 56 ch.Reject(UnknownChannelType, "unknown channel t
ype") |
57 continue | 57 continue |
58 } | 58 } |
59 | 59 |
60 » » » channel, err := ch.Accept() | 60 » » » if err = ch.Accept(); err != nil { |
61 » » » if err != nil { | |
62 t.Errorf("Accept: %v", err) | 61 t.Errorf("Accept: %v", err) |
63 } | 62 } |
64 go func() { | 63 go func() { |
65 defer close(done) | 64 defer close(done) |
66 » » » » handler(channel, t) | 65 » » » » handler(ch.(*compatChannel).channel, t) |
67 }() | 66 }() |
68 } | 67 } |
69 <-done | 68 <-done |
70 }() | 69 }() |
71 | 70 |
72 config := &ClientConfig{ | 71 config := &ClientConfig{ |
73 User: "testuser", | 72 User: "testuser", |
74 Auth: []ClientAuth{ | 73 Auth: []ClientAuth{ |
75 ClientAuthPassword(clientPassword), | 74 ClientAuthPassword(clientPassword), |
76 }, | 75 }, |
(...skipping 343 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
420 Status uint32 | 419 Status uint32 |
421 } | 420 } |
422 | 421 |
423 type exitSignalMsg struct { | 422 type exitSignalMsg struct { |
424 Signal string | 423 Signal string |
425 CoreDumped bool | 424 CoreDumped bool |
426 Errmsg string | 425 Errmsg string |
427 Lang string | 426 Lang string |
428 } | 427 } |
429 | 428 |
430 func newServerShell(ch Channel, prompt string) *ServerTerminal { | 429 func newServerShell(ch *channel, prompt string) *ServerTerminal { |
431 term := terminal.NewTerminal(ch, prompt) | 430 term := terminal.NewTerminal(ch, prompt) |
432 s := &ServerTerminal{ | 431 s := &ServerTerminal{ |
433 Term: term, | 432 Term: term, |
434 » » Channel: ch, | 433 » » Channel: newCompatChannel(ch), |
435 » } | 434 » } |
436 » go s.HandleRequests() | |
437 return s | 435 return s |
438 } | 436 } |
439 | 437 |
440 func exitStatusZeroHandler(ch Channel, t *testing.T) { | 438 func exitStatusZeroHandler(ch *channel, t *testing.T) { |
441 defer ch.Close() | 439 defer ch.Close() |
442 // this string is returned to stdout | 440 // this string is returned to stdout |
443 shell := newServerShell(ch, "> ") | 441 shell := newServerShell(ch, "> ") |
444 readLine(shell, t) | 442 readLine(shell, t) |
445 sendStatus(0, ch, t) | 443 sendStatus(0, ch, t) |
446 } | 444 } |
447 | 445 |
448 func exitStatusNonZeroHandler(ch Channel, t *testing.T) { | 446 func exitStatusNonZeroHandler(ch *channel, t *testing.T) { |
449 defer ch.Close() | 447 defer ch.Close() |
450 shell := newServerShell(ch, "> ") | 448 shell := newServerShell(ch, "> ") |
451 readLine(shell, t) | 449 readLine(shell, t) |
452 sendStatus(15, ch, t) | 450 sendStatus(15, ch, t) |
453 } | 451 } |
454 | 452 |
455 func exitSignalAndStatusHandler(ch Channel, t *testing.T) { | 453 func exitSignalAndStatusHandler(ch *channel, t *testing.T) { |
456 defer ch.Close() | 454 defer ch.Close() |
457 shell := newServerShell(ch, "> ") | 455 shell := newServerShell(ch, "> ") |
458 readLine(shell, t) | 456 readLine(shell, t) |
459 sendStatus(15, ch, t) | 457 sendStatus(15, ch, t) |
460 sendSignal("TERM", ch, t) | 458 sendSignal("TERM", ch, t) |
461 } | 459 } |
462 | 460 |
463 func exitSignalHandler(ch Channel, t *testing.T) { | 461 func exitSignalHandler(ch *channel, t *testing.T) { |
464 defer ch.Close() | 462 defer ch.Close() |
465 shell := newServerShell(ch, "> ") | 463 shell := newServerShell(ch, "> ") |
466 readLine(shell, t) | 464 readLine(shell, t) |
467 sendSignal("TERM", ch, t) | 465 sendSignal("TERM", ch, t) |
468 } | 466 } |
469 | 467 |
470 func exitSignalUnknownHandler(ch Channel, t *testing.T) { | 468 func exitSignalUnknownHandler(ch *channel, t *testing.T) { |
471 defer ch.Close() | 469 defer ch.Close() |
472 shell := newServerShell(ch, "> ") | 470 shell := newServerShell(ch, "> ") |
473 readLine(shell, t) | 471 readLine(shell, t) |
474 sendSignal("SYS", ch, t) | 472 sendSignal("SYS", ch, t) |
475 } | 473 } |
476 | 474 |
477 func exitWithoutSignalOrStatus(ch Channel, t *testing.T) { | 475 func exitWithoutSignalOrStatus(ch *channel, t *testing.T) { |
478 defer ch.Close() | 476 defer ch.Close() |
479 shell := newServerShell(ch, "> ") | 477 shell := newServerShell(ch, "> ") |
480 readLine(shell, t) | 478 readLine(shell, t) |
481 } | 479 } |
482 | 480 |
483 func shellHandler(ch Channel, t *testing.T) { | 481 func shellHandler(ch *channel, t *testing.T) { |
484 defer ch.Close() | 482 defer ch.Close() |
485 // this string is returned to stdout | 483 // this string is returned to stdout |
486 shell := newServerShell(ch, "golang") | 484 shell := newServerShell(ch, "golang") |
487 readLine(shell, t) | 485 readLine(shell, t) |
488 sendStatus(0, ch, t) | 486 sendStatus(0, ch, t) |
489 } | 487 } |
490 | 488 |
491 // Ignores the command, writes fixed strings to stderr and stdout. | 489 // Ignores the command, writes fixed strings to stderr and stdout. |
492 // Strings are "this-is-stdout." and "this-is-stderr.". | 490 // Strings are "this-is-stdout." and "this-is-stderr.". |
493 func fixedOutputHandler(ch Channel, t *testing.T) { | 491 func fixedOutputHandler(ch *channel, t *testing.T) { |
494 » defer ch.Close() | 492 » defer ch.Close() |
495 | 493 » _, err := ch.Read(make([]byte, 0)) |
496 » _ = <-ch.IncomingRequests() | 494 » if _, ok := err.(ChannelRequest); !ok { |
| 495 » » t.Fatalf("error: expected channel request, got: %#v", err) |
| 496 » » return |
| 497 » } |
| 498 |
497 // ignore request, always send some text | 499 // ignore request, always send some text |
498 ch.AckRequest(true) | 500 ch.AckRequest(true) |
499 | 501 |
500 » _, err := io.WriteString(ch, "this-is-stdout.") | 502 » _, err = io.WriteString(ch, "this-is-stdout.") |
501 if err != nil { | 503 if err != nil { |
502 t.Fatalf("error writing on server: %v", err) | 504 t.Fatalf("error writing on server: %v", err) |
503 } | 505 } |
504 » _, err = io.WriteString(ch.Stderr(), "this-is-stderr.") | 506 » _, err = io.WriteString(ch.Extended(1), "this-is-stderr.") |
505 if err != nil { | 507 if err != nil { |
506 t.Fatalf("error writing on server: %v", err) | 508 t.Fatalf("error writing on server: %v", err) |
507 } | 509 } |
508 sendStatus(0, ch, t) | 510 sendStatus(0, ch, t) |
509 } | 511 } |
510 | 512 |
511 func readLine(shell *ServerTerminal, t *testing.T) { | 513 func readLine(shell *ServerTerminal, t *testing.T) { |
512 if _, err := shell.ReadLine(); err != nil && err != io.EOF { | 514 if _, err := shell.ReadLine(); err != nil && err != io.EOF { |
513 t.Errorf("unable to read line: %v", err) | 515 t.Errorf("unable to read line: %v", err) |
514 } | 516 } |
515 } | 517 } |
516 | 518 |
517 func sendStatus(status uint32, ch Channel, t *testing.T) { | 519 func sendStatus(status uint32, ch *channel, t *testing.T) { |
518 msg := exitStatusMsg{ | 520 msg := exitStatusMsg{ |
519 Status: status, | 521 Status: status, |
520 } | 522 } |
521 if _, err := ch.SendRequest("exit-status", false, marshal(0, msg)); err
!= nil { | 523 if _, err := ch.SendRequest("exit-status", false, marshal(0, msg)); err
!= nil { |
522 t.Errorf("unable to send status: %v", err) | 524 t.Errorf("unable to send status: %v", err) |
523 } | 525 } |
524 } | 526 } |
525 | 527 |
526 func sendSignal(signal string, ch Channel, t *testing.T) { | 528 func sendSignal(signal string, ch *channel, t *testing.T) { |
527 sig := exitSignalMsg{ | 529 sig := exitSignalMsg{ |
528 Signal: signal, | 530 Signal: signal, |
529 CoreDumped: false, | 531 CoreDumped: false, |
530 Errmsg: "Process terminated", | 532 Errmsg: "Process terminated", |
531 Lang: "en-GB-oed", | 533 Lang: "en-GB-oed", |
532 } | 534 } |
533 if _, err := ch.SendRequest("exit-signal", false, marshal(0, sig)); err
!= nil { | 535 if _, err := ch.SendRequest("exit-signal", false, marshal(0, sig)); err
!= nil { |
534 t.Errorf("unable to send signal: %v", err) | 536 t.Errorf("unable to send signal: %v", err) |
535 } | 537 } |
536 } | 538 } |
537 | 539 |
538 func discardHandler(ch Channel, t *testing.T) { | 540 func discardHandler(ch *channel, t *testing.T) { |
539 defer ch.Close() | 541 defer ch.Close() |
540 // grow the window to avoid being fooled by | 542 // grow the window to avoid being fooled by |
541 // the initial 1 << 14 window. | 543 // the initial 1 << 14 window. |
542 » ch.(*channel).adjustWindow(1024 * 1024) | 544 » ch.adjustWindow(1024 * 1024) |
543 | 545 |
544 io.Copy(ioutil.Discard, ch) | 546 io.Copy(ioutil.Discard, ch) |
545 } | 547 } |
546 | 548 |
547 func echoHandler(ch Channel, t *testing.T) { | 549 func echoHandler(ch *channel, t *testing.T) { |
548 defer ch.Close() | 550 defer ch.Close() |
549 if n, err := copyNRandomly("echohandler", ch, ch, windowTestBytes); err
!= nil { | 551 if n, err := copyNRandomly("echohandler", ch, ch, windowTestBytes); err
!= nil { |
550 t.Errorf("short write, wrote %d, expected %d: %v ", n, windowTes
tBytes, err) | 552 t.Errorf("short write, wrote %d, expected %d: %v ", n, windowTes
tBytes, err) |
551 } | 553 } |
552 } | 554 } |
553 | 555 |
554 // copyNRandomly copies n bytes from src to dst. It uses a variable, and random, | 556 // copyNRandomly copies n bytes from src to dst. It uses a variable, and random, |
555 // buffer size to exercise more code paths. | 557 // buffer size to exercise more code paths. |
556 func copyNRandomly(title string, dst io.Writer, src io.Reader, n int) (int, erro
r) { | 558 func copyNRandomly(title string, dst io.Writer, src io.Reader, n int) (int, erro
r) { |
557 var ( | 559 var ( |
(...skipping 16 matching lines...) Expand all Loading... |
574 if nr != nw { | 576 if nr != nw { |
575 return written, io.ErrShortWrite | 577 return written, io.ErrShortWrite |
576 } | 578 } |
577 if er != nil && er != io.EOF { | 579 if er != nil && er != io.EOF { |
578 return written, er | 580 return written, er |
579 } | 581 } |
580 } | 582 } |
581 return written, nil | 583 return written, nil |
582 } | 584 } |
583 | 585 |
584 func channelKeepaliveSender(ch Channel, t *testing.T) { | 586 func channelKeepaliveSender(ch *channel, t *testing.T) { |
585 defer ch.Close() | 587 defer ch.Close() |
586 shell := newServerShell(ch, "> ") | 588 shell := newServerShell(ch, "> ") |
587 readLine(shell, t) | 589 readLine(shell, t) |
588 if _, err := ch.SendRequest("keepalive@openssh.com", true, nil); err !=
nil { | 590 if _, err := ch.SendRequest("keepalive@openssh.com", true, nil); err !=
nil { |
589 t.Errorf("unable to send channel keepalive request: %v", err) | 591 t.Errorf("unable to send channel keepalive request: %v", err) |
590 } | 592 } |
591 sendStatus(0, ch, t) | 593 sendStatus(0, ch, t) |
592 } | 594 } |
593 | 595 |
594 func TestClientWriteEOF(t *testing.T) { | 596 func TestClientWriteEOF(t *testing.T) { |
(...skipping 24 matching lines...) Expand all Loading... |
619 res, err := ioutil.ReadAll(stdout) | 621 res, err := ioutil.ReadAll(stdout) |
620 if err != nil { | 622 if err != nil { |
621 t.Fatalf("Read failed: %v", err) | 623 t.Fatalf("Read failed: %v", err) |
622 } | 624 } |
623 | 625 |
624 if !bytes.Equal(data, res) { | 626 if !bytes.Equal(data, res) { |
625 t.Fatalf("Read differed from write, wrote: %v, read: %v", data,
res) | 627 t.Fatalf("Read differed from write, wrote: %v, read: %v", data,
res) |
626 } | 628 } |
627 } | 629 } |
628 | 630 |
629 func simpleEchoHandler(ch Channel, t *testing.T) { | 631 func simpleEchoHandler(ch *channel, t *testing.T) { |
630 defer ch.Close() | 632 defer ch.Close() |
631 data, err := ioutil.ReadAll(ch) | 633 data, err := ioutil.ReadAll(ch) |
632 if err != nil { | 634 if err != nil { |
633 t.Errorf("handler read error: %v", err) | 635 t.Errorf("handler read error: %v", err) |
634 } | 636 } |
635 _, err = ch.Write(data) | 637 _, err = ch.Write(data) |
636 if err != nil { | 638 if err != nil { |
637 t.Errorf("handler write error: %v", err) | 639 t.Errorf("handler write error: %v", err) |
638 } | 640 } |
639 } | 641 } |
LEFT | RIGHT |