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.
Files changed (139) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +0 -3
  3. data/.travis.yml +1 -0
  4. data/README.md +208 -46
  5. data/demo/client.rb +71 -0
  6. data/demo/echo_server.rb +8 -3
  7. data/demo/more_flexible_auth.rb +105 -0
  8. data/demo/multi_step_auth.rb +99 -0
  9. data/demo/server.rb +10 -4
  10. data/demo/subsystem_echo_server.rb +8 -3
  11. data/hrr_rb_ssh.gemspec +6 -6
  12. data/lib/hrr_rb_ssh.rb +1 -1
  13. data/lib/hrr_rb_ssh/algorithm/publickey.rb +0 -1
  14. data/lib/hrr_rb_ssh/algorithm/publickey/ecdsa_sha2.rb +12 -9
  15. data/lib/hrr_rb_ssh/algorithm/publickey/ecdsa_sha2/ecdsa_signature_blob.rb +2 -4
  16. data/lib/hrr_rb_ssh/algorithm/publickey/ecdsa_sha2/public_key_blob.rb +2 -4
  17. data/lib/hrr_rb_ssh/algorithm/publickey/ecdsa_sha2/signature.rb +2 -4
  18. data/lib/hrr_rb_ssh/algorithm/publickey/ssh_dss.rb +10 -7
  19. data/lib/hrr_rb_ssh/algorithm/publickey/ssh_dss/public_key_blob.rb +2 -4
  20. data/lib/hrr_rb_ssh/algorithm/publickey/ssh_dss/signature.rb +2 -4
  21. data/lib/hrr_rb_ssh/algorithm/publickey/ssh_rsa.rb +9 -6
  22. data/lib/hrr_rb_ssh/algorithm/publickey/ssh_rsa/public_key_blob.rb +2 -4
  23. data/lib/hrr_rb_ssh/algorithm/publickey/ssh_rsa/signature.rb +2 -4
  24. data/lib/hrr_rb_ssh/authentication.rb +103 -22
  25. data/lib/hrr_rb_ssh/authentication/constant.rb +14 -0
  26. data/lib/hrr_rb_ssh/authentication/method/keyboard_interactive.rb +44 -7
  27. data/lib/hrr_rb_ssh/authentication/method/keyboard_interactive/context.rb +16 -9
  28. data/lib/hrr_rb_ssh/authentication/method/keyboard_interactive/info_request.rb +7 -6
  29. data/lib/hrr_rb_ssh/authentication/method/keyboard_interactive/info_response.rb +5 -2
  30. data/lib/hrr_rb_ssh/authentication/method/none.rb +23 -7
  31. data/lib/hrr_rb_ssh/authentication/method/none/context.rb +15 -7
  32. data/lib/hrr_rb_ssh/authentication/method/password.rb +28 -7
  33. data/lib/hrr_rb_ssh/authentication/method/password/context.rb +16 -7
  34. data/lib/hrr_rb_ssh/authentication/method/publickey.rb +63 -10
  35. data/lib/hrr_rb_ssh/authentication/method/publickey/algorithm.rb +0 -1
  36. data/lib/hrr_rb_ssh/authentication/method/publickey/algorithm/functionable.rb +32 -8
  37. data/lib/hrr_rb_ssh/authentication/method/publickey/algorithm/signature_blob.rb +2 -4
  38. data/lib/hrr_rb_ssh/authentication/method/publickey/context.rb +11 -2
  39. data/lib/hrr_rb_ssh/client.rb +234 -0
  40. data/lib/hrr_rb_ssh/codable.rb +15 -13
  41. data/lib/hrr_rb_ssh/compat/ruby.rb +0 -1
  42. data/lib/hrr_rb_ssh/connection.rb +145 -75
  43. data/lib/hrr_rb_ssh/connection/channel.rb +342 -109
  44. data/lib/hrr_rb_ssh/connection/channel/channel_type/direct_tcpip.rb +24 -19
  45. data/lib/hrr_rb_ssh/connection/channel/channel_type/forwarded_tcpip.rb +24 -19
  46. data/lib/hrr_rb_ssh/connection/channel/channel_type/session.rb +19 -12
  47. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/proc_chain.rb +0 -2
  48. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/proc_chain/chain_context.rb +0 -3
  49. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/env.rb +2 -5
  50. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/env/context.rb +5 -4
  51. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/exec.rb +2 -5
  52. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/exec/context.rb +5 -4
  53. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/pty_req.rb +2 -5
  54. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/pty_req/context.rb +5 -4
  55. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/shell.rb +2 -5
  56. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/shell/context.rb +5 -4
  57. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/subsystem.rb +2 -5
  58. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/subsystem/context.rb +5 -4
  59. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/window_change.rb +2 -5
  60. data/lib/hrr_rb_ssh/connection/channel/channel_type/session/request_type/window_change/context.rb +5 -4
  61. data/lib/hrr_rb_ssh/connection/global_request_handler.rb +14 -12
  62. data/lib/hrr_rb_ssh/connection/request_handler.rb +1 -3
  63. data/lib/hrr_rb_ssh/connection/request_handler/reference_env_request_handler.rb +0 -2
  64. data/lib/hrr_rb_ssh/connection/request_handler/reference_exec_request_handler.rb +4 -6
  65. data/lib/hrr_rb_ssh/connection/request_handler/reference_pty_req_request_handler.rb +10 -12
  66. data/lib/hrr_rb_ssh/connection/request_handler/reference_shell_request_handler.rb +4 -6
  67. data/lib/hrr_rb_ssh/connection/request_handler/reference_window_change_request_handler.rb +0 -2
  68. data/lib/hrr_rb_ssh/error/closed_authentication.rb +1 -1
  69. data/lib/hrr_rb_ssh/error/closed_connection.rb +1 -1
  70. data/lib/hrr_rb_ssh/error/closed_transport.rb +1 -1
  71. data/lib/hrr_rb_ssh/loggable.rb +42 -0
  72. data/lib/hrr_rb_ssh/message/001_ssh_msg_disconnect.rb +2 -4
  73. data/lib/hrr_rb_ssh/message/002_ssh_msg_ignore.rb +2 -4
  74. data/lib/hrr_rb_ssh/message/003_ssh_msg_unimplemented.rb +2 -4
  75. data/lib/hrr_rb_ssh/message/004_ssh_msg_debug.rb +2 -4
  76. data/lib/hrr_rb_ssh/message/005_ssh_msg_service_request.rb +2 -4
  77. data/lib/hrr_rb_ssh/message/006_ssh_msg_service_accept.rb +2 -4
  78. data/lib/hrr_rb_ssh/message/020_ssh_msg_kexinit.rb +2 -4
  79. data/lib/hrr_rb_ssh/message/021_ssh_msg_newkeys.rb +2 -4
  80. data/lib/hrr_rb_ssh/message/030_ssh_msg_kex_dh_gex_request_old.rb +2 -4
  81. data/lib/hrr_rb_ssh/message/030_ssh_msg_kexdh_init.rb +2 -4
  82. data/lib/hrr_rb_ssh/message/030_ssh_msg_kexecdh_init.rb +2 -4
  83. data/lib/hrr_rb_ssh/message/031_ssh_msg_kex_dh_gex_group.rb +2 -4
  84. data/lib/hrr_rb_ssh/message/031_ssh_msg_kexdh_reply.rb +2 -4
  85. data/lib/hrr_rb_ssh/message/031_ssh_msg_kexecdh_reply.rb +2 -4
  86. data/lib/hrr_rb_ssh/message/032_ssh_msg_kex_dh_gex_init.rb +2 -4
  87. data/lib/hrr_rb_ssh/message/033_ssh_msg_kex_dh_gex_reply.rb +2 -4
  88. data/lib/hrr_rb_ssh/message/034_ssh_msg_kex_dh_gex_request.rb +2 -4
  89. data/lib/hrr_rb_ssh/message/050_ssh_msg_userauth_request.rb +2 -4
  90. data/lib/hrr_rb_ssh/message/051_ssh_msg_userauth_failure.rb +2 -4
  91. data/lib/hrr_rb_ssh/message/052_ssh_msg_userauth_success.rb +2 -4
  92. data/lib/hrr_rb_ssh/message/060_ssh_msg_userauth_info_request.rb +2 -4
  93. data/lib/hrr_rb_ssh/message/060_ssh_msg_userauth_pk_ok.rb +2 -4
  94. data/lib/hrr_rb_ssh/message/061_ssh_msg_userauth_info_response.rb +2 -4
  95. data/lib/hrr_rb_ssh/message/080_ssh_msg_global_request.rb +2 -4
  96. data/lib/hrr_rb_ssh/message/081_ssh_msg_request_success.rb +2 -4
  97. data/lib/hrr_rb_ssh/message/082_ssh_msg_request_failure.rb +2 -4
  98. data/lib/hrr_rb_ssh/message/090_ssh_msg_channel_open.rb +2 -4
  99. data/lib/hrr_rb_ssh/message/091_ssh_msg_channel_open_confirmation.rb +2 -4
  100. data/lib/hrr_rb_ssh/message/092_ssh_msg_channel_open_failure.rb +2 -4
  101. data/lib/hrr_rb_ssh/message/093_ssh_msg_channel_window_adjust.rb +2 -4
  102. data/lib/hrr_rb_ssh/message/094_ssh_msg_channel_data.rb +2 -4
  103. data/lib/hrr_rb_ssh/message/095_ssh_msg_channel_extended_data.rb +2 -4
  104. data/lib/hrr_rb_ssh/message/096_ssh_msg_channel_eof.rb +2 -4
  105. data/lib/hrr_rb_ssh/message/097_ssh_msg_channel_close.rb +2 -4
  106. data/lib/hrr_rb_ssh/message/098_ssh_msg_channel_request.rb +3 -5
  107. data/lib/hrr_rb_ssh/message/099_ssh_msg_channel_success.rb +2 -4
  108. data/lib/hrr_rb_ssh/message/100_ssh_msg_channel_failure.rb +2 -4
  109. data/lib/hrr_rb_ssh/server.rb +16 -10
  110. data/lib/hrr_rb_ssh/transport.rb +113 -77
  111. data/lib/hrr_rb_ssh/transport/compression_algorithm/functionable.rb +5 -3
  112. data/lib/hrr_rb_ssh/transport/compression_algorithm/unfunctionable.rb +5 -3
  113. data/lib/hrr_rb_ssh/transport/encryption_algorithm/functionable.rb +5 -3
  114. data/lib/hrr_rb_ssh/transport/encryption_algorithm/unfunctionable.rb +5 -3
  115. data/lib/hrr_rb_ssh/transport/kex_algorithm/diffie_hellman.rb +43 -37
  116. data/lib/hrr_rb_ssh/transport/kex_algorithm/diffie_hellman/h0.rb +2 -4
  117. data/lib/hrr_rb_ssh/transport/kex_algorithm/diffie_hellman_group_exchange.rb +87 -52
  118. data/lib/hrr_rb_ssh/transport/kex_algorithm/diffie_hellman_group_exchange/h0.rb +2 -4
  119. data/lib/hrr_rb_ssh/transport/kex_algorithm/elliptic_curve_diffie_hellman.rb +43 -37
  120. data/lib/hrr_rb_ssh/transport/kex_algorithm/elliptic_curve_diffie_hellman/h0.rb +2 -4
  121. data/lib/hrr_rb_ssh/transport/mac_algorithm/functionable.rb +5 -3
  122. data/lib/hrr_rb_ssh/transport/mac_algorithm/unfunctionable.rb +5 -3
  123. data/lib/hrr_rb_ssh/transport/receiver.rb +8 -7
  124. data/lib/hrr_rb_ssh/transport/sender.rb +5 -3
  125. data/lib/hrr_rb_ssh/transport/sequence_number.rb +0 -4
  126. data/lib/hrr_rb_ssh/transport/server_host_key_algorithm.rb +0 -1
  127. data/lib/hrr_rb_ssh/transport/server_host_key_algorithm/functionable.rb +5 -3
  128. data/lib/hrr_rb_ssh/version.rb +1 -1
  129. metadata +18 -51
  130. data/lib/hrr_rb_ssh/algorithm/publickey/ssh_ed25519.rb +0 -61
  131. data/lib/hrr_rb_ssh/algorithm/publickey/ssh_ed25519/openssh_private_key.rb +0 -29
  132. data/lib/hrr_rb_ssh/algorithm/publickey/ssh_ed25519/openssh_private_key_content.rb +0 -26
  133. data/lib/hrr_rb_ssh/algorithm/publickey/ssh_ed25519/pkey.rb +0 -158
  134. data/lib/hrr_rb_ssh/algorithm/publickey/ssh_ed25519/public_key_blob.rb +0 -23
  135. data/lib/hrr_rb_ssh/algorithm/publickey/ssh_ed25519/signature.rb +0 -23
  136. data/lib/hrr_rb_ssh/authentication/method/publickey/algorithm/ssh_ed25519.rb +0 -21
  137. data/lib/hrr_rb_ssh/compat/ruby/array.rb +0 -14
  138. data/lib/hrr_rb_ssh/logger.rb +0 -56
  139. data/lib/hrr_rb_ssh/transport/server_host_key_algorithm/ssh_ed25519.rb +0 -20
