Class: Net::SSH::Authentication::Pageant::Socket
- Inherits:
-
Object
- Object
- Net::SSH::Authentication::Pageant::Socket
- Defined in:
- lib/net/ssh/authentication/pageant.rb
Overview
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.
Class Method Summary collapse
-
.open(location = nil) ⇒ Object
The factory method for creating a new Socket instance.
Instance Method Summary collapse
- #close ⇒ Object
-
#initialize ⇒ Socket
constructor
Create a new instance that communicates with the running pageant instance.
-
#read(n = nil) ⇒ Object
Reads
n
bytes from the cached result of the last query. -
#send(data, *args) ⇒ Object
Forwards the data to #send_query, ignoring any arguments after the first.
-
#send_query(query) ⇒ Object
Packages the given query string and sends it to the pageant process via the Windows messaging subsystem.
Constructor Details
#initialize ⇒ Socket
Create a new instance that communicates with the running pageant instance. If no such instance is running, this will cause an error.
300 301 302 303 304 305 306 307 308 309 310 |
# File 'lib/net/ssh/authentication/pageant.rb', line 300 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 |
Class Method Details
.open(location = nil) ⇒ Object
The factory method for creating a new Socket instance. The location parameter is ignored, and is only needed for compatibility with the general Socket interface.
294 295 296 |
# File 'lib/net/ssh/authentication/pageant.rb', line 294 def self.open(location=nil) new end |
Instance Method Details
#close ⇒ Object
336 337 |
# File 'lib/net/ssh/authentication/pageant.rb', line 336 def close end |
#read(n = nil) ⇒ Object
Reads n
bytes from the cached result of the last query. If n
is nil
, returns all remaining data from the last query.
332 333 334 |
# File 'lib/net/ssh/authentication/pageant.rb', line 332 def read(n = nil) @output_buffer.read(n) end |
#send(data, *args) ⇒ Object
Forwards the data to #send_query, ignoring any arguments after the first.
314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 |
# File 'lib/net/ssh/authentication/pageant.rb', line 314 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 |
#send_query(query) ⇒ Object
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.
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 |
# File 'lib/net/ssh/authentication/pageant.rb', line 342 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 |