summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDelano Mandelbaum <delano@delanotes.com>2014-01-15 16:51:59 -0800
committerDelano Mandelbaum <delano@delanotes.com>2014-01-15 16:51:59 -0800
commitbd61eeab4927e9a68a5217ad9d8c04a99156efb2 (patch)
treeeb74455e3477ad6db69a23f1911e6312d02d619c
parent7692be37ddb35df0646f406270f3fcd46c66e8c1 (diff)
parent6ccd0fd0961f52115739e4f61e2c1774ca24feab (diff)
downloadnet-ssh-bd61eeab4927e9a68a5217ad9d8c04a99156efb2.tar.gz
Merge pull request #140 from jarredholman/pageant
Fixed pageant support.
-rw-r--r--lib/net/ssh/authentication/agent/socket.rb2
-rw-r--r--lib/net/ssh/authentication/pageant.rb86
-rw-r--r--lib/net/ssh/service/forward.rb24
3 files changed, 59 insertions, 53 deletions
diff --git a/lib/net/ssh/authentication/agent/socket.rb b/lib/net/ssh/authentication/agent/socket.rb
index 78b6382..8fa20a0 100644
--- a/lib/net/ssh/authentication/agent/socket.rb
+++ b/lib/net/ssh/authentication/agent/socket.rb
@@ -126,7 +126,7 @@ module Net; module SSH; module Authentication
# Returns the agent socket factory to use.
def agent_socket_factory
if Net::SSH::Authentication::PLATFORM == :win32
- Pageant::socket_factory
+ Pageant::Socket
else
UNIXSocket
end
diff --git a/lib/net/ssh/authentication/pageant.rb b/lib/net/ssh/authentication/pageant.rb
index bbeb6a3..e351cac 100644
--- a/lib/net/ssh/authentication/pageant.rb
+++ b/lib/net/ssh/authentication/pageant.rb
@@ -110,21 +110,49 @@ module Net; module SSH; module Authentication
"pageant process not running"
end
- @res = nil
- @pos = 0
+ @input_buffer = Net::SSH::Buffer.new
+ @output_buffer = Net::SSH::Buffer.new
end
# Forwards the data to #send_query, ignoring any arguments after
- # the first. Returns 0.
+ # the first.
def send(data, *args)
- @res = send_query(data)
- @pos = 0
+ @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
+
+ # Reads +n+ bytes from the cached result of the last query. If +n+
+ # is +nil+, returns all remaining data from the last query.
+ def read(n = nil)
+ @output_buffer.read(n)
end
+ def close
+ end
+
+ 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.
- def send_query(query)
+ def send_query_18(query)
res = nil
filemap = 0
ptr = nil
@@ -165,43 +193,10 @@ module Net; module SSH; module Authentication
Win.closeHandle(filemap) if filemap != 0
end
- # Conceptually close the socket. This doesn't really do anthing
- # significant, but merely complies with the Socket interface.
- def close
- @res = nil
- @pos = 0
- end
-
- # Conceptually asks if the socket is closed. As with #close,
- # this doesn't really do anything significant, but merely
- # complies with the Socket interface.
- def closed?
- @res.nil? && @pos.zero?
- end
-
- # Reads +n+ bytes from the cached result of the last query. If +n+
- # is +nil+, returns all remaining data from the last query.
- 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
-
- end
-
- # Socket changes for Ruby 1.9
- # Functionality is the same as Ruby 1.8 but it includes the new calls to
- # the DL module as well as other pointer transformations
- class Socket19 < Socket
# 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.
- def send_query(query)
+ def send_query_19(query)
res = nil
filemap = 0
ptr = nil
@@ -244,17 +239,6 @@ module Net; module SSH; module Authentication
Win.CloseHandle(filemap) if filemap != 0
end
end
-
- # Selects which socket to use depending on the ruby version
- # This is needed due changes in the DL module.
- def self.socket_factory
- if RUBY_VERSION < "1.9"
- Socket
- else
- Socket19
- end
- end
-
end
end; end; end
diff --git a/lib/net/ssh/service/forward.rb b/lib/net/ssh/service/forward.rb
index 5e23e36..3b0face 100644
--- a/lib/net/ssh/service/forward.rb
+++ b/lib/net/ssh/service/forward.rb
@@ -257,6 +257,24 @@ module Net; module SSH; module Service
end
end
+ # not a real socket, so use a simpler behaviour
+ def prepare_simple_client(client, channel, type)
+ channel[:socket] = client
+
+ channel.on_data do |ch, data|
+ ch.debug { "data:#{data.length} on #{type} forwarded channel" }
+ ch[:socket].send(data)
+ end
+
+ channel.on_process do |ch|
+ data = ch[:socket].read(8192)
+ if data
+ ch.debug { "read #{data.length} bytes from client, sending over #{type} forwarded connection" }
+ ch.send_data(data)
+ end
+ end
+ end
+
# The callback used when a new "forwarded-tcpip" channel is requested
# by the server. This will open a new socket to the host/port specified
# when the forwarded connection was first requested.
@@ -287,7 +305,11 @@ module Net; module SSH; module Service
begin
agent = Authentication::Agent.connect(logger)
- prepare_client(agent.socket, channel, :agent)
+ if (agent.socket.is_a? ::IO)
+ prepare_client(agent.socket, channel, :agent)
+ else
+ prepare_simple_client(agent.socket, channel, :agent)
+ end
rescue Exception => e
error { "attempted to connect to agent but failed: #{e.class.name} (#{e.message})" }
raise Net::SSH::ChannelOpenFailed.new(2, "could not connect to authentication agent")