This is the pseudo-socket implementation that mimics the interface of a socket, translating each request into a Windows messaging call to the pageant daemon. This allows pageant support to be implemented simply by replacing the socket factory used by the Agent class.
Create a new instance that communicates with the running pageant instance. If no such instance is running, this will cause an error.
# File lib/net/ssh/authentication/pageant.rb, line 105 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
# File lib/net/ssh/authentication/pageant.rb, line 141 def close end
Reads n
bytes from the cached result of the last query. If
n
is nil
, returns all remaining data from the
last query.
# File lib/net/ssh/authentication/pageant.rb, line 137 def read(n = nil) @output_buffer.read(n) end
Forwards the data to send_query, ignoring any arguments after the first.
# File lib/net/ssh/authentication/pageant.rb, line 119 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
# File lib/net/ssh/authentication/pageant.rb, line 144 def send_query(query) if RUBY_VERSION < "1.9" send_query_18(query) else send_query_19(query) end end
Packages the given query string and sends it to the pageant process via the Windows messaging subsystem. The result is cached, to be returned piece-wise when read is called.
# File lib/net/ssh/authentication/pageant.rb, line 155 def send_query_18(query) res = nil filemap = 0 ptr = nil id = DL::PtrData.malloc(DL.sizeof("L")) mapname = "PageantRequest%08x\0000" % Win.getCurrentThreadId() filemap = Win.createFileMapping(Win::INVALID_HANDLE_VALUE, Win::NULL, Win::PAGE_READWRITE, 0, AGENT_MAX_MSGLEN, mapname) if filemap == 0 raise Net::SSH::Exception, "Creation of file mapping failed" end ptr = Win.mapViewOfFile(filemap, Win::FILE_MAP_WRITE, 0, 0, AGENT_MAX_MSGLEN) if ptr.nil? || ptr.null? raise Net::SSH::Exception, "Mapping of file failed" end ptr[0] = query cds = [AGENT_COPYDATA_ID, mapname.size + 1, mapname]. pack("LLp").to_ptr 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) end return res ensure Win.unmapViewOfFile(ptr) unless ptr.nil? || ptr.null? Win.closeHandle(filemap) if filemap != 0 end
Packages the given query string and sends it to the pageant process via the Windows messaging subsystem. The result is cached, to be returned piece-wise when read is called.
# File lib/net/ssh/authentication/pageant.rb, line 199 def send_query_19(query) res = nil filemap = 0 ptr = nil id = DL.malloc(DL::SIZEOF_LONG) mapname = "PageantRequest%08x\0000" % Win.GetCurrentThreadId() filemap = Win.CreateFileMapping(Win::INVALID_HANDLE_VALUE, Win::NULL, 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" 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 DL::CPtr.new(ptr)[0,query.size]=query cds = DL::CPtr.to_ptr [AGENT_COPYDATA_ID, mapname.size + 1, 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) end return res ensure Win.UnmapViewOfFile(ptr) unless ptr.nil? || ptr.null? Win.CloseHandle(filemap) if filemap != 0 end