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 ⇒ 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.
402 403 404 405 406 407 408 409 410 411 412 |
# File 'lib/net/ssh/authentication/pageant.rb', line 402 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 |
Class Method Details
.open ⇒ Object
The factory method for creating a new Socket instance.
396 397 398 |
# File 'lib/net/ssh/authentication/pageant.rb', line 396 def self.open new end |
Instance Method Details
#close ⇒ Object
440 |
# File 'lib/net/ssh/authentication/pageant.rb', line 440 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.
436 437 438 |
# File 'lib/net/ssh/authentication/pageant.rb', line 436 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.
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 |
# File 'lib/net/ssh/authentication/pageant.rb', line 416 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.
445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 |
# File 'lib/net/ssh/authentication/pageant.rb', line 445 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 |