Object
This class implements an agent for JRuby + Pageant.
Written by Artūras Šlajus
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).
Instantiates a new agent object, connects to a running SSH agent, negotiates the agent protocol version, and returns the agent object.
# File lib/net/ssh/authentication/agent/java_pageant.rb, line 22 22: def self.connect(logger=nil) 23: agent = new(logger) 24: agent.connect! 25: agent 26: end
Instantiates a new agent object, connects to a running SSH agent, negotiates the agent protocol version, and returns the agent object.
# File lib/net/ssh/authentication/agent/socket.rb, line 45 45: def self.connect(logger=nil) 46: agent = new(logger) 47: agent.connect! 48: agent.negotiate! 49: agent 50: end
Creates a new Agent object, using the optional logger instance to report status.
# File lib/net/ssh/authentication/agent/java_pageant.rb, line 30 30: def initialize(logger=nil) 31: self.logger = logger 32: end
Creates a new Agent object, using the optional logger instance to report status.
# File lib/net/ssh/authentication/agent/socket.rb, line 54 54: def initialize(logger=nil) 55: self.logger = logger 56: end
Simulate agent close. This agent reference is no longer able to query the agent.
# File lib/net/ssh/authentication/agent/java_pageant.rb, line 69 69: def close 70: @agent_proxy = nil 71: end
Closes this socket. This agent reference is no longer able to query the agent.
# File lib/net/ssh/authentication/agent/socket.rb, line 106 106: def close 107: @socket.close 108: 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).
# File lib/net/ssh/authentication/agent/socket.rb, line 62 62: def connect! 63: begin 64: debug { "connecting to ssh-agent" } 65: @socket = agent_socket_factory.open(ENV['SSH_AUTH_SOCK']) 66: rescue 67: error { "could not connect to ssh-agent" } 68: raise AgentNotAvailable, $!.message 69: end 70: 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).
# File lib/net/ssh/authentication/agent/java_pageant.rb, line 38 38: def connect! 39: debug { "connecting to Pageant ssh-agent (via java connector)" } 40: @agent_proxy = JRubyPageant.create 41: unless @agent_proxy.is_running 42: raise AgentNotAvailable, "Pageant is not running!" 43: end 44: debug { "connection to Pageant ssh-agent (via java connector) succeeded" } 45: rescue AgentProxyException => e 46: error { "could not connect to Pageant ssh-agent (via java connector)" } 47: raise AgentNotAvailable, e.message, e.backtrace 48: 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.
# File lib/net/ssh/authentication/agent/socket.rb, line 88 88: def identities 89: type, body = send_and_wait(SSH2_AGENT_REQUEST_IDENTITIES) 90: raise AgentError, "could not get identity count" if agent_failed(type) 91: raise AgentError, "bad authentication reply: #{type}" if type != SSH2_AGENT_IDENTITIES_ANSWER 92: 93: identities = [] 94: body.read_long.times do 95: key = Buffer.new(body.read_string).read_key 96: key.extend(Comment) 97: key.comment = body.read_string 98: identities.push key 99: end 100: 101: return identities 102: 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.
# File lib/net/ssh/authentication/agent/java_pageant.rb, line 53 53: def identities 54: debug { "getting identities from Pageant" } 55: @agent_proxy.get_identities.map do |identity| 56: blob = identity.get_blob 57: key = Buffer.new(String.from_java_bytes(blob)).read_key 58: key.extend(Key) 59: key.java_blob = blob 60: key.comment = String.from_java_bytes(identity.get_comment) 61: key 62: end 63: rescue AgentProxyException => e 64: raise AgentError, "Cannot get identities: #{e.message}", e.backtrace 65: end
Attempts to negotiate the SSH agent protocol version. Raises an error if the version could not be negotiated successfully.
# File lib/net/ssh/authentication/agent/socket.rb, line 74 74: def negotiate! 75: # determine what type of agent we're communicating with 76: type, body = send_and_wait(SSH2_AGENT_REQUEST_VERSION, :string, Transport::ServerVersion::PROTO_VERSION) 77: 78: if type == SSH2_AGENT_VERSION_RESPONSE 79: raise NotImplementedError, "SSH2 agents are not yet supported" 80: elsif type != SSH_AGENT_RSA_IDENTITIES_ANSWER1 && type != SSH_AGENT_RSA_IDENTITIES_ANSWER2 81: raise AgentError, "unknown response from agent: #{type}, #{body.to_s.inspect}" 82: end 83: end
Using the agent and the given public key, sign the given data. The signature is returned in SSH2 format.
# File lib/net/ssh/authentication/agent/socket.rb, line 112 112: def sign(key, data) 113: type, reply = send_and_wait(SSH2_AGENT_SIGN_REQUEST, :string, Buffer.from(:key, key), :string, data, :long, 0) 114: 115: if agent_failed(type) 116: raise AgentError, "agent could not sign data with requested identity" 117: elsif type != SSH2_AGENT_SIGN_RESPONSE 118: raise AgentError, "bad authentication response #{type}" 119: end 120: 121: return reply.read_string 122: end
Using the agent and the given public key, sign the given data. The signature is returned in SSH2 format.
# File lib/net/ssh/authentication/agent/java_pageant.rb, line 75 75: def sign(key, data) 76: signed = @agent_proxy.sign(key.java_blob, data.to_java_bytes) 77: String.from_java_bytes(signed) 78: rescue AgentProxyException => e 79: raise AgentError, 80: "agent could not sign data with requested identity: #{e.message}", 81: e.backtrace 82: end
Returns true if the parameter indicates a “failure” response from the agent, and false otherwise.
# File lib/net/ssh/authentication/agent/socket.rb, line 163 163: def agent_failed(type) 164: type == SSH_AGENT_FAILURE || 165: type == SSH2_AGENT_FAILURE || 166: type == SSH_COM_AGENT2_FAILURE 167: end
Returns the agent socket factory to use.
# File lib/net/ssh/authentication/agent/socket.rb, line 127 127: def agent_socket_factory 128: if Net::SSH::Authentication::PLATFORM == :win32 129: Pageant::socket_factory 130: else 131: UNIXSocket 132: end 133: end
Read the next packet from the agent. This will return a two-part tuple consisting of the packet type, and the packet’s body (which is returned as a Net::SSH::Buffer).
# File lib/net/ssh/authentication/agent/socket.rb, line 146 146: def read_packet 147: buffer = Net::SSH::Buffer.new(@socket.read(4)) 148: buffer.append(@socket.read(buffer.read_long)) 149: type = buffer.read_byte 150: debug { "received agent packet #{type} len #{buffer.length-4}" } 151: return type, buffer 152: end
Send a new packet of the given type, with the associated data.
# File lib/net/ssh/authentication/agent/socket.rb, line 136 136: def send_packet(type, *args) 137: buffer = Buffer.from(*args) 138: data = [buffer.length + 1, type.to_i, buffer.to_s].pack("NCA*") 139: debug { "sending agent request #{type} len #{buffer.length}" } 140: @socket.send data, 0 141: end
Disabled; run with --debug to generate this.
Generated with the Darkfish Rdoc Generator 1.1.6.