Class Net::SSH::Authentication::Agent
In: lib/net/ssh/authentication/agent.rb
lib/net/ssh/authentication/agent.rb
Parent: Object

This class implements a simple client for the ssh-agent protocol. It does not implement any specific protocol, but instead copies the behavior of the ssh-agent functions in the OpenSSH library (3.8).

This means that although it behaves like a SSH1 client, it also has some SSH2 functionality (like signing data).

Methods

close   close   connect   connect   connect!   connect!   identities   identities   negotiate!   negotiate!   new   new   sign   sign  

Included Modules

Loggable Loggable

Classes and Modules

Module Net::SSH::Authentication::Agent::Comment

Constants

SSH2_AGENT_REQUEST_VERSION = 1
SSH2_AGENT_REQUEST_IDENTITIES = 11
SSH2_AGENT_IDENTITIES_ANSWER = 12
SSH2_AGENT_SIGN_REQUEST = 13
SSH2_AGENT_SIGN_RESPONSE = 14
SSH2_AGENT_FAILURE = 30
SSH2_AGENT_VERSION_RESPONSE = 103
SSH_COM_AGENT2_FAILURE = 102
SSH_AGENT_REQUEST_RSA_IDENTITIES = 1
SSH_AGENT_RSA_IDENTITIES_ANSWER1 = 2
SSH_AGENT_RSA_IDENTITIES_ANSWER2 = 5
SSH_AGENT_FAILURE = 5
SSH2_AGENT_REQUEST_VERSION = 1
SSH2_AGENT_REQUEST_IDENTITIES = 11
SSH2_AGENT_IDENTITIES_ANSWER = 12
SSH2_AGENT_SIGN_REQUEST = 13
SSH2_AGENT_SIGN_RESPONSE = 14
SSH2_AGENT_FAILURE = 30
SSH2_AGENT_VERSION_RESPONSE = 103
SSH_COM_AGENT2_FAILURE = 102
SSH_AGENT_REQUEST_RSA_IDENTITIES = 1
SSH_AGENT_RSA_IDENTITIES_ANSWER1 = 2
SSH_AGENT_RSA_IDENTITIES_ANSWER2 = 5
SSH_AGENT_FAILURE = 5

Attributes

socket  [R]  The underlying socket being used to communicate with the SSH agent.
socket  [R]  The underlying socket being used to communicate with the SSH agent.

Public Class methods

Instantiates a new agent object, connects to a running SSH agent, negotiates the agent protocol version, and returns the agent object.

[Source]

    # File lib/net/ssh/authentication/agent.rb, line 51
51:     def self.connect(logger=nil)
52:       agent = new(logger)
53:       agent.connect!
54:       agent.negotiate!
55:       agent
56:     end

Instantiates a new agent object, connects to a running SSH agent, negotiates the agent protocol version, and returns the agent object.

[Source]

    # File lib/net/ssh/authentication/agent.rb, line 51
51:     def self.connect(logger=nil)
52:       agent = new(logger)
53:       agent.connect!
54:       agent.negotiate!
55:       agent
56:     end

Creates a new Agent object, using the optional logger instance to report status.

[Source]

    # File lib/net/ssh/authentication/agent.rb, line 60
60:     def initialize(logger=nil)
61:       self.logger = logger
62:     end

Creates a new Agent object, using the optional logger instance to report status.

[Source]

    # File lib/net/ssh/authentication/agent.rb, line 60
60:     def initialize(logger=nil)
61:       self.logger = logger
62:     end

Public Instance methods

Closes this socket. This agent reference is no longer able to query the agent.

[Source]

     # File lib/net/ssh/authentication/agent.rb, line 112
112:     def close
113:       @socket.close
114:     end

Closes this socket. This agent reference is no longer able to query the agent.

[Source]

     # File lib/net/ssh/authentication/agent.rb, line 112
112:     def close
113:       @socket.close
114:     end

Connect to the agent process using the socket factory and socket name given by the attribute writers. If the agent on the other end of the socket reports that it is an SSH2-compatible agent, this will fail (it only supports the ssh-agent distributed by OpenSSH).

[Source]

    # File lib/net/ssh/authentication/agent.rb, line 68
68:     def connect!
69:       begin
70:         debug { "connecting to ssh-agent" }
71:         @socket = agent_socket_factory.open(ENV['SSH_AUTH_SOCK'])
72:       rescue
73:         error { "could not connect to ssh-agent" }
74:         raise AgentNotAvailable, $!.message
75:       end
76:     end

Connect to the agent process using the socket factory and socket name given by the attribute writers. If the agent on the other end of the socket reports that it is an SSH2-compatible agent, this will fail (it only supports the ssh-agent distributed by OpenSSH).

[Source]

    # File lib/net/ssh/authentication/agent.rb, line 68
