1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 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 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298
|
require_relative '../common'
require 'net/ssh/authentication/session'
module Authentication
class TestSession < NetSSHTest
include Net::SSH::Transport::Constants
include Net::SSH::Authentication::Constants
def test_constructor_should_set_defaults
assert_equal %w[none publickey password keyboard-interactive], session.auth_methods
assert_equal session.auth_methods, session.allowed_auth_methods
end
def test_authenticate_should_continue_if_method_disallowed
transport.expect do |t, packet|
assert_equal SERVICE_REQUEST, packet.type
assert_equal "ssh-userauth", packet.read_string
t.return(SERVICE_ACCEPT)
end
Net::SSH::Authentication::Methods::Publickey.any_instance.expects(:authenticate).with("next service", "username", "password").raises(Net::SSH::Authentication::DisallowedMethod)
Net::SSH::Authentication::Methods::Password.any_instance.expects(:authenticate).with("next service", "username", "password").returns(true)
Net::SSH::Authentication::Methods::None.any_instance.expects(:authenticate).with("next service", "username", "password").returns(false)
assert session.authenticate("next service", "username", "password")
end
def test_authenticate_should_raise_error_if_service_request_fails
transport.expect do |t, packet|
assert_equal SERVICE_REQUEST, packet.type
assert_equal "ssh-userauth", packet.read_string
t.return(255)
end
assert_raises(Net::SSH::Exception) { session.authenticate("next service", "username", "password") }
end
def test_authenticate_should_return_false_if_all_auth_methods_fail
transport.expect do |t, packet|
assert_equal SERVICE_REQUEST, packet.type
assert_equal "ssh-userauth", packet.read_string
t.return(SERVICE_ACCEPT)
end
Net::SSH::Authentication::Methods::Publickey.any_instance.expects(:authenticate).with("next service", "username", "password").returns(false)
Net::SSH::Authentication::Methods::Password.any_instance.expects(:authenticate).with("next service", "username", "password").returns(false)
Net::SSH::Authentication::Methods::KeyboardInteractive.any_instance.expects(:authenticate).with("next service", "username", "password").returns(false)
Net::SSH::Authentication::Methods::None.any_instance.expects(:authenticate).with("next service", "username", "password").returns(false)
assert_equal false, session.authenticate("next service", "username", "password")
end
def test_next_message_should_silently_handle_USERAUTH_BANNER_packets
transport.return(USERAUTH_BANNER, :string, "Howdy, folks!")
transport.return(SERVICE_ACCEPT)
assert_equal SERVICE_ACCEPT, session.next_message.type
end
def test_next_message_should_understand_USERAUTH_FAILURE
transport.return(USERAUTH_FAILURE, :string, "a,b,c", :bool, false)
packet = session.next_message
assert_equal USERAUTH_FAILURE, packet.type
assert_equal %w[a b c], session.allowed_auth_methods
end
(60..79).each do |type|
define_method("test_next_message_should_return_packets_of_type_#{type}") do
transport.return(type)
assert_equal type, session.next_message.type
end
end
def test_next_message_should_understand_USERAUTH_SUCCESS
transport.return(USERAUTH_SUCCESS)
assert !transport.hints[:authenticated]
assert_equal USERAUTH_SUCCESS, session.next_message.type
assert transport.hints[:authenticated]
end
def test_next_message_should_raise_error_on_unrecognized_packet_types
transport.return(1)
assert_raises(Net::SSH::Exception) { session.next_message }
end
def test_expect_message_should_raise_exception_if_next_packet_is_not_expected_type
transport.return(SERVICE_ACCEPT)
assert_raises(Net::SSH::Exception) { session.expect_message(USERAUTH_BANNER) }
end
def test_expect_message_should_return_packet_if_next_packet_is_expected_type
transport.return(SERVICE_ACCEPT)
assert_equal SERVICE_ACCEPT, session.expect_message(SERVICE_ACCEPT).type
end
def test_uses_some_default_keys_if_none_are_provided
File.stubs(:file?).returns(false)
file_on_filesystem("~/.ssh/id_rsa", default_private_key)
transport.expect do |t, packet|
assert_equal SERVICE_REQUEST, packet.type
assert_equal "ssh-userauth", packet.read_string
t.return(SERVICE_ACCEPT)
end
transport.expect do |t, packet|
assert_none_request packet
t.return(USERAUTH_FAILURE, :string, "publickey")
end
transport.expect do |t, packet|
assert_public_key_request default_public_key, packet
t.return(USERAUTH_FAILURE, :string, "publickey")
end
session.authenticate("next service", "username")
end
def test_does_not_use_default_keys_if_keys_are_present_in_options
File.stubs(:file?).returns(false)
file_on_filesystem("~/.ssh/id_rsa", default_private_key)
file_on_filesystem("custom_rsa_id", custom_private_key)
transport.expect do |t, packet|
assert_equal SERVICE_REQUEST, packet.type
assert_equal "ssh-userauth", packet.read_string
t.return(SERVICE_ACCEPT)
end
transport.expect do |t, packet|
assert_none_request packet
t.return(USERAUTH_FAILURE, :string, "publickey")
end
transport.expect do |t, packet|
assert_public_key_request custom_public_key, packet
t.return(USERAUTH_FAILURE, :string, "publickey")
end
session(keys: "custom_rsa_id").authenticate("next service", "username")
end
def test_does_not_use_default_keys_if_key_data_are_present_in_options
File.stubs(:file?).returns(false)
file_on_filesystem("~/.ssh/id_rsa", default_private_key)
transport.expect do |t, packet|
assert_equal SERVICE_REQUEST, packet.type
assert_equal "ssh-userauth", packet.read_string
t.return(SERVICE_ACCEPT)
end
transport.expect do |t, packet|
assert_none_request packet
t.return(USERAUTH_FAILURE, :string, "publickey")
end
transport.expect do |t, packet|
assert_public_key_request custom_public_key, packet
t.return(USERAUTH_FAILURE, :string, "publickey")
end
session(key_data: custom_private_key).authenticate("next service", "username")
end
private
def session(options = {})
session_opts = options.clone
session_opts[:pubkey_algorithms] = %w[ssh-rsa]
@session ||= Net::SSH::Authentication::Session.new(transport(options), session_opts)
end
def transport(options={})
@transport ||= MockTransport.new(options)
end
def assert_none_request(packet)
assert_equal "username", packet.read_string
assert_equal "next service", packet.read_string
assert_equal "none", packet.read_string
end
def assert_public_key_request(public_key, packet)
assert_equal "username", packet.read_string
assert_equal "next service", packet.read_string
assert_equal "publickey", packet.read_string
assert_equal false, packet.read_bool
assert_equal "ssh-rsa", packet.read_string
key_in_packet = Net::SSH::Buffer.new(packet.read_string).read_key
assert_equal public_key, key_in_packet.to_pem
end
def file_on_filesystem(name, contents)
path = File.expand_path(name)
File.stubs(:read).with(path).returns(contents)
File.stubs(:file?).with(path).returns(true)
File.stubs(:readable?).with(path).returns(true)
end
def custom_private_key
<<~EOF
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC3id5gZ6bglJth
yli8JNaRxhsqKwwPlReEI/mplzz5IP6gWQ92LogXbdBXtHf9ZpA53BeLmtcNBEY0
Ygd7sPBhlHABS5D5///zltSSX2+L5GCEiC6dpfGsySjqymWF+SZ2PaqfZbkWLmCD
9u4ysueaHf7xbF6txGprNp69efttWxdy+vU5tno7HVxemMZQUalpShFrdAYKKXEo
cV7MtbkQjzubS14gaWGpWCXIl9uNKQeHpLKtre1Qn5Ft/zVpCHmhLQcYDuB1LAj9
7eoev4rIiOE2sfdkvKDlmFxvzq3myYH4o27WwAg9OZ5SBusn2zesKkRCBBEZ55rl
uVknOGHXAgMBAAECggEAZE0U2OxsNxkfXS6+lXswQ5PW7pF90towcsdSPgrniGIu
pKRnHbfKKbuaewOl+zZcpTIRL/rbgUKPtzrHSiJlC36aQyrvvJ/ZWV5ZJvC+vd19
nY/qob65NyrrkHwxRSjmiwGiR9/IaUXI+vUsMUqx5Ph1hawqhZ3sZlEAKR4LeDO8
M+OguG77jLaqj5/SNfi+GwyUDe85de4VfEG4S9HrMQk2Cp66rx0BqDnCLacyFQaI
R0VczMXTU52q0uETmgUr8G9A1SaRc5ZWKAfZwxJTvqdIImWC9E+CY7wm+mZD4FE6
iVzVC0ngcdEd596kTDdU2BPVMluWzLkfqIrTt/5CeQKBgQDzgRzCPNxFtai6RAIi
ekBSHqrDnrbeTaw32GVq5ACk1Zfk2I0svctz1iQ9qJ2SRINpygQhcyJKQ4r/LXi1
7Av9H/d6QV4T2AZzS4WcqBkxxRXFUfARtnKChzuCzNt9tNz4EZiv75RyQmztGZjV
i94+ZvCyqup5be4Svf4MBxin9QKBgQDA9P4nHzFWZakTMei78LGb/4Auc+r0rZp7
8xg8Z92tvrDeJjMdesdhiFrPP1qiSYHnQ81MSWpn6BycBsHZqitejQmYnYput/s4
qG+m7SrkN8WL6rijYsbB+U14VDjMlBlOgcEgjlSNU2oeS+68u+uVI/fgyXcXn4Jq
33TSWSgfGwKBgA2tRdE/G9wqfOShZ0FKfoxePpcoNfs8f5zPYbrkPYkEmjh3VU6b
Bm9mKrjv3JHXmU3608qRLe7f5lG42xvUu0OnZP4P59nTe2FEb6fB5VBfUn63wHUu
OzZLpDMPkJB59SNV0a6oFT1pr7aNhoEQDxaQL5rJcMwLOaEB3OAOEft1AoGASz7+
4Zi7b7rDPVYIMUpCqNfxT6wqovIUPWPmPqAuhXPIm0kAQ+2+VN2MtCc7m+/Ydawu
IiK7GPweNAY6kDxZH00WweolstmSYVzl9Y2lXUwWgGKvUB/T7I7g1Bzb7YOPftsA
ykZW2Kn/xwLLfdQ2oXleT82g4Jh2jmDHuMPF7qMCgYEA6QF45PvOgnrJessgmwO/
dEmkLl07PQYJPGZLaZteuWrvfMrn+AiW5aAdHzhzNaOtNy5B3T7zGUHtgxXegqgd
/QdCVCJgnZUO/zdAxkr22dDn+WEXkL4wgBVStQvvnQp9C2NJcoOExvex5PLzKWQg
WEKt5v3QsUEgVrzkM4K9UbI=
-----END PRIVATE KEY-----
EOF
end
def custom_public_key
<<~EOF
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt4neYGem4JSbYcpYvCTW
kcYbKisMD5UXhCP5qZc8+SD+oFkPdi6IF23QV7R3/WaQOdwXi5rXDQRGNGIHe7Dw
YZRwAUuQ+f//85bUkl9vi+RghIgunaXxrMko6splhfkmdj2qn2W5Fi5gg/buMrLn
mh3+8WxercRqazaevXn7bVsXcvr1ObZ6Ox1cXpjGUFGpaUoRa3QGCilxKHFezLW5
EI87m0teIGlhqVglyJfbjSkHh6Syra3tUJ+Rbf81aQh5oS0HGA7gdSwI/e3qHr+K
yIjhNrH3ZLyg5Zhcb86t5smB+KNu1sAIPTmeUgbrJ9s3rCpEQgQRGeea5blZJzhh
1wIDAQAB
-----END PUBLIC KEY-----
EOF
end
def default_private_key
<<~EOF
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAxbz0rp+Z7MklMtSkfiRfceOeTOhOgkGqonCL1B0MRzSjA3yf
onvEobQNYv7uyQ+ZMGT9RL7AlUSUxeWF00A/O6kuwfs4JlPS/FMPy/B2V0UmoteT
p40LmclZHpKZs9yKmgkfa5j8Jjvd/VvV1r/DbkHjZetIe07pSnP3EOAG7sjyV7yr
HPvkgG5h/Vn2U19vTsvYIENcj5OCLF7eUSJZ/6m4qem+wZ4/9cau5E2t57oS8bTd
5k00Jn0E+qRVionLVLtHXKnr0nWlGPinL+UhKBMhLA6Olm5Y8W77sYcUSvlJMy4G
mpIvnWFKQE5vim4zKt3dBF256QPmRCWPTQ+sxwIDAQABAoIBAQCG+vrILVjEo3ZK
IY/8L9Ybh3arJzVYg3z4j/1TmVSlUtAodC0AnJ5Yh/FPb5kPFR/MQlQFVnVeL8ei
45Ab6dKAZnftoRDuUPBIoGa7H3WZEzJRnPlFOen+W80DKq3TcqwGhE23hGIzs1BR
QBxUEOlWXZHeI+OBkRd9ZHX2RgdVfhGK1eCRGkxVUx6lygK7RcLSDJgPGvTUL+Gz
xF4D03pDo2r6oghNk3Fbw4GMXMBLfrKfiee/QyBLEkq+nykVioxXO16ShJfxOzM4
Pt6/7XJW7uMBGSblS89svrsn7i+29wcgkX4rGWyswV6xicpLNBEmkYx119QKLGBk
a1QebsYxAoGBAOJL/KEGyO8z9l+b2xzWlAURCNJEqPgeAk6ck7woA+nnj2KH+/51
1vvbQlvdwN1eP753g3eACvro7XQmVpJzqwBqAGyxtgPoI4F+HR++3lIOA+zfZs3p
1R1/4AEN0E16sV54gVmvkoSm9UCUDM4RXDdC/YgjpVyXla7HFp2KSrTvAoGBAN+x
VzK/7hCFod5KZXq/Nfy4/Wg/1GTwzg8eQCUbRJ3jqk0UWvNnhwWTEHfa8ywDSJFi
bNMlTKtdlGKPHB9dGMt9izGoyeybz0RJz8aCLODN9PBr1GSAhWfqFNYgksScEOy9
c7eEn25Q91tanmni38Y0KZU9iOYAcKJR5Xulw3WpAoGAO/3lBVNlJXTjFcmdtvFz
4Dv52LR3Dv/1oJ2F1NXO482Nh5OBTJ401iP0XaJWJNl9kKLiaWW6g3YIrUgUn1Km
vL9dSXN7S2HZN9UVJ3tUOPCaPcuj12bsJpvl6KGe3UtvhhnwQLR45U3Vqr8U/fRA
PC44REUe64MMHX+OEUm+MGUCgYB/4UgyURruAxdIl0twYsOgWLk10dfAZRHH/sk4
7V/Ky45eRlbAc9zyyOJPQrJl5PKlepkwFFDCXtsnhRzUqUo1eu4KU64sP9678V6A
44Z4dgWjNGHVmsupXl7PEwwUrgvW62+t6HmkfVELvsB1VCgNjWCAWw9aPcImaZ9B
ksAtEQKBgQCs2ZwTMQOX0IyBMRxVDD8JLCYMNZPBisGTjtYQv6F1ITZOzAPwJjI8
3FzbcqCWtmbCe6rCd9p9NDU42cuizlSZfO+2emM5CnKdvb0IeHqODfBZm2vYYJ6p
Euy/YLiXxrwHUo1KecuH04+/s6OxEzMnrYxXqvcK9SwcNTwAkDaBUw==
-----END RSA PRIVATE KEY-----
EOF
end
def default_public_key
<<~EOF
-----BEGIN PUBLIC KEY-----
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxbz0rp+Z7MklMtSkfiRf
ceOeTOhOgkGqonCL1B0MRzSjA3yfonvEobQNYv7uyQ+ZMGT9RL7AlUSUxeWF00A/
O6kuwfs4JlPS/FMPy/B2V0UmoteTp40LmclZHpKZs9yKmgkfa5j8Jjvd/VvV1r/D
bkHjZetIe07pSnP3EOAG7sjyV7yrHPvkgG5h/Vn2U19vTsvYIENcj5OCLF7eUSJZ
/6m4qem+wZ4/9cau5E2t57oS8bTd5k00Jn0E+qRVionLVLtHXKnr0nWlGPinL+Uh
KBMhLA6Olm5Y8W77sYcUSvlJMy4GmpIvnWFKQE5vim4zKt3dBF256QPmRCWPTQ+s
xwIDAQAB
-----END PUBLIC KEY-----
EOF
end
end
end
|