hrr_rb_ssh 0.3.0.pre1 → 0.4.2
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/demo/echo_server.rb
CHANGED
@@ -12,8 +12,6 @@ def start_service io, logger=nil
|
|
12
12
|
require 'hrr_rb_ssh'
|
13
13
|
end
|
14
14
|
|
15
|
-
HrrRbSsh::Logger.initialize logger if logger
|
16
|
-
|
17
15
|
auth_password = HrrRbSsh::Authentication::Authenticator.new { |context|
|
18
16
|
true # accept any user and password
|
19
17
|
}
|
@@ -39,12 +37,19 @@ def start_service io, logger=nil
|
|
39
37
|
options['authentication_password_authenticator'] = auth_password
|
40
38
|
options['connection_channel_request_shell'] = conn_echo
|
41
39
|
|
42
|
-
server = HrrRbSsh::Server.new options
|
40
|
+
server = HrrRbSsh::Server.new options, logger: logger
|
43
41
|
server.start io
|
44
42
|
end
|
45
43
|
|
44
|
+
class MyLoggerFormatter < ::Logger::Formatter
|
45
|
+
def call severity, time, progname, msg
|
46
|
+
"%s, [%s#%d.%x] %5s -- %s: %s\n" % [severity[0..0], format_datetime(time), Process.pid, Thread.current.object_id, severity, progname, msg2str(msg)]
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
46
50
|
logger = Logger.new STDOUT
|
47
51
|
logger.level = Logger::INFO
|
52
|
+
logger.formatter = MyLoggerFormatter.new
|
48
53
|
|
49
54
|
server = TCPServer.new 10022
|
50
55
|
loop do
|
@@ -0,0 +1,105 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
3
|
+
|
4
|
+
require 'logger'
|
5
|
+
require 'socket'
|
6
|
+
|
7
|
+
|
8
|
+
def start_service io, logger=nil
|
9
|
+
require 'etc'
|
10
|
+
|
11
|
+
begin
|
12
|
+
require 'hrr_rb_ssh'
|
13
|
+
rescue LoadError
|
14
|
+
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
15
|
+
require 'hrr_rb_ssh'
|
16
|
+
end
|
17
|
+
|
18
|
+
auth_none = HrrRbSsh::Authentication::Authenticator.new { |context|
|
19
|
+
context.authentication_methods.push 'publickey'
|
20
|
+
HrrRbSsh::Authentication::PARTIAL_SUCCESS
|
21
|
+
}
|
22
|
+
auth_publickey = HrrRbSsh::Authentication::Authenticator.new { |context|
|
23
|
+
users = ['user1', 'user2']
|
24
|
+
is_verified = users.any?{ |username|
|
25
|
+
passwd = Etc.getpwnam(username)
|
26
|
+
homedir = passwd.dir
|
27
|
+
authorized_keys = HrrRbSsh::Compat::OpenSSH::AuthorizedKeys.new(File.read(File.join(homedir, '.ssh', 'authorized_keys')))
|
28
|
+
authorized_keys.any?{ |public_key| context.verify username, public_key.algorithm_name, public_key.to_pem }
|
29
|
+
}
|
30
|
+
if is_verified
|
31
|
+
context.authentication_methods.push 'password'
|
32
|
+
HrrRbSsh::Authentication::PARTIAL_SUCCESS
|
33
|
+
else
|
34
|
+
HrrRbSsh::Authentication::FAILURE
|
35
|
+
end
|
36
|
+
}
|
37
|
+
auth_password = HrrRbSsh::Authentication::Authenticator.new { |context|
|
38
|
+
user_and_pass = [
|
39
|
+
['user1', 'password1'],
|
40
|
+
['user2', 'password2'],
|
41
|
+
]
|
42
|
+
is_verified = user_and_pass.any? { |user, pass| context.verify user, pass }
|
43
|
+
if is_verified
|
44
|
+
HrrRbSsh::Authentication::SUCCESS # or HrrRbSsh::Authentication::PARTIAL_SUCCESS
|
45
|
+
else
|
46
|
+
HrrRbSsh::Authentication::FAILURE
|
47
|
+
end
|
48
|
+
}
|
49
|
+
|
50
|
+
auth_preferred_authentication_methods = ["none"]
|
51
|
+
|
52
|
+
|
53
|
+
options = {}
|
54
|
+
|
55
|
+
options['authentication_none_authenticator'] = auth_none
|
56
|
+
options['authentication_publickey_authenticator'] = auth_publickey
|
57
|
+
options['authentication_password_authenticator'] = auth_password
|
58
|
+
|
59
|
+
options['authentication_preferred_authentication_methods'] = auth_preferred_authentication_methods
|
60
|
+
|
61
|
+
options['connection_channel_request_pty_req'] = HrrRbSsh::Connection::RequestHandler::ReferencePtyReqRequestHandler.new
|
62
|
+
options['connection_channel_request_env'] = HrrRbSsh::Connection::RequestHandler::ReferenceEnvRequestHandler.new
|
63
|
+
options['connection_channel_request_shell'] = HrrRbSsh::Connection::RequestHandler::ReferenceShellRequestHandler.new
|
64
|
+
options['connection_channel_request_exec'] = HrrRbSsh::Connection::RequestHandler::ReferenceExecRequestHandler.new
|
65
|
+
options['connection_channel_request_window_change'] = HrrRbSsh::Connection::RequestHandler::ReferenceWindowChangeRequestHandler.new
|
66
|
+
|
67
|
+
server = HrrRbSsh::Server.new options, logger: logger
|
68
|
+
server.start io
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
class MyLoggerFormatter < ::Logger::Formatter
|
73
|
+
def call severity, time, progname, msg
|
74
|
+
"%s, [%s#%d.%x] %5s -- %s: %s\n" % [severity[0..0], format_datetime(time), Process.pid, Thread.current.object_id, severity, progname, msg2str(msg)]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
logger = Logger.new STDOUT
|
80
|
+
logger.level = Logger::INFO
|
81
|
+
logger.formatter = MyLoggerFormatter.new
|
82
|
+
|
83
|
+
server = TCPServer.new 10022
|
84
|
+
loop do
|
85
|
+
Thread.new(server.accept) do |io|
|
86
|
+
begin
|
87
|
+
pid = fork do
|
88
|
+
begin
|
89
|
+
start_service io, logger
|
90
|
+
rescue => e
|
91
|
+
logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
92
|
+
exit false
|
93
|
+
end
|
94
|
+
end
|
95
|
+
logger.info { "process #{pid} started" }
|
96
|
+
io.close rescue nil
|
97
|
+
pid, status = Process.waitpid2 pid
|
98
|
+
rescue => e
|
99
|
+
logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
100
|
+
ensure
|
101
|
+
status ||= nil
|
102
|
+
logger.info { "process #{pid} finished with status #{status.inspect}" }
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
3
|
+
|
4
|
+
require 'logger'
|
5
|
+
require 'socket'
|
6
|
+
|
7
|
+
|
8
|
+
def start_service io, logger=nil
|
9
|
+
require 'etc'
|
10
|
+
|
11
|
+
begin
|
12
|
+
require 'hrr_rb_ssh'
|
13
|
+
rescue LoadError
|
14
|
+
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
15
|
+
require 'hrr_rb_ssh'
|
16
|
+
end
|
17
|
+
|
18
|
+
auth_publickey = HrrRbSsh::Authentication::Authenticator.new { |context|
|
19
|
+
users = ['user1', 'user2']
|
20
|
+
is_verified = users.any?{ |username|
|
21
|
+
passwd = Etc.getpwnam(username)
|
22
|
+
homedir = passwd.dir
|
23
|
+
authorized_keys = HrrRbSsh::Compat::OpenSSH::AuthorizedKeys.new(File.read(File.join(homedir, '.ssh', 'authorized_keys')))
|
24
|
+
authorized_keys.any?{ |public_key| context.verify username, public_key.algorithm_name, public_key.to_pem }
|
25
|
+
}
|
26
|
+
if is_verified
|
27
|
+
HrrRbSsh::Authentication::PARTIAL_SUCCESS
|
28
|
+
else
|
29
|
+
HrrRbSsh::Authentication::FAILURE
|
30
|
+
end
|
31
|
+
}
|
32
|
+
auth_password = HrrRbSsh::Authentication::Authenticator.new { |context|
|
33
|
+
user_and_pass = [
|
34
|
+
['user1', 'password1'],
|
35
|
+
['user2', 'password2'],
|
36
|
+
]
|
37
|
+
is_verified = user_and_pass.any? { |user, pass| context.verify user, pass }
|
38
|
+
if is_verified
|
39
|
+
HrrRbSsh::Authentication::PARTIAL_SUCCESS
|
40
|
+
else
|
41
|
+
HrrRbSsh::Authentication::FAILURE
|
42
|
+
end
|
43
|
+
}
|
44
|
+
|
45
|
+
auth_preferred_authentication_methods = ["publickey", "password"]
|
46
|
+
|
47
|
+
|
48
|
+
options = {}
|
49
|
+
|
50
|
+
options['authentication_publickey_authenticator'] = auth_publickey
|
51
|
+
options['authentication_password_authenticator'] = auth_password
|
52
|
+
|
53
|
+
options['authentication_preferred_authentication_methods'] = auth_preferred_authentication_methods
|
54
|
+
|
55
|
+
options['connection_channel_request_pty_req'] = HrrRbSsh::Connection::RequestHandler::ReferencePtyReqRequestHandler.new
|
56
|
+
options['connection_channel_request_env'] = HrrRbSsh::Connection::RequestHandler::ReferenceEnvRequestHandler.new
|
57
|
+
options['connection_channel_request_shell'] = HrrRbSsh::Connection::RequestHandler::ReferenceShellRequestHandler.new
|
58
|
+
options['connection_channel_request_exec'] = HrrRbSsh::Connection::RequestHandler::ReferenceExecRequestHandler.new
|
59
|
+
options['connection_channel_request_window_change'] = HrrRbSsh::Connection::RequestHandler::ReferenceWindowChangeRequestHandler.new
|
60
|
+
|
61
|
+
server = HrrRbSsh::Server.new options, logger: logger
|
62
|
+
server.start io
|
63
|
+
end
|
64
|
+
|
65
|
+
|
66
|
+
class MyLoggerFormatter < ::Logger::Formatter
|
67
|
+
def call severity, time, progname, msg
|
68
|
+
"%s, [%s#%d.%x] %5s -- %s: %s\n" % [severity[0..0], format_datetime(time), Process.pid, Thread.current.object_id, severity, progname, msg2str(msg)]
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
logger = Logger.new STDOUT
|
74
|
+
logger.level = Logger::INFO
|
75
|
+
logger.formatter = MyLoggerFormatter.new
|
76
|
+
|
77
|
+
server = TCPServer.new 10022
|
78
|
+
loop do
|
79
|
+
Thread.new(server.accept) do |io|
|
80
|
+
begin
|
81
|
+
pid = fork do
|
82
|
+
begin
|
83
|
+
start_service io, logger
|
84
|
+
rescue => e
|
85
|
+
logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
86
|
+
exit false
|
87
|
+
end
|
88
|
+
end
|
89
|
+
logger.info { "process #{pid} started" }
|
90
|
+
io.close rescue nil
|
91
|
+
pid, status = Process.waitpid2 pid
|
92
|
+
rescue => e
|
93
|
+
logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
|
94
|
+
ensure
|
95
|
+
status ||= nil
|
96
|
+
logger.info { "process #{pid} finished with status #{status.inspect}" }
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
data/demo/server.rb
CHANGED
@@ -15,10 +15,8 @@ def start_service io, logger=nil
|
|
15
15
|
require 'hrr_rb_ssh'
|
16
16
|
end
|
17
17
|
|
18
|
-
HrrRbSsh::Logger.initialize logger if logger
|
19
|
-
|
20
18
|
tran_preferred_encryption_algorithms = %w(aes128-ctr aes192-ctr aes256-ctr aes128-cbc 3des-cbc blowfish-cbc cast128-cbc aes192-cbc aes256-cbc arcfour)
|
21
|
-
tran_preferred_server_host_key_algorithms = %w(
|
19
|
+
tran_preferred_server_host_key_algorithms = %w(ecdsa-sha2-nistp521 ecdsa-sha2-nistp384 ecdsa-sha2-nistp256 ssh-rsa ssh-dss)
|
22
20
|
tran_preferred_kex_algorithms = %w(ecdh-sha2-nistp521 ecdh-sha2-nistp384 ecdh-sha2-nistp256 diffie-hellman-group14-sha1 diffie-hellman-group1-sha1)
|
23
21
|
tran_preferred_mac_algorithms = %w(hmac-sha2-512 hmac-sha2-256 hmac-sha1 hmac-md5 hmac-sha1-96 hmac-md5-96)
|
24
22
|
tran_preferred_compression_algorithms = %w(none zlib)
|
@@ -89,13 +87,21 @@ OfeosJOO9twerD7pPhmXREkygblPsEXaVA==
|
|
89
87
|
options['connection_channel_request_exec'] = HrrRbSsh::Connection::RequestHandler::ReferenceExecRequestHandler.new
|
90
88
|
options['connection_channel_request_window_change'] = HrrRbSsh::Connection::RequestHandler::ReferenceWindowChangeRequestHandler.new
|
91
89
|
|
92
|
-
server = HrrRbSsh::Server.new options
|
90
|
+
server = HrrRbSsh::Server.new options, logger: logger
|
93
91
|
server.start io
|
94
92
|
end
|
95
93
|
|
96
94
|
|
95
|
+
class MyLoggerFormatter < ::Logger::Formatter
|
96
|
+
def call severity, time, progname, msg
|
97
|
+
"%s, [%s#%d.%x] %5s -- %s: %s\n" % [severity[0..0], format_datetime(time), Process.pid, Thread.current.object_id, severity, progname, msg2str(msg)]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
|
97
102
|
logger = Logger.new STDOUT
|
98
103
|
logger.level = Logger::INFO
|
104
|
+
logger.formatter = MyLoggerFormatter.new
|
99
105
|
|
100
106
|
server = TCPServer.new 10022
|
101
107
|
loop do
|
@@ -12,8 +12,6 @@ def start_service io, logger=nil
|
|
12
12
|
require 'hrr_rb_ssh'
|
13
13
|
end
|
14
14
|
|
15
|
-
HrrRbSsh::Logger.initialize logger if logger
|
16
|
-
|
17
15
|
auth_password = HrrRbSsh::Authentication::Authenticator.new { |context|
|
18
16
|
true # accept any user and password
|
19
17
|
}
|
@@ -47,12 +45,19 @@ def start_service io, logger=nil
|
|
47
45
|
options['authentication_password_authenticator'] = auth_password
|
48
46
|
options['connection_channel_request_subsystem'] = conn_echo
|
49
47
|
|
50
|
-
server = HrrRbSsh::Server.new options
|
48
|
+
server = HrrRbSsh::Server.new options, logger: logger
|
51
49
|
server.start io
|
52
50
|
end
|
53
51
|
|
52
|
+
class MyLoggerFormatter < ::Logger::Formatter
|
53
|
+
def call severity, time, progname, msg
|
54
|
+
"%s, [%s#%d.%x] %5s -- %s: %s\n" % [severity[0..0], format_datetime(time), Process.pid, Thread.current.object_id, severity, progname, msg2str(msg)]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
54
58
|
logger = Logger.new STDOUT
|
55
59
|
logger.level = Logger::INFO
|
60
|
+
logger.formatter = MyLoggerFormatter.new
|
56
61
|
|
57
62
|
server = TCPServer.new 10022
|
58
63
|
while true
|
data/hrr_rb_ssh.gemspec
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
# vim: et ts=2 sw=2
|
1
3
|
|
2
4
|
lib = File.expand_path("../lib", __FILE__)
|
3
5
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
@@ -7,8 +9,8 @@ Gem::Specification.new do |spec|
|
|
7
9
|
spec.name = "hrr_rb_ssh"
|
8
10
|
spec.version = HrrRbSsh::VERSION
|
9
11
|
spec.license = 'Apache-2.0'
|
10
|
-
spec.summary = %q{Pure Ruby SSH 2.0 server implementation}
|
11
|
-
spec.description = %q{Pure Ruby SSH 2.0 server implementation}
|
12
|
+
spec.summary = %q{Pure Ruby SSH 2.0 server and client implementation}
|
13
|
+
spec.description = %q{Pure Ruby SSH 2.0 server and client implementation}
|
12
14
|
spec.authors = ["hirura"]
|
13
15
|
spec.email = ["hirura@gmail.com"]
|
14
16
|
spec.homepage = "https://github.com/hirura/hrr_rb_ssh"
|
@@ -20,9 +22,7 @@ Gem::Specification.new do |spec|
|
|
20
22
|
|
21
23
|
spec.required_ruby_version = '>= 2.0.0'
|
22
24
|
|
23
|
-
spec.
|
24
|
-
spec.add_development_dependency "bundler", "~> 1.16"
|
25
|
-
spec.add_development_dependency "rake", "~> 10.0"
|
25
|
+
spec.add_development_dependency "rake", "~> 12.0"
|
26
26
|
spec.add_development_dependency "rspec", "~> 3.0"
|
27
|
-
spec.add_development_dependency "
|
27
|
+
spec.add_development_dependency "simplecov", "~> 0.16"
|
28
28
|
end
|
data/lib/hrr_rb_ssh.rb
CHANGED
@@ -9,7 +9,6 @@ end
|
|
9
9
|
|
10
10
|
require "hrr_rb_ssh/version"
|
11
11
|
require "hrr_rb_ssh/compat"
|
12
|
-
require "hrr_rb_ssh/logger"
|
13
12
|
require "hrr_rb_ssh/mode"
|
14
13
|
require "hrr_rb_ssh/algorithm"
|
15
14
|
require "hrr_rb_ssh/error"
|
@@ -17,3 +16,4 @@ require "hrr_rb_ssh/transport"
|
|
17
16
|
require "hrr_rb_ssh/authentication"
|
18
17
|
require "hrr_rb_ssh/connection"
|
19
18
|
require "hrr_rb_ssh/server"
|
19
|
+
require "hrr_rb_ssh/client"
|
@@ -19,4 +19,3 @@ require 'hrr_rb_ssh/algorithm/publickey/ssh_rsa'
|
|
19
19
|
require 'hrr_rb_ssh/algorithm/publickey/ecdsa_sha2_nistp256'
|
20
20
|
require 'hrr_rb_ssh/algorithm/publickey/ecdsa_sha2_nistp384'
|
21
21
|
require 'hrr_rb_ssh/algorithm/publickey/ecdsa_sha2_nistp521'
|
22
|
-
require 'hrr_rb_ssh/algorithm/publickey/ssh_ed25519'
|
@@ -1,14 +1,17 @@
|
|
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/data_type'
|
6
6
|
|
7
7
|
module HrrRbSsh
|
8
8
|
module Algorithm
|
9
9
|
class Publickey
|
10
10
|
module EcdsaSha2
|
11
|
-
|
11
|
+
include Loggable
|
12
|
+
|
13
|
+
def initialize arg, logger: nil
|
14
|
+
self.logger = logger
|
12
15
|
begin
|
13
16
|
new_by_key_str arg
|
14
17
|
rescue OpenSSL::PKey::ECError
|
@@ -21,7 +24,7 @@ module HrrRbSsh
|
|
21
24
|
end
|
22
25
|
|
23
26
|
def new_by_public_key_blob public_key_blob
|
24
|
-
public_key_blob_h = PublicKeyBlob.decode
|
27
|
+
public_key_blob_h = PublicKeyBlob.new(logger: logger).decode public_key_blob
|
25
28
|
@publickey = OpenSSL::PKey::EC.new(self.class::CURVE_NAME)
|
26
29
|
@publickey.public_key = OpenSSL::PKey::EC::Point.new(@publickey.group, OpenSSL::BN.new(public_key_blob_h[:'Q'], 2))
|
27
30
|
end
|
@@ -36,20 +39,20 @@ module HrrRbSsh
|
|
36
39
|
:'identifier' => self.class::IDENTIFIER,
|
37
40
|
:'Q' => @publickey.public_key.to_bn.to_s(2)
|
38
41
|
}
|
39
|
-
PublicKeyBlob.encode
|
42
|
+
PublicKeyBlob.new(logger: logger).encode public_key_blob_h
|
40
43
|
end
|
41
44
|
|
42
45
|
def ecdsa_signature_blob signature_blob
|
43
46
|
hash = OpenSSL::Digest.digest(self.class::DIGEST, signature_blob)
|
44
47
|
sign_der = @publickey.dsa_sign_asn1(hash)
|
45
|
-
sign_asn1 = OpenSSL::ASN1.decode
|
48
|
+
sign_asn1 = OpenSSL::ASN1.decode sign_der
|
46
49
|
r = sign_asn1.value[0].value.to_i
|
47
50
|
s = sign_asn1.value[1].value.to_i
|
48
51
|
ecdsa_signature_blob_h = {
|
49
52
|
:'r' => r,
|
50
53
|
:'s' => s,
|
51
54
|
}
|
52
|
-
EcdsaSignatureBlob.encode ecdsa_signature_blob_h
|
55
|
+
EcdsaSignatureBlob.new(logger: logger).encode ecdsa_signature_blob_h
|
53
56
|
end
|
54
57
|
|
55
58
|
def sign signature_blob
|
@@ -57,12 +60,12 @@ module HrrRbSsh
|
|
57
60
|
:'public key algorithm name' => self.class::NAME,
|
58
61
|
:'ecdsa signature blob' => ecdsa_signature_blob(signature_blob),
|
59
62
|
}
|
60
|
-
Signature.encode signature_h
|
63
|
+
Signature.new(logger: logger).encode signature_h
|
61
64
|
end
|
62
65
|
|
63
66
|
def verify signature, signature_blob
|
64
|
-
signature_h = Signature.decode signature
|
65
|
-
ecdsa_signature_blob_h = EcdsaSignatureBlob.decode signature_h[:'ecdsa signature blob']
|
67
|
+
signature_h = Signature.new(logger: logger).decode signature
|
68
|
+
ecdsa_signature_blob_h = EcdsaSignatureBlob.new(logger: logger).decode signature_h[:'ecdsa signature blob']
|
66
69
|
r = ecdsa_signature_blob_h[:'r']
|
67
70
|
s = ecdsa_signature_blob_h[:'s']
|
68
71
|
sign_asn1 = OpenSSL::ASN1::Sequence.new(
|
@@ -8,10 +8,8 @@ module HrrRbSsh
|
|
8
8
|
module Algorithm
|
9
9
|
class Publickey
|
10
10
|
module EcdsaSha2
|
11
|
-
|
12
|
-
|
13
|
-
include Codable
|
14
|
-
end
|
11
|
+
class EcdsaSignatureBlob
|
12
|
+
include Codable
|
15
13
|
DEFINITION = [
|
16
14
|
[DataType::Mpint, :'r'],
|
17
15
|
[DataType::Mpint, :'s'],
|
@@ -8,10 +8,8 @@ module HrrRbSsh
|
|
8
8
|
module Algorithm
|
9
9
|
class Publickey
|
10
10
|
module EcdsaSha2
|
11
|
-
|
12
|
-
|
13
|
-
include Codable
|
14
|
-
end
|
11
|
+
class PublicKeyBlob
|
12
|
+
include Codable
|
15
13
|
DEFINITION = [
|
16
14
|
[DataType::String, :'public key algorithm name'],
|
17
15
|
[DataType::String, :'identifier'],
|