ddollar-net-ssh 2.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG.rdoc +42 -0
- data/Manifest +101 -0
- data/README.rdoc +110 -0
- data/Rakefile +26 -0
- data/THANKS.rdoc +16 -0
- data/lib/net/ssh.rb +199 -0
- data/lib/net/ssh/authentication/agent.rb +175 -0
- data/lib/net/ssh/authentication/constants.rb +18 -0
- data/lib/net/ssh/authentication/key_manager.rb +169 -0
- data/lib/net/ssh/authentication/methods/abstract.rb +60 -0
- data/lib/net/ssh/authentication/methods/hostbased.rb +71 -0
- data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +66 -0
- data/lib/net/ssh/authentication/methods/password.rb +39 -0
- data/lib/net/ssh/authentication/methods/publickey.rb +92 -0
- data/lib/net/ssh/authentication/pageant.rb +176 -0
- data/lib/net/ssh/authentication/session.rb +127 -0
- data/lib/net/ssh/buffer.rb +339 -0
- data/lib/net/ssh/buffered_io.rb +149 -0
- data/lib/net/ssh/config.rb +173 -0
- data/lib/net/ssh/connection/channel.rb +625 -0
- data/lib/net/ssh/connection/constants.rb +33 -0
- data/lib/net/ssh/connection/session.rb +569 -0
- data/lib/net/ssh/connection/term.rb +178 -0
- data/lib/net/ssh/errors.rb +85 -0
- data/lib/net/ssh/key_factory.rb +85 -0
- data/lib/net/ssh/known_hosts.rb +129 -0
- data/lib/net/ssh/loggable.rb +61 -0
- data/lib/net/ssh/packet.rb +102 -0
- data/lib/net/ssh/prompt.rb +93 -0
- data/lib/net/ssh/proxy/errors.rb +14 -0
- data/lib/net/ssh/proxy/http.rb +94 -0
- data/lib/net/ssh/proxy/socks4.rb +70 -0
- data/lib/net/ssh/proxy/socks5.rb +128 -0
- data/lib/net/ssh/service/forward.rb +267 -0
- data/lib/net/ssh/test.rb +89 -0
- data/lib/net/ssh/test/channel.rb +129 -0
- data/lib/net/ssh/test/extensions.rb +152 -0
- data/lib/net/ssh/test/kex.rb +44 -0
- data/lib/net/ssh/test/local_packet.rb +51 -0
- data/lib/net/ssh/test/packet.rb +81 -0
- data/lib/net/ssh/test/remote_packet.rb +38 -0
- data/lib/net/ssh/test/script.rb +157 -0
- data/lib/net/ssh/test/socket.rb +59 -0
- data/lib/net/ssh/transport/algorithms.rb +384 -0
- data/lib/net/ssh/transport/cipher_factory.rb +72 -0
- data/lib/net/ssh/transport/constants.rb +30 -0
- data/lib/net/ssh/transport/hmac.rb +31 -0
- data/lib/net/ssh/transport/hmac/abstract.rb +48 -0
- data/lib/net/ssh/transport/hmac/md5.rb +12 -0
- data/lib/net/ssh/transport/hmac/md5_96.rb +11 -0
- data/lib/net/ssh/transport/hmac/none.rb +15 -0
- data/lib/net/ssh/transport/hmac/sha1.rb +13 -0
- data/lib/net/ssh/transport/hmac/sha1_96.rb +11 -0
- data/lib/net/ssh/transport/identity_cipher.rb +40 -0
- data/lib/net/ssh/transport/kex.rb +13 -0
- data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +208 -0
- data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +77 -0
- data/lib/net/ssh/transport/openssl.rb +128 -0
- data/lib/net/ssh/transport/packet_stream.rb +230 -0
- data/lib/net/ssh/transport/server_version.rb +61 -0
- data/lib/net/ssh/transport/session.rb +262 -0
- data/lib/net/ssh/transport/state.rb +170 -0
- data/lib/net/ssh/verifiers/lenient.rb +30 -0
- data/lib/net/ssh/verifiers/null.rb +12 -0
- data/lib/net/ssh/verifiers/strict.rb +53 -0
- data/lib/net/ssh/version.rb +60 -0
- data/net-ssh.gemspec +56 -0
- data/setup.rb +1585 -0
- data/test/authentication/methods/common.rb +28 -0
- data/test/authentication/methods/test_abstract.rb +51 -0
- data/test/authentication/methods/test_hostbased.rb +108 -0
- data/test/authentication/methods/test_keyboard_interactive.rb +98 -0
- data/test/authentication/methods/test_password.rb +50 -0
- data/test/authentication/methods/test_publickey.rb +123 -0
- data/test/authentication/test_agent.rb +205 -0
- data/test/authentication/test_key_manager.rb +100 -0
- data/test/authentication/test_session.rb +93 -0
- data/test/common.rb +106 -0
- data/test/configs/exact_match +8 -0
- data/test/configs/wild_cards +14 -0
- data/test/connection/test_channel.rb +452 -0
- data/test/connection/test_session.rb +483 -0
- data/test/test_all.rb +6 -0
- data/test/test_buffer.rb +336 -0
- data/test/test_buffered_io.rb +63 -0
- data/test/test_config.rb +78 -0
- data/test/test_key_factory.rb +67 -0
- data/test/transport/hmac/test_md5.rb +34 -0
- data/test/transport/hmac/test_md5_96.rb +25 -0
- data/test/transport/hmac/test_none.rb +34 -0
- data/test/transport/hmac/test_sha1.rb +34 -0
- data/test/transport/hmac/test_sha1_96.rb +25 -0
- data/test/transport/kex/test_diffie_hellman_group1_sha1.rb +146 -0
- data/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb +92 -0
- data/test/transport/test_algorithms.rb +302 -0
- data/test/transport/test_cipher_factory.rb +163 -0
- data/test/transport/test_hmac.rb +34 -0
- data/test/transport/test_identity_cipher.rb +40 -0
- data/test/transport/test_packet_stream.rb +433 -0
- data/test/transport/test_server_version.rb +55 -0
- data/test/transport/test_session.rb +312 -0
- data/test/transport/test_state.rb +173 -0
- metadata +222 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
module Authentication; module Methods
|
2
|
+
|
3
|
+
module Common
|
4
|
+
include Net::SSH::Authentication::Constants
|
5
|
+
|
6
|
+
private
|
7
|
+
|
8
|
+
def socket(options={})
|
9
|
+
@socket ||= stub("socket", :client_name => "me.ssh.test")
|
10
|
+
end
|
11
|
+
|
12
|
+
def transport(options={})
|
13
|
+
@transport ||= MockTransport.new(options.merge(:socket => socket))
|
14
|
+
end
|
15
|
+
|
16
|
+
def session(options={})
|
17
|
+
@session ||= begin
|
18
|
+
sess = stub("auth-session", :logger => nil, :transport => transport(options))
|
19
|
+
def sess.next_message
|
20
|
+
transport.next_message
|
21
|
+
end
|
22
|
+
sess
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
|
28
|
+
end; end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'common'
|
2
|
+
require 'authentication/methods/common'
|
3
|
+
require 'net/ssh/authentication/methods/abstract'
|
4
|
+
|
5
|
+
module Authentication; module Methods
|
6
|
+
|
7
|
+
class TestAbstract < Test::Unit::TestCase
|
8
|
+
include Common
|
9
|
+
|
10
|
+
def test_constructor_should_set_defaults
|
11
|
+
assert_nil subject.key_manager
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_constructor_should_honor_options
|
15
|
+
assert_equal :manager, subject(:key_manager => :manager).key_manager
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_session_id_should_query_session_id_from_key_exchange
|
19
|
+
transport.stubs(:algorithms).returns(stub("algorithms", :session_id => "abcxyz123"))
|
20
|
+
assert_equal "abcxyz123", subject.session_id
|
21
|
+
end
|
22
|
+
|
23
|
+
def test_send_message_should_delegate_to_transport
|
24
|
+
transport.expects(:send_message).with("abcxyz123")
|
25
|
+
subject.send_message("abcxyz123")
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_userauth_request_should_build_well_formed_userauth_packet
|
29
|
+
packet = subject.userauth_request("jamis", "ssh-connection", "password")
|
30
|
+
assert_equal "\062\0\0\0\005jamis\0\0\0\016ssh-connection\0\0\0\010password", packet.to_s
|
31
|
+
end
|
32
|
+
|
33
|
+
def test_userauth_request_should_translate_extra_booleans_onto_end
|
34
|
+
packet = subject.userauth_request("jamis", "ssh-connection", "password", true, false)
|
35
|
+
assert_equal "\062\0\0\0\005jamis\0\0\0\016ssh-connection\0\0\0\010password\1\0", packet.to_s
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_userauth_request_should_translate_extra_strings_onto_end
|
39
|
+
packet = subject.userauth_request("jamis", "ssh-connection", "password", "foo", "bar")
|
40
|
+
assert_equal "\062\0\0\0\005jamis\0\0\0\016ssh-connection\0\0\0\010password\0\0\0\3foo\0\0\0\3bar", packet.to_s
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def subject(options={})
|
46
|
+
@subject ||= Net::SSH::Authentication::Methods::Abstract.new(session(options), options)
|
47
|
+
end
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
end; end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'common'
|
2
|
+
require 'net/ssh/authentication/methods/hostbased'
|
3
|
+
require 'authentication/methods/common'
|
4
|
+
|
5
|
+
module Authentication; module Methods
|
6
|
+
|
7
|
+
class TestHostbased < Test::Unit::TestCase
|
8
|
+
include Common
|
9
|
+
|
10
|
+
def test_authenticate_should_return_false_when_no_key_manager_has_been_set
|
11
|
+
assert_equal false, subject(:key_manager => nil).authenticate("ssh-connection", "jamis")
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_authenticate_should_return_false_when_key_manager_has_no_keys
|
15
|
+
assert_equal false, subject(:keys => []).authenticate("ssh-connection", "jamis")
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_authenticate_should_return_false_if_no_keys_can_authenticate
|
19
|
+
key_manager.expects(:sign).with(&signature_parameters(keys.first)).returns("sig-one")
|
20
|
+
key_manager.expects(:sign).with(&signature_parameters(keys.last)).returns("sig-two")
|
21
|
+
|
22
|
+
transport.expect do |t, packet|
|
23
|
+
assert_equal USERAUTH_REQUEST, packet.type
|
24
|
+
assert verify_userauth_request_packet(packet, keys.first)
|
25
|
+
assert_equal "sig-one", packet.read_string
|
26
|
+
t.return(USERAUTH_FAILURE, :string, "hostbased,password")
|
27
|
+
|
28
|
+
t.expect do |t, packet|
|
29
|
+
assert_equal USERAUTH_REQUEST, packet.type
|
30
|
+
assert verify_userauth_request_packet(packet, keys.last)
|
31
|
+
assert_equal "sig-two", packet.read_string
|
32
|
+
t.return(USERAUTH_FAILURE, :string, "hostbased,password")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
assert_equal false, subject.authenticate("ssh-connection", "jamis")
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_authenticate_should_return_true_if_any_key_can_authenticate
|
40
|
+
key_manager.expects(:sign).with(&signature_parameters(keys.first)).returns("sig-one")
|
41
|
+
|
42
|
+
transport.expect do |t, packet|
|
43
|
+
assert_equal USERAUTH_REQUEST, packet.type
|
44
|
+
assert verify_userauth_request_packet(packet, keys.first)
|
45
|
+
assert_equal "sig-one", packet.read_string
|
46
|
+
t.return(USERAUTH_SUCCESS)
|
47
|
+
end
|
48
|
+
|
49
|
+
assert subject.authenticate("ssh-connection", "jamis")
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def signature_parameters(key)
|
55
|
+
Proc.new do |given_key, data|
|
56
|
+
next false unless given_key.to_blob == key.to_blob
|
57
|
+
buffer = Net::SSH::Buffer.new(data)
|
58
|
+
buffer.read_string == "abcxyz123" && # session-id
|
59
|
+
buffer.read_byte == USERAUTH_REQUEST && # type
|
60
|
+
verify_userauth_request_packet(buffer, key)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def verify_userauth_request_packet(packet, key)
|
65
|
+
packet.read_string == "jamis" && # user-name
|
66
|
+
packet.read_string == "ssh-connection" && # next service
|
67
|
+
packet.read_string == "hostbased" && # auth-method
|
68
|
+
packet.read_string == key.ssh_type && # key type
|
69
|
+
packet.read_buffer.read_key.to_blob == key.to_blob && # key
|
70
|
+
packet.read_string == "me.ssh.test." && # client hostname
|
71
|
+
packet.read_string == "jamis" # client username
|
72
|
+
end
|
73
|
+
|
74
|
+
@@keys = nil
|
75
|
+
def keys
|
76
|
+
@@keys ||= [OpenSSL::PKey::RSA.new(32), OpenSSL::PKey::DSA.new(32)]
|
77
|
+
end
|
78
|
+
|
79
|
+
def key_manager(options={})
|
80
|
+
@key_manager ||= stub("key_manager", :identities => options[:keys] || keys)
|
81
|
+
end
|
82
|
+
|
83
|
+
def subject(options={})
|
84
|
+
options[:key_manager] = key_manager(options) unless options.key?(:key_manager)
|
85
|
+
@subject ||= Net::SSH::Authentication::Methods::Hostbased.new(session(options), options)
|
86
|
+
end
|
87
|
+
|
88
|
+
def socket(options={})
|
89
|
+
@socket ||= stub("socket", :client_name => "me.ssh.test")
|
90
|
+
end
|
91
|
+
|
92
|
+
def transport(options={})
|
93
|
+
@transport ||= MockTransport.new(options.merge(:socket => socket))
|
94
|
+
end
|
95
|
+
|
96
|
+
def session(options={})
|
97
|
+
@session ||= begin
|
98
|
+
sess = stub("auth-session", :logger => nil, :transport => transport(options))
|
99
|
+
def sess.next_message
|
100
|
+
transport.next_message
|
101
|
+
end
|
102
|
+
sess
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
end; end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'common'
|
2
|
+
require 'net/ssh/authentication/methods/keyboard_interactive'
|
3
|
+
require 'authentication/methods/common'
|
4
|
+
|
5
|
+
module Authentication; module Methods
|
6
|
+
|
7
|
+
class TestKeyboardInteractive < Test::Unit::TestCase
|
8
|
+
include Common
|
9
|
+
|
10
|
+
USERAUTH_INFO_REQUEST = 60
|
11
|
+
USERAUTH_INFO_RESPONSE = 61
|
12
|
+
|
13
|
+
def test_authenticate_should_be_false_when_server_does_not_support_this_method
|
14
|
+
transport.expect do |t,packet|
|
15
|
+
assert_equal USERAUTH_REQUEST, packet.type
|
16
|
+
assert_equal "jamis", packet.read_string
|
17
|
+
assert_equal "ssh-connection", packet.read_string
|
18
|
+
assert_equal "keyboard-interactive", packet.read_string
|
19
|
+
assert_equal "", packet.read_string # language tags
|
20
|
+
assert_equal "", packet.read_string # submethods
|
21
|
+
|
22
|
+
t.return(USERAUTH_FAILURE, :string, "password")
|
23
|
+
end
|
24
|
+
|
25
|
+
assert_equal false, subject.authenticate("ssh-connection", "jamis")
|
26
|
+
end
|
27
|
+
|
28
|
+
def test_authenticate_should_be_false_if_given_password_is_not_accepted
|
29
|
+
transport.expect do |t,packet|
|
30
|
+
assert_equal USERAUTH_REQUEST, packet.type
|
31
|
+
t.return(USERAUTH_INFO_REQUEST, :string, "", :string, "", :string, "", :long, 1, :string, "Password:", :bool, false)
|
32
|
+
t.expect do |t,packet|
|
33
|
+
assert_equal USERAUTH_INFO_RESPONSE, packet.type
|
34
|
+
assert_equal 1, packet.read_long
|
35
|
+
assert_equal "the-password", packet.read_string
|
36
|
+
t.return(USERAUTH_FAILURE, :string, "publickey")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
assert_equal false, subject.authenticate("ssh-connection", "jamis", "the-password")
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_authenticate_should_be_true_if_given_password_is_accepted
|
44
|
+
transport.expect do |t,packet|
|
45
|
+
assert_equal USERAUTH_REQUEST, packet.type
|
46
|
+
t.return(USERAUTH_INFO_REQUEST, :string, "", :string, "", :string, "", :long, 1, :string, "Password:", :bool, false)
|
47
|
+
t.expect do |t,packet|
|
48
|
+
assert_equal USERAUTH_INFO_RESPONSE, packet.type
|
49
|
+
t.return(USERAUTH_SUCCESS)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
assert subject.authenticate("ssh-connection", "jamis", "the-password")
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_authenticate_should_duplicate_password_as_needed_to_fill_request
|
57
|
+
transport.expect do |t,packet|
|
58
|
+
assert_equal USERAUTH_REQUEST, packet.type
|
59
|
+
t.return(USERAUTH_INFO_REQUEST, :string, "", :string, "", :string, "", :long, 2, :string, "Password:", :bool, false, :string, "Again:", :bool, false)
|
60
|
+
t.expect do |t,packet|
|
61
|
+
assert_equal USERAUTH_INFO_RESPONSE, packet.type
|
62
|
+
assert_equal 2, packet.read_long
|
63
|
+
assert_equal "the-password", packet.read_string
|
64
|
+
assert_equal "the-password", packet.read_string
|
65
|
+
t.return(USERAUTH_SUCCESS)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
assert subject.authenticate("ssh-connection", "jamis", "the-password")
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_authenticate_should_prompt_for_input_when_password_is_not_given
|
73
|
+
subject.expects(:prompt).with("Name:", true).returns("name")
|
74
|
+
subject.expects(:prompt).with("Password:", false).returns("password")
|
75
|
+
|
76
|
+
transport.expect do |t,packet|
|
77
|
+
assert_equal USERAUTH_REQUEST, packet.type
|
78
|
+
t.return(USERAUTH_INFO_REQUEST, :string, "", :string, "", :string, "", :long, 2, :string, "Name:", :bool, true, :string, "Password:", :bool, false)
|
79
|
+
t.expect do |t,packet|
|
80
|
+
assert_equal USERAUTH_INFO_RESPONSE, packet.type
|
81
|
+
assert_equal 2, packet.read_long
|
82
|
+
assert_equal "name", packet.read_string
|
83
|
+
assert_equal "password", packet.read_string
|
84
|
+
t.return(USERAUTH_SUCCESS)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
assert subject.authenticate("ssh-connection", "jamis", nil)
|
89
|
+
end
|
90
|
+
|
91
|
+
private
|
92
|
+
|
93
|
+
def subject(options={})
|
94
|
+
@subject ||= Net::SSH::Authentication::Methods::KeyboardInteractive.new(session(options), options)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end; end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'common'
|
2
|
+
require 'net/ssh/authentication/methods/password'
|
3
|
+
require 'authentication/methods/common'
|
4
|
+
|
5
|
+
module Authentication; module Methods
|
6
|
+
|
7
|
+
class TestPassword < Test::Unit::TestCase
|
8
|
+
include Common
|
9
|
+
|
10
|
+
def test_authenticate_when_password_is_unacceptible_should_return_false
|
11
|
+
transport.expect do |t,packet|
|
12
|
+
assert_equal USERAUTH_REQUEST, packet.type
|
13
|
+
assert_equal "jamis", packet.read_string
|
14
|
+
assert_equal "ssh-connection", packet.read_string
|
15
|
+
assert_equal "password", packet.read_string
|
16
|
+
assert_equal false, packet.read_bool
|
17
|
+
assert_equal "the-password", packet.read_string
|
18
|
+
|
19
|
+
t.return(USERAUTH_FAILURE, :string, "publickey")
|
20
|
+
end
|
21
|
+
|
22
|
+
assert !subject.authenticate("ssh-connection", "jamis", "the-password")
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_authenticate_when_password_is_acceptible_should_return_true
|
26
|
+
transport.expect do |t,packet|
|
27
|
+
assert_equal USERAUTH_REQUEST, packet.type
|
28
|
+
t.return(USERAUTH_SUCCESS)
|
29
|
+
end
|
30
|
+
|
31
|
+
assert subject.authenticate("ssh-connection", "jamis", "the-password")
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_authenticate_should_return_false_if_password_change_request_is_received
|
35
|
+
transport.expect do |t,packet|
|
36
|
+
assert_equal USERAUTH_REQUEST, packet.type
|
37
|
+
t.return(USERAUTH_PASSWD_CHANGEREQ, :string, "Change your password:", :string, "")
|
38
|
+
end
|
39
|
+
|
40
|
+
assert !subject.authenticate("ssh-connection", "jamis", "the-password")
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def subject(options={})
|
46
|
+
@subject ||= Net::SSH::Authentication::Methods::Password.new(session(options), options)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end; end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'common'
|
2
|
+
require 'net/ssh/authentication/methods/publickey'
|
3
|
+
require 'authentication/methods/common'
|
4
|
+
|
5
|
+
module Authentication; module Methods
|
6
|
+
|
7
|
+
class TestPublickey < Test::Unit::TestCase
|
8
|
+
include Common
|
9
|
+
|
10
|
+
def test_authenticate_should_return_false_when_no_key_manager_has_been_set
|
11
|
+
assert_equal false, subject(:key_manager => nil).authenticate("ssh-connection", "jamis")
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_authenticate_should_return_false_when_key_manager_has_no_keys
|
15
|
+
assert_equal false, subject(:keys => []).authenticate("ssh-connection", "jamis")
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_authenticate_should_return_false_if_no_keys_can_authenticate
|
19
|
+
transport.expect do |t, packet|
|
20
|
+
assert_equal USERAUTH_REQUEST, packet.type
|
21
|
+
assert verify_userauth_request_packet(packet, keys.first, false)
|
22
|
+
t.return(USERAUTH_FAILURE, :string, "hostbased,password")
|
23
|
+
|
24
|
+
t.expect do |t, packet|
|
25
|
+
assert_equal USERAUTH_REQUEST, packet.type
|
26
|
+
assert verify_userauth_request_packet(packet, keys.last, false)
|
27
|
+
t.return(USERAUTH_FAILURE, :string, "hostbased,password")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
assert_equal false, subject.authenticate("ssh-connection", "jamis")
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_authenticate_should_return_false_if_signature_exchange_fails
|
35
|
+
key_manager.expects(:sign).with(&signature_parameters(keys.first)).returns("sig-one")
|
36
|
+
key_manager.expects(:sign).with(&signature_parameters(keys.last)).returns("sig-two")
|
37
|
+
|
38
|
+
transport.expect do |t, packet|
|
39
|
+
assert_equal USERAUTH_REQUEST, packet.type
|
40
|
+
assert verify_userauth_request_packet(packet, keys.first, false)
|
41
|
+
t.return(USERAUTH_PK_OK, :string, keys.first.ssh_type, :string, Net::SSH::Buffer.from(:key, keys.first))
|
42
|
+
|
43
|
+
t.expect do |t,packet|
|
44
|
+
assert_equal USERAUTH_REQUEST, packet.type
|
45
|
+
assert verify_userauth_request_packet(packet, keys.first, true)
|
46
|
+
assert_equal "sig-one", packet.read_string
|
47
|
+
t.return(USERAUTH_FAILURE, :string, "hostbased,password")
|
48
|
+
|
49
|
+
t.expect do |t, packet|
|
50
|
+
assert_equal USERAUTH_REQUEST, packet.type
|
51
|
+
assert verify_userauth_request_packet(packet, keys.last, false)
|
52
|
+
t.return(USERAUTH_PK_OK, :string, keys.last.ssh_type, :string, Net::SSH::Buffer.from(:key, keys.last))
|
53
|
+
|
54
|
+
t.expect do |t,packet|
|
55
|
+
assert_equal USERAUTH_REQUEST, packet.type
|
56
|
+
assert verify_userauth_request_packet(packet, keys.last, true)
|
57
|
+
assert_equal "sig-two", packet.read_string
|
58
|
+
t.return(USERAUTH_FAILURE, :string, "hostbased,password")
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
assert !subject.authenticate("ssh-connection", "jamis")
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_authenticate_should_return_true_if_any_key_can_authenticate
|
68
|
+
key_manager.expects(:sign).with(&signature_parameters(keys.first)).returns("sig-one")
|
69
|
+
|
70
|
+
transport.expect do |t, packet|
|
71
|
+
assert_equal USERAUTH_REQUEST, packet.type
|
72
|
+
assert verify_userauth_request_packet(packet, keys.first, false)
|
73
|
+
t.return(USERAUTH_PK_OK, :string, keys.first.ssh_type, :string, Net::SSH::Buffer.from(:key, keys.first))
|
74
|
+
|
75
|
+
t.expect do |t,packet|
|
76
|
+
assert_equal USERAUTH_REQUEST, packet.type
|
77
|
+
assert verify_userauth_request_packet(packet, keys.first, true)
|
78
|
+
assert_equal "sig-one", packet.read_string
|
79
|
+
t.return(USERAUTH_SUCCESS)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
assert subject.authenticate("ssh-connection", "jamis")
|
84
|
+
end
|
85
|
+
|
86
|
+
private
|
87
|
+
|
88
|
+
def signature_parameters(key)
|
89
|
+
Proc.new do |given_key, data|
|
90
|
+
next false unless given_key.to_blob == key.to_blob
|
91
|
+
buffer = Net::SSH::Buffer.new(data)
|
92
|
+
buffer.read_string == "abcxyz123" && # session-id
|
93
|
+
buffer.read_byte == USERAUTH_REQUEST && # type
|
94
|
+
verify_userauth_request_packet(buffer, key, true)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def verify_userauth_request_packet(packet, key, has_sig)
|
99
|
+
packet.read_string == "jamis" && # user-name
|
100
|
+
packet.read_string == "ssh-connection" && # next service
|
101
|
+
packet.read_string == "publickey" && # auth-method
|
102
|
+
packet.read_bool == has_sig && # whether a signature is appended
|
103
|
+
packet.read_string == key.ssh_type && # ssh key type
|
104
|
+
packet.read_buffer.read_key.to_blob == key.to_blob # key
|
105
|
+
end
|
106
|
+
|
107
|
+
@@keys = nil
|
108
|
+
def keys
|
109
|
+
@@keys ||= [OpenSSL::PKey::RSA.new(32), OpenSSL::PKey::DSA.new(32)]
|
110
|
+
end
|
111
|
+
|
112
|
+
def key_manager(options={})
|
113
|
+
@key_manager ||= stub("key_manager", :identities => options[:keys] || keys)
|
114
|
+
end
|
115
|
+
|
116
|
+
def subject(options={})
|
117
|
+
options[:key_manager] = key_manager(options) unless options.key?(:key_manager)
|
118
|
+
@subject ||= Net::SSH::Authentication::Methods::Publickey.new(session(options), options)
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
122
|
+
|
123
|
+
end; end
|