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.
[ show source ]
# File lib/net/ssh/userauth/pageant.rb, line 108
108: def initialize
109: @win = Win.findWindow( "Pageant", "Pageant" )
110:
111: if @win == 0
112: raise Net::SSH::Exception,
113: "pageant process not running"
114: end
115:
116: @res = nil
117: @pos = 0
118: end
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.
[ show source ]
# File lib/net/ssh/userauth/pageant.rb, line 102
102: def self.open( location=nil )
103: new
104: end
Conceptually close the socket. This doesn‘t really do anthing significant, but merely complies with the Socket interface.
[ show source ]
# File lib/net/ssh/userauth/pageant.rb, line 173
173: def close
174: @res = nil
175: @pos = 0
176: end
Reads n bytes from the cached result of the last query. If n is nil, returns all remaining data from the last query.
[ show source ]
# File lib/net/ssh/userauth/pageant.rb, line 180
180: def read(n = nil)
181: return nil unless @res
182: if n.nil?
183: start, @pos = @pos, @res.size
184: return @res[start..-1]
185: else
186: start, @pos = @pos, @pos + n
187: return @res[start, n]
188: end
189: end
Forwards the data to send_query, ignoring any arguments after the first. Returns 0.
[ show source ]
# File lib/net/ssh/userauth/pageant.rb, line 122
122: def send( data, *args )
123: @res = send_query( data )
124: @pos = 0
125: 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.
[ show source ]
# File lib/net/ssh/userauth/pageant.rb, line 130
130: def send_query( query )
131: res = nil
132: filemap = 0
133: ptr = nil
134: id = DL::PtrData.malloc( DL.sizeof("L") )
135:
136: mapname = "PageantRequest%08x\000" % Win.getCurrentThreadId()
137: filemap = Win.createFileMapping(Win::INVALID_HANDLE_VALUE,
138: Win::NULL,
139: Win::PAGE_READWRITE, 0,
140: AGENT_MAX_MSGLEN, mapname)
141: if filemap == 0
142: raise Net::SSH::Exception,
143: "Creation of file mapping failed"
144: end
145:
146: ptr = Win.mapViewOfFile( filemap, Win::FILE_MAP_WRITE, 0, 0,
147: AGENT_MAX_MSGLEN )
148:
149: if ptr.nil? || ptr.null?
150: raise Net::SSH::Exception, "Mapping of file failed"
151: end
152:
153: ptr[0] = query
154:
155: cds = [AGENT_COPYDATA_ID, mapname.size + 1, mapname].
156: pack("LLp").to_ptr
157: succ = Win.sendMessageTimeout( @win, Win::WM_COPYDATA, Win::NULL,
158: cds, Win::SMTO_NORMAL, 5000, id )
159:
160: if succ > 0
161: retlen = 4 + ptr.to_s(4).unpack("N")[0]
162: res = ptr.to_s(retlen)
163: end
164:
165: return res
166: ensure
167: Win.unmapViewOfFile( ptr ) unless ptr.nil? || ptr.null?
168: Win.closeHandle( filemap ) if filemap != 0
169: end