@@ -6,10 +6,8 @@ require 'hrr_rb_ssh/codable'
6
6
 
7
7
  module HrrRbSsh
8
8
  module Message
9
- module SSH_MSG_CHANNEL_OPEN
10
- class << self
11
- include Codable
12
- end
9
+ class SSH_MSG_CHANNEL_OPEN
10
+ include Codable
13
11
 
14
12
  ID = self.name.split('::').last
15
13
  VALUE = 90
@@ -6,10 +6,8 @@ require 'hrr_rb_ssh/codable'
6
6
 
7
7
  module HrrRbSsh
8
8
  module Message
9
- module SSH_MSG_CHANNEL_OPEN_CONFIRMATION
10
- class << self
11
- include Codable
12
- end
9
+ class SSH_MSG_CHANNEL_OPEN_CONFIRMATION
10
+ include Codable
13
11
 
14
12
  ID = self.name.split('::').last
15
13
  VALUE = 91
@@ -6,7 +6,7 @@ require 'hrr_rb_ssh/codable'
6
6
 
7
7
  module HrrRbSsh
8
8
  module Message
9
- module SSH_MSG_CHANNEL_OPEN_FAILURE
9
+ class SSH_MSG_CHANNEL_OPEN_FAILURE
10
10
  module ReasonCode
