Exemple #1
0
func TestAgentForward(t *testing.T) {
	server := newServer(t)
	defer server.Shutdown()
	conn := server.Dial(clientConfig())
	defer conn.Close()

	keyring := agent.NewKeyring()
	keyring.Add(testPrivateKeys["dsa"], nil, "")
	pub := testPublicKeys["dsa"]

	sess, err := conn.NewSession()
	if err != nil {
		t.Fatalf("NewSession: %v", err)
	}
	if err := agent.RequestAgentForwarding(sess); err != nil {
		t.Fatalf("RequestAgentForwarding: %v", err)
	}

	if err := agent.ForwardToAgent(conn, keyring); err != nil {
		t.Fatalf("SetupForwardKeyring: %v", err)
	}
	out, err := sess.CombinedOutput("ssh-add -L")
	if err != nil {
		t.Fatalf("running ssh-add: %v, out %s", err, out)
	}
	key, _, _, _, err := ssh.ParseAuthorizedKey(out)
	if err != nil {
		t.Fatalf("ParseAuthorizedKey(%q): %v", out, err)
	}

	if !bytes.Equal(key.Marshal(), pub.Marshal()) {
		t.Fatalf("got key %s, want %s", ssh.MarshalAuthorizedKey(key), ssh.MarshalAuthorizedKey(pub))
	}
}
Exemple #2
0
func (s *SSHForwardingClient) ForwardAgentAuthentication(session *gossh.Session) error {
	if s.agentForwarding && !s.authAgentReqSent {
		// We are allowed to send "*****@*****.**" request only once per channel
		// otherwise ssh daemon replies with the "SSH2_MSG_CHANNEL_FAILURE 100"
		s.authAgentReqSent = true
		return gosshagent.RequestAgentForwarding(session)
	}
	return nil
}
Exemple #3
0
func (s *SSHConn) requestAgentForwarding(session *ssh.Session) error {
	if !s.forwardAgent {
		return nil
	}
	if err := agent.RequestAgentForwarding(session); err != nil {
		return fmt.Errorf("RequestAgentForwarding: %v", err)
	}
	return nil
}
Exemple #4
0
func (c *comm) connectToAgent() {
	if c.client == nil {
		return
	}

	if c.config.DisableAgent {
		log.Printf("[INFO] SSH agent forwarding is disabled.")
		return
	}

	// open connection to the local agent
	socketLocation := os.Getenv("SSH_AUTH_SOCK")
	if socketLocation == "" {
		log.Printf("[INFO] no local agent socket, will not connect agent")
		return
	}
	agentConn, err := net.Dial("unix", socketLocation)
	if err != nil {
		log.Printf("[ERROR] could not connect to local agent socket: %s", socketLocation)
		return
	}

	// create agent and add in auth
	forwardingAgent := agent.NewClient(agentConn)
	if forwardingAgent == nil {
		log.Printf("[ERROR] Could not create agent client")
		agentConn.Close()
		return
	}

	// add callback for forwarding agent to SSH config
	// XXX - might want to handle reconnects appending multiple callbacks
	auth := ssh.PublicKeysCallback(forwardingAgent.Signers)
	c.config.SSHConfig.Auth = append(c.config.SSHConfig.Auth, auth)
	agent.ForwardToAgent(c.client, forwardingAgent)

	// Setup a session to request agent forwarding
	session, err := c.newSession()
	if err != nil {
		return
	}
	defer session.Close()

	err = agent.RequestAgentForwarding(session)
	if err != nil {
		log.Printf("[ERROR] RequestAgentForwarding: %#v", err)
		return
	}

	log.Printf("[INFO] agent forwarding enabled")
	return
}
Exemple #5
0
func (c *comm) connectToAgent() {
	if c.client == nil {
		return
	}

	if c.config.DisableAgent {
		return
	}

	// open connection to the local agent
	socketLocation := os.Getenv("SSH_AUTH_SOCK")
	if socketLocation == "" {
		return
	}
	agentConn, err := net.Dial("unix", socketLocation)
	if err != nil {
		c.config.Logger.Error("could not connect to local agent socket", "socket_path", socketLocation)
		return
	}
	defer agentConn.Close()

	// create agent and add in auth
	forwardingAgent := agent.NewClient(agentConn)
	if forwardingAgent == nil {
		c.config.Logger.Error("could not create agent client")
		return
	}

	// add callback for forwarding agent to SSH config
	// XXX - might want to handle reconnects appending multiple callbacks
	auth := ssh.PublicKeysCallback(forwardingAgent.Signers)
	c.config.SSHConfig.Auth = append(c.config.SSHConfig.Auth, auth)
	agent.ForwardToAgent(c.client, forwardingAgent)

	// Setup a session to request agent forwarding
	session, err := c.NewSession()
	if err != nil {
		return
	}
	defer session.Close()

	err = agent.RequestAgentForwarding(session)
	if err != nil {
		c.config.Logger.Error("error requesting agent forwarding", "error", err)
		return
	}
	return
}
Exemple #6
0
func (s *sshClientConfig) NewSession(host string) (*sshSession, error) {
	conn, err := ssh.Dial("tcp", host, s.ClientConfig)
	if err != nil {
		return nil, err
	}

	if s.agent != nil {
		if err := agent.ForwardToAgent(conn, s.agent); err != nil {
			return nil, err
		}
	}

	session, err := conn.NewSession()
	if s.agent != nil {
		err = agent.RequestAgentForwarding(session)
	}

	return &sshSession{
		conn:    conn,
		Session: session,
	}, err
}
Exemple #7
0
// NewSession creates a new ssh session with the host.
// It forwards authentication to the agent when it's configured.
func (c *ClientConfig) NewSession(host string) (*Session, error) {
	conn, err := ssh.Dial("tcp", host, c.ClientConfig)
	if err != nil {
		return nil, err
	}

	if c.a != nil && c.ForwardAgent {
		if err := agent.ForwardToAgent(conn, c.a); err != nil {
			return nil, err
		}
	}

	session, err := conn.NewSession()
	// Move this up
	if c.a != nil && c.ForwardAgent {
		err = agent.RequestAgentForwarding(session)
	}

	return &Session{
		conn:    conn,
		Session: session,
	}, err
}
Exemple #8
0
// Connect implementation of communicator.Communicator interface
func (c *Communicator) Connect(o terraform.UIOutput) (err error) {
	if c.conn != nil {
		c.conn.Close()
	}

	// Set the conn and client to nil since we'll recreate it
	c.conn = nil
	c.client = nil

	if o != nil {
		o.Output(fmt.Sprintf(
			"Connecting to remote host via SSH...\n"+
				"  Host: %s\n"+
				"  User: %s\n"+
				"  Password: %t\n"+
				"  Private key: %t\n"+
				"  SSH Agent: %t",
			c.connInfo.Host, c.connInfo.User,
			c.connInfo.Password != "",
			c.connInfo.KeyFile != "",
			c.connInfo.Agent,
		))

		if c.connInfo.BastionHost != "" {
			o.Output(fmt.Sprintf(
				"Using configured bastion host...\n"+
					"  Host: %s\n"+
					"  User: %s\n"+
					"  Password: %t\n"+
					"  Private key: %t\n"+
					"  SSH Agent: %t",
				c.connInfo.BastionHost, c.connInfo.BastionUser,
				c.connInfo.BastionPassword != "",
				c.connInfo.BastionKeyFile != "",
				c.connInfo.Agent,
			))
		}
	}

	log.Printf("connecting to TCP connection for SSH")
	c.conn, err = c.config.connection()
	if err != nil {
		// Explicitly set this to the REAL nil. Connection() can return
		// a nil implementation of net.Conn which will make the
		// "if c.conn == nil" check fail above. Read here for more information
		// on this psychotic language feature:
		//
		// http://golang.org/doc/faq#nil_error
		c.conn = nil

		log.Printf("connection error: %s", err)
		return err
	}

	log.Printf("handshaking with SSH")
	host := fmt.Sprintf("%s:%d", c.connInfo.Host, c.connInfo.Port)
	sshConn, sshChan, req, err := ssh.NewClientConn(c.conn, host, c.config.config)
	if err != nil {
		log.Printf("handshake error: %s", err)
		return err
	}

	c.client = ssh.NewClient(sshConn, sshChan, req)

	if c.config.sshAgent != nil {
		log.Printf("[DEBUG] Telling SSH config to foward to agent")
		if err := c.config.sshAgent.ForwardToAgent(c.client); err != nil {
			return err
		}

		log.Printf("[DEBUG] Setting up a session to request agent forwarding")
		session, err := c.newSession()
		if err != nil {
			return err
		}
		defer session.Close()

		err = agent.RequestAgentForwarding(session)

		if err == nil {
			log.Printf("[INFO] agent forwarding enabled")
		} else {
			log.Printf("[WARN] error forwarding agent: %s", err)
		}
	}

	if o != nil {
		o.Output("Connected!")
	}

	return err
}
Exemple #9
0
func (s *SSHForwardingClient) ForwardAgentAuthentication(session *gossh.Session) error {
	if s.agentForwarding {
		return gosshagent.RequestAgentForwarding(session)
	}
	return nil
}
Exemple #10
0
// Exec runs command on remote server.
// It is a low-layer method to be used Run, Script and others method.
func (c *Communicator) Exec(cmd string, opt *Option, L *lua.LState) (*Result, error) {
	// get a client
	client, err := c.Client()
	if err != nil {
		return nil, err
	}

	// get a session
	sess, err := client.NewSession()
	if err != nil {
		return nil, err
	}
	defer sess.Close()

	// RequestAgentForwarding
	if c.Config.ForwardAgent && c.Agent != nil {
		agent.ForwardToAgent(client, c.Agent)
		if err = agent.RequestAgentForwarding(sess); err != nil {
			return nil, err
		}
	}

	// Request a PTY
	if c.Config.Pty {
		// refers to https://github.com/markpeek/packer/blob/53446bf713ed2866b451aa1d00813a90308ee9e9/communicator/ssh/communicator.go
		termModes := ssh.TerminalModes{
			ssh.ECHO:          0,     // do not echo
			ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
			ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
		}
		err = sess.RequestPty("xterm", 80, 40, termModes)
		if err != nil {
			return nil, err
		}
	}

	// Compose sudo command line.
	if opt.Sudo {
		if opt.User != "" {
			cmd = "sudo -Sku " + opt.User + " /bin/sh -l -c '" + cmd + "'"
		} else {
			cmd = "sudo -Sk /bin/sh -l -c '" + cmd + "'"
		}
	}

	// apply io
	var outWriter io.Writer
	var errWriter io.Writer
	var inReader io.Reader

	// buffer
	var outBuffer = new(bytes.Buffer)
	var errBuffer = new(bytes.Buffer)
	var inBuffer = new(bytes.Buffer)

	// append stdio to buffer
	if opt.UseStdout {
		if opt.OutputFunc != nil {
			outWriter = io.MultiWriter(os.Stdout, outBuffer, NewLFuncWriter(1, opt.OutputFunc, L))
		} else {
			outWriter = io.MultiWriter(os.Stdout, outBuffer)
		}
	} else {
		outWriter = io.MultiWriter(outBuffer)
	}

	if opt.UseStderr {
		if opt.OutputFunc != nil {
			errWriter = io.MultiWriter(os.Stderr, errBuffer, NewLFuncWriter(2, opt.OutputFunc, L))
		} else {
			errWriter = io.MultiWriter(os.Stderr, errBuffer)
		}
	} else {
		errWriter = io.MultiWriter(errBuffer)
	}

	inReader = io.MultiReader(inBuffer, os.Stdin)

	sess.Stdin = inReader
	sess.Stdout = outWriter
	sess.Stderr = errWriter

	// write sudo password
	if opt.Password != "" {
		// If it try to use sudo password, write password to input buffer
		fmt.Fprintln(inBuffer, opt.Password)
	}

	err = sess.Run(cmd)
	if err != nil {
		if exitErr, ok := err.(*ssh.ExitError); ok {
			return NewResult(outBuffer, errBuffer, exitErr.ExitStatus()), err
		} else {
			return NewResult(outBuffer, errBuffer, 1), err
		}
	}

	return NewResult(outBuffer, errBuffer, 0), nil
}