class Net::SSH::Authentication::Pageant::Socket
simply by replacing the socket factory used by the Agent class.
the pageant daemon. This allows pageant support to be implemented
a socket, translating each request into a Windows messaging call to
This is the pseudo-socket implementation that mimics the interface of
def self.open(location=nil)
parameter is ignored, and is only needed for compatibility with
The factory method for creating a new Socket instance. The location
def self.open(location=nil) new end
def close
def close end
def initialize
Create a new instance that communicates with the running pageant
def initialize @win = Win.FindWindow("Pageant", "Pageant") if @win == 0 raise Net::SSH::Exception, "pageant process not running" end @input_buffer = Net::SSH::Buffer.new @output_buffer = Net::SSH::Buffer.new end
def read(n = nil)
Reads +n+ bytes from the cached result of the last query. If +n+
def read(n = nil) @output_buffer.read(n) end
def send(data, *args)
Forwards the data to #send_query, ignoring any arguments after
def send(data, *args) @input_buffer.append(data) ret = data.length while true return ret if @input_buffer.length < 4 msg_length = @input_buffer.read_long + 4 @input_buffer.reset! return ret if @input_buffer.length < msg_length msg = @input_buffer.read!(msg_length) @output_buffer.append(send_query(msg)) end end
def send_query(query)
process via the Windows messaging subsystem. The result is
Packages the given query string and sends it to the pageant
def send_query(query) res = nil filemap = 0 ptr = nil id = Win.malloc_ptr(Win::SIZEOF_DWORD) mapname = "PageantRequest%08x" % Win.GetCurrentThreadId() security_attributes = Win.get_ptr Win.get_security_attributes_for_user filemap = Win.CreateFileMapping(Win::INVALID_HANDLE_VALUE, security_attributes, Win::PAGE_READWRITE, 0, AGENT_MAX_MSGLEN, mapname) if filemap == 0 || filemap == Win::INVALID_HANDLE_VALUE raise Net::SSH::Exception, "Creation of file mapping failed with error: #{Win.GetLastError}" end ptr = Win.MapViewOfFile(filemap, Win::FILE_MAP_WRITE, 0, 0, 0) if ptr.nil? || ptr.null? raise Net::SSH::Exception, "Mapping of file failed" end Win.set_ptr_data(ptr, query) cds = Win.get_ptr [AGENT_COPYDATA_ID, mapname.size + 1, Win.get_cstr(mapname)].pack("LLp") succ = Win.SendMessageTimeout(@win, Win::WM_COPYDATA, Win::NULL, cds, Win::SMTO_NORMAL, 5000, id) if succ > 0 retlen = 4 + ptr.to_s(4).unpack("N")[0] res = ptr.to_s(retlen) else raise Net::SSH::Exception, "Message failed with error: #{Win.GetLastError}" end return res ensure Win.UnmapViewOfFile(ptr) unless ptr.nil? || ptr.null? Win.CloseHandle(filemap) if filemap != 0 end