11
11
  SSH_OPEN_ADMINISTRATIVELY_PROHIBITED = 1
12
12
  SSH_OPEN_CONNECT_FAILED = 2
@@ -14,9 +14,7 @@ module HrrRbSsh
14
14
  SSH_OPEN_RESOURCE_SHORTAGE = 4
15
15
  end
16
16
 
17
- class << self
18
- include Codable
19
- end
17
+ include Codable
20
18
 
21
19
  ID = self.name.split('::').last
22
20
  VALUE = 92
@@ -6,10 +6,8 @@ require 'hrr_rb_ssh/codable'
6
6
 
7
7
  module HrrRbSsh
8
8
  module Message
9
- module SSH_MSG_CHANNEL_WINDOW_ADJUST
10
- class << self
11
- include Codable
12
- end
9
+ class SSH_MSG_CHANNEL_WINDOW_ADJUST
10
+ include Codable
13
11
 
14
12
  ID = self.name.split('::').last
15
13
  VALUE = 93
@@ -6,10 +6,8 @@ require 'hrr_rb_ssh/codable'
6
6
 
7
7
  module HrrRbSsh
8
8
  module Message
9
- module SSH_MSG_CHANNEL_DATA
10
- class << self
11
- include Codable
12
- end
9
+ class SSH_MSG_CHANNEL_DATA
10
+ include Codable
13
11
 
