Example #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))
	}
}
Example #2
0
// Dial creates a client connection to the given SSH server.
//
// `addr` should be provided in the following format:
//
//     user@host:port
//
// if `forwardAgent` is true then forwarding of the authentication agent connection will be enabled.
func Dial(addr string, socket string, forwardAgent bool) (*SSHConn, error) {
	agentConn, err := net.Dial("unix", socket)
	if err != nil {
		return nil, err
	}
	var agentOk bool
	defer func() {
		if !agentOk {
			agentConn.Close()
		}
	}()

	sshAgent := agent.NewClient(agentConn)
	signers, err := sshAgent.Signers()
	if err != nil {
		return nil, err
	}

	host, port, user, err := ParseAddr(addr)
	if err != nil {
		return nil, err
	}

	config := &ssh.ClientConfig{
		User:    user,
		Auth:    []ssh.AuthMethod{ssh.PublicKeys(signers...)},
		Timeout: ConnTimeout,
	}
	client, err := ssh.Dial("tcp", fmt.Sprintf("%s:%d", host, port), config)
	if err != nil {
		return nil, err
	}
	var clientOk bool
	defer func() {
		if !clientOk {
			client.Close()
		}
	}()

	if forwardAgent {
		if err := agent.ForwardToAgent(client, sshAgent); err != nil {
			return nil, fmt.Errorf("SetupForwardKeyring: %v", err)
		}
	}

	agentOk = true
	clientOk = true

	c := SSHConn{
		client:       client,
		agentConn:    agentConn,
		forwardAgent: forwardAgent,
	}
	return &c, nil
}
Example #3
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
}
Example #4
0
func newSSHForwardingClient(client *gossh.Client, agentForwarding bool) (*SSHForwardingClient, error) {
	a, err := SSHAgentClient()
	if err != nil {
		return nil, err
	}

	err = gosshagent.ForwardToAgent(client, a)
	if err != nil {
		return nil, err
	}

	return &SSHForwardingClient{agentForwarding, client}, nil
}
Example #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
}
Example #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
}
Example #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
}
Example #8
0
func (a *sshAgent) ForwardToAgent(client *ssh.Client) error {
	return agent.ForwardToAgent(client, a.agent)
}
Example #9
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
}