예제 #1
0
파일: ssh.go 프로젝트: simudream/duplex
func ssh_acceptChannels(chans <-chan ssh.NewChannel, peerConn *ssh_peerConnection, peer *Peer) {
	var meta ssh_channelData
	for newCh := range chans {
		switch newCh.ChannelType() {
		case "@duplex":
			go func() {
				err := ssh.Unmarshal(newCh.ExtraData(), &meta)
				if err != nil {
					newCh.Reject(ssh.UnknownChannelType, "failed to parse channel data")
					return
				}
				ch, reqs, err := newCh.Accept()
				if err != nil {
					debug("accept error:", err)
					return
				}
				peerConn.attachedCh[ch.LocalID()] = make(chan interface{}, 1024)
				duplexChan := &ssh_channel{
					Channel:         ch,
					ssh_channelData: meta,
					peerConn:        peerConn,
				}

				go duplexChan.handleRequests(reqs)

				if meta.FlagAttached {
					peerConn.attachedCh[meta.Attach] <- duplexChan
				} else {
					peer.incomingCh <- duplexChan
				}

			}()
		}
	}
}
예제 #2
0
파일: ssh.go 프로젝트: simudream/duplex
func (c *ssh_channel) handleRequests(in <-chan *ssh.Request) {
	for req := range in {
		switch req.Type {
		case "trailers":
			var trailers ssh_trailerPayload
			if err := ssh.Unmarshal(req.Payload, &trailers); err != nil {
				req.Reply(false, nil)
			}

			c.ssh_channelData.Trailers = trailers.Trailers

			req.Reply(true, nil)

		default:
			if req.WantReply {
				req.Reply(false, nil)
			}
		}
	}
}
예제 #3
0
파일: ssh.go 프로젝트: simudream/duplex
func newPeerConnection_ssh(peer *Peer, u *url.URL) (peerConnection, error) {
	pk, err := loadPrivateKey(peer.GetOption(OptPrivateKey).(string))
	if err != nil {
		return nil, err
	}
	config := &ssh.ClientConfig{
		User: peer.GetOption(OptName).(string),
		Auth: []ssh.AuthMethod{ssh.PublicKeys(pk)},
	}
	var addr string
	if u.Scheme == "unix" {
		addr = u.Path
	} else {
		addr = u.Host
	}
	netConn, err := net.Dial(u.Scheme, addr)
	if err != nil {
		return nil, err
	}
	conn, chans, reqs, err := ssh.NewClientConn(netConn, addr, config)
	if err != nil {
		return nil, err
	}
	nameCh := make(chan string)
	go func() {
		for r := range reqs {
			switch r.Type {
			case "@duplex-greeting":
				var greeting ssh_greetingPayload
				err := ssh.Unmarshal(r.Payload, &greeting)
				if err != nil {
					continue
				}
				nameCh <- greeting.Name
				r.Reply(true, nil)
			default:
				// This handles keepalive messages and matches
				// the behaviour of OpenSSH.
				r.Reply(false, nil)
			}
		}
	}()
	var name string
	select {
	case name = <-nameCh:
	case <-time.After(time.Second * 5):
		return nil, errors.New("greeting timeout")
	}
	go func() {
		conn.Wait()
		//debug("client disconnection: ", err)
		// TODO: handle unexpected disconnect
	}()
	pc := &ssh_peerConnection{
		endpoint:   u.String(),
		remote:     name,
		conn:       conn,
		local:      peer.GetOption(OptName).(string),
		attachedCh: make(map[uint32]chan interface{}),
	}
	go ssh_acceptChannels(chans, pc, peer)
	return pc, nil
}