14
12
  ID = self.name.split('::').last
15
13
  VALUE = 94
@@ -6,14 +6,12 @@ require 'hrr_rb_ssh/codable'
6
6
 
7
7
  module HrrRbSsh
8
8
  module Message
9
- module SSH_MSG_CHANNEL_EXTENDED_DATA
9
+ class SSH_MSG_CHANNEL_EXTENDED_DATA
10
10
  module DataTypeCode
11
11
  SSH_EXTENDED_DATA_STDERR = 1
12
12
  end
13
13
 
14
- class << self
15
- include Codable
16
- end
14
+ include Codable
17
15
 
18
16
  ID = self.name.split('::').last
19
17
  VALUE = 95
@@ -6,10 +6,8 @@ require 'hrr_rb_ssh/codable'
6
6
 
7
7
  module HrrRbSsh
8
8
  module Message
9
- module SSH_MSG_CHANNEL_EOF
10
- class << self
11
- include Codable
12
- end
9
+ class SSH_MSG_CHANNEL_EOF
10
+ include Codable
13
11
 
14
12
  ID = self.name.split('::').last
15
13
  VALUE = 96
@@ -6,10 +6,8 @@ require 'hrr_rb_ssh/codable'
6
6
 
7
7
  module HrrRbSsh
8
8
  module Message
9
- module SSH_MSG_CHANNEL_CLOSE
10
- class << self
11
- include Codable
12
- end
9
+ class SSH_MSG_CHANNEL_CLOSE
10
+ include Codable
13
11
 
14
12
  ID = self.name.split('::').last
15
13
  VALUE = 97
@@ -6,7 +6,7 @@ require 'hrr_rb_ssh/codable'
6
6
 
7
7
  module HrrRbSsh
8
8
  module Message
9
- module SSH_MSG_CHANNEL_REQUEST
9
+ class SSH_MSG_CHANNEL_REQUEST
10
10
  module SignalName
11
11
  ABRT = 'ABRT'
12
12
  ALRM = 'ALRM'
@@ -82,14 +82,12 @@ module HrrRbSsh
82
82
  TTY_OP_OSPEED = 129
83
83
  end
84
84
 
85
- class << self
86
- include Codable
87
- end
85
+ include Codable
88
86
 
89
87
  ID = self.name.split('::').last
90
88
  VALUE = 98
91
89
 
92
- TERMINAL_MODE_INV = TerminalMode.constants.map{|c| [TerminalMode.const_get(c), c.to_s]}.to_h
90
+ TERMINAL_MODE_INV = TerminalMode.constants.map{|c| [TerminalMode.const_get(c), c.to_s]}.inject(Hash.new){ |h, (k, v)| h.update({k => v}) }
93
91
 