68:     def connect!
69:       begin
70:         debug { "connecting to ssh-agent" }
71:         @socket = agent_socket_factory.open(ENV['SSH_AUTH_SOCK'])
72:       rescue
73:         error { "could not connect to ssh-agent" }
74:         raise AgentNotAvailable, $!.message
75:       end
76:     end

Return an array of all identities (public keys) known to the agent. Each key returned is augmented with a comment property which is set to the comment returned by the agent for that key.

[Source]

     # File lib/net/ssh/authentication/agent.rb, line 94
 94:     def identities
 95:       type, body = send_and_wait(SSH2_AGENT_REQUEST_IDENTITIES)
 96:       raise AgentError, "could not get identity count" if agent_failed(type)
 97:       raise AgentError, "bad authentication reply: #{type}" if type != SSH2_AGENT_IDENTITIES_ANSWER
 98: 
 99:       identities = []
100:       body.read_long.times do
101:         key = Buffer.new(body.read_string).read_key
102:         key.extend(Comment)
103:         key.comment = body.read_string
104:         identities.push key
105:       end
106: 
107:       return identities
108:     end

Return an array of all identities (public keys) known to the agent. Each key returned is augmented with a comment property which is set to the comment returned by the agent for that key.

[Source]

     # File lib/net/ssh/authentication/agent.rb, line 94
 94:     def identities
 95:       type, body = send_and_wait(SSH2_AGENT_REQUEST_IDENTITIES)
 96:       raise AgentError, "could not get identity count" if agent_failed(type)
 97:       raise AgentError, "bad authentication reply: #{type}" if type != SSH2_AGENT_IDENTITIES_ANSWER
 98: 
 99:       identities = []
100:       body.read_long.times do
101:         key = Buffer.new(body.read_string).read_key
102:         key.extend(Comment)
103:         key.comment = body.read_string
104:         identities.push key
105:       end
106: 
107:       return identities
108:     end

Attempts to negotiate the SSH agent protocol version. Raises an error if the version could not be negotiated successfully.

[Source]

    # File lib/net/ssh/authentication/agent.rb, line 80
80:     def negotiate!
81:       # determine what type of agent we're communicating with
82:       type, body = send_and_wait(SSH2_AGENT_REQUEST_VERSION, :string, Transport::ServerVersion::PROTO_VERSION)
83: 
84:       if type == SSH2_AGENT_VERSION_RESPONSE
85:         raise NotImplementedError, "SSH2 agents are not yet supported"
86:       elsif type != SSH_AGENT_RSA_IDENTITIES_ANSWER1 && type != SSH_AGENT_RSA_IDENTITIES_ANSWER2
87:         raise AgentError, "unknown response from agent: #{type}, #{body.to_s.inspect}"
88:       end
89:     end

Attempts to negotiate the SSH agent protocol version. Raises an error if the version could not be negotiated successfully.

[Source]

    # File lib/net/ssh/authentication/agent.rb, line 80
80:     def negotiate!
81:       # determine what type of agent we're communicating with
82:       type, body = send_and_wait(SSH2_AGENT_REQUEST_VERSION, :string, Transport::ServerVersion::PROTO_VERSION)
83: 
84:       if type == SSH2_AGENT_VERSION_RESPONSE
85:         raise NotImplementedError, "SSH2 agents are not yet supported"
86:       elsif type != SSH_AGENT_RSA_IDENTITIES_ANSWER1 && type != SSH_AGENT_RSA_IDENTITIES_ANSWER2
87:         raise AgentError, "unknown response from agent: #{type}, #{body.to_s.inspect}"
88:       end
89:     end

Using the agent and the given public key, sign the given data. The signature is returned in SSH2 format.

[Source]

     # File lib/net/ssh/authentication/agent.rb, line 118
118:     def sign(key, data)
119:       type, reply = send_and_wait(SSH2_AGENT_SIGN_REQUEST, :string, Buffer.from(:key, key), :string, data, :long, 0)
120: 
121:       if agent_failed(type)
122:         raise AgentError, "agent could not sign data with requested identity"
123:       elsif type != SSH2_AGENT_SIGN_RESPONSE
124:         raise AgentError, "bad authentication response #{type}"
125:       end
126: 
127:       return reply.read_string
128:     end

Using the agent and the given public key, sign the given data. The signature is returned in SSH2 format.

[Source]

     # File lib/net/ssh/authentication/agent.rb, line 118
118:     def sign(key, data)
119:       type, reply = send_and_wait(SSH2_AGENT_SIGN_REQUEST, :string, Buffer.from(:key, key), :string, data, :long, 0)
120: 
121:       if agent_failed(type)
122:         raise AgentError, "agent could not sign data with requested identity"
123:       elsif type != SSH2_AGENT_SIGN_RESPONSE
124:         raise AgentError, "bad authentication response #{type}"
125:       end
126: 
127:       return reply.read_string
128:     end

[Validate]