Class: Net::SSH::Authentication::Pageant::Socket

Inherits:
Object
  • Object
show all
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.

Direct Known Subclasses

Socket19

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeSocket

Create a new instance that communicates with the running pageant instance. If no such instance is running, this will cause an error.



105
106
107
108
109
110
111
112
113
114
115
# 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

  @res = nil
  @pos = 0
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.



99
100
101
# File 'lib/net/ssh/authentication/pageant.rb', line 99

def self.open(location=nil)
  new
end

Instance Method Details

#closeObject

Conceptually close the socket. This doesn’t really do anthing significant, but merely complies with the Socket interface.



170
171
172
173
# File 'lib/net/ssh/authentication/pageant.rb', line 170

def close
  @res = nil
  @pos = 0
end

#closed?Boolean

Conceptually asks if the socket is closed. As with #close, this doesn’t really do anything significant, but merely complies with the Socket interface.

Returns:

  • (Boolean)


178
179
180
# File 'lib/net/ssh/authentication/pageant.rb', line 178

def closed?
  @res.nil? && @pos.zero?
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.



184
185
186
187
188
189
190
191
192
193
# File 'lib/net/ssh/authentication/pageant.rb', line 184

def read(n = nil)
  return nil unless @res
  if n.nil?
    start, @pos = @pos, @res.size
    return @res[start..-1]
  else
    start, @pos = @pos, @pos + n
    return @res[start, n]
  end
end

#send(data, *args) ⇒ Object

Forwards the data to #send_query, ignoring any arguments after the first. Returns 0.



119
120
121
122
# File 'lib/net/ssh/authentication/pageant.rb', line 119

def send(data, *args)
  @res = send_query(data)
  @pos = 0
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.



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# File 'lib/net/ssh/authentication/pageant.rb', line 127

def send_query(query)
  res = nil
  filemap = 0
  ptr = nil
  id = DL::PtrData.malloc(DL.sizeof("L"))

  mapname = "PageantRequest%08x\000" % 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