94
92
  DEFINITION = [
95
93
  #[DataType, Field Name]
@@ -6,10 +6,8 @@ require 'hrr_rb_ssh/codable'
6
6
 
7
7
  module HrrRbSsh
8
8
  module Message
9
- module SSH_MSG_CHANNEL_SUCCESS
10
- class << self
11
- include Codable
12
- end
9
+ class SSH_MSG_CHANNEL_SUCCESS
10
+ include Codable
13
11
 
14
12
  ID = self.name.split('::').last
15
13
  VALUE = 99
@@ -6,10 +6,8 @@ require 'hrr_rb_ssh/codable'
6
6
 
7
7
  module HrrRbSsh
8
8
  module Message
9
- module SSH_MSG_CHANNEL_FAILURE
10
- class << self
11
- include Codable
12
- end
9
+ class SSH_MSG_CHANNEL_FAILURE
10
+ include Codable
13
11
 
14
12
  ID = self.name.split('::').last
15
13
  VALUE = 100
@@ -1,29 +1,35 @@
1
1
  # coding: utf-8
2
2
  # vim: et ts=2 sw=2
3
3
 
4
- require 'hrr_rb_ssh/logger'
4
+ require 'hrr_rb_ssh/loggable'
5
5
  require 'hrr_rb_ssh/transport'
6
6
  require 'hrr_rb_ssh/authentication'
7
7
  require 'hrr_rb_ssh/connection'
8
8
 
9
9
  module HrrRbSsh
10
10
  class Server
11
- def self.start io, options={}
12
- server = self.new options
11
+ include Loggable
12
+
13
+ def self.start io, options={}, logger: nil
14
+ server = self.new options, logger: logger
13
15
  server.start io
14
16
  end
15
17
 
16
- def initialize options={}
17
- @logger = Logger.new self.class.name
18
+ def initialize options={}, logger: nil
19
+ self.logger = logger
18
20
  @options = options
19
21
  end
20
22
 
21
23
  def start io
22
- @logger.info { "start server service" }
23
- transport = HrrRbSsh::Transport.new io, HrrRbSsh::Mode::SERVER, @options
24
- authentication = HrrRbSsh::Authentication.new transport, @options
25
- connection = HrrRbSsh::Connection.new authentication, @options
26
- connection.start
24
+ log_info { "start server service" }
25
+ transport = Transport.new io, Mode::SERVER, @options, logger: logger
26
+ authentication = Authentication.new transport, Mode::SERVER, @options, logger: logger
27
+ connection = Connection.new authentication, Mode::SERVER, @options, logger: logger
28
+ begin
29
+ connection.start
30
+ rescue Error::ClosedConnection
31
+ end
32
+ log_info { "server service finished" }
27
33
  end
28
34
  end
29
35
  end
@@ -3,7 +3,7 @@
3
3
 
4
4
  require 'monitor'
5
5
  require 'hrr_rb_ssh/version'
6
- require 'hrr_rb_ssh/logger'
6
+ require 'hrr_rb_ssh/loggable'
7
7
  require 'hrr_rb_ssh/data_type'
8
8
  require 'hrr_rb_ssh/message'
9
9
  require 'hrr_rb_ssh/error/closed_transport'
@@ -20,10 +20,12 @@ require 'hrr_rb_ssh/transport/compression_algorithm'
20
20
 
21
21
  module HrrRbSsh
22
22
  class Transport
23
+ include Loggable
23
24
  include Constant
24
25
 
25
26
  attr_reader \
26
27
  :io,
28
+ :mode,
27
29
  :supported_encryption_algorithms,
28
30
  :supported_server_host_key_algorithms,
29
31
  :supported_kex_algorithms,
@@ -49,20 +51,19 @@ module HrrRbSsh
49
51
  :i_s,
50
52
  :session_id
51
53
 
52
- def initialize io, mode, options={}
54
+ def initialize io, mode, options={}, logger: nil
55
+ self.logger = logger
56
+
53
57
  @io = io
54
58
  @mode = mode
55
59
  @options = options
56
60
 
57
- @logger = Logger.new self.class.name
58
-
59
61
  @closed = nil
60
- @disconnected = nil
61
62
 
62
63
  @in_kex = false
63
64
 
64
- @sender = Sender.new
65
- @receiver = Receiver.new
65
+ @sender = Sender.new logger: logger
66
+ @receiver = Receiver.new logger: logger
66
67
 
67
68
  @sender_monitor = Monitor.new
68
69
  @receiver_monitor = Monitor.new
@@ -86,15 +87,16 @@ module HrrRbSsh
86
87
  end
87
88
 
88
89
  def send payload
90
+ raise Error::ClosedTransport if @closed
89
91
  @sender_monitor.synchronize do
90
92
  begin
91
93
  @sender.send self, payload
92
- rescue Errno::EPIPE => e
93
- @logger.warn { "IO is Broken PIPE" }
94
+ rescue IOError, SystemCallError => e
95
+ log_info { "#{e.message} (#{e.class})" }
94
96
  close
95
97
  raise Error::ClosedTransport
96
98
  rescue => e
97
- @logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
99
+ log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
98
100
  close
99
101
  raise Error::ClosedTransport
100
102
  end
@@ -108,25 +110,24 @@ module HrrRbSsh
108
110
  payload = @receiver.receive self
109
111
  case payload[0,1].unpack("C")[0]
110
112
  when Message::SSH_MSG_DISCONNECT::VALUE
111
- message = Message::SSH_MSG_DISCONNECT.decode payload
112
- @logger.debug { "received disconnect message: #{message.inspect}" }
113
- @disconnected = true
113
+ log_info { "received disconnect message" }
114
+ message = Message::SSH_MSG_DISCONNECT.new(logger: logger).decode payload
114
115
  close
115
116
  raise Error::ClosedTransport
116
117
  when Message::SSH_MSG_IGNORE::VALUE
117
- message = Message::SSH_MSG_IGNORE.decode payload
118
- @logger.debug { "received ignore message: #{message.inspect}" }
118
+ log_info { "received ignore message" }
119
+ message = Message::SSH_MSG_IGNORE.new(logger: logger).decode payload
119
120
  receive
120
121
  when Message::SSH_MSG_UNIMPLEMENTED::VALUE
121
- message = Message::SSH_MSG_UNIMPLEMENTED.decode payload
122
- @logger.debug { "received unimplemented message: #{message.inspect}" }
122
+ log_info { "received unimplemented message" }
123
+ message = Message::SSH_MSG_UNIMPLEMENTED.new(logger: logger).decode payload
123
124
  receive
124
125
  when Message::SSH_MSG_DEBUG::VALUE
125
- message = Message::SSH_MSG_DEBUG.decode payload
126
- @logger.debug { "received debug message: #{message.inspect}" }
126
+ log_info { "received debug message" }
127
+ message = Message::SSH_MSG_DEBUG.new(logger: logger).decode payload
127
128
  receive
128
129
  when Message::SSH_MSG_KEXINIT::VALUE
129
- @logger.debug { "received kexinit message" }
130
+ log_info { "received kexinit message" }
130
131
  if @in_kex
131
132
  payload
132
133
  else
@@ -137,20 +138,13 @@ module HrrRbSsh
137
138
  payload
138
139
  end
139
140
  rescue Error::ClosedTransport
140
- raise Error::ClosedTransport
141
- rescue EOFError => e
142
- close
143
- raise Error::ClosedTransport
144
- rescue IOError => e
145
- @logger.warn { "IO is closed" }
146
- close
147
- raise Error::ClosedTransport
148
- rescue Errno::ECONNRESET => e
149
- @logger.warn { "IO is RESET" }
141
+ raise
142
+ rescue EOFError, IOError, SystemCallError => e
143
+ log_info { "#{e.message} (#{e.class})" }
150
144
  close
151
145
  raise Error::ClosedTransport
152
146
  rescue => e
153
- @logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
147
+ log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
154
148
  close
155
149
  raise Error::ClosedTransport
156
150
  end
@@ -158,36 +152,47 @@ module HrrRbSsh
158
152
  end
159
153
 
160
154
  def start
161
- @logger.info { "start transport" }
162
-
155
+ log_info { "start transport" }
163
156
  begin
164
157
  exchange_version
165
158
  exchange_key
166
-
167
159
  case @mode
168
160
  when Mode::SERVER
169
161
  verify_service_request
162
+ when Mode::CLIENT
163
+ send_service_request
170
164
  end
171
-
172
165
  @closed = false
173
- rescue EOFError => e
166
+ rescue Error::ClosedTransport
167
+ raise
168
+ rescue EOFError, IOError, SystemCallError => e
169
+ log_info { "#{e.message} (#{e.class})" }
174
170
  close
171
+ raise Error::ClosedTransport
175
172
  rescue => e
176
- @logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
173
+ log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
177
174
  close
175
+ raise Error::ClosedTransport
178
176
  else
179
- @logger.info { "transport started" }
177
+ log_info { "transport started" }
180
178
  end
181
179
  end
182
180
 
183
181
  def close
184
- return if @closed
185
- @logger.info { "close transport" }
186
- @closed = true
187
- disconnect
188
- @incoming_compression_algorithm.close
189
- @outgoing_compression_algorithm.close
190
- @logger.info { "transport closed" }
182
+ @sender_monitor.synchronize do
183
+ return if @closed
184
+ log_info { "close transport" }
185
+ begin
186
+ disconnect
187
+ @incoming_compression_algorithm.close
188
+ @outgoing_compression_algorithm.close
189
+ rescue => e
190
+ log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
191
+ ensure
192
+ @closed = true
193
+ log_info { "transport closed" }
194
+ end
195
+ end
191
196
  end
192
197
 
193
198
  def closed?
@@ -195,17 +200,9 @@ module HrrRbSsh
195
200
  end
196
201
 
197
202
  def disconnect
198
- return if @disconnected
199
- @logger.info { "disconnect transport" }
200
- @disconnected = true
201
- begin
202
- send_disconnect
203
- rescue IOError
204
- @logger.warn { "IO is closed" }
205
- rescue => e
206
- @logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
207
- end
208
- @logger.info { "transport disconnected" }
203
+ log_info { "disconnect transport" }
204
+ send_disconnect
205
+ log_info { "transport disconnected" }
209
206
  end
210
207
 
211
208
  def exchange_version
@@ -235,7 +232,7 @@ module HrrRbSsh
235
232
  end
236
233
 
237
234
  def start_kex_algorithm
238
- @kex_algorithm.start self, @mode
235
+ @kex_algorithm.start self
239
236
  end
240
237
 
241
238
  def verify_service_request
@@ -314,10 +311,10 @@ module HrrRbSsh
314
311
  if str_io.string[-2..-1] == "#{CR}#{LF}"
315
312
  if str_io.string[0..3] == "SSH-"
316
313
  @remote_version = str_io.string[0..-3]
317
- @logger.info { "received remote version string: #{@remote_version}" }
314
+ log_info { "received remote version string: #{@remote_version}" }
318
315
  break
319
316
  else
320
- @logger.info { "received message before remote version string: #{str_io.string}" }
317
+ log_info { "received message before remote version string: #{str_io.string}" }
321
318
  str_io.rewind
322
319
  str_io.truncate(0)
323
320
  end
@@ -343,8 +340,16 @@ module HrrRbSsh
343
340
  :'description' => "disconnected by user",
344
341
  :'language tag' => ""
345
342
  }
