예제 #1
0
func (s *server) handleChanReq(chanReq ssh.NewChannel, authInfo map[string]string) {
	if chanReq.ChannelType() != "session" {
		chanReq.Reject(ssh.Prohibited, "channel type is not a session")
		return
	}

	ch, reqs, err := chanReq.Accept()
	if err != nil {
		log.Errorf("fail to accept channel request %v", err)
		return
	}

	for {
		req := <-reqs

		switch req.Type {
		case "env":
		case "exec":
			s.handleExec(ch, req, authInfo)
			return
		default:
			ch.Write([]byte(fmt.Sprintf("request type %q not allowed\r\n", req.Type)))
			ch.Close()
			return
		}
	}
}
예제 #2
0
파일: client.go 프로젝트: moul/ssh2docker
// HandleChannel handles one SSH channel
func (c *Client) HandleChannel(newChannel ssh.NewChannel) error {
	if newChannel.ChannelType() != "session" {
		log.Debugf("Unknown channel type: %s", newChannel.ChannelType())
		newChannel.Reject(ssh.UnknownChannelType, "unknown channel type")
		return nil
	}

	channel, requests, err := newChannel.Accept()
	if err != nil {
		log.Errorf("newChannel.Accept failed: %v", err)
		return err
	}
	c.ChannelIdx++
	log.Debugf("HandleChannel.channel (client=%d channel=%d)", c.Idx, c.ChannelIdx)

	log.Debug("Creating pty...")
	c.Pty, c.Tty, err = pty.Open()
	if err != nil {
		log.Errorf("pty.Open failed: %v", err)
		return nil
	}

	c.HandleChannelRequests(channel, requests)

	return nil
}
예제 #3
0
파일: server.go 프로젝트: Lanzafame/butter
func handleChannel(chanRequest ssh.NewChannel) {
	handle, err := NewHandle(chanRequest.ChannelType())
	if err != nil {
		config.Log.Debug("wrong handler %v", err)
		chanRequest.Reject(ssh.UnknownChannelType, err.Error())
		return
	}

	ch, reqs, err := chanRequest.Accept()
	if err != nil {
		config.Log.Debug("fail to accept channel request %v", err)
		return
	}

	defer ch.Close()

	for req := range reqs {
		done, err := handle.Request(ch, req)
		if err != nil {
			config.Log.Debug("request errored out %v", err)
			_, err := ch.Write([]byte(fmt.Sprintf("%v\r\n", err)))
			if err != nil {
				config.Log.Debug(err.Error())
			}
		}
		if done {
			return
		}
	}
}
func (handler *DirectTcpipChannelHandler) HandleNewChannel(logger lager.Logger, newChannel ssh.NewChannel) {
	type channelOpenDirectTcpipMsg struct {
		TargetAddr string
		TargetPort uint32
		OriginAddr string
		OriginPort uint32
	}
	var directTcpipMessage channelOpenDirectTcpipMsg

	err := ssh.Unmarshal(newChannel.ExtraData(), &directTcpipMessage)
	if err != nil {
		newChannel.Reject(ssh.ConnectionFailed, "Failed to parse open channel message")
		return
	}

	destination := fmt.Sprintf("%s:%d", directTcpipMessage.TargetAddr, directTcpipMessage.TargetPort)
	conn, err := handler.dialer.Dial("tcp", destination)
	if err != nil {
		newChannel.Reject(ssh.ConnectionFailed, err.Error())
		return
	}

	channel, requests, err := newChannel.Accept()
	go ssh.DiscardRequests(requests)

	wg := &sync.WaitGroup{}

	wg.Add(2)
	go helpers.CopyAndClose(logger.Session("to-target"), wg, conn, channel)
	go helpers.CopyAndClose(logger.Session("to-channel"), wg, channel, conn)

	wg.Wait()
}
예제 #5
0
파일: socket.go 프로젝트: agriffis/envy
func handleSSHChannel(newChan ssh.NewChannel, session *Session) {
	ch, reqs, err := newChan.Accept()
	if err != nil {
		log.Println("handle channel failed:", err)
		return
	}
	exitCh := make(chan int)
	go func() {
		status := struct{ Status uint32 }{uint32(<-exitCh)}
		_, err = ch.SendRequest("exit-status", false, ssh.Marshal(&status))
		assert(err)
		ch.Close()
	}()
	for req := range reqs {
		go func(req *ssh.Request) {
			if req.WantReply {
				req.Reply(true, nil)
			}
			switch req.Type {
			case "exec":
				var payload = struct{ Value string }{}
				ssh.Unmarshal(req.Payload, &payload)
				line := strings.Trim(payload.Value, "\n")
				var args []string
				if line != "" {
					args = strings.Split(line, " ")
				}
				RunCmd(args, ch, ch, ch.Stderr(), exitCh, session)
			}
		}(req)
	}
}
예제 #6
0
func (s *Session) HandleDirectChannel(newChannel ssh.NewChannel) (bool, ssh.RejectionReason) {

	data, err := UnmarshalTunnelData(newChannel.ExtraData())
	if err != nil {
		return false, ssh.UnknownChannelType
	}

	// look up session by name
	session, host, port := s.Gateway().LookupSessionService(data.Host, uint16(data.Port))
	if session == nil {
		return false, ssh.ConnectionFailed
	}

	// found the service, attempt to open a channel
	data.Host = host
	data.Port = uint32(port)

	c2, err := session.OpenChannel("forwarded-tcpip", MarshalTunnelData(data))
	if err != nil {
		return false, ssh.ConnectionFailed
	}
	defer func() {
		if c2 != nil {
			c2.Close()
		}
	}()

	// accept the channel
	channel, requests, err := newChannel.Accept()
	if err != nil {
		return false, ssh.ResourceShortage
	}

	// cannot return false from this point on
	// also need to accepted close the channel
	defer func() {
		if channel != nil {
			if err := channel.Close(); err != nil {
				glog.Warningf("failed to close accepted channel: %s", err)
			}
		}
	}()

	c, err := NewChannel(s, channel, newChannel.ChannelType(), newChannel.ExtraData())
	if err != nil {
		glog.Errorf("failed to create accepted channel: %s", err)
		return true, 0
	}
	s.AddChannel(c)

	// no failure
	go c.HandleRequests(requests)
	go c.HandleTunnelChannel(c2)

	// do not close channel on exit
	channel = nil
	c2 = nil
	return true, 0
}
예제 #7
0
파일: ssh.go 프로젝트: cdshann/minimega
func sshHandleChannel(conn net.Conn, newChannel ssh.NewChannel) {
	// Channels have a type, depending on the application level protocol
	// intended. In the case of a shell, the type is "session" and ServerShell
	// may be used to present a simple terminal interface.
	if newChannel.ChannelType() != "session" {
		newChannel.Reject(ssh.UnknownChannelType, "unknown channel type")
		return
	}
	channel, requests, err := newChannel.Accept()
	if err != nil {
		log.Errorln(err)
		return
	}

	// Sessions have out-of-band requests such as "shell", "pty-req" and "env".
	// Here we handle only the "shell" request.
	go func(in <-chan *ssh.Request) {
		for req := range in {
			ok := false
			switch req.Type {
			case "shell":
				ok = true
				if len(req.Payload) > 0 {
					// We don't accept any commands, only the default shell.
					ok = false
				}
			case "pty-req":
				ok = true
			}
			req.Reply(ok, nil)
		}
	}(requests)

	term := terminal.NewTerminal(channel, "> ")

	go func() {
		defer channel.Close()

		for {
			line, err := term.ReadLine()
			start := time.Now().UnixNano()
			if err != nil {
				if err != io.EOF {
					log.Errorln(err)
				}
				return
			}
			sshReportChan <- uint64(len(line))
			// just echo the message
			log.Debugln("ssh received: ", line)
			term.Write([]byte(line))
			term.Write([]byte{'\r', '\n'})

			stop := time.Now().UnixNano()
			log.Info("ssh %v %vns", conn.RemoteAddr(), uint64(stop-start))
		}
	}()
}
func (handler *SessionChannelHandler) HandleNewChannel(logger lager.Logger, newChannel ssh.NewChannel) {
	channel, requests, err := newChannel.Accept()
	if err != nil {
		logger.Error("handle-new-session-channel-failed", err)
		return
	}

	handler.newSession(logger, channel, handler.keepalive).serviceRequests(requests)
}
예제 #9
0
파일: scp.go 프로젝트: zqzca/back
func (s *Server) handleChannel(ch ssh.NewChannel) {
	id := rand.Int()
	s.Debug("Handling Channel", "id", id, "chan", ch.ChannelType())

	if ch.ChannelType() != "session" {
		s.Info("Received unknown channel type", "chan", ch.ChannelType())
		ch.Reject(ssh.UnknownChannelType, "unknown channel type")
		return
	}

	channel, requests, err := ch.Accept()
	if err != nil {
		s.Error("Failed to accept channe", "err", err)
		return
	}

	var closer sync.Once
	closeChannel := func() {
		s.Debug("Closed Channel", "id", id)
		channel.Close()
	}

	defer closer.Do(closeChannel)

	for req := range requests {
		spew.Dump(req.Type)
		switch req.Type {
		case "exec":
			// Let it through
		case "env":
			if req.WantReply {
				if err = req.Reply(true, nil); err != nil {
					s.Error("Failed to ignore env command", "err", err)
				}
			}
			continue
		default:
			s.Info("Received unhandled request type", "type", req.Type)
			continue
		}

		r := &scpRequest{db: s.DB}
		processors := []processor{
			r.ParseSCPRequest, r.DownloadFile, r.EndConnectionGracefully,
		}

		for _, proc := range processors {
			if err := proc(channel, req); err != nil {
				fmt.Fprintln(channel, "failed to process request:", err.Error())
				// log.Printf("%+v", err)
				break
			}
		}

		closer.Do(closeChannel)
	}
}
예제 #10
0
파일: sshserver.go 프로젝트: d-dorazio/gork
func (server *SshServer) handleChannel(user string, newChannel ssh.NewChannel) {
	if t := newChannel.ChannelType(); t != "session" {
		newChannel.Reject(ssh.UnknownChannelType, fmt.Sprintf("unknown channel type: %s", t))
		return
	}

	connection, requests, err := newChannel.Accept()
	if err != nil {
		fmt.Printf("Could not accept channel (%s)", err)
		return
	}
	defer connection.Close()

	logfile, err := os.Create(fmt.Sprintf("%s_%s", user, storyLogFilename(server.story)))
	if err != nil {
		panic(err)
	}
	defer logfile.Close()

	logger := log.New(logfile, "", log.LstdFlags)

	terminal := terminal.NewTerminal(connection, "")
	zsshterm := &gork.ZSshTerminal{Term: terminal}

	zm, err := gork.NewZMachine(server.mem, server.header, zsshterm, logger)
	if err != nil {
		fmt.Println(err)
		return
	}

	go func() {
		for req := range requests {
			switch req.Type {
			case "shell":
				if len(req.Payload) == 0 {
					req.Reply(true, nil)
				}
			case "pty-req":
				termLen := req.Payload[3]
				w, h := parseDims(req.Payload[termLen+4:])
				terminal.SetSize(w, h)
			case "window-change":
				w, h := parseDims(req.Payload)
				terminal.SetSize(w, h)
			}
		}
	}()

	defer func() {
		recover()
	}()

	zm.InterpretAll()

}
예제 #11
0
func (u *UrlDispatcher) Dispatch(c context.Context, conn *ssh.ServerConn, ch ssh.NewChannel) {
	defer conn.Close()

	// Get channel type
	chType := ch.ChannelType()

	// Parse channel URI
	uri, err := url.ParseRequestURI(chType)
	if err != nil {
		u.Logger.Warn("Error parsing channel type", "type", chType, "err", err)
		ch.Reject(InvalidChannelType, "invalid channel URI")
		return
	} else if reject(chType, uri, ch, u.Logger) {
		return
	}
	chType = uri.Path

	// Parse query params
	values, err := url.ParseQuery(uri.RawQuery)
	if err != nil {
		u.Logger.Warn("Error parsing query params", "values", values, "err", err)
		ch.Reject(InvalidQueryParams, "invalid query params in channel type")
		return
	}

	// Determine if channel is acceptable (has a registered handler)
	if !u.Router.HasRoute(chType) {
		u.Logger.Info("UnknownChannelType", "type", chType)
		ch.Reject(ssh.UnknownChannelType, chType)
		return
	}

	// Otherwise, accept the channel
	channel, requests, err := ch.Accept()
	if err != nil {
		u.Logger.Warn("Error creating channel", "type", chType, "err", err)
		ch.Reject(ChannelAcceptError, chType)
		return
	}

	// Handle the channel
	err = u.Router.Handle(&router.UrlContext{
		Path:     uri.Path,
		Context:  c,
		Values:   values,
		Channel:  channel,
		Requests: requests,
	})
	if err != nil {
		u.Logger.Warn("Error handling channel", "type", chType, "err", err)
		ch.Reject(ChannelHandleError, fmt.Sprintf("error handling channel: %s", err.Error()))
		return
	}
}
예제 #12
0
func handleChannel(c ssh.NewChannel) {
	if t := c.ChannelType(); t != "session" {
		log.Println("rejected unknown channel type:", t)
		c.Reject(ssh.UnknownChannelType, "unknown channel type")
	}
	connection, requests, err := c.Accept()
	if err != nil {
		log.Println("channel not accepted:", err)
		return
	}
	bash := exec.Command("/bin/bash")
	close := func() {
		connection.Close()
		_, err := bash.Process.Wait()
		if err != nil {
			log.Println("bash not exited:", err)
		}
		log.Println("session closed")
	}
	bashf, err := pty.Start(bash)
	if err != nil {
		log.Println("pty not started:", err)
		close()
		return
	}
	var once sync.Once
	go func() {
		io.Copy(connection, bashf)
		once.Do(close)
	}()
	go func() {
		io.Copy(bashf, connection)
		once.Do(close)
	}()
	go func() {
		for req := range requests {
			log.Println("got request:", req.Type, "want reply:", req.WantReply)
			switch req.Type {
			case "shell":
				if len(req.Payload) == 0 {
					req.Reply(true, nil)
				}
			case "pty-req":
				termLen := req.Payload[3]
				w, h := parseDims(req.Payload[termLen+4:])
				SetWinsize(bashf.Fd(), w, h)
				req.Reply(true, nil)
			case "window-change":
				w, h := parseDims(req.Payload)
				SetWinsize(bashf.Fd(), w, h)
			}
		}
	}()
}
예제 #13
0
파일: test_utils.go 프로젝트: jak-atx/vic
func handleChannel(newChannel ssh.NewChannel, sh SessionHandler) {
	// At this point, we have the opportunity to reject the client's
	// request for another logical connection
	channel, requests, err := newChannel.Accept()
	if err != nil {
		log.Printf("Could not accept channel (%s)", err)
		return
	}

	// Prepare teardown function
	close := func() {
		channel.Close()
		log.Printf("Session closed")
	}
	defer close()

	sh.SetChannel(&channel)
	var payload []byte
	ok := true

	for req := range requests {

		if len(req.Payload) == 0 {
			req.Reply(true, nil)
		}

		path := string(req.Payload)
		typ := Mode(req.Type)

		switch typ {
		// in reality, this would be an scp with the appropriate args,
		// but for testing this is fine.
		case SOURCE:
			ok, payload = sh.Source(path)
		case DEST:
			ok, payload = sh.Destination(path)
		default:
			return
		}

		// make sure that errors get send back if we failed
		if req.WantReply {
			log.Printf("Wants reply %s", string(payload))
			req.Reply(ok, payload)
		}

		// run any pending work now that a reply has been sent
		pendingFn := sh.GetPendingWork()
		if pendingFn != nil {
			pendingFn()
		}
	}
}
예제 #14
0
파일: forward.go 프로젝트: boazy/sshmux
// ChannelForward establishes a secure channel forward (ssh -W) to the server
// requested by the user, assuming it is a permitted host.
func (s *Server) ChannelForward(session *Session, newChannel ssh.NewChannel) {
	var msg channelOpenDirectMsg
	ssh.Unmarshal(newChannel.ExtraData(), &msg)
	address := fmt.Sprintf("%s:%d", msg.RAddr, msg.RPort)

	permitted := false
	for _, remote := range session.Remotes {
		if remote == address {
			permitted = true
			break
		}
	}

	if !permitted {
		log.Printf("Disallowed access to %s for user %s", address, session.User.Name)
		newChannel.Reject(ssh.Prohibited, "remote host access denied for user")
		return
	}

	// Log the selection
	if s.Selected != nil {
		if err := s.Selected(session, address); err != nil {
			newChannel.Reject(ssh.Prohibited, "access denied")
			return
		}
	}

	conn, err := net.Dial("tcp", address)
	if err != nil {
		newChannel.Reject(ssh.ConnectionFailed, fmt.Sprintf("error: %v", err))
		return
	}

	channel, reqs, err := newChannel.Accept()

	go ssh.DiscardRequests(reqs)
	var closer sync.Once
	closeFunc := func() {
		channel.Close()
		conn.Close()
	}

	go func() {
		io.Copy(channel, conn)
		closer.Do(closeFunc)
	}()

	go func() {
		io.Copy(conn, channel)
		closer.Do(closeFunc)
	}()
}
예제 #15
0
func (s *sshServer) handleChannel(newChannel ssh.NewChannel) error {
	if newChannel.ChannelType() != "session" {
		newChannel.Reject(ssh.UnknownChannelType, "unknown channel type")
		return nil
	}

	channel, requests, err := newChannel.Accept()
	if err != nil {
		log.Println("newChannel accept failed: ", err)
		return nil
	}

	return s.handleRequests(channel, requests)
}
예제 #16
0
func handleChanReq(chanReq ssh.NewChannel) {
	if chanReq.ChannelType() != "session" {
		chanReq.Reject(ssh.UnknownChannelType, "unknown channel type")
		return
	}

	channel, requests, err := chanReq.Accept()
	if err != nil {
		return
	}

	exitloop := false
	for {
		select {
		case req := <-requests:
			if req == nil {
				continue
			}
			if req.Type == "exec" {
				handleExec(channel, req)
				if req.WantReply {
					req.Reply(true, nil)
				}
				exitloop = true
			}
			req.Reply(false, nil)
		case <-time.After(3 * time.Second):
			log.Println("no exec chanreq received, time out")
			exitloop = true
			break
		}
		if exitloop {
			break
		}
	}

	/*
	   todo: return exit status:

	   byte      SSH_MSG_CHANNEL_REQUEST
	   uint32    recipient channel
	   string    "exit-status"
	   boolean   FALSE
	   uint32    exit_status
	*/
	channel.Close()
}
예제 #17
0
func (svr *sshServer) handleChanReq(chanReq ssh.NewChannel) {
	fmt.Fprintf(sshServerDebugStream, "channel request: %v, extra: '%v'\n", chanReq.ChannelType(), hex.EncodeToString(chanReq.ExtraData()))
	switch chanReq.ChannelType() {
	case "session":
		if ch, reqs, err := chanReq.Accept(); err != nil {
			fmt.Fprintf(sshServerDebugStream, "fail to accept channel request: %v\n", err)
			chanReq.Reject(ssh.ResourceShortage, "channel accept failure")
		} else {
			chsvr := &sshSessionChannelServer{
				sshChannelServer: &sshChannelServer{svr, chanReq, ch, reqs},
				env:              append([]string{}, os.Environ()...),
			}
			chsvr.handle()
		}
	default:
		chanReq.Reject(ssh.UnknownChannelType, "channel type is not a session")
	}
}
예제 #18
0
파일: session.go 프로젝트: smaccona/envy
func handleSSHChannel(newChan ssh.NewChannel) {
	ch, reqs, err := newChan.Accept()
	if err != nil {
		log.Println("handle channel failed:", err)
		return
	}
	for req := range reqs {
		go func(req *ssh.Request) {
			if req.WantReply {
				req.Reply(true, nil)
			}
			switch req.Type {
			case "exec":
				defer ch.Close()
				var payload = struct{ Value string }{}
				ssh.Unmarshal(req.Payload, &payload)
				line := strings.Trim(payload.Value, "\n")
				var args []string
				if line != "" {
					args = strings.Split(line, " ")
				}
				cmd := exec.Command("/bin/envy", args...)
				cmd.Stdout = ch
				cmd.Stderr = ch.Stderr()
				err := cmd.Run()
				status := struct{ Status uint32 }{0}
				if err != nil {
					if exiterr, ok := err.(*exec.ExitError); ok {
						if stat, ok := exiterr.Sys().(syscall.WaitStatus); ok {
							status = struct{ Status uint32 }{uint32(stat.ExitStatus())}
						} else {
							assert(err)
						}
					}
				}
				_, err = ch.SendRequest("exit-status", false, ssh.Marshal(&status))
				assert(err)
				return
			}
		}(req)
	}
}
예제 #19
0
func handleChannel(newChannel ssh.NewChannel, rClient *ssh.Client) {
	if newChannel.ChannelType() != "session" {
		newChannel.Reject(ssh.UnknownChannelType, "unknown channel type: "+newChannel.ChannelType())
		return
	}
	psChannel, psRequests, err := newChannel.Accept()
	if err != nil {
		panic("could not accept channel.")
	}

	sChannel, sRequests, err := rClient.OpenChannel(newChannel.ChannelType(), nil)
	if err != nil {
		panic("Failed to create session: " + err.Error())
	}

	go pipeRequests(psChannel, sChannel, psRequests, sRequests)
	time.Sleep(50 * time.Millisecond)
	go pipe(sChannel, psChannel)
	go pipe(psChannel, sChannel)
}
예제 #20
0
파일: sshd.go 프로젝트: bachue/pages
func (server *Server) handleChannel(newChannel ssh.NewChannel, conn *ssh.ServerConn) {
	channelType := newChannel.ChannelType()
	if channelType != "session" {
		newChannel.Reject(ssh.UnknownChannelType,
			fmt.Sprintf("Unknown SSH Channel Type: %s, only `session` is supported", channelType))
		server.Logger.Errorf("Rejected SSH Channel Request from %s due to unknown channel type: %s",
			conn.RemoteAddr().String(), newChannel.ChannelType())
		return
	}
	channel, requests, err := newChannel.Accept()
	if err != nil {
		newChannel.Reject(ssh.ConnectionFailed, "Failed to accept SSH Channel Request, developers are working on it.")
		server.Logger.Errorf("Rejected SSH Channel Request from %s due to accept request failure: %s",
			conn.RemoteAddr().String(), err)
		return
	}
	server.Logger.Debugf("Accepted new SSH Channel Request from %s", conn.RemoteAddr().String())

	server.handleRequest(channel, requests, conn)
}
예제 #21
0
func handleChanReq(chanReq ssh.NewChannel) {
	if chanReq.ChannelType() != "session" {
		chanReq.Reject(ssh.Prohibited, "channel type is not a session")
		return
	}

	ch, reqs, err := chanReq.Accept()
	if err != nil {
		log.Println("fail to accept channel request", err)
		return
	}

	req := <-reqs
	if req.Type != "exec" {
		ch.Write([]byte("request type '" + req.Type + "' is not 'exec'\r\n"))
		ch.Close()
		return
	}

	handleExec(ch, req)
}
예제 #22
0
func handleChannel(conn *ssh.ServerConn, newChan ssh.NewChannel, execHandler []string) {
	ch, reqs, err := newChan.Accept()
	if err != nil {
		log.Println("newChan.Accept failed:", err)
		return
	}

	// Setup stdout/stderr
	var stdout, stderr io.Writer
	if *debug {
		stdout = io.MultiWriter(ch, os.Stdout)
		stderr = io.MultiWriter(ch.Stderr(), os.Stdout)
	} else {
		stdout = ch
		stderr = ch.Stderr()
	}

	handler := sshHandler{
		ExecHandler: execHandler,
		channel:     ch,
		stdout:      stdout,
		stderr:      stderr,
	}

	// Load default environment
	if *env {
		handler.Env = os.Environ()
	}
	if conn.Permissions != nil {
		// Using Permissions.Extensions as a way to get state from PublicKeyCallback
		if conn.Permissions.Extensions["environ"] != "" {
			handler.Env = append(handler.Env, strings.Split(conn.Permissions.Extensions["environ"], "\n")...)
		}
		handler.Env = append(handler.Env, "USER="******"user"])
	}

	for req := range reqs {
		go handler.Request(req)
	}
}
예제 #23
0
func (u *SimpleDispatcher) Dispatch(c context.Context, conn *ssh.ServerConn, ch ssh.NewChannel) {
	defer conn.Close()

	var ctx *Context
	if u.PanicHandler != nil {
		if rcv := recover(); rcv != nil {
			u.PanicHandler.Handle(ctx, rcv)
		}
	}

	// Get channel type
	chType := ch.ChannelType()

	handler, ok := u.Handlers[chType]
	if !ok {
		return
	}

	// Otherwise, accept the channel
	channel, requests, err := ch.Accept()
	if err != nil {
		u.Logger.Warn("Error creating channel", "type", chType, "err", err)
		ch.Reject(ChannelAcceptError, chType)
		return
	}

	// Handle the channel
	ctx = &Context{
		Context:  c,
		Channel:  channel,
		Requests: requests,
	}
	err = handler.Handle(ctx)
	if err != nil {
		u.Logger.Warn("Error handling channel", "type", chType, "err", err)
		ch.Reject(ChannelHandleError, fmt.Sprintf("error handling channel: %s", err.Error()))
		return
	}
}
예제 #24
0
func (s *SSHServer) handleChannel(newChannel ssh.NewChannel) {
	defer GinkgoRecover()

	Expect(newChannel.ChannelType()).To(Equal("session"))

	if s.RejectSession {
		Expect(newChannel.Reject(ssh.ConnectionFailed, "session rejected")).To(Succeed())
		return
	}

	channel, requests, err := newChannel.Accept()
	Expect(err).NotTo(HaveOccurred())

	go func() {
		defer GinkgoRecover()

		for request := range requests {
			switch request.Type {
			case "exec":
				payloadLen := binary.BigEndian.Uint32(request.Payload[:4])
				Expect(request.Payload).To(HaveLen(int(payloadLen) + 4))

				s.CommandChan <- string(request.Payload[4:])

				Expect(request.Reply(true, nil)).To(Succeed())

				_, err := channel.SendRequest("exit-status", false, []byte{0, 0, 0, s.CommandExitStatus})
				Expect(err).To(Succeed())

				channel.Close()
				break
			}
		}
	}()
	go func() {
		defer GinkgoRecover()
		io.Copy(s.Data, channel)
	}()
}
예제 #25
0
func handleChannel(newChannel ssh.NewChannel) {
	// Since we're handling a shell, we expect a
	// channel type of "session". The also describes
	// "x11", "direct-tcpip" and "forwarded-tcpip"
	// channel types.
	if t := newChannel.ChannelType(); t != "session" {
		newChannel.Reject(ssh.UnknownChannelType, fmt.Sprintf("unknown channel type: %s", t))
		return
	}

	// At this point, we have the opportunity to reject the client's
	// request for another logical connection
	connection, _, err := newChannel.Accept()
	if err != nil {
		log.Printf("Could not accept channel (%s)", err)
		return
	}

	defer connection.Close()

	connection.Write([]byte("Hello!\n"))
}
예제 #26
0
// Make new terminal from a session channel
func NewTerminal(conn *ssh.ServerConn, ch ssh.NewChannel) (*Terminal, error) {
	if ch.ChannelType() != "session" {
		return nil, errors.New("terminal requires session channel")
	}
	channel, requests, err := ch.Accept()
	if err != nil {
		return nil, err
	}
	term := Terminal{
		*terminal.NewTerminal(channel, "Connecting..."),
		sshConn{conn},
		channel,
	}

	go term.listen(requests)
	go func() {
		// FIXME: Is this necessary?
		conn.Wait()
		channel.Close()
	}()

	return &term, nil
}
예제 #27
0
func (s *Session) HandleSessionChannel(newChannel ssh.NewChannel) (bool, ssh.RejectionReason) {
	if len(newChannel.ExtraData()) > 0 {
		// do not accept extra data in session channel request
		return false, ssh.Prohibited
	}

	// accept the channel
	channel, requests, err := newChannel.Accept()
	if err != nil {
		return false, ssh.ResourceShortage
	}

	// cannot return false from this point on
	// also need to accepted close the channel
	defer func() {
		if channel != nil {
			if err := channel.Close(); err != nil {
				glog.Warningf("failed to close accepted channel: %s", err)
			}
		}
	}()

	c, err := NewChannel(s, channel, newChannel.ChannelType(), newChannel.ExtraData())
	if err != nil {
		glog.Errorf("failed to create accepted channel: %s", err)
		return true, 0
	}
	s.AddChannel(c)

	// no failure
	go c.HandleRequests(requests)
	go c.HandleSessionChannel()

	// do not close channel on exit
	channel = nil
	return true, 0
}
예제 #28
0
// handleUDPChannel implements UDP port forwarding. A single UDP
// SSH channel follows the udpgw protocol, which multiplexes many
// UDP port forwards.
//
// The udpgw protocol and original server implementation:
// Copyright (c) 2009, Ambroz Bizjak <*****@*****.**>
// https://github.com/ambrop72/badvpn
//
func (sshClient *sshClient) handleUDPChannel(newChannel ssh.NewChannel) {

	// Accept this channel immediately. This channel will replace any
	// previously existing UDP channel for this client.

	sshChannel, requests, err := newChannel.Accept()
	if err != nil {
		log.WithContextFields(LogFields{"error": err}).Warning("accept new channel failed")
		return
	}
	go ssh.DiscardRequests(requests)
	defer sshChannel.Close()

	sshClient.setUDPChannel(sshChannel)

	multiplexer := &udpPortForwardMultiplexer{
		sshClient:      sshClient,
		sshChannel:     sshChannel,
		portForwards:   make(map[uint16]*udpPortForward),
		portForwardLRU: psiphon.NewLRUConns(),
		relayWaitGroup: new(sync.WaitGroup),
	}
	multiplexer.run()
}
예제 #29
0
// SessionForward performs a regular forward, providing the user with an
// interactive remote host selection if necessary. This forwarding type
// requires agent forwarding in order to work.
func (s *Server) SessionForward(session *Session, newChannel ssh.NewChannel, chans <-chan ssh.NewChannel) {

	// Okay, we're handling this as a regular session
	sesschan, sessReqs, err := newChannel.Accept()
	if err != nil {
		return
	}

	stderr := sesschan.Stderr()

	remote := ""
	switch len(session.Remotes) {
	case 0:
		sesschan.Close()
		return
	case 1:
		remote = session.Remotes[0]
	default:
		comm := rw{Reader: sesschan, Writer: stderr}
		if s.Interactive == nil {
			remote, err = DefaultInteractive(comm, session)
		} else {
			remote, err = s.Interactive(comm, session)
		}
		if err != nil {
			sesschan.Close()
			return
		}
	}

	fmt.Fprintf(stderr, "Connecting to %s\r\n", remote)

	// Set up the agent

	agentChan, agentReqs, err := session.Conn.OpenChannel("*****@*****.**", nil)
	if err != nil {
		fmt.Fprintf(stderr, "\r\n====== sshmux ======\r\n")
		fmt.Fprintf(stderr, "sshmux requires either agent forwarding or secure channel forwarding.\r\n")
		fmt.Fprintf(stderr, "Either enable agent forwarding (-A), or use a ssh -W proxy command.\r\n")
		fmt.Fprintf(stderr, "For more info, see the sshmux wiki.\r\n")
		sesschan.Close()
		return
	}
	defer agentChan.Close()
	go ssh.DiscardRequests(agentReqs)

	// Set up the client

	ag := agent.NewClient(agentChan)

	clientConfig := &ssh.ClientConfig{
		User: session.Conn.User(),
		Auth: []ssh.AuthMethod{
			ssh.PublicKeysCallback(ag.Signers),
		},
	}

	client, err := ssh.Dial("tcp", remote, clientConfig)
	if err != nil {
		fmt.Fprintf(stderr, "Connect failed: %v\r\n", err)
		sesschan.Close()
		return
	}

	// Handle all incoming channel requests
	go func() {
		for newChannel = range chans {
			if newChannel == nil {
				return
			}

			channel2, reqs2, err := client.OpenChannel(newChannel.ChannelType(), newChannel.ExtraData())
			if err != nil {
				x, ok := err.(*ssh.OpenChannelError)
				if ok {
					newChannel.Reject(x.Reason, x.Message)
				} else {
					newChannel.Reject(ssh.Prohibited, "remote server denied channel request")
				}
				continue
			}

			channel, reqs, err := newChannel.Accept()
			if err != nil {
				channel2.Close()
				continue
			}
			go proxy(reqs, reqs2, channel, channel2)
		}
	}()

	// Forward the session channel
	channel2, reqs2, err := client.OpenChannel("session", []byte{})
	if err != nil {
		fmt.Fprintf(stderr, "Remote session setup failed: %v\r\n", err)
		sesschan.Close()
		return
	}

	// Proxy the channel and its requests
	maskedReqs := make(chan *ssh.Request, 1)
	go func() {
		for req := range sessReqs {
			if req.Type == "*****@*****.**" {
				continue
			}
			maskedReqs <- req
		}
	}()
	proxy(maskedReqs, reqs2, sesschan, channel2)

}
예제 #30
0
파일: adapter.go 프로젝트: arizvisa/packer
func (c *adapter) handleSession(newChannel ssh.NewChannel) error {
	channel, requests, err := newChannel.Accept()
	if err != nil {
		return err
	}
	defer channel.Close()

	done := make(chan struct{})

	// Sessions have requests such as "pty-req", "shell", "env", and "exec".
	// see RFC 4254, section 6
	go func(in <-chan *ssh.Request) {
		env := make([]envRequestPayload, 4)
		for req := range in {
			switch req.Type {
			case "pty-req":
				log.Println("ansible provisioner pty-req request")
				// accept pty-req requests, but don't actually do anything. Necessary for OpenSSH and sudo.
				req.Reply(true, nil)

			case "env":
				req, err := newEnvRequest(req)
				if err != nil {
					c.ui.Error(err.Error())
					req.Reply(false, nil)
					continue
				}
				env = append(env, req.Payload)
				log.Printf("new env request: %s", req.Payload)
				req.Reply(true, nil)
			case "exec":
				req, err := newExecRequest(req)
				if err != nil {
					c.ui.Error(err.Error())
					req.Reply(false, nil)
					close(done)
					continue
				}

				log.Printf("new exec request: %s", req.Payload)

				if len(req.Payload) == 0 {
					req.Reply(false, nil)
					close(done)
					return
				}

				go func(channel ssh.Channel) {
					exit := c.exec(string(req.Payload), channel, channel, channel.Stderr())

					exitStatus := make([]byte, 4)
					binary.BigEndian.PutUint32(exitStatus, uint32(exit))
					channel.SendRequest("exit-status", false, exitStatus)
					close(done)
				}(channel)
				req.Reply(true, nil)
			case "subsystem":
				req, err := newSubsystemRequest(req)
				if err != nil {
					c.ui.Error(err.Error())
					req.Reply(false, nil)
					continue
				}

				log.Printf("new subsystem request: %s", req.Payload)
				switch req.Payload {
				case "sftp":
					sftpCmd := c.sftpCmd
					if len(sftpCmd) == 0 {
						sftpCmd = "/usr/lib/sftp-server -e"
					}

					log.Print("starting sftp subsystem")
					go func() {
						_ = c.remoteExec(sftpCmd, channel, channel, channel.Stderr())
						close(done)
					}()
					req.Reply(true, nil)
				default:
					c.ui.Error(fmt.Sprintf("unsupported subsystem requested: %s", req.Payload))
					req.Reply(false, nil)
				}
			default:
				log.Printf("rejecting %s request", req.Type)
				req.Reply(false, nil)
			}
		}
	}(requests)

	<-done
	return nil
}