net-ssh 4.0.0.beta3 → 4.0.0.beta4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +0 -0
- data/.travis.yml +2 -1
- data/CHANGES.txt +9 -0
- data/Gemfile +9 -1
- data/Gemfile.norbnacl +6 -1
- data/Gemfile.norbnacl.lock +4 -3
- data/ISSUE_TEMPLATE.md +30 -0
- data/README.rdoc +5 -1
- data/Rakefile +4 -0
- data/appveyor.yml +36 -5
- data/lib/net/ssh.rb +5 -5
- data/lib/net/ssh/authentication/agent.rb +174 -14
- data/lib/net/ssh/authentication/key_manager.rb +1 -1
- data/lib/net/ssh/authentication/pageant.rb +116 -19
- data/lib/net/ssh/buffered_io.rb +17 -12
- data/lib/net/ssh/connection/session.rb +29 -7
- data/lib/net/ssh/key_factory.rb +7 -7
- data/lib/net/ssh/proxy/http.rb +7 -4
- data/lib/net/ssh/proxy/https.rb +49 -0
- data/lib/net/ssh/test.rb +2 -2
- data/lib/net/ssh/test/extensions.rb +17 -0
- data/lib/net/ssh/transport/ctr.rb +7 -9
- data/lib/net/ssh/version.rb +2 -2
- data/net-ssh.gemspec +3 -4
- metadata +8 -21
- metadata.gz.sig +0 -0
- data/lib/net/ssh/authentication/agent/java_pageant.rb +0 -85
- data/lib/net/ssh/authentication/agent/socket.rb +0 -178
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5651b877a83649b20a9c8643125f5bd30bd982b3
|
4
|
+
data.tar.gz: 46d37efc38505e66f1049894b15cdb214e3016b3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b657629b5e8cb5ced31e567d7a6353679683fa4a2024fdb41460fce8314c15b928f7b5b5101b6e4dc1565c1462780cdabc7716a9a2388eceae4ddeaab60cbe3
|
7
|
+
data.tar.gz: 55783d5ebe87f2bb7561f689e4bba5d4fcf22bea6f4661c2aea410fd2d3fcfb2e1f62175db46997f9406182b5e6dc4f8c68ffccd9ed9037ad884b190da6dea74
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
data/.travis.yml
CHANGED
@@ -26,6 +26,7 @@ matrix:
|
|
26
26
|
allow_failures:
|
27
27
|
- rvm: rbx-3.25
|
28
28
|
- rvm: jruby-9.1.2.0
|
29
|
+
- rvm: ruby-head
|
29
30
|
|
30
31
|
install:
|
31
32
|
- export JRUBY_OPTS='--client -J-XX:+TieredCompilation -J-XX:TieredStopAtLevel=1 -Xcext.enabled=false -J-Xss2m -Xcompile.invokedynamic=false'
|
@@ -33,7 +34,7 @@ install:
|
|
33
34
|
- gem install bundler -v "= 1.11.2"
|
34
35
|
- bundle _1.11.2_ install
|
35
36
|
- BUNDLE_GEMFILE=./Gemfile.norbnacl bundle _1.11.2_ install
|
36
|
-
- sudo ansible-galaxy install rvm_io.
|
37
|
+
- sudo ansible-galaxy install rvm_io.ruby
|
37
38
|
- sudo chown -R travis:travis /home/travis/.ansible
|
38
39
|
- ansible-playbook ./test/integration/playbook.yml -i "localhost," --become -c local -e 'no_rvm=true' -e 'myuser=travis' -e 'mygroup=travis' -e 'homedir=/home/travis'
|
39
40
|
|
data/CHANGES.txt
CHANGED
@@ -1,3 +1,12 @@
|
|
1
|
+
=== 4.0.0.beta4
|
2
|
+
|
3
|
+
* Added exitstatus method to exec's return [Miklós Fazekas, #452]
|
4
|
+
* Don't raise from exec if server closes transport just after channel close [Miklós Fazekas, #450]
|
5
|
+
* Removed java_pageant, as jruby should be using regular pagent impl [Miklós Fazekas, ]
|
6
|
+
* Use SSH_AUTH_SOCK if possible on windows (cygwin) [Miklós Fazekas, Martin Dürst, #365, #361]
|
7
|
+
* HTTPS proxy support [Marcus Ilgner, #432]
|
8
|
+
* Supports ruby 2.4.0.dev new exception type from OpenSSL::PKey.read
|
9
|
+
|
1
10
|
=== 4.0.0.beta3
|
2
11
|
|
3
12
|
* Fix Net::SSH::Disconnect exceptions when channels are closed cleanly [Miklos Fazekas, #421, #422]
|
data/Gemfile
CHANGED
@@ -1,4 +1,12 @@
|
|
1
1
|
source 'https://rubygems.org'
|
2
2
|
|
3
3
|
# Specify your gem's dependencies in mygem.gemspec
|
4
|
-
gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
unless Gem.win_platform? || RUBY_PLATFORM == "java"
|
7
|
+
gem 'byebug', group: [:development, :test]
|
8
|
+
end
|
9
|
+
|
10
|
+
gem 'simplecov', require: false, group: :test
|
11
|
+
|
12
|
+
gem 'codecov', require: false, group: :test if ENV["CI"]
|
data/Gemfile.norbnacl
CHANGED
@@ -2,4 +2,9 @@ source 'https://rubygems.org'
|
|
2
2
|
|
3
3
|
ENV['NET_SSH_NO_RBNACL'] = 'true'
|
4
4
|
# Specify your gem's dependencies in mygem.gemspec
|
5
|
-
gemspec
|
5
|
+
gemspec
|
6
|
+
|
7
|
+
unless Gem.win_platform?
|
8
|
+
gem 'simplecov', require: false, group: :test
|
9
|
+
gem 'codecov', require: false, group: :test if ENV["CI"]
|
10
|
+
end
|
data/Gemfile.norbnacl.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
net-ssh (4.0.0.
|
4
|
+
net-ssh (4.0.0.beta3)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
@@ -27,9 +27,10 @@ GEM
|
|
27
27
|
|
28
28
|
PLATFORMS
|
29
29
|
ruby
|
30
|
+
x86-mingw32
|
30
31
|
|
31
32
|
DEPENDENCIES
|
32
|
-
bundler (~> 1.11
|
33
|
+
bundler (~> 1.11)
|
33
34
|
minitest (~> 5.0)
|
34
35
|
mocha (>= 1.1.0)
|
35
36
|
net-ssh!
|
@@ -37,4 +38,4 @@ DEPENDENCIES
|
|
37
38
|
rubocop (~> 0.39.0)
|
38
39
|
|
39
40
|
BUNDLED WITH
|
40
|
-
1.
|
41
|
+
1.13.5
|
data/ISSUE_TEMPLATE.md
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
### Expected behavior
|
2
|
+
|
3
|
+
Tell us what should happen
|
4
|
+
|
5
|
+
### Actual behavior
|
6
|
+
|
7
|
+
Tell us what happens instead.
|
8
|
+
|
9
|
+
### System configuration
|
10
|
+
|
11
|
+
- net-ssh version
|
12
|
+
- Ruby version
|
13
|
+
|
14
|
+
### Example App
|
15
|
+
|
16
|
+
Please provide an example script that reproduces the problem. This will save maintainers time so they can spend it fixing your issues instead of trying to build a reproduction case from sparse instructions.
|
17
|
+
|
18
|
+
You can use this as stating point:
|
19
|
+
|
20
|
+
```ruby
|
21
|
+
gem 'net-ssh', '= 4.0.0.beta3'
|
22
|
+
require 'net/ssh'
|
23
|
+
puts Net::SSH::Version::CURRENT
|
24
|
+
|
25
|
+
@host = 'localhost'
|
26
|
+
@user = ENV['USER']
|
27
|
+
Net::SSH.start(@host, @user) do |ssh|
|
28
|
+
puts ssh.exec!('echo "hello"')
|
29
|
+
end
|
30
|
+
```
|
data/README.rdoc
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
{<img src="https://badge.fury.io/rb/net-ssh.svg" alt="Gem Version" />}[https://badge.fury.io/rb/net-ssh]
|
2
|
+
{<img src="https://badges.gitter.im/net-ssh/net-ssh.svg" alt="Join the chat at https://gitter.im/net-ssh/net-ssh">}[https://gitter.im/net-ssh/net-ssh?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge]
|
3
|
+
{<img src="https://travis-ci.org/net-ssh/net-ssh.svg?branch=master" alt="Build Status" />}[https://travis-ci.org/net-ssh/net-ssh]
|
4
|
+
|
1
5
|
= Net::SSH 4.x
|
2
6
|
|
3
7
|
* Docs: http://net-ssh.github.com/net-ssh
|
@@ -105,7 +109,7 @@ If you don't add the public key, you'll see an error like "Couldn't verify data
|
|
105
109
|
|
106
110
|
* Ruby 1.8.x is supported up until the net-ssh 2.5.1 release.
|
107
111
|
* Ruby 1.9.x is supported up until the net-ssh 2.9.x release.
|
108
|
-
* Current net-ssh releases require Ruby 2.0 or later.
|
112
|
+
* Current net-ssh releases require Ruby 2.0 or later. JRuby 1.7+ (with `compat.version=2.0` set) or JRuby 9k+
|
109
113
|
|
110
114
|
== RUNNING TESTS
|
111
115
|
|
data/Rakefile
CHANGED
@@ -73,8 +73,12 @@ require 'rake/testtask'
|
|
73
73
|
Rake::TestTask.new do |t|
|
74
74
|
t.libs = ["lib", "test"]
|
75
75
|
t.libs << "test/integration" if ENV['NET_SSH_RUN_INTEGRATION_TESTS']
|
76
|
+
t.libs << "test/win_integration" if ENV['NET_SSH_RUN_WIN_INTEGRATION_TESTS']
|
76
77
|
test_files = FileList['test/**/test_*.rb']
|
77
78
|
test_files -= FileList['test/integration/**/test_*.rb'] unless ENV['NET_SSH_RUN_INTEGRATION_TESTS']
|
79
|
+
test_files -= FileList['test/win_integration/**/test_*.rb'] unless ENV['NET_SSH_RUN_WIN_INTEGRATION_TESTS']
|
80
|
+
test_files -= FileList['test/manual/test_*.rb']
|
81
|
+
test_files -= FileList['test/test_pageant.rb']
|
78
82
|
test_files -= FileList['test/test/**/test_*.rb']
|
79
83
|
t.test_files = test_files
|
80
84
|
end
|
data/appveyor.yml
CHANGED
@@ -4,17 +4,48 @@ skip_tags: true
|
|
4
4
|
|
5
5
|
environment:
|
6
6
|
matrix:
|
7
|
-
- ruby_version: "
|
8
|
-
- ruby_version: "
|
7
|
+
- ruby_version: "jruby-9.1.2.0"
|
8
|
+
- ruby_version: "23"
|
9
|
+
- ruby_version: "23-x64"
|
10
|
+
|
11
|
+
#init:
|
12
|
+
# - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
13
|
+
|
14
|
+
#on_finish:
|
15
|
+
# - ps: $blockRdp = $true; iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1'))
|
16
|
+
|
17
|
+
|
18
|
+
platform:
|
19
|
+
- x86
|
9
20
|
|
10
21
|
install:
|
11
22
|
- SET PATH=C:\Ruby%ruby_version%\bin;%PATH%
|
12
|
-
-
|
23
|
+
- if "%ruby_version%" == "jruby-9.1.2.0" ( cinst javaruntime -i )
|
24
|
+
- if "%ruby_version%" == "jruby-9.1.2.0" ( cinst jruby --version 9.1.2.0 -i )
|
25
|
+
- if "%ruby_version%" == "jruby-9.1.2.0" ( SET "PATH=C:\jruby-9.1.2.0\bin\;%PATH%" )
|
26
|
+
- ruby --version
|
27
|
+
- gem install bundler --no-document -v 1.13.5
|
13
28
|
- SET BUNDLE_GEMFILE=Gemfile.norbnacl
|
14
|
-
- bundle _1.
|
29
|
+
- bundle _1.13.5_ install --retry=3
|
30
|
+
- cinst freesshd
|
31
|
+
- cinst putty
|
32
|
+
- ps: |
|
33
|
+
if ($env:Processor_Architecture -eq "x86")
|
34
|
+
{
|
35
|
+
dir 'C:\Program Files\'
|
36
|
+
dir 'C:\Program Files\freeSSHd'
|
37
|
+
cp 'test\win_integration\FreeSSHDService.ini' 'C:\Program Files\freeSSHd\FreeSSHDService.ini'
|
38
|
+
& 'C:\Program Files\freeSSHd\FreeSSHDService.exe'
|
39
|
+
} else {
|
40
|
+
dir 'C:\Program Files (x86)\'
|
41
|
+
dir 'C:\Program Files (x86)\freeSSHd'
|
42
|
+
cp 'test\win_integration\FreeSSHDService32.ini' 'C:\Program Files (x86)\freeSSHd\FreeSSHDService.ini'
|
43
|
+
& 'C:\Program Files (x86)\freeSSHd\FreeSSHDService.exe'
|
44
|
+
}
|
15
45
|
|
16
46
|
test_script:
|
17
47
|
- SET BUNDLE_GEMFILE=Gemfile.norbnacl
|
18
|
-
-
|
48
|
+
- SET NET_SSH_RUN_WIN_INTEGRATION_TESTS=YES
|
49
|
+
- bundle _1.13.5_ exec rake test
|
19
50
|
|
20
51
|
build: off
|
data/lib/net/ssh.rb
CHANGED
@@ -153,6 +153,10 @@ module Net
|
|
153
153
|
# for better performance if your SSH server supports it (most do).
|
154
154
|
# * :max_win_size => maximum size we tell the other side that is supported for
|
155
155
|
# the window.
|
156
|
+
# * :non_interactive => set to true if your app is non interactive and prefers
|
157
|
+
# authentication failure vs password prompt. Non-interactive applications
|
158
|
+
# should set it to true to prefer failing a password/etc auth methods vs.
|
159
|
+
# asking for password.
|
156
160
|
# * :paranoid => either false, true, :very, or :secure specifying how
|
157
161
|
# strict host-key verification should be (in increasing order here).
|
158
162
|
# You can also provide an own Object which responds to +verify+. The argument
|
@@ -181,8 +185,6 @@ module Net
|
|
181
185
|
# Defaults to %w(~/.ssh/known_hosts ~/.ssh/known_hosts2).
|
182
186
|
# * :use_agent => Set false to disable the use of ssh-agent. Defaults to
|
183
187
|
# true
|
184
|
-
# * :non_interactive => set to true if your app is non interactive and prefers
|
185
|
-
# authentication failure vs password prompt
|
186
188
|
# * :verbose => how verbose to be (Logger verbosity constants, Logger::DEBUG
|
187
189
|
# is very verbose, Logger::FATAL is all but silent). Logger::FATAL is the
|
188
190
|
# default. The symbols :debug, :info, :warn, :error, and :fatal are also
|
@@ -192,8 +194,6 @@ module Net
|
|
192
194
|
# * :number_of_password_prompts => Number of prompts for the password
|
193
195
|
# authentication method defaults to 3 set to 0 to disable prompt for
|
194
196
|
# password auth method
|
195
|
-
# * :non_interactive => non interactive applications should set it to true
|
196
|
-
# to prefer failing a password/etc auth methods vs asking for password
|
197
197
|
# * :password_prompt => a custom prompt object with ask method. See Net::SSH::Prompt
|
198
198
|
#
|
199
199
|
# * :agent_socket_factory => enables the user to pass a lambda/block that will serve as the socket factory
|
@@ -264,7 +264,7 @@ module Net
|
|
264
264
|
# to read.
|
265
265
|
#
|
266
266
|
# See Net::SSH::Config for the full description of all supported options.
|
267
|
-
def self.configuration_for(host, use_ssh_config
|
267
|
+
def self.configuration_for(host, use_ssh_config)
|
268
268
|
files = case use_ssh_config
|
269
269
|
when true then Net::SSH::Config.default_files
|
270
270
|
when false, nil then return {}
|
@@ -2,22 +2,182 @@ require 'net/ssh/buffer'
|
|
2
2
|
require 'net/ssh/errors'
|
3
3
|
require 'net/ssh/loggable'
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
: RUBY_PLATFORM =~ /java/ ? :java : :unix
|
5
|
+
require 'net/ssh/transport/server_version'
|
6
|
+
require 'socket'
|
7
|
+
require 'rubygems'
|
9
8
|
|
10
|
-
|
11
|
-
class AgentError < Net::SSH::Exception; end
|
9
|
+
require 'net/ssh/authentication/pageant' if Gem.win_platform? && RUBY_PLATFORM != "java"
|
12
10
|
|
11
|
+
module Net; module SSH; module Authentication
|
12
|
+
# Class for representing agent-specific errors.
|
13
|
+
class AgentError < Net::SSH::Exception; end
|
13
14
|
# An exception for indicating that the SSH agent is not available.
|
14
15
|
class AgentNotAvailable < AgentError; end
|
15
|
-
end; end; end
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
#
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
17
|
+
# This class implements a simple client for the ssh-agent protocol. It
|
18
|
+
# does not implement any specific protocol, but instead copies the
|
19
|
+
# behavior of the ssh-agent functions in the OpenSSH library (3.8).
|
20
|
+
#
|
21
|
+
# This means that although it behaves like a SSH1 client, it also has
|
22
|
+
# some SSH2 functionality (like signing data).
|
23
|
+
class Agent
|
24
|
+
include Loggable
|
25
|
+
|
26
|
+
# A simple module for extending keys, to allow comments to be specified
|
27
|
+
# for them.
|
28
|
+
module Comment
|
29
|
+
attr_accessor :comment
|
30
|
+
end
|
31
|
+
|
32
|
+
SSH2_AGENT_REQUEST_VERSION = 1
|
33
|
+
SSH2_AGENT_REQUEST_IDENTITIES = 11
|
34
|
+
SSH2_AGENT_IDENTITIES_ANSWER = 12
|
35
|
+
SSH2_AGENT_SIGN_REQUEST = 13
|
36
|
+
SSH2_AGENT_SIGN_RESPONSE = 14
|
37
|
+
SSH2_AGENT_FAILURE = 30
|
38
|
+
SSH2_AGENT_VERSION_RESPONSE = 103
|
39
|
+
|
40
|
+
SSH_COM_AGENT2_FAILURE = 102
|
41
|
+
|
42
|
+
SSH_AGENT_REQUEST_RSA_IDENTITIES = 1
|
43
|
+
SSH_AGENT_RSA_IDENTITIES_ANSWER1 = 2
|
44
|
+
SSH_AGENT_RSA_IDENTITIES_ANSWER2 = 5
|
45
|
+
SSH_AGENT_FAILURE = 5
|
46
|
+
|
47
|
+
# The underlying socket being used to communicate with the SSH agent.
|
48
|
+
attr_reader :socket
|
49
|
+
|
50
|
+
# Instantiates a new agent object, connects to a running SSH agent,
|
51
|
+
# negotiates the agent protocol version, and returns the agent object.
|
52
|
+
def self.connect(logger=nil, agent_socket_factory = nil)
|
53
|
+
agent = new(logger)
|
54
|
+
agent.connect!(agent_socket_factory)
|
55
|
+
agent.negotiate!
|
56
|
+
agent
|
57
|
+
end
|
58
|
+
|
59
|
+
# Creates a new Agent object, using the optional logger instance to
|
60
|
+
# report status.
|
61
|
+
def initialize(logger=nil)
|
62
|
+
self.logger = logger
|
63
|
+
end
|
64
|
+
|
65
|
+
# Connect to the agent process using the socket factory and socket name
|
66
|
+
# given by the attribute writers. If the agent on the other end of the
|
67
|
+
# socket reports that it is an SSH2-compatible agent, this will fail
|
68
|
+
# (it only supports the ssh-agent distributed by OpenSSH).
|
69
|
+
def connect!(agent_socket_factory = nil)
|
70
|
+
debug { "connecting to ssh-agent" }
|
71
|
+
@socket =
|
72
|
+
if agent_socket_factory
|
73
|
+
agent_socket_factory.call
|
74
|
+
elsif ENV['SSH_AUTH_SOCK'] && defined?(unix_socket_class)
|
75
|
+
unix_socket_class.open(ENV['SSH_AUTH_SOCK'])
|
76
|
+
elsif Gem.win_platform? && RUBY_ENGINE != "jruby"
|
77
|
+
Pageant::Socket.open
|
78
|
+
else
|
79
|
+
raise AgentNotAvailable, "Agent not configured"
|
80
|
+
end
|
81
|
+
rescue StandardError => e
|
82
|
+
error { "could not connect to ssh-agent: #{e.message}" }
|
83
|
+
raise AgentNotAvailable, $!.message
|
84
|
+
end
|
85
|
+
|
86
|
+
# Attempts to negotiate the SSH agent protocol version. Raises an error
|
87
|
+
# if the version could not be negotiated successfully.
|
88
|
+
def negotiate!
|
89
|
+
# determine what type of agent we're communicating with
|
90
|
+
type, body = send_and_wait(SSH2_AGENT_REQUEST_VERSION, :string, Transport::ServerVersion::PROTO_VERSION)
|
91
|
+
|
92
|
+
raise AgentNotAvailable, "SSH2 agents are not yet supported" if type == SSH2_AGENT_VERSION_RESPONSE
|
93
|
+
if type == SSH2_AGENT_FAILURE
|
94
|
+
debug { "Unexpected response type==#{type}, this will be ignored" }
|
95
|
+
elsif type != SSH_AGENT_RSA_IDENTITIES_ANSWER1 && type != SSH_AGENT_RSA_IDENTITIES_ANSWER2
|
96
|
+
raise AgentNotAvailable, "unknown response from agent: #{type}, #{body.to_s.inspect}"
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
# Return an array of all identities (public keys) known to the agent.
|
101
|
+
# Each key returned is augmented with a +comment+ property which is set
|
102
|
+
# to the comment returned by the agent for that key.
|
103
|
+
def identities
|
104
|
+
type, body = send_and_wait(SSH2_AGENT_REQUEST_IDENTITIES)
|
105
|
+
raise AgentError, "could not get identity count" if agent_failed(type)
|
106
|
+
raise AgentError, "bad authentication reply: #{type}" if type != SSH2_AGENT_IDENTITIES_ANSWER
|
107
|
+
|
108
|
+
identities = []
|
109
|
+
body.read_long.times do
|
110
|
+
key_str = body.read_string
|
111
|
+
comment_str = body.read_string
|
112
|
+
begin
|
113
|
+
key = Buffer.new(key_str).read_key
|
114
|
+
key.extend(Comment)
|
115
|
+
key.comment = comment_str
|
116
|
+
identities.push key
|
117
|
+
rescue NotImplementedError => e
|
118
|
+
error { "ignoring unimplemented key:#{e.message} #{comment_str}" }
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
return identities
|
123
|
+
end
|
124
|
+
|
125
|
+
# Closes this socket. This agent reference is no longer able to
|
126
|
+
# query the agent.
|
127
|
+
def close
|
128
|
+
@socket.close
|
129
|
+
end
|
130
|
+
|
131
|
+
# Using the agent and the given public key, sign the given data. The
|
132
|
+
# signature is returned in SSH2 format.
|
133
|
+
def sign(key, data)
|
134
|
+
type, reply = send_and_wait(SSH2_AGENT_SIGN_REQUEST, :string, Buffer.from(:key, key), :string, data, :long, 0)
|
135
|
+
|
136
|
+
raise AgentError, "agent could not sign data with requested identity" if agent_failed(type)
|
137
|
+
raise AgentError, "bad authentication response #{type}" if type != SSH2_AGENT_SIGN_RESPONSE
|
138
|
+
|
139
|
+
return reply.read_string
|
140
|
+
end
|
141
|
+
|
142
|
+
private
|
143
|
+
|
144
|
+
def unix_socket_class
|
145
|
+
UNIXSocket
|
146
|
+
end
|
147
|
+
|
148
|
+
# Send a new packet of the given type, with the associated data.
|
149
|
+
def send_packet(type, *args)
|
150
|
+
buffer = Buffer.from(*args)
|
151
|
+
data = [buffer.length + 1, type.to_i, buffer.to_s].pack("NCA*")
|
152
|
+
debug { "sending agent request #{type} len #{buffer.length}" }
|
153
|
+
@socket.send data, 0
|
154
|
+
end
|
155
|
+
|
156
|
+
# Read the next packet from the agent. This will return a two-part
|
157
|
+
# tuple consisting of the packet type, and the packet's body (which
|
158
|
+
# is returned as a Net::SSH::Buffer).
|
159
|
+
def read_packet
|
160
|
+
buffer = Net::SSH::Buffer.new(@socket.read(4))
|
161
|
+
buffer.append(@socket.read(buffer.read_long))
|
162
|
+
type = buffer.read_byte
|
163
|
+
debug { "received agent packet #{type} len #{buffer.length-4}" }
|
164
|
+
return type, buffer
|
165
|
+
end
|
166
|
+
|
167
|
+
# Send the given packet and return the subsequent reply from the agent.
|
168
|
+
# (See #send_packet and #read_packet).
|
169
|
+
def send_and_wait(type, *args)
|
170
|
+
send_packet(type, *args)
|
171
|
+
read_packet
|
172
|
+
end
|
173
|
+
|
174
|
+
# Returns +true+ if the parameter indicates a "failure" response from
|
175
|
+
# the agent, and +false+ otherwise.
|
176
|
+
def agent_failed(type)
|
177
|
+
type == SSH_AGENT_FAILURE ||
|
178
|
+
type == SSH2_AGENT_FAILURE ||
|
179
|
+
type == SSH_COM_AGENT2_FAILURE
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
end; end; end
|