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).
| 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_ANSWER | = | 2 |
| SSH_AGENT_FAILURE | = | 5 |
| [W] | buffers | The buffer factory to use to obtain buffer instances. |
| [W] | keys | The key factory to use to obtain key instances. |
| [W] | socket_factory | The socket factory used to connect to the agent process. It must respond to open, and accept a single parameter (the name of the socket to open). |
| [W] | socket_name | The name of the socket to open. |
| [W] | version | The version of the SSH protocol version to report. |
Closes this socket. This agent reference is no longer able to query the agent.
[ show source ]
# File lib/net/ssh/userauth/agent.rb, line 145
145: def close
146: @socket.close
147: 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).
[ show source ]
# File lib/net/ssh/userauth/agent.rb, line 69
69: def connect!
70: @socket = @socket_factory.open( @socket_name )
71:
72: # determine what type of agent we're communicating with
73: buffer = @buffers.writer
74: buffer.write_string Net::SSH::Transport::Session.version
75: type, body = send_with_reply SSH2_AGENT_REQUEST_VERSION, buffer
76:
77: if type == SSH2_AGENT_VERSION_RESPONSE
78: raise NotImplementedError, "SSH2 agents are not yet supported"
79: elsif type != SSH_AGENT_RSA_IDENTITIES_ANSWER
80: raise AgentError,
81: "unknown response from agent: #{type}, #{body.to_s.inspect}"
82: end
83: 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.
[ show source ]
# File lib/net/ssh/userauth/agent.rb, line 88
88: def identities
89: case @version
90: when 1
91: code1 = SSH_AGENT_REQUEST_RSA_IDENTITIES
92: code2 = SSH_AGENT_RSA_IDENTITIES_ANSWER
93: when 2
94: code1 = SSH2_AGENT_REQUEST_IDENTITIES
95: code2 = SSH2_AGENT_IDENTITIES_ANSWER
96: else
97: raise NotImplementedError, "SSH version #{@version}"
98: end
99:
100: type, body = send_with_reply code1
101: raise AgentError,
102: "could not get identity count" if agent_failed( type )
103: raise AgentError, "bad authentication reply: #{type}" if type != code2
104:
105: identities = []
106: body.read_long.times do
107: case @version
108: when 1
109: key = @keys.get( "rsa" )
110: bits = body.read_long
111: key.e = body.read_bignum
112: key.n = body.read_bignum
113: when 2
114: blob = @buffers.reader( body.read_string )
115: key = blob.read_key
116: end
117:
118: unless key.respond_to?( :comment= )
119: key.instance_eval "def comment=(cmt)\n@comment = cmt\nend\n"
120: end
121:
122: unless key.respond_to?( :comment )
123: key.instance_eval "def comment\n@comment\nend\n"
124: end
125:
126: key.comment = body.read_string
127: identities.push key
128: end
129:
130: return identities
131: end
Using the agent and the given public key, sign the given data. The signature is returned in SSH2 format.
[ show source ]
# File lib/net/ssh/userauth/agent.rb, line 151
151: def sign( key, data )
152: blob = @buffers.writer
153: blob.write_key key
154:
155: packet_data = @buffers.writer
156: packet_data.write_string blob.to_s
157: packet_data.write_string data.to_s
158: packet_data.write_long 0
159:
160: type, reply = send_with_reply SSH2_AGENT_SIGN_REQUEST, packet_data
161: if agent_failed( type )
162: raise AgentError,
163: "agent could not sign data with requested identity"
164: elsif type != SSH2_AGENT_SIGN_RESPONSE
165: raise AgentError, "bad authentication response #{type}"
166: end
167:
168: return reply.read_string
169: end