Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(361)

Delta Between Two Patch Sets: ssh/session_test.go

Issue 14225043: code review 14225043: go.crypto/ssh: reimplement SSH connection protocol modu... (Closed)
Left Patch Set: diff -r 2cd6b3b93cdb https://code.google.com/p/go.crypto Created 10 years, 5 months ago
Right Patch Set: diff -r cd1eea1eb828 https://code.google.com/p/go.crypto Created 10 years, 5 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
« no previous file with change/comment | « ssh/session.go ('k') | ssh/tcpip.go » ('j') | no next file with change/comment »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
LEFTRIGHT
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 "log"
15 "math/rand" 14 "math/rand"
16 "net" 15 "net"
17 "testing" 16 "testing"
18 17
19 "code.google.com/p/go.crypto/ssh/terminal" 18 "code.google.com/p/go.crypto/ssh/terminal"
20 ) 19 )
21 20
22 var _ = log.Println 21 type serverType func(*channel, *testing.T)
23
24 type serverType func(Channel, *testing.T)
25 22
26 // dial constructs a new test server and returns a *ClientConn. 23 // dial constructs a new test server and returns a *ClientConn.
27 func dial(handler serverType, t *testing.T) *ClientConn { 24 func dial(handler serverType, t *testing.T) *ClientConn {
28 l, err := Listen("tcp", "127.0.0.1:0", serverConfig) 25 l, err := Listen("tcp", "127.0.0.1:0", serverConfig)
29 if err != nil { 26 if err != nil {
30 t.Fatalf("unable to listen: %v", err) 27 t.Fatalf("unable to listen: %v", err)
31 } 28 }
32 go func() { 29 go func() {
33 defer l.Close() 30 defer l.Close()
34 conn, err := l.Accept() 31 conn, err := l.Accept()
(...skipping 18 matching lines...) Expand all
53 } 50 }
54 if err != nil { 51 if err != nil {
55 t.Errorf("Unable to accept incoming channel requ est: %v", err) 52 t.Errorf("Unable to accept incoming channel requ est: %v", err)
56 return 53 return
57 } 54 }
58 if ch.ChannelType() != "session" { 55 if ch.ChannelType() != "session" {
59 ch.Reject(UnknownChannelType, "unknown channel t ype") 56 ch.Reject(UnknownChannelType, "unknown channel t ype")
60 continue 57 continue
61 } 58 }
62 59
63 » » » ch.Accept() 60 » » » if err = ch.Accept(); err != nil {
61 » » » » t.Errorf("Accept: %v", err)
62 » » » }
64 go func() { 63 go func() {
65 defer close(done) 64 defer close(done)
66 » » » » handler(ch, 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 },
77 } 76 }
78 77
79 c, err := Dial("tcp", l.Addr().String(), config) 78 c, err := Dial("tcp", l.Addr().String(), config)
80 if err != nil { 79 if err != nil {
81 t.Fatalf("unable to dial remote side: %v", err) 80 t.Fatalf("unable to dial remote side: %v", err)
82 } 81 }
83 return c 82 return c
84 } 83 }
85 84
86 // TEST a simple string is returned to session.Stdout. 85 // Test a simple string is returned to session.Stdout.
87 func TestSessionShell(t *testing.T) { 86 func TestSessionShell(t *testing.T) {
88 conn := dial(shellHandler, t) 87 conn := dial(shellHandler, t)
89 defer conn.Close() 88 defer conn.Close()
90 session, err := conn.NewSession() 89 session, err := conn.NewSession()
91 if err != nil { 90 if err != nil {
92 t.Fatalf("Unable to request new session: %v", err) 91 t.Fatalf("Unable to request new session: %v", err)
93 } 92 }
94 defer session.Close() 93 defer session.Close()
95 stdout := new(bytes.Buffer) 94 stdout := new(bytes.Buffer)
96 session.Stdout = stdout 95 session.Stdout = stdout
(...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 t.Fatalf("expected command to fail but it didn't") 326 t.Fatalf("expected command to fail but it didn't")
328 } 327 }
329 _, ok := err.(*ExitError) 328 _, ok := err.(*ExitError)
330 if ok { 329 if ok {
331 // you can't actually test for errors.errorString 330 // you can't actually test for errors.errorString
332 // because it's not exported. 331 // because it's not exported.
333 t.Fatalf("expected *errorString but got %T", err) 332 t.Fatalf("expected *errorString but got %T", err)
334 } 333 }
335 } 334 }
336 335
337 // Verify that the client never accepts a packet larger than maxpacket.
338 func TestServerStdoutRespectsMaxPacketSize(t *testing.T) {
339 conn := dial(largeSendHandler, t)
340 defer conn.Close()
341 session, err := conn.NewSession()
342 if err != nil {
343 t.Fatalf("Unable to request new session: %v", err)
344 }
345 defer session.Close()
346 out, err := session.StdoutPipe()
347 if err != nil {
348 t.Fatalf("Unable to connect to Stdout: %v", err)
349 }
350 if err := session.Shell(); err != nil {
351 t.Fatalf("Unable to execute command: %v", err)
352 }
353 if _, err := ioutil.ReadAll(out); err != nil {
354 t.Fatalf("failed to read: %v", err)
355 }
356 }
357
358 // TODO(hanwen): this test should be at the transport level. 336 // TODO(hanwen): this test should be at the transport level.
359 func TestClientCannotSendHugePacket(t *testing.T) { 337 func TestClientCannotSendHugePacket(t *testing.T) {
360 // client and server use the same transport write code so this 338 // client and server use the same transport write code so this
361 // test suffices for both. 339 // test suffices for both.
362 conn := dial(shellHandler, t) 340 conn := dial(shellHandler, t)
363 defer conn.Close() 341 defer conn.Close()
364 if err := conn.transport.writePacket(make([]byte, maxPacket*2)); err == nil { 342 if err := conn.transport.writePacket(make([]byte, maxPacket*2)); err == nil {
365 t.Fatalf("huge packet write should fail") 343 t.Fatalf("huge packet write should fail")
366 } 344 }
367 } 345 }
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
399 } 377 }
400 result <- echoedBuf.Bytes() 378 result <- echoedBuf.Bytes()
401 }() 379 }()
402 380
403 serverStdin, err := session.StdinPipe() 381 serverStdin, err := session.StdinPipe()
404 if err != nil { 382 if err != nil {
405 t.Fatalf("StdinPipe failed: %v", err) 383 t.Fatalf("StdinPipe failed: %v", err)
406 } 384 }
407 written, err := copyNRandomly("stdin", serverStdin, origBuf, windowTestB ytes) 385 written, err := copyNRandomly("stdin", serverStdin, origBuf, windowTestB ytes)
408 if err != nil { 386 if err != nil {
409 » » t.Fatalf("falied to copy origBuf to serverStdin: %v", err) 387 » » t.Fatalf("failed to copy origBuf to serverStdin: %v", err)
410 } 388 }
411 if written != windowTestBytes { 389 if written != windowTestBytes {
412 t.Fatalf("Wrote only %d of %d bytes to server", written, windowT estBytes) 390 t.Fatalf("Wrote only %d of %d bytes to server", written, windowT estBytes)
413 } 391 }
414 392
415 echoedBytes := <-result 393 echoedBytes := <-result
416 394
417 if !bytes.Equal(origBytes, echoedBytes) { 395 if !bytes.Equal(origBytes, echoedBytes) {
418 t.Fatalf("Echoed buffer differed from original, orig %d, echoed %d", len(origBytes), len(echoedBytes)) 396 t.Fatalf("Echoed buffer differed from original, orig %d, echoed %d", len(origBytes), len(echoedBytes))
419 } 397 }
(...skipping 21 matching lines...) Expand all
441 Status uint32 419 Status uint32
442 } 420 }
443 421
444 type exitSignalMsg struct { 422 type exitSignalMsg struct {
445 Signal string 423 Signal string
446 CoreDumped bool 424 CoreDumped bool
447 Errmsg string 425 Errmsg string
448 Lang string 426 Lang string
449 } 427 }
450 428
451 func newServerShell(ch Channel, prompt string) *ServerTerminal { 429 func newServerShell(ch *channel, prompt string) *ServerTerminal {
452 term := terminal.NewTerminal(ch, prompt) 430 term := terminal.NewTerminal(ch, prompt)
453 s := &ServerTerminal{ 431 s := &ServerTerminal{
454 Term: term, 432 Term: term,
455 » » Channel: ch, 433 » » Channel: newCompatChannel(ch),
456 » } 434 » }
457 » go s.HandleRequests()
458 return s 435 return s
459 } 436 }
460 437
461 func exitStatusZeroHandler(ch Channel, t *testing.T) { 438 func exitStatusZeroHandler(ch *channel, t *testing.T) {
462 defer ch.Close() 439 defer ch.Close()
463 // this string is returned to stdout 440 // this string is returned to stdout
464 shell := newServerShell(ch, "> ") 441 shell := newServerShell(ch, "> ")
465 readLine(shell, t) 442 readLine(shell, t)
466 sendStatus(0, ch, t) 443 sendStatus(0, ch, t)
467 } 444 }
468 445
469 func exitStatusNonZeroHandler(ch Channel, t *testing.T) { 446 func exitStatusNonZeroHandler(ch *channel, t *testing.T) {
470 defer ch.Close() 447 defer ch.Close()
471 shell := newServerShell(ch, "> ") 448 shell := newServerShell(ch, "> ")
472 readLine(shell, t) 449 readLine(shell, t)
473 sendStatus(15, ch, t) 450 sendStatus(15, ch, t)
474 } 451 }
475 452
476 func exitSignalAndStatusHandler(ch Channel, t *testing.T) { 453 func exitSignalAndStatusHandler(ch *channel, t *testing.T) {
477 defer ch.Close() 454 defer ch.Close()
478 shell := newServerShell(ch, "> ") 455 shell := newServerShell(ch, "> ")
479 readLine(shell, t) 456 readLine(shell, t)
480 sendStatus(15, ch, t) 457 sendStatus(15, ch, t)
481 sendSignal("TERM", ch, t) 458 sendSignal("TERM", ch, t)
482 } 459 }
483 460
484 func exitSignalHandler(ch Channel, t *testing.T) { 461 func exitSignalHandler(ch *channel, t *testing.T) {
485 defer ch.Close() 462 defer ch.Close()
486 shell := newServerShell(ch, "> ") 463 shell := newServerShell(ch, "> ")
487 readLine(shell, t) 464 readLine(shell, t)
488 sendSignal("TERM", ch, t) 465 sendSignal("TERM", ch, t)
489 } 466 }
490 467
491 func exitSignalUnknownHandler(ch Channel, t *testing.T) { 468 func exitSignalUnknownHandler(ch *channel, t *testing.T) {
492 defer ch.Close() 469 defer ch.Close()
493 shell := newServerShell(ch, "> ") 470 shell := newServerShell(ch, "> ")
494 readLine(shell, t) 471 readLine(shell, t)
495 sendSignal("SYS", ch, t) 472 sendSignal("SYS", ch, t)
496 } 473 }
497 474
498 func exitWithoutSignalOrStatus(ch Channel, t *testing.T) { 475 func exitWithoutSignalOrStatus(ch *channel, t *testing.T) {
499 defer ch.Close() 476 defer ch.Close()
500 shell := newServerShell(ch, "> ") 477 shell := newServerShell(ch, "> ")
501 readLine(shell, t) 478 readLine(shell, t)
502 } 479 }
503 480
504 func shellHandler(ch Channel, t *testing.T) { 481 func shellHandler(ch *channel, t *testing.T) {
505 defer ch.Close() 482 defer ch.Close()
506 // this string is returned to stdout 483 // this string is returned to stdout
507 shell := newServerShell(ch, "golang") 484 shell := newServerShell(ch, "golang")
508 readLine(shell, t) 485 readLine(shell, t)
509 sendStatus(0, ch, t) 486 sendStatus(0, ch, t)
510 } 487 }
511 488
512 // Ignores the command, writes fixed strings to stderr and stdout. 489 // Ignores the command, writes fixed strings to stderr and stdout.
513 // Strings are "this-is-stdout." and "this-is-stderr.". 490 // Strings are "this-is-stdout." and "this-is-stderr.".
514 func fixedOutputHandler(ch Channel, t *testing.T) { 491 func fixedOutputHandler(ch *channel, t *testing.T) {
515 » defer ch.Close() 492 » defer ch.Close()
516 493 » _, err := ch.Read(make([]byte, 0))
517 » _ = <-ch.ReceivedRequests() 494 » if _, ok := err.(ChannelRequest); !ok {
495 » » t.Fatalf("error: expected channel request, got: %#v", err)
496 » » return
497 » }
498
518 // ignore request, always send some text 499 // ignore request, always send some text
519 ch.AckRequest(true) 500 ch.AckRequest(true)
520 501
521 » _, err := io.WriteString(ch, "this-is-stdout.") 502 » _, err = io.WriteString(ch, "this-is-stdout.")
522 if err != nil { 503 if err != nil {
523 t.Fatalf("error writing on server: %v", err) 504 t.Fatalf("error writing on server: %v", err)
524 } 505 }
525 » _, err = io.WriteString(ch.Stderr(), "this-is-stderr.") 506 » _, err = io.WriteString(ch.Extended(1), "this-is-stderr.")
526 if err != nil { 507 if err != nil {
527 t.Fatalf("error writing on server: %v", err) 508 t.Fatalf("error writing on server: %v", err)
528 } 509 }
529 sendStatus(0, ch, t) 510 sendStatus(0, ch, t)
530 } 511 }
531 512
532 func readLine(shell *ServerTerminal, t *testing.T) { 513 func readLine(shell *ServerTerminal, t *testing.T) {
533 if _, err := shell.ReadLine(); err != nil && err != io.EOF { 514 if _, err := shell.ReadLine(); err != nil && err != io.EOF {
534 t.Errorf("unable to read line: %v", err) 515 t.Errorf("unable to read line: %v", err)
535 } 516 }
536 } 517 }
537 518
538 func sendStatus(status uint32, ch Channel, t *testing.T) { 519 func sendStatus(status uint32, ch *channel, t *testing.T) {
539 msg := exitStatusMsg{ 520 msg := exitStatusMsg{
540 Status: status, 521 Status: status,
541 } 522 }
542 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 {
543 t.Errorf("unable to send status: %v", err) 524 t.Errorf("unable to send status: %v", err)
544 } 525 }
545 } 526 }
546 527
547 func sendSignal(signal string, ch Channel, t *testing.T) { 528 func sendSignal(signal string, ch *channel, t *testing.T) {
548 sig := exitSignalMsg{ 529 sig := exitSignalMsg{
549 Signal: signal, 530 Signal: signal,
550 CoreDumped: false, 531 CoreDumped: false,
551 Errmsg: "Process terminated", 532 Errmsg: "Process terminated",
552 Lang: "en-GB-oed", 533 Lang: "en-GB-oed",
553 } 534 }
554 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 {
555 t.Errorf("unable to send signal: %v", err) 536 t.Errorf("unable to send signal: %v", err)
556 } 537 }
557 } 538 }
558 539
559 func discardHandler(ch Channel, t *testing.T) { 540 func discardHandler(ch *channel, t *testing.T) {
560 defer ch.Close() 541 defer ch.Close()
561 // grow the window to avoid being fooled by 542 // grow the window to avoid being fooled by
562 // the initial 1 << 14 window. 543 // the initial 1 << 14 window.
563 » ch.(*channel).adjustWindow(1024 * 1024) 544 » ch.adjustWindow(1024 * 1024)
564 545
565 io.Copy(ioutil.Discard, ch) 546 io.Copy(ioutil.Discard, ch)
566 } 547 }
567 548
568 func largeSendHandler(ch Channel, t *testing.T) { 549 func echoHandler(ch *channel, t *testing.T) {
569 » defer ch.Close()
570 » // grow the window to avoid being fooled by
571 » // the initial 1 << 14 window.
572 » pCh := ch.(*channel)
573 » pCh.adjustWindow(1024 * 1024)
574 » shell := newServerShell(ch, "> ")
575 » readLine(shell, t)
576 » // try to send more than the 32k window
577 » // will allow
578 » if err := pCh.writePacket(make([]byte, 128*1024)); err == nil {
579 » » t.Errorf("wrote packet larger than 32k")
580 » }
581 }
582
583 func echoHandler(ch Channel, t *testing.T) {
584 defer ch.Close() 550 defer ch.Close()
585 if n, err := copyNRandomly("echohandler", ch, ch, windowTestBytes); err != nil { 551 if n, err := copyNRandomly("echohandler", ch, ch, windowTestBytes); err != nil {
586 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)
587 } 553 }
588 } 554 }
589 555
590 // 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,
591 // buffer size to exercise more code paths. 557 // buffer size to exercise more code paths.
592 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) {
593 var ( 559 var (
(...skipping 16 matching lines...) Expand all
610 if nr != nw { 576 if nr != nw {
611 return written, io.ErrShortWrite 577 return written, io.ErrShortWrite
612 } 578 }
613 if er != nil && er != io.EOF { 579 if er != nil && er != io.EOF {
614 return written, er 580 return written, er
615 } 581 }
616 } 582 }
617 return written, nil 583 return written, nil
618 } 584 }
619 585
620 func channelKeepaliveSender(ch Channel, t *testing.T) { 586 func channelKeepaliveSender(ch *channel, t *testing.T) {
621 defer ch.Close() 587 defer ch.Close()
622 shell := newServerShell(ch, "> ") 588 shell := newServerShell(ch, "> ")
623 readLine(shell, t) 589 readLine(shell, t)
624 if _, err := ch.SendRequest("keepalive@openssh.com", true, nil); err != nil { 590 if _, err := ch.SendRequest("keepalive@openssh.com", true, nil); err != nil {
625 t.Errorf("unable to send channel keepalive request: %v", err) 591 t.Errorf("unable to send channel keepalive request: %v", err)
626 } 592 }
627 sendStatus(0, ch, t) 593 sendStatus(0, ch, t)
628 } 594 }
595
596 func TestClientWriteEOF(t *testing.T) {
597 conn := dial(simpleEchoHandler, t)
598 defer conn.Close()
599
600 session, err := conn.NewSession()
601 if err != nil {
602 t.Fatal(err)
603 }
604 defer session.Close()
605 stdin, err := session.StdinPipe()
606 if err != nil {
607 t.Fatalf("StdinPipe failed: %v", err)
608 }
609 stdout, err := session.StdoutPipe()
610 if err != nil {
611 t.Fatalf("StdoutPipe failed: %v", err)
612 }
613
614 data := []byte(`0000`)
615 _, err = stdin.Write(data)
616 if err != nil {
617 t.Fatalf("Write failed: %v", err)
618 }
619 stdin.Close()
620
621 res, err := ioutil.ReadAll(stdout)
622 if err != nil {
623 t.Fatalf("Read failed: %v", err)
624 }
625
626 if !bytes.Equal(data, res) {
627 t.Fatalf("Read differed from write, wrote: %v, read: %v", data, res)
628 }
629 }
630
631 func simpleEchoHandler(ch *channel, t *testing.T) {
632 defer ch.Close()
633 data, err := ioutil.ReadAll(ch)
634 if err != nil {
635 t.Errorf("handler read error: %v", err)
636 }
637 _, err = ch.Write(data)
638 if err != nil {
639 t.Errorf("handler write error: %v", err)
640 }
641 }
LEFTRIGHT

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b