346
- payload = Message::SSH_MSG_DISCONNECT.encode message
347
- send payload
343
+ payload = Message::SSH_MSG_DISCONNECT.new(logger: logger).encode message
344
+ @sender_monitor.synchronize do
345
+ begin
346
+ @sender.send self, payload
347
+ rescue IOError, SystemCallError => e
348
+ log_info { "#{e.message} (#{e.class})" }
349
+ rescue => e
350
+ log_error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
351
+ end
352
+ end
348
353
  end
349
354
 
350
355
  def send_kexinit
@@ -364,7 +369,7 @@ module HrrRbSsh
364
369
  :'first_kex_packet_follows' => false,
365
370
  :'0 (reserved for future extension)' => 0,
366
371
  }
367
- payload = Message::SSH_MSG_KEXINIT.encode message
372
+ payload = Message::SSH_MSG_KEXINIT.new(logger: logger).encode message
368
373
  send payload
369
374
 
370
375
  case @mode
@@ -382,7 +387,7 @@ module HrrRbSsh
382
387
  when Mode::CLIENT
383
388
  @i_s = payload
384
389
  end
385
- message = Message::SSH_MSG_KEXINIT.decode payload
390
+ message = Message::SSH_MSG_KEXINIT.new(logger: logger).decode payload
386
391
  update_remote_algorithms message
