Left: | ||
Right: |
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 import ( | 7 import ( |
8 "crypto" | 8 "crypto" |
9 "crypto/rand" | 9 "crypto/rand" |
10 "encoding/binary" | 10 "encoding/binary" |
(...skipping 20 matching lines...) Expand all Loading... | |
31 dialAddress string | 31 dialAddress string |
32 | 32 |
33 serverVersion string | 33 serverVersion string |
34 } | 34 } |
35 | 35 |
36 type globalRequest struct { | 36 type globalRequest struct { |
37 sync.Mutex | 37 sync.Mutex |
38 response chan interface{} | 38 response chan interface{} |
39 } | 39 } |
40 | 40 |
41 // AgentConnector connects to the proper ssh-agent | 41 // AgentDialer connects to the proper ssh-agent |
jpsugar
2013/08/26 19:13:34
Un-wrap this comment now? Lines seem a little shor
| |
42 // for key forwarding | 42 // for key forwarding. |
43 type AgentConnector interface { | 43 type AgentDialer interface { |
44 » Connect() (io.ReadWriteCloser, error) | 44 » Dial() (io.ReadWriteCloser, error) |
45 } | 45 } |
46 | 46 |
47 // Client returns a new SSH client connection using c as the underlying transpor t. | 47 // Client returns a new SSH client connection using c as the underlying transpor t. |
48 func Client(c net.Conn, config *ClientConfig) (*ClientConn, error) { | 48 func Client(c net.Conn, config *ClientConfig) (*ClientConn, error) { |
49 return clientWithAddress(c, "", config) | 49 return clientWithAddress(c, "", config) |
50 } | 50 } |
51 | 51 |
52 func clientWithAddress(c net.Conn, addr string, config *ClientConfig) (*ClientCo nn, error) { | 52 func clientWithAddress(c net.Conn, addr string, config *ClientConfig) (*ClientCo nn, error) { |
53 conn := &ClientConn{ | 53 conn := &ClientConn{ |
54 transport: newTransport(c, config.rand()), | 54 transport: newTransport(c, config.rand()), |
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
209 marshalInt(K, kInt) | 209 marshalInt(K, kInt) |
210 h.Write(K) | 210 h.Write(K) |
211 | 211 |
212 H := h.Sum(nil) | 212 H := h.Sum(nil) |
213 | 213 |
214 return H, K, nil | 214 return H, K, nil |
215 } | 215 } |
216 | 216 |
217 // Run a very simple proxy back to the ssh-agent when | 217 // Run a very simple proxy back to the ssh-agent when |
218 // the server has requested an auth channel (and the client | 218 // the server has requested an auth channel (and the client |
219 // has enabled proxying | 219 // has enabled proxying). |
220 func (c *ClientConn) agentForward(agentSock io.ReadWriteCloser, ch *clientChan) { | 220 func (c *ClientConn) agentForward(agentSock io.ReadWriteCloser, ch *clientChan) { |
221 » // Server -> Agent | 221 » // Server -> Agent. |
222 » go io.Copy(agentSock, ch.stdout) | 222 » go func() { |
223 » // Agent -> Server | 223 » » defer agentSock.Close() |
224 » go io.Copy(ch.stdin, agentSock) | 224 » » io.Copy(agentSock, ch.stdout) |
225 » }() | |
226 » // Agent -> Server. | |
227 » go func() { | |
228 » » defer ch.stdin.Close() | |
229 » » io.Copy(ch.stdin, agentSock) | |
230 » }() | |
225 } | 231 } |
226 | 232 |
227 // mainLoop reads incoming messages and routes channel messages | 233 // mainLoop reads incoming messages and routes channel messages |
228 // to their respective ClientChans. | 234 // to their respective ClientChans. |
229 func (c *ClientConn) mainLoop() { | 235 func (c *ClientConn) mainLoop() { |
230 defer func() { | 236 defer func() { |
231 c.Close() | 237 c.Close() |
232 c.chanList.closeAll() | 238 c.chanList.closeAll() |
233 c.forwardList.closeAll() | 239 c.forwardList.closeAll() |
234 }() | 240 }() |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
408 MyId: ch.localId, | 414 MyId: ch.localId, |
409 MyWindow: 1 << 14, | 415 MyWindow: 1 << 14, |
410 | 416 |
411 // As per RFC 4253 6.1, 32k is also the minimum. | 417 // As per RFC 4253 6.1, 32k is also the minimum. |
412 MaxPacketSize: 1 << 15, | 418 MaxPacketSize: 1 << 15, |
413 } | 419 } |
414 | 420 |
415 c.writePacket(marshal(msgChannelOpenConfirm, m)) | 421 c.writePacket(marshal(msgChannelOpenConfirm, m)) |
416 l <- forward{ch, raddr} | 422 l <- forward{ch, raddr} |
417 case "auth-agent@openssh.com": | 423 case "auth-agent@openssh.com": |
418 » » if c.config.ForwardingAgentConnector != nil { | 424 » » if c.config.ForwardingAgentDialer == nil { |
419 » » » agentConn, err := c.config.ForwardingAgentConnector.Conn ect() | |
420 » » » if err != nil { | |
421 » » » » c.sendConnectionFailed(msg.PeersId) | |
422 » » » } else { | |
423 » » » » ch := c.newChan(c.transport) | |
424 » » » » ch.remoteId = msg.PeersId | |
425 » » » » ch.remoteWin.add(msg.PeersWindow) | |
jpsugar
2013/08/23 18:50:37
This needs to be moved down. If the window is open
jamwt
2013/08/23 19:17:46
I see what you're saying, but I copied the pattern
jpsugar
2013/08/23 19:53:54
No, because there cannot be any data sent on the f
| |
426 » » » » ch.maxPacket = msg.MaxPacketSize | |
427 » » » » c.agentForward(agentConn, ch) | |
428 | |
429 » » » » m := channelOpenConfirmMsg{ | |
430 » » » » » PeersId: ch.remoteId, | |
431 » » » » » MyId: ch.localId, | |
432 » » » » » MyWindow: 1 << 14, | |
433 | |
434 » » » » » // As per RFC 4253 6.1, 32k is also the minimum. | |
435 » » » » » MaxPacketSize: 1 << 15, | |
436 » » » » } | |
437 | |
438 » » » » c.writePacket(marshal(msgChannelOpenConfirm, m)) | |
439 » » » } | |
440 » » } else { | |
441 // Client did not ask for key forwarding! | 425 // Client did not ask for key forwarding! |
442 c.sendUnknownChannel(msg.PeersId) | 426 c.sendUnknownChannel(msg.PeersId) |
443 » » } | 427 » » » return |
428 » » } | |
429 » » agentConn, err := c.config.ForwardingAgentDialer.Dial() | |
430 » » if err != nil { | |
431 » » » c.sendConnectionFailed(msg.PeersId) | |
432 » » » return | |
433 » » } | |
434 » » ch := c.newChan(c.transport) | |
435 » » ch.remoteId = msg.PeersId | |
436 » » ch.remoteWin.add(msg.PeersWindow) | |
437 » » ch.maxPacket = msg.MaxPacketSize | |
438 | |
439 » » m := channelOpenConfirmMsg{ | |
440 » » » PeersId: ch.remoteId, | |
441 » » » MyId: ch.localId, | |
442 » » » MyWindow: 1 << 14, | |
443 | |
444 » » » // As per RFC 4253 6.1, 32k is also the minimum. | |
445 » » » MaxPacketSize: 1 << 15, | |
446 » » } | |
447 | |
448 » » c.writePacket(marshal(msgChannelOpenConfirm, m)) | |
449 » » c.agentForward(agentConn, ch) | |
444 default: | 450 default: |
445 // unknown channel type | 451 // unknown channel type |
446 c.sendUnknownChannel(msg.PeersId) | 452 c.sendUnknownChannel(msg.PeersId) |
447 } | 453 } |
448 } | 454 } |
449 | 455 |
450 // sendGlobalRequest sends a global request message as specified | 456 // sendGlobalRequest sends a global request message as specified |
451 // in RFC4254 section 4. To correctly synchronise messages, a lock | 457 // in RFC4254 section 4. To correctly synchronise messages, a lock |
452 // is held internally until a response is returned. | 458 // is held internally until a response is returned. |
453 func (c *ClientConn) sendGlobalRequest(m interface{}) (*globalRequestSuccessMsg, error) { | 459 func (c *ClientConn) sendGlobalRequest(m interface{}) (*globalRequestSuccessMsg, error) { |
(...skipping 15 matching lines...) Expand all Loading... | |
469 m := channelOpenFailureMsg{ | 475 m := channelOpenFailureMsg{ |
470 PeersId: remoteId, | 476 PeersId: remoteId, |
471 Reason: ConnectionFailed, | 477 Reason: ConnectionFailed, |
472 Message: "invalid request", | 478 Message: "invalid request", |
473 Language: "en_US.UTF-8", | 479 Language: "en_US.UTF-8", |
474 } | 480 } |
475 return c.writePacket(marshal(msgChannelOpenFailure, m)) | 481 return c.writePacket(marshal(msgChannelOpenFailure, m)) |
476 } | 482 } |
477 | 483 |
478 // sendUnknownChannel rejects an incoming channel identified | 484 // sendUnknownChannel rejects an incoming channel identified |
479 // by remoteId on the basis of invalid or unrecognized type | 485 // by remoteId on the basis of invalid or unrecognized type. |
480 func (c *ClientConn) sendUnknownChannel(remoteId uint32) error { | 486 func (c *ClientConn) sendUnknownChannel(remoteId uint32) error { |
481 m := channelOpenFailureMsg{ | 487 m := channelOpenFailureMsg{ |
482 PeersId: remoteId, | 488 PeersId: remoteId, |
483 Reason: UnknownChannelType, | 489 Reason: UnknownChannelType, |
484 Message: "unknown or invalid channel type", | 490 Message: "unknown or invalid channel type", |
485 Language: "en_US.UTF-8", | 491 Language: "en_US.UTF-8", |
486 } | 492 } |
487 return c.writePacket(marshal(msgChannelOpenFailure, m)) | 493 return c.writePacket(marshal(msgChannelOpenFailure, m)) |
488 } | 494 } |
489 | 495 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
532 Auth []ClientAuth | 538 Auth []ClientAuth |
533 | 539 |
534 // HostKeyChecker, if not nil, is called during the cryptographic | 540 // HostKeyChecker, if not nil, is called during the cryptographic |
535 // handshake to validate the server's host key. A nil HostKeyChecker | 541 // handshake to validate the server's host key. A nil HostKeyChecker |
536 // implies that all host keys are accepted. | 542 // implies that all host keys are accepted. |
537 HostKeyChecker HostKeyChecker | 543 HostKeyChecker HostKeyChecker |
538 | 544 |
539 // Cryptographic-related configuration. | 545 // Cryptographic-related configuration. |
540 Crypto CryptoConfig | 546 Crypto CryptoConfig |
541 | 547 |
542 » // Connector to the local ssh-agent for key forwarding. | 548 » // Dialer to the local ssh-agent for key forwarding. |
543 » // If nil, no key forwarding will take place | 549 » // If nil, no key forwarding will take place. |
544 » // See `man ssh_config` on "ForwardAgent" for security implications | 550 » // See `man ssh_config` on "ForwardAgent" for security implications. |
545 » ForwardingAgentConnector AgentConnector | 551 » ForwardingAgentDialer AgentDialer |
546 } | 552 } |
547 | 553 |
548 func (c *ClientConfig) rand() io.Reader { | 554 func (c *ClientConfig) rand() io.Reader { |
549 if c.Rand == nil { | 555 if c.Rand == nil { |
550 return rand.Reader | 556 return rand.Reader |
551 } | 557 } |
552 return c.Rand | 558 return c.Rand |
553 } | 559 } |
554 | 560 |
555 // Thread safe channel list. | 561 // Thread safe channel list. |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
599 defer c.Unlock() | 605 defer c.Unlock() |
600 | 606 |
601 for _, ch := range c.chans { | 607 for _, ch := range c.chans { |
602 if ch == nil { | 608 if ch == nil { |
603 continue | 609 continue |
604 } | 610 } |
605 ch.Close() | 611 ch.Close() |
606 close(ch.msg) | 612 close(ch.msg) |
607 } | 613 } |
608 } | 614 } |
LEFT | RIGHT |