hrr_rb_ssh 0.3.0.pre1 → 0.4.2
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.
- checksums.yaml +4 -4
- data/.gitignore +0 -3
- data/.travis.yml +1 -0
- data/README.md +208 -46
- data/demo/client.rb +71 -0
- data/demo/echo_server.rb +8 -3
- data/demo/more_flexible_auth.rb +105 -0
- data/demo/multi_step_auth.rb +99 -0
- data/demo/server.rb +10 -4
- data/demo/subsystem_echo_server.rb +8 -3
- data/hrr_rb_ssh.gemspec +6 -6
- data/lib/hrr_rb_ssh.rb +1 -1
- data/lib/hrr_rb_ssh/algorithm/publickey.rb +0 -1
- data/lib/hrr_rb_ssh/algorithm/publickey/ecdsa_sha2.rb +12 -9
- data/lib/hrr_rb_ssh/algorithm/publickey/ecdsa_sha2/ecdsa_signature_blob.rb +2 -4
- data/lib/hrr_rb_ssh/algorithm/publickey/ecdsa_sha2/public_key_blob.rb +2 -4
- data/lib/hrr_rb_ssh/algorithm/publickey/ecdsa_sha2/signature.rb +2 -4
- data/lib/hrr_rb_ssh/algorithm/publickey/ssh_dss.rb +10 -7
- data/lib/hrr_rb_ssh/algorithm/publickey/ssh_dss/public_key_blob.rb +2 -4
- data/lib/hrr_rb_ssh/algorithm/publickey/ssh_dss/signature.rb +2 -4
- data/lib/hrr_rb_ssh/algorithm/publickey/ssh_rsa.rb +9 -6
- data/lib/hrr_rb_ssh/algorithm/publickey/ssh_rsa/public_key_blob.rb +2 -4
- data/lib/hrr_rb_ssh/algorithm/publickey/ssh_rsa/signature.rb +2 -4
- data/lib/hrr_rb_ssh/authentication.rb +103 -22
- data/lib/hrr_rb_ssh/authentication/constant.rb +14 -0
- data/lib/hrr_rb_ssh/authentication/method/keyboard_interactive.rb +44 -7
- data/lib/hrr_rb_ssh/authentication/method/keyboard_interactive/context.rb +16 -9
- data/lib/hrr_rb_ssh/authentication/method/keyboard_interactive/info_request.rb +7 -6
- data/lib/hrr_rb_ssh/authentication/method/keyboard_interactive/info_response.rb +5 -2
- data/lib/hrr_rb_ssh/authentication/method/none.rb +23 -7
- data/lib/hrr_rb_ssh/authentication/method/none/context.rb +15 -7
- data/lib/hrr_rb_ssh/authentication/method/password.rb +28 -7
- data/lib/hrr_rb_ssh/authentication/method/password/context.rb +16 -7
- data/lib/hrr_rb_ssh/authentication/method/publickey.rb +63 -10
- data/lib/hrr_rb_ssh/authentication/method/publickey/algorithm.rb +0 -1
- data/lib/hrr_rb_ssh/authentication/method/publickey/algorithm/functionable.rb +32 -8
- data/lib/hrr_rb_ssh/authentication/method/publickey/algorithm/signature_blob.rb +2 -4
- data/lib/hrr_rb_ssh/authentication/method/publickey/context.rb +11 -2
- data/lib/hrr_rb_ssh/client.rb +234 -0
- data/lib/hrr_rb_ssh/codable.rb +15 -13
- data/lib/hrr_rb_ssh/compat/ruby.rb +0 -1
- data/lib/hrr_rb_ssh/connection.rb +145 -75
- data/lib/hrr_rb_ssh/connection/channel.rb +342 -109
- data/lib/hrr_rb_ssh/connection/channel/channel_type/direct_tcpip.rb +24 -19
- data/lib/hrr_rb_ssh/connection/channel/channel_type/forwarded_tcpip.rb +24 -19
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session.rb +19 -12
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/proc_chain.rb +0 -2
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/proc_chain/chain_context.rb +0 -3
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/env.rb +2 -5
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/env/context.rb +5 -4
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/exec.rb +2 -5
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/exec/context.rb +5 -4
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/pty_req.rb +2 -5
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/pty_req/context.rb +5 -4
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/shell.rb +2 -5
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/shell/context.rb +5 -4
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/subsystem.rb +2 -5
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/subsystem/context.rb +5 -4
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/window_change.rb +2 -5
- data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/window_change/context.rb +5 -4
- data/lib/hrr_rb_ssh/connection/global_request_handler.rb +14 -12
- data/lib/hrr_rb_ssh/connection/request_handler.rb +1 -3
- data/lib/hrr_rb_ssh/connection/request_handler/reference_env_request_handler.rb +0 -2
- data/lib/hrr_rb_ssh/connection/request_handler/reference_exec_request_handler.rb +4 -6
- data/lib/hrr_rb_ssh/connection/request_handler/reference_pty_req_request_handler.rb +10 -12
- data/lib/hrr_rb_ssh/connection/request_handler/reference_shell_request_handler.rb +4 -6
- data/lib/hrr_rb_ssh/connection/request_handler/reference_window_change_request_handler.rb +0 -2
- data/lib/hrr_rb_ssh/error/closed_authentication.rb +1 -1
- data/lib/hrr_rb_ssh/error/closed_connection.rb +1 -1
- data/lib/hrr_rb_ssh/error/closed_transport.rb +1 -1
- data/lib/hrr_rb_ssh/loggable.rb +42 -0
- data/lib/hrr_rb_ssh/message/001_ssh_msg_disconnect.rb +2 -4
- data/lib/hrr_rb_ssh/message/002_ssh_msg_ignore.rb +2 -4
- data/lib/hrr_rb_ssh/message/003_ssh_msg_unimplemented.rb +2 -4
- data/lib/hrr_rb_ssh/message/004_ssh_msg_debug.rb +2 -4
- data/lib/hrr_rb_ssh/message/005_ssh_msg_service_request.rb +2 -4
- data/lib/hrr_rb_ssh/message/006_ssh_msg_service_accept.rb +2 -4
- data/lib/hrr_rb_ssh/message/020_ssh_msg_kexinit.rb +2 -4
- data/lib/hrr_rb_ssh/message/021_ssh_msg_newkeys.rb +2 -4
- data/lib/hrr_rb_ssh/message/030_ssh_msg_kex_dh_gex_request_old.rb +2 -4
- data/lib/hrr_rb_ssh/message/030_ssh_msg_kexdh_init.rb +2 -4
- data/lib/hrr_rb_ssh/message/030_ssh_msg_kexecdh_init.rb +2 -4
- data/lib/hrr_rb_ssh/message/031_ssh_msg_kex_dh_gex_group.rb +2 -4
- data/lib/hrr_rb_ssh/message/031_ssh_msg_kexdh_reply.rb +2 -4
- data/lib/hrr_rb_ssh/message/031_ssh_msg_kexecdh_reply.rb +2 -4
- data/lib/hrr_rb_ssh/message/032_ssh_msg_kex_dh_gex_init.rb +2 -4
- data/lib/hrr_rb_ssh/message/033_ssh_msg_kex_dh_gex_reply.rb +2 -4
- data/lib/hrr_rb_ssh/message/034_ssh_msg_kex_dh_gex_request.rb +2 -4
- data/lib/hrr_rb_ssh/message/050_ssh_msg_userauth_request.rb +2 -4
- data/lib/hrr_rb_ssh/message/051_ssh_msg_userauth_failure.rb +2 -4
- data/lib/hrr_rb_ssh/message/052_ssh_msg_userauth_success.rb +2 -4
- data/lib/hrr_rb_ssh/message/060_ssh_msg_userauth_info_request.rb +2 -4
- data/lib/hrr_rb_ssh/message/060_ssh_msg_userauth_pk_ok.rb +2 -4
- data/lib/hrr_rb_ssh/message/061_ssh_msg_userauth_info_response.rb +2 -4
- data/lib/hrr_rb_ssh/message/080_ssh_msg_global_request.rb +2 -4
- data/lib/hrr_rb_ssh/message/081_ssh_msg_request_success.rb +2 -4
- data/lib/hrr_rb_ssh/message/082_ssh_msg_request_failure.rb +2 -4
- data/lib/hrr_rb_ssh/message/090_ssh_msg_channel_open.rb +2 -4
- data/lib/hrr_rb_ssh/message/091_ssh_msg_channel_open_confirmation.rb +2 -4
- data/lib/hrr_rb_ssh/message/092_ssh_msg_channel_open_failure.rb +2 -4
- data/lib/hrr_rb_ssh/message/093_ssh_msg_channel_window_adjust.rb +2 -4
- data/lib/hrr_rb_ssh/message/094_ssh_msg_channel_data.rb +2 -4
- data/lib/hrr_rb_ssh/message/095_ssh_msg_channel_extended_data.rb +2 -4
- data/lib/hrr_rb_ssh/message/096_ssh_msg_channel_eof.rb +2 -4
- data/lib/hrr_rb_ssh/message/097_ssh_msg_channel_close.rb +2 -4
- data/lib/hrr_rb_ssh/message/098_ssh_msg_channel_request.rb +3 -5
- data/lib/hrr_rb_ssh/message/099_ssh_msg_channel_success.rb +2 -4
- data/lib/hrr_rb_ssh/message/100_ssh_msg_channel_failure.rb +2 -4
- data/lib/hrr_rb_ssh/server.rb +16 -10
- data/lib/hrr_rb_ssh/transport.rb +113 -77
- data/lib/hrr_rb_ssh/transport/compression_algorithm/functionable.rb +5 -3
- data/lib/hrr_rb_ssh/transport/compression_algorithm/unfunctionable.rb +5 -3
- data/lib/hrr_rb_ssh/transport/encryption_algorithm/functionable.rb +5 -3
- data/lib/hrr_rb_ssh/transport/encryption_algorithm/unfunctionable.rb +5 -3
- data/lib/hrr_rb_ssh/transport/kex_algorithm/diffie_hellman.rb +43 -37
- data/lib/hrr_rb_ssh/transport/kex_algorithm/diffie_hellman/h0.rb +2 -4
- data/lib/hrr_rb_ssh/transport/kex_algorithm/diffie_hellman_group_exchange.rb +87 -52
- data/lib/hrr_rb_ssh/transport/kex_algorithm/diffie_hellman_group_exchange/h0.rb +2 -4
- data/lib/hrr_rb_ssh/transport/kex_algorithm/elliptic_curve_diffie_hellman.rb +43 -37
- data/lib/hrr_rb_ssh/transport/kex_algorithm/elliptic_curve_diffie_hellman/h0.rb +2 -4
- data/lib/hrr_rb_ssh/transport/mac_algorithm/functionable.rb +5 -3
- data/lib/hrr_rb_ssh/transport/mac_algorithm/unfunctionable.rb +5 -3
- data/lib/hrr_rb_ssh/transport/receiver.rb +8 -7
- data/lib/hrr_rb_ssh/transport/sender.rb +5 -3
- data/lib/hrr_rb_ssh/transport/sequence_number.rb +0 -4
- data/lib/hrr_rb_ssh/transport/server_host_key_algorithm.rb +0 -1
- data/lib/hrr_rb_ssh/transport/server_host_key_algorithm/functionable.rb +5 -3
- data/lib/hrr_rb_ssh/version.rb +1 -1
- metadata +18 -51
- data/lib/hrr_rb_ssh/algorithm/publickey/ssh_ed25519.rb +0 -61
- data/lib/hrr_rb_ssh/algorithm/publickey/ssh_ed25519/openssh_private_key.rb +0 -29
- data/lib/hrr_rb_ssh/algorithm/publickey/ssh_ed25519/openssh_private_key_content.rb +0 -26
- data/lib/hrr_rb_ssh/algorithm/publickey/ssh_ed25519/pkey.rb +0 -158
- data/lib/hrr_rb_ssh/algorithm/publickey/ssh_ed25519/public_key_blob.rb +0 -23
- data/lib/hrr_rb_ssh/algorithm/publickey/ssh_ed25519/signature.rb +0 -23
- data/lib/hrr_rb_ssh/authentication/method/publickey/algorithm/ssh_ed25519.rb +0 -21
- data/lib/hrr_rb_ssh/compat/ruby/array.rb +0 -14
- data/lib/hrr_rb_ssh/logger.rb +0 -56
- data/lib/hrr_rb_ssh/transport/server_host_key_algorithm/ssh_ed25519.rb +0 -20
@@ -1,7 +1,7 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
# vim: et ts=2 sw=2
|
3
3
|
|
4
|
-
require 'hrr_rb_ssh/
|
4
|
+
require 'hrr_rb_ssh/loggable'
|
5
5
|
require 'hrr_rb_ssh/authentication/method/keyboard_interactive/info_request'
|
6
6
|
require 'hrr_rb_ssh/authentication/method/keyboard_interactive/info_response'
|
7
7
|
|
@@ -10,24 +10,31 @@ module HrrRbSsh
|
|
10
10
|
class Method
|
11
11
|
class KeyboardInteractive
|
12
12
|
class Context
|
13
|
+
include Loggable
|
14
|
+
|
13
15
|
attr_reader \
|
14
16
|
:username,
|
15
17
|
:submethods,
|
16
|
-
:info_response
|
18
|
+
:info_response,
|
19
|
+
:variables,
|
20
|
+
:vars,
|
21
|
+
:authentication_methods
|
17
22
|
|
18
|
-
def initialize transport, username, submethods
|
23
|
+
def initialize transport, username, submethods, variables, authentication_methods, logger: nil
|
24
|
+
self.logger = logger
|
19
25
|
@transport = transport
|
20
26
|
@username = username
|
21
27
|
@submethods = submethods
|
22
|
-
|
23
|
-
@
|
28
|
+
@variables = variables
|
29
|
+
@vars = variables
|
30
|
+
@authentication_methods = authentication_methods
|
24
31
|
end
|
25
32
|
|
26
33
|
def info_request name, instruction, language_tag, prompts
|
27
|
-
|
28
|
-
@transport.send InfoRequest.new(name, instruction, language_tag, prompts).to_payload
|
29
|
-
|
30
|
-
@info_response = InfoResponse.new @transport.receive
|
34
|
+
log_info { "send userauth info request" }
|
35
|
+
@transport.send InfoRequest.new(name, instruction, language_tag, prompts, logger: logger).to_payload
|
36
|
+
log_info { "receive userauth info response" }
|
37
|
+
@info_response = InfoResponse.new @transport.receive, logger: logger
|
31
38
|
end
|
32
39
|
end
|
33
40
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
# vim: et ts=2 sw=2
|
3
3
|
|
4
|
-
require 'hrr_rb_ssh/
|
4
|
+
require 'hrr_rb_ssh/loggable'
|
5
5
|
require 'hrr_rb_ssh/message'
|
6
6
|
|
7
7
|
module HrrRbSsh
|
@@ -9,13 +9,14 @@ module HrrRbSsh
|
|
9
9
|
class Method
|
10
10
|
class KeyboardInteractive
|
11
11
|
class InfoRequest
|
12
|
-
|
12
|
+
include Loggable
|
13
|
+
|
14
|
+
def initialize name, instruction, language_tag, prompts, logger: nil
|
15
|
+
self.logger = logger
|
13
16
|
@name = name
|
14
17
|
@instruction = instruction
|
15
18
|
@language_tag = language_tag
|
16
19
|
@prompts = prompts
|
17
|
-
|
18
|
-
@logger = Logger.new self.class.name
|
19
20
|
end
|
20
21
|
|
21
22
|
def to_message
|
@@ -30,13 +31,13 @@ module HrrRbSsh
|
|
30
31
|
[
|
31
32
|
[:"prompt[#{i+1}]", prompt],
|
32
33
|
[:"echo[#{i+1}]", echo],
|
33
|
-
].
|
34
|
+
].inject(Hash.new){ |h, (k, v)| h.update({k => v}) }
|
34
35
|
}.inject(Hash.new){ |a, b| a.merge(b) }
|
35
36
|
message.merge(message_prompts)
|
36
37
|
end
|
37
38
|
|
38
39
|
def to_payload
|
39
|
-
Message::SSH_MSG_USERAUTH_INFO_REQUEST.encode self.to_message
|
40
|
+
Message::SSH_MSG_USERAUTH_INFO_REQUEST.new(logger: logger).encode self.to_message
|
40
41
|
end
|
41
42
|
end
|
42
43
|
end
|
@@ -8,14 +8,17 @@ module HrrRbSsh
|
|
8
8
|
class Method
|
9
9
|
class KeyboardInteractive
|
10
10
|
class InfoResponse
|
11
|
+
include Loggable
|
12
|
+
|
11
13
|
attr_reader \
|
12
14
|
:num_responses,
|
13
15
|
:responses
|
14
16
|
|
15
|
-
def initialize payload
|
17
|
+
def initialize payload, logger: nil
|
18
|
+
self.logger = logger
|
16
19
|
case payload[0,1].unpack("C")[0]
|
17
20
|
when Message::SSH_MSG_USERAUTH_INFO_RESPONSE::VALUE
|
18
|
-
message = Message::SSH_MSG_USERAUTH_INFO_RESPONSE.decode payload
|
21
|
+
message = Message::SSH_MSG_USERAUTH_INFO_RESPONSE.new(logger: logger).decode payload
|
19
22
|
@num_responses = message[:'num-responses']
|
20
23
|
@responses = Array.new(message[:'num-responses']){ |i| message[:"response[#{i+1}]"] }
|
21
24
|
else
|
@@ -1,26 +1,42 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
# vim: et ts=2 sw=2
|
3
3
|
|
4
|
-
require 'hrr_rb_ssh/
|
4
|
+
require 'hrr_rb_ssh/loggable'
|
5
5
|
|
6
6
|
module HrrRbSsh
|
7
7
|
class Authentication
|
8
8
|
class Method
|
9
9
|
class None < Method
|
10
|
+
include Loggable
|
11
|
+
|
10
12
|
NAME = 'none'
|
11
13
|
PREFERENCE = 0
|
12
14
|
|
13
|
-
def initialize transport, options
|
14
|
-
|
15
|
-
@
|
15
|
+
def initialize transport, options, variables, authentication_methods, logger: nil
|
16
|
+
self.logger = logger
|
17
|
+
@transport = transport
|
18
|
+
@authenticator = options.fetch( 'authentication_none_authenticator', Authenticator.new{ false } )
|
19
|
+
@variables = variables
|
20
|
+
@authentication_methods = authentication_methods
|
16
21
|
end
|
17
22
|
|
18
23
|
def authenticate userauth_request_message
|
19
|
-
|
20
|
-
|
21
|
-
context = Context.new(userauth_request_message[:'user name'])
|
24
|
+
log_info { "authenticate" }
|
25
|
+
context = Context.new(userauth_request_message[:'user name'], @variables, @authentication_methods, logger: logger)
|
22
26
|
@authenticator.authenticate context
|
23
27
|
end
|
28
|
+
|
29
|
+
def request_authentication username, service_name
|
30
|
+
message = {
|
31
|
+
:'message number' => Message::SSH_MSG_USERAUTH_REQUEST::VALUE,
|
32
|
+
:"user name" => username,
|
33
|
+
:"service name" => service_name,
|
34
|
+
:"method name" => NAME,
|
35
|
+
}
|
36
|
+
payload = Message::SSH_MSG_USERAUTH_REQUEST.new(logger: logger).encode message
|
37
|
+
@transport.send payload
|
38
|
+
payload = @transport.receive
|
39
|
+
end
|
24
40
|
end
|
25
41
|
end
|
26
42
|
end
|
@@ -1,24 +1,32 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
# vim: et ts=2 sw=2
|
3
3
|
|
4
|
-
require 'hrr_rb_ssh/
|
4
|
+
require 'hrr_rb_ssh/loggable'
|
5
5
|
|
6
6
|
module HrrRbSsh
|
7
7
|
class Authentication
|
8
8
|
class Method
|
9
9
|
class None
|
10
10
|
class Context
|
11
|
-
|
11
|
+
include Loggable
|
12
12
|
|
13
|
-
|
14
|
-
|
13
|
+
attr_reader \
|
14
|
+
:username,
|
15
|
+
:variables,
|
16
|
+
:vars,
|
17
|
+
:authentication_methods
|
15
18
|
|
16
|
-
|
19
|
+
def initialize username, variables, authentication_methods, logger: nil
|
20
|
+
self.logger = logger
|
21
|
+
@username = username
|
22
|
+
@variables = variables
|
23
|
+
@vars = variables
|
24
|
+
@authentication_methods = authentication_methods
|
17
25
|
end
|
18
26
|
|
19
27
|
def verify username
|
20
|
-
|
21
|
-
|
28
|
+
log_info { "verify username" }
|
29
|
+
log_debug { "username is #{username}, @username is #{@username}" }
|
22
30
|
username == @username
|
23
31
|
end
|
24
32
|
end
|
@@ -1,28 +1,49 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
# vim: et ts=2 sw=2
|
3
3
|
|
4
|
-
require 'hrr_rb_ssh/
|
4
|
+
require 'hrr_rb_ssh/loggable'
|
5
5
|
|
6
6
|
module HrrRbSsh
|
7
7
|
class Authentication
|
8
8
|
class Method
|
9
9
|
class Password < Method
|
10
|
+
include Loggable
|
11
|
+
|
10
12
|
NAME = 'password'
|
11
13
|
PREFERENCE = 10
|
12
14
|
|
13
|
-
def initialize transport, options
|
14
|
-
|
15
|
-
@
|
15
|
+
def initialize transport, options, variables, authentication_methods, logger: nil
|
16
|
+
self.logger = logger
|
17
|
+
@transport = transport
|
18
|
+
@authenticator = options.fetch( 'authentication_password_authenticator', Authenticator.new{ false } )
|
19
|
+
@options = options
|
20
|
+
@variables = variables
|
21
|
+
@authentication_methods = authentication_methods
|
16
22
|
end
|
17
23
|
|
18
24
|
def authenticate userauth_request_message
|
19
|
-
|
20
|
-
@logger.debug { "userauth request: " + userauth_request_message.inspect }
|
25
|
+
log_info { "authenticate" }
|
21
26
|
username = userauth_request_message[:'user name']
|
22
27
|
password = userauth_request_message[:'plaintext password']
|
23
|
-
context = Context.new(username, password)
|
28
|
+
context = Context.new(username, password, @variables, @authentication_methods, logger: logger)
|
24
29
|
@authenticator.authenticate context
|
25
30
|
end
|
31
|
+
|
32
|
+
def request_authentication username, service_name
|
33
|
+
password = @options['client_authentication_password']
|
34
|
+
message = {
|
35
|
+
:'message number' => Message::SSH_MSG_USERAUTH_REQUEST::VALUE,
|
36
|
+
:"user name" => username,
|
37
|
+
:"service name" => service_name,
|
38
|
+
:"method name" => NAME,
|
39
|
+
:"FALSE" => false,
|
40
|
+
:"plaintext password" => password,
|
41
|
+
}
|
42
|
+
payload = Message::SSH_MSG_USERAUTH_REQUEST.new(logger: logger).encode message
|
43
|
+
@transport.send payload
|
44
|
+
|
45
|
+
payload = @transport.receive
|
46
|
+
end
|
26
47
|
end
|
27
48
|
end
|
28
49
|
end
|
@@ -1,25 +1,34 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
# vim: et ts=2 sw=2
|
3
3
|
|
4
|
-
require 'hrr_rb_ssh/
|
4
|
+
require 'hrr_rb_ssh/loggable'
|
5
5
|
|
6
6
|
module HrrRbSsh
|
7
7
|
class Authentication
|
8
8
|
class Method
|
9
9
|
class Password
|
10
10
|
class Context
|
11
|
-
|
11
|
+
include Loggable
|
12
12
|
|
13
|
-
|
13
|
+
attr_reader \
|
14
|
+
:username,
|
15
|
+
:password,
|
16
|
+
:variables,
|
17
|
+
:vars,
|
18
|
+
:authentication_methods
|
19
|
+
|
20
|
+
def initialize username, password, variables, authentication_methods, logger: nil
|
21
|
+
self.logger = logger
|
14
22
|
@username = username
|
15
23
|
@password = password
|
16
|
-
|
17
|
-
@
|
24
|
+
@variables = variables
|
25
|
+
@vars = variables
|
26
|
+
@authentication_methods = authentication_methods
|
18
27
|
end
|
19
28
|
|
20
29
|
def verify username, password
|
21
|
-
|
22
|
-
|
30
|
+
log_info { "verify username and password" }
|
31
|
+
log_debug { "username is #{username}, @username is #{@username}, and password is #{password}, @password is #{@password}" }
|
23
32
|
username == @username and password == @password
|
24
33
|
end
|
25
34
|
end
|
@@ -1,36 +1,42 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
# vim: et ts=2 sw=2
|
3
3
|
|
4
|
-
require 'hrr_rb_ssh/
|
4
|
+
require 'hrr_rb_ssh/loggable'
|
5
5
|
|
6
6
|
module HrrRbSsh
|
7
7
|
class Authentication
|
8
8
|
class Method
|
9
9
|
class Publickey < Method
|
10
|
+
include Loggable
|
11
|
+
|
10
12
|
NAME = 'publickey'
|
11
13
|
PREFERENCE = 20
|
12
14
|
|
13
|
-
def initialize transport, options
|
14
|
-
|
15
|
+
def initialize transport, options, variables, authentication_methods, logger: nil
|
16
|
+
self.logger = logger
|
17
|
+
@transport = transport
|
18
|
+
@options = options
|
15
19
|
@session_id = options['session id']
|
16
|
-
@authenticator = options.fetch( 'authentication_publickey_authenticator', Authenticator.new
|
20
|
+
@authenticator = options.fetch( 'authentication_publickey_authenticator', Authenticator.new{ false } )
|
21
|
+
@variables = variables
|
22
|
+
@authentication_methods = authentication_methods
|
17
23
|
end
|
18
24
|
|
19
25
|
def authenticate userauth_request_message
|
20
26
|
public_key_algorithm_name = userauth_request_message[:'public key algorithm name']
|
21
27
|
unless Algorithm.list_preferred.include?(public_key_algorithm_name)
|
22
|
-
|
28
|
+
log_info { "unsupported public key algorithm: #{public_key_algorithm_name}" }
|
23
29
|
return false
|
24
30
|
end
|
25
31
|
unless userauth_request_message[:'with signature']
|
26
|
-
|
32
|
+
log_info { "public key algorithm is ok, require signature" }
|
27
33
|
public_key_blob = userauth_request_message[:'public key blob']
|
28
34
|
userauth_pk_ok_message public_key_algorithm_name, public_key_blob
|
29
35
|
else
|
30
|
-
|
36
|
+
log_info { "verify signature" }
|
31
37
|
username = userauth_request_message[:'user name']
|
32
|
-
algorithm = Algorithm[public_key_algorithm_name].new
|
33
|
-
context = Context.new(username, algorithm, @session_id, userauth_request_message)
|
38
|
+
algorithm = Algorithm[public_key_algorithm_name].new logger: logger
|
39
|
+
context = Context.new(username, algorithm, @session_id, userauth_request_message, @variables, @authentication_methods, logger: logger)
|
34
40
|
@authenticator.authenticate context
|
35
41
|
end
|
36
42
|
end
|
@@ -41,7 +47,54 @@ module HrrRbSsh
|
|
41
47
|
:'public key algorithm name from the request' => public_key_algorithm_name,
|
42
48
|
:'public key blob from the request' => public_key_blob,
|
43
49
|
}
|
44
|
-
payload = Message::SSH_MSG_USERAUTH_PK_OK.encode message
|
50
|
+
payload = Message::SSH_MSG_USERAUTH_PK_OK.new(logger: logger).encode message
|
51
|
+
end
|
52
|
+
|
53
|
+
def request_authentication username, service_name
|
54
|
+
public_key_algorithm_name, secret_key = @options['client_authentication_publickey']
|
55
|
+
send_request_without_signature username, service_name, public_key_algorithm_name, secret_key
|
56
|
+
payload = @transport.receive
|
57
|
+
case payload[0,1].unpack("C")[0]
|
58
|
+
when Message::SSH_MSG_USERAUTH_PK_OK::VALUE
|
59
|
+
send_request_with_signature username, service_name, public_key_algorithm_name, secret_key
|
60
|
+
@transport.receive
|
61
|
+
else
|
62
|
+
payload
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def send_request_without_signature username, service_name, public_key_algorithm_name, secret_key
|
67
|
+
algorithm = Algorithm[public_key_algorithm_name].new logger: logger
|
68
|
+
public_key_blob = algorithm.generate_public_key_blob(secret_key)
|
69
|
+
message = {
|
70
|
+
:'message number' => Message::SSH_MSG_USERAUTH_REQUEST::VALUE,
|
71
|
+
:"user name" => username,
|
72
|
+
:"service name" => service_name,
|
73
|
+
:"method name" => NAME,
|
74
|
+
:"with signature" => false,
|
75
|
+
:'public key algorithm name' => public_key_algorithm_name,
|
76
|
+
:'public key blob' => public_key_blob,
|
77
|
+
}
|
78
|
+
payload = Message::SSH_MSG_USERAUTH_REQUEST.new(logger: logger).encode message
|
79
|
+
@transport.send payload
|
80
|
+
end
|
81
|
+
|
82
|
+
def send_request_with_signature username, service_name, public_key_algorithm_name, secret_key
|
83
|
+
algorithm = Algorithm[public_key_algorithm_name].new logger: logger
|
84
|
+
public_key_blob = algorithm.generate_public_key_blob(secret_key)
|
85
|
+
signature = algorithm.generate_signature(@session_id, username, service_name, 'publickey', secret_key)
|
86
|
+
message = {
|
87
|
+
:'message number' => Message::SSH_MSG_USERAUTH_REQUEST::VALUE,
|
88
|
+
:"user name" => username,
|
89
|
+
:"service name" => service_name,
|
90
|
+
:"method name" => NAME,
|
91
|
+
:"with signature" => true,
|
92
|
+
:'public key algorithm name' => public_key_algorithm_name,
|
93
|
+
:'public key blob' => public_key_blob,
|
94
|
+
:'signature' => signature,
|
95
|
+
}
|
96
|
+
payload = Message::SSH_MSG_USERAUTH_REQUEST.new(logger: logger).encode message
|
97
|
+
@transport.send payload
|
45
98
|
end
|
46
99
|
end
|
47
100
|
end
|
@@ -23,4 +23,3 @@ require 'hrr_rb_ssh/authentication/method/publickey/algorithm/ssh_rsa'
|
|
23
23
|
require 'hrr_rb_ssh/authentication/method/publickey/algorithm/ecdsa_sha2_nistp256'
|
24
24
|
require 'hrr_rb_ssh/authentication/method/publickey/algorithm/ecdsa_sha2_nistp384'
|
25
25
|
require 'hrr_rb_ssh/authentication/method/publickey/algorithm/ecdsa_sha2_nistp521'
|
26
|
-
require 'hrr_rb_ssh/authentication/method/publickey/algorithm/ssh_ed25519'
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# coding: utf-8
|
2
2
|
# vim: et ts=2 sw=2
|
3
3
|
|
4
|
-
require 'hrr_rb_ssh/
|
4
|
+
require 'hrr_rb_ssh/loggable'
|
5
5
|
require 'hrr_rb_ssh/algorithm/publickey'
|
6
6
|
|
7
7
|
module HrrRbSsh
|
@@ -10,16 +10,18 @@ module HrrRbSsh
|
|
10
10
|
class Publickey
|
11
11
|
class Algorithm
|
12
12
|
module Functionable
|
13
|
-
|
14
|
-
|
13
|
+
include Loggable
|
14
|
+
|
15
|
+
def initialize logger: nil
|
16
|
+
self.logger = logger
|
15
17
|
end
|
16
18
|
|
17
19
|
def verify_public_key public_key_algorithm_name, public_key, public_key_blob
|
18
20
|
begin
|
19
|
-
publickey = HrrRbSsh::Algorithm::Publickey[self.class::NAME].new public_key
|
21
|
+
publickey = HrrRbSsh::Algorithm::Publickey[self.class::NAME].new public_key, logger: logger
|
20
22
|
public_key_algorithm_name == self.class::NAME && public_key_blob == publickey.to_public_key_blob
|
21
23
|
rescue => e
|
22
|
-
|
24
|
+
log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
23
25
|
false
|
24
26
|
end
|
25
27
|
end
|
@@ -36,14 +38,36 @@ module HrrRbSsh
|
|
36
38
|
:'public key algorithm name' => message[:'public key algorithm name'],
|
37
39
|
:'public key blob' => message[:'public key blob'],
|
38
40
|
}
|
39
|
-
signature_blob = SignatureBlob.encode signature_blob_h
|
40
|
-
publickey = HrrRbSsh::Algorithm::Publickey[self.class::NAME].new message[:'public key blob']
|
41
|
+
signature_blob = SignatureBlob.new(logger: logger).encode signature_blob_h
|
42
|
+
publickey = HrrRbSsh::Algorithm::Publickey[self.class::NAME].new message[:'public key blob'], logger: logger
|
41
43
|
publickey.verify message[:'signature'], signature_blob
|
42
44
|
rescue => e
|
43
|
-
|
45
|
+
log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
44
46
|
false
|
45
47
|
end
|
46
48
|
end
|
49
|
+
|
50
|
+
def generate_public_key_blob secret_key
|
51
|
+
publickey = HrrRbSsh::Algorithm::Publickey[self.class::NAME].new secret_key, logger: logger
|
52
|
+
publickey.to_public_key_blob
|
53
|
+
end
|
54
|
+
|
55
|
+
def generate_signature session_id, username, service_name, method_name, secret_key
|
56
|
+
publickey = HrrRbSsh::Algorithm::Publickey[self.class::NAME].new secret_key, logger: logger
|
57
|
+
publickey_blob = publickey.to_public_key_blob
|
58
|
+
signature_blob_h = {
|
59
|
+
:'session identifier' => session_id,
|
60
|
+
:'message number' => Message::SSH_MSG_USERAUTH_REQUEST::VALUE,
|
61
|
+
:'user name' => username,
|
62
|
+
:'service name' => service_name,
|
63
|
+
:'method name' => method_name,
|
64
|
+
:'with signature' => true,
|
65
|
+
:'public key algorithm name' => self.class::NAME,
|
66
|
+
:'public key blob' => publickey_blob
|
67
|
+
}
|
68
|
+
signature_blob = SignatureBlob.new(logger: logger).encode signature_blob_h
|
69
|
+
publickey.sign signature_blob
|
70
|
+
end
|
47
71
|
end
|
48
72
|
end
|
49
73
|
end
|