387
392
  end
388
393
 
@@ -390,28 +395,38 @@ module HrrRbSsh
390
395
  message = {
391
396
  :'message number' => Message::SSH_MSG_NEWKEYS::VALUE,
392
397
  }
393
- payload = Message::SSH_MSG_NEWKEYS.encode message
398
+ payload = Message::SSH_MSG_NEWKEYS.new(logger: logger).encode message
394
399
  send payload
395
400
  end
396
401
 
397
402
  def receive_newkeys payload
398
- message = Message::SSH_MSG_NEWKEYS.decode payload
403
+ message = Message::SSH_MSG_NEWKEYS.new(logger: logger).decode payload
399
404
  end
400
405
 
401
- def receive_service_request
406
+ def send_service_request
407
+ message = {
408
+ :'message number' => Message::SSH_MSG_SERVICE_REQUEST::VALUE,
409
+ :'service name' => 'ssh-userauth',
410
+ }
411
+ payload = Message::SSH_MSG_SERVICE_REQUEST.new(logger: logger).encode message
412
+ send payload
413
+
402
414
  payload = @receiver.receive self
403
- message = Message::SSH_MSG_SERVICE_REQUEST.decode payload
415
+ message = Message::SSH_MSG_SERVICE_ACCEPT.new(logger: logger).decode payload
416
+ end
404
417
 
405
- message
418
+ def receive_service_request
419
+ payload = @receiver.receive self
420
+ message = Message::SSH_MSG_SERVICE_REQUEST.new(logger: logger).decode payload
406
421
  end
407
422
 
408
423
  def send_service_accept service_name
409
- message = {
410
- :'message number' => Message::SSH_MSG_SERVICE_ACCEPT::VALUE,
411
- :'service name' => service_name,
412
- }
413
- payload = Message::SSH_MSG_SERVICE_ACCEPT.encode message
414
- send payload
424
+ message = {
425
+ :'message number' => Message::SSH_MSG_SERVICE_ACCEPT::VALUE,
426
+ :'service name' => service_name,
427
+ }
428
+ payload = Message::SSH_MSG_SERVICE_ACCEPT.new(logger: logger).encode message
429
+ send payload
415
430
  end
416
431
 
417
432
  def update_remote_algorithms message
@@ -430,14 +445,14 @@ module HrrRbSsh
430
445
  when Mode::SERVER
431
446
  kex_algorithm_name = @remote_kex_algorithms.find{ |a| @local_kex_algorithms.include? a } or raise
432
447
  server_host_key_algorithm_name = @remote_server_host_key_algorithms.find{ |a| @local_server_host_key_algorithms.include? a } or raise
448
+ server_secret_host_key = @options.fetch('transport_server_secret_host_keys', {}).fetch(server_host_key_algorithm_name, nil)
433
449
  when Mode::CLIENT
434
450
  kex_algorithm_name = @local_kex_algorithms.find{ |a| @remote_kex_algorithms.include? a } or raise
435
451
  server_host_key_algorithm_name = @local_server_host_key_algorithms.find{ |a| @remote_server_host_key_algorithms.include? a } or raise
452
+ server_secret_host_key = nil
436
453
  end
437
-
438
- server_secret_host_key = @options.fetch('transport_server_secret_host_keys', {}).fetch(server_host_key_algorithm_name, nil)
439
- @kex_algorithm = KexAlgorithm[kex_algorithm_name].new
440
454
  @server_host_key_algorithm = ServerHostKeyAlgorithm[server_host_key_algorithm_name].new server_secret_host_key
455
+ @kex_algorithm = KexAlgorithm[kex_algorithm_name].new
441
456
  end
442
457
 
443
458
  def update_encryption_mac_compression_algorithms
@@ -458,6 +473,15 @@ module HrrRbSsh
458
473
  outgoing_crpt_iv = @kex_algorithm.iv_s_to_c self, outgoing_encryption_algorithm_name
459
474
  incoming_crpt_key = @kex_algorithm.key_c_to_s self, incoming_encryption_algorithm_name
460
475
  outgoing_crpt_key = @kex_algorithm.key_s_to_c self, outgoing_encryption_algorithm_name
476
+ when Mode::CLIENT
477
+ encryption_algorithm_s_to_c_name = @local_encryption_algorithms_server_to_client.find{ |a| @remote_encryption_algorithms_server_to_client.include? a } or raise
478
+ encryption_algorithm_c_to_s_name = @local_encryption_algorithms_client_to_server.find{ |a| @remote_encryption_algorithms_client_to_server.include? a } or raise
479
+ incoming_encryption_algorithm_name = encryption_algorithm_s_to_c_name
480
+ outgoing_encryption_algorithm_name = encryption_algorithm_c_to_s_name
481
+ incoming_crpt_iv = @kex_algorithm.iv_s_to_c self, incoming_encryption_algorithm_name
482
+ outgoing_crpt_iv = @kex_algorithm.iv_c_to_s self, outgoing_encryption_algorithm_name
483
+ incoming_crpt_key = @kex_algorithm.key_s_to_c self, incoming_encryption_algorithm_name
484
+ outgoing_crpt_key = @kex_algorithm.key_c_to_s self, outgoing_encryption_algorithm_name
461
485
  end
462
486
  @incoming_encryption_algorithm = EncryptionAlgorithm[incoming_encryption_algorithm_name].new Direction::INCOMING, incoming_crpt_iv, incoming_crpt_key
463
487
  @outgoing_encryption_algorithm = EncryptionAlgorithm[outgoing_encryption_algorithm_name].new Direction::OUTGOING, outgoing_crpt_iv, outgoing_crpt_key
@@ -472,6 +496,13 @@ module HrrRbSsh
472
496
  outgoing_mac_algorithm_name = mac_algorithm_s_to_c_name
473
497
  incoming_mac_key = @kex_algorithm.mac_c_to_s self, incoming_mac_algorithm_name
474
498
  outgoing_mac_key = @kex_algorithm.mac_s_to_c self, outgoing_mac_algorithm_name
499
+ when Mode::CLIENT
500
+ mac_algorithm_s_to_c_name = @local_mac_algorithms_server_to_client.find{ |a| @remote_mac_algorithms_server_to_client.include? a } or raise
501
+ mac_algorithm_c_to_s_name = @local_mac_algorithms_client_to_server.find{ |a| @remote_mac_algorithms_client_to_server.include? a } or raise
502
+ incoming_mac_algorithm_name = mac_algorithm_s_to_c_name
503
+ outgoing_mac_algorithm_name = mac_algorithm_c_to_s_name
504
+ incoming_mac_key = @kex_algorithm.mac_s_to_c self, incoming_mac_algorithm_name
505
+ outgoing_mac_key = @kex_algorithm.mac_c_to_s self, outgoing_mac_algorithm_name
475
506
  end
476
507
  @incoming_mac_algorithm = MacAlgorithm[incoming_mac_algorithm_name].new incoming_mac_key
477
508
  @outgoing_mac_algorithm = MacAlgorithm[outgoing_mac_algorithm_name].new outgoing_mac_key
@@ -484,6 +515,11 @@ module HrrRbSsh
484
515
  compression_algorithm_s_to_c_name = @remote_compression_algorithms_server_to_client.find{ |a| @local_compression_algorithms_server_to_client.include? a } or raise
485
516
  incoming_compression_algorithm_name = compression_algorithm_c_to_s_name
486
517
  outgoing_compression_algorithm_name = compression_algorithm_s_to_c_name
518
+ when Mode::CLIENT
519
+ compression_algorithm_s_to_c_name = @local_compression_algorithms_server_to_client.find{ |a| @remote_compression_algorithms_server_to_client.include? a } or raise
520
+ compression_algorithm_c_to_s_name = @local_compression_algorithms_client_to_server.find{ |a| @remote_compression_algorithms_client_to_server.include? a } or raise
521
+ incoming_compression_algorithm_name = compression_algorithm_s_to_c_name
522
+ outgoing_compression_algorithm_name = compression_algorithm_c_to_s_name
487
523
  end
488
524
  @incoming_compression_algorithm.close
489
525
  @outgoing_compression_algorithm.close