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
def self.open new end
def close; end
def close; end
def initialize
Create a new instance that communicates with the running pageant
def initialize @win = Win.FindWindow("Pageant", "Pageant") if @win.to_i == 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) # using struct to achieve proper alignment and field size on 64-bit platform cds = Win::COPYDATASTRUCT.new(Win.malloc_ptr(Win::COPYDATASTRUCT.size)) cds.dwData = AGENT_COPYDATA_ID cds.cbData = mapname.size + 1 cds.lpData = Win.get_cstr(mapname) succ = Win.SendMessageTimeout(@win, Win::WM_COPYDATA, Win::NULL, cds.to_ptr, 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