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
@@ -2,14 +2,16 @@
2
2
  # vim: et ts=2 sw=2
3
3
 
4
4
  require 'zlib'
5
- require 'hrr_rb_ssh/logger'
5
+ require 'hrr_rb_ssh/loggable'
6
6
 
7
7
  module HrrRbSsh
8
8
  class Transport
9
9
  class CompressionAlgorithm
10
10
  module Functionable
11
- def initialize direction
12
- @logger = Logger.new(self.class.name)
11
+ include Loggable
12
+
13
+ def initialize direction, logger: nil
14
+ self.logger = logger
13
15
  case direction
14
16
  when Direction::OUTGOING
15
17
  @deflator = ::Zlib::Deflate.new
@@ -1,14 +1,16 @@
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
 
6
6
  module HrrRbSsh
7
7
  class Transport
8
8
  class CompressionAlgorithm
9
9
  module Unfunctionable
10
- def initialize direction=nil
11
- @logger = Logger.new(self.class.name)
10
+ include Loggable
11
+
12
+ def initialize direction=nil, logger: nil
13
+ self.logger = logger
12
14
  end
13
15
 
14
16
  def deflate data
@@ -1,20 +1,22 @@
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
 
6
6
  module HrrRbSsh
7
7
  class Transport
8
8
  class EncryptionAlgorithm
9
9
  module Functionable
10
+ include Loggable
11
+
10
12
  def self.included klass
11
13
  cipher = OpenSSL::Cipher.new(klass::CIPHER_NAME)
12
14
  klass.const_set(:IV_LENGTH, cipher.iv_len)
13
15
  klass.const_set(:KEY_LENGTH, cipher.key_len)
14
16
  end
15
17
 
16
- def initialize direction, iv, key
17
- @logger = Logger.new(self.class.name)
18
+ def initialize direction, iv, key, logger: nil
19
+ self.logger = logger
18
20
  @cipher = OpenSSL::Cipher.new(self.class::CIPHER_NAME)
19
21
  case direction
20
22
  when Direction::OUTGOING
@@ -1,19 +1,21 @@
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
 
6
6
  module HrrRbSsh
7
7
  class Transport
8
8
  class EncryptionAlgorithm
9
9
  module Unfunctionable
10
+ include Loggable
11
+
10
12
  def self.included klass
11
13
  klass.const_set(:IV_LENGTH, 0)
12
14
  klass.const_set(:KEY_LENGTH, 0)
13
15
  end
14
16
 
15
- def initialize direction=nil, iv=nil, key=nil
16
- @logger = Logger.new(self.class.name)
17
+ def initialize direction=nil, iv=nil, key=nil, logger: nil
18
+ self.logger = logger
17
19
  end
18
20
 
19
21
  def block_size
@@ -2,7 +2,7 @@
2
2
  # vim: et ts=2 sw=2
3
3
 
4
4
  require 'openssl'
5
- require 'hrr_rb_ssh/logger'
5
+ require 'hrr_rb_ssh/loggable'
6
6
  require 'hrr_rb_ssh/data_type'
7
7
  require 'hrr_rb_ssh/transport/kex_algorithm/iv_computable'
8
8
 
@@ -10,10 +10,11 @@ module HrrRbSsh
10
10
  class Transport
11
11
  class KexAlgorithm
12
12
  module DiffieHellman
13
+ include Loggable
13
14
  include IvComputable
14
15
 
15
- def initialize
16
- @logger = Logger.new(self.class.name)
16
+ def initialize logger: nil
17
+ self.logger = logger
17
18
  @dh = OpenSSL::PKey::DH.new
18
19
  if @dh.respond_to?(:set_pqg)
19
20
  @dh.set_pqg OpenSSL::BN.new(self.class::P, 16), nil, OpenSSL::BN.new(self.class::G)
@@ -22,74 +23,79 @@ module HrrRbSsh
22
23
  @dh.g = OpenSSL::BN.new(self.class::G)
23
24
  end
24
25
  @dh.generate_key!
26
+ @public_key = @dh.pub_key.to_i
25
27
  end
26
28
 
27
- def start transport, mode
28
- case mode
29
+ def start transport
30
+ case transport.mode
29
31
  when Mode::SERVER
30
- receive_kexdh_init transport.receive
32
+ @k_s = transport.server_host_key_algorithm.server_public_host_key
33
+ @f = @public_key
34
+ message = receive_kexdh_init transport.receive
35
+ @e = message[:'e']
36
+ @shared_secret = OpenSSL::BN.new(@dh.compute_key(OpenSSL::BN.new(@e)), 2).to_i
31
37
  send_kexdh_reply transport
32
- else
33
- raise "unsupported mode"
38
+ when Mode::CLIENT
39
+ @e = @public_key
40
+ send_kexdh_init transport
41
+ message = receive_kexdh_reply transport.receive
42
+ @k_s = message[:'server public host key and certificates (K_S)']
43
+ @f = message[:'f']
44
+ @shared_secret = OpenSSL::BN.new(@dh.compute_key(OpenSSL::BN.new(@f)), 2).to_i
34
45
  end
35
46
  end
36
47
 
37
- def set_e e
38
- @e = e
39
- end
40
-
41
48
  def shared_secret
42
- k = OpenSSL::BN.new(@dh.compute_key(OpenSSL::BN.new(@e)), 2).to_i
43
- end
44
-
45
- def pub_key
46
- f = @dh.pub_key.to_i
49
+ @shared_secret
47
50
  end
48
51
 
49
52
  def hash transport
50
- e = @e
51
- k = shared_secret
52
- f = pub_key
53
-
54
53
  h0_payload = {
55
54
  :'V_C' => transport.v_c,
56
55
  :'V_S' => transport.v_s,
57
56
  :'I_C' => transport.i_c,
58
57
  :'I_S' => transport.i_s,
59
- :'K_S' => transport.server_host_key_algorithm.server_public_host_key,
60
- :'e' => e,
61
- :'f' => f,
62
- :'k' => k,
58
+ :'K_S' => @k_s,
59
+ :'e' => @e,
60
+ :'f' => @f,
61
+ :'k' => @shared_secret,
63
62
  }
64
- h0 = H0.encode h0_payload
65
-
66
- h = OpenSSL::Digest.digest self.class::DIGEST, h0
67
-
68
- h
63
+ h0 = H0.new(logger: logger).encode h0_payload
64
+ h = OpenSSL::Digest.digest self.class::DIGEST, h0
69
65
  end
70
66
 
71
67
  def sign transport
72
68
  h = hash transport
73
69
  s = transport.server_host_key_algorithm.sign h
74
-
75
- s
76
70
  end
77
71
 
78
72
  def receive_kexdh_init payload
79
- message = Message::SSH_MSG_KEXDH_INIT.decode payload
80
- set_e message[:'e']
73
+ Message::SSH_MSG_KEXDH_INIT.new(logger: logger).decode payload
81
74
  end
82
75
 
83
76
  def send_kexdh_reply transport
84
77
  message = {
85
78
  :'message number' => Message::SSH_MSG_KEXDH_REPLY::VALUE,
86
- :'server public host key and certificates (K_S)' => transport.server_host_key_algorithm.server_public_host_key,
87
- :'f' => pub_key,
79
+ :'server public host key and certificates (K_S)' => @k_s,
80
+ :'f' => @f,
88
81
  :'signature of H' => sign(transport),
89
82
  }
90
- payload = Message::SSH_MSG_KEXDH_REPLY.encode message
83
+ payload = Message::SSH_MSG_KEXDH_REPLY.new(logger: logger).encode message
84
+ transport.send payload
85
+ end
86
+
87
+ def send_kexdh_init transport
88
+ message = {
89
+ :'message number' => Message::SSH_MSG_KEXDH_INIT::VALUE,
90
+ :'e' => @e,
91
+ }
92
+ payload = Message::SSH_MSG_KEXDH_INIT.new(logger: logger).encode message
91
93
  transport.send payload
92
94
  end
95
+
96
+ def receive_kexdh_reply payload
97
+ Message::SSH_MSG_KEXDH_REPLY.new(logger: logger).decode payload
98
+ end
93
99
  end
94
100
  end
95
101
  end
@@ -8,10 +8,8 @@ module HrrRbSsh
8
8
  class Transport
9
9
  class KexAlgorithm
10
10
  module DiffieHellman
11
- module H0
12
- class << self
13
- include Codable
14
- end
11
+ class H0
12
+ include Codable
15
13
  DEFINITION = [
16
14
  [DataType::String, :'V_C'],
17
15
  [DataType::String, :'V_S'],
@@ -2,7 +2,7 @@
2
2
  # vim: et ts=2 sw=2
3
3
 
4
4
  require 'openssl'
5
- require 'hrr_rb_ssh/logger'
5
+ require 'hrr_rb_ssh/loggable'
6
6
  require 'hrr_rb_ssh/data_type'
7
7
  require 'hrr_rb_ssh/transport/kex_algorithm/iv_computable'
8
8
 
@@ -10,31 +10,57 @@ module HrrRbSsh
10
10
  class Transport
11
11
  class KexAlgorithm
12
12
  module DiffieHellmanGroupExchange
13
+ include Loggable
13
14
  include IvComputable
14
15
 
15
- def initialize
16
- @logger = Logger.new(self.class.name)
16
+ def initialize logger: nil
17
+ self.logger = logger
17
18
  end
18
19
 
19
- def start transport, mode
20
- case mode
20
+ def start transport
21
+ case transport.mode
21
22
  when Mode::SERVER
22
- receive_kex_dh_gex_request transport.receive
23
- set_dh
23
+ message = receive_kex_dh_gex_request transport.receive
24
+ @min = message[:'min']
25
+ @n = message[:'n']
26
+ @max = message[:'max']
27
+ initialize_dh
28
+ @p = @dh.p.to_i
29
+ @g = @dh.g.to_i
24
30
  send_kex_dh_gex_group transport
25
- receive_kex_dh_gex_init transport.receive
31
+ @k_s = transport.server_host_key_algorithm.server_public_host_key
32
+ @f = @public_key
33
+ message = receive_kex_dh_gex_init transport.receive
34
+ @e = message[:'e']
35
+ @shared_secret = OpenSSL::BN.new(@dh.compute_key(OpenSSL::BN.new(@e)), 2).to_i
26
36
  send_kex_dh_gex_reply transport
27
- else
28
- raise "unsupported mode"
37
+ when Mode::CLIENT
38
+ @min = 1024
39
+ @n = 2048
40
+ @max = 8192
41
+ send_kex_dh_gex_request transport
42
+ message = receive_kex_dh_gex_group transport.receive
43
+ @p = message[:'p']
44
+ @g = message[:'g']
45
+ initialize_dh [@p, @g]
46
+ @e = @public_key
47
+ send_kex_dh_gex_init transport
48
+ message = receive_kex_dh_gex_reply transport.receive
49
+ @k_s = message[:'server public host key and certificates (K_S)']
50
+ @f = message[:'f']
51
+ @shared_secret = OpenSSL::BN.new(@dh.compute_key(OpenSSL::BN.new(@f)), 2).to_i
29
52
  end
30
53
  end
31
54
 
32
- def set_dh
33
- p_list = KexAlgorithm.list_supported.map{ |e| KexAlgorithm[e] }.select{ |e| e.const_defined?(:P) }.map{ |e| [OpenSSL::BN.new(e::P,16).num_bits, e::P] }.sort_by{ |e| e[0] }.reverse
34
- candidate = p_list.find{ |e| e[0] <= @n }
35
- raise unless (@min .. @max).include?(candidate[0])
36
- p = candidate[1]
37
- g = 2
55
+ def initialize_dh pg=nil
56
+ unless pg
57
+ p_list = KexAlgorithm.list_supported.map{ |e| KexAlgorithm[e] }.select{ |e| e.const_defined?(:P) }.map{ |e| [OpenSSL::BN.new(e::P,16).num_bits, e::P] }.sort_by{ |e| e[0] }.reverse
58
+ candidate = p_list.find{ |e| e[0] <= @n }
59
+ raise unless (@min .. @max).include?(candidate[0])
60
+ p, g = candidate[1], 2
61
+ else
62
+ p, g = pg
63
+ end
38
64
  @dh = OpenSSL::PKey::DH.new
39
65
  if @dh.respond_to?(:set_pqg)
40
66
  @dh.set_pqg OpenSSL::BN.new(p, 16), nil, OpenSSL::BN.new(g)
@@ -43,85 +69,94 @@ module HrrRbSsh
43
69
  @dh.g = OpenSSL::BN.new(g)
44
70
  end
45
71
  @dh.generate_key!
46
- end
47
-
48
- def set_e e
49
- @e = e
72
+ @public_key = @dh.pub_key.to_i
50
73
  end
51
74
 
52
75
  def shared_secret
53
- k = OpenSSL::BN.new(@dh.compute_key(OpenSSL::BN.new(@e)), 2).to_i
54
- end
55
-
56
- def pub_key
57
- f = @dh.pub_key.to_i
76
+ @shared_secret
58
77
  end
59
78
 
60
79
  def hash transport
61
- e = @e
62
- k = shared_secret
63
- f = pub_key
64
-
65
80
  h0_payload = {
66
81
  :'V_C' => transport.v_c,
67
82
  :'V_S' => transport.v_s,
68
83
  :'I_C' => transport.i_c,
69
84
  :'I_S' => transport.i_s,
70
- :'K_S' => transport.server_host_key_algorithm.server_public_host_key,
85
+ :'K_S' => @k_s,
71
86
  :'min' => @min,
72
87
  :'n' => @n,
73
88
  :'max' => @max,
74
- :'p' => @dh.p.to_i,
75
- :'g' => @dh.g.to_i,
76
- :'e' => e,
77
- :'f' => f,
78
- :'k' => k,
89
+ :'p' => @p,
90
+ :'g' => @g,
91
+ :'e' => @e,
92
+ :'f' => @f,
93
+ :'k' => @shared_secret,
79
94
  }
80
- h0 = H0.encode h0_payload
81
-
95
+ h0 = H0.new(logger: logger).encode h0_payload
82
96
  h = OpenSSL::Digest.digest self.class::DIGEST, h0
83
-
84
- h
85
97
  end
86
98
 
87
99
  def sign transport
88
100
  h = hash transport
89
101
  s = transport.server_host_key_algorithm.sign h
90
- s
91
102
  end
92
103
 
93
104
  def receive_kex_dh_gex_request payload
94
- message = Message::SSH_MSG_KEX_DH_GEX_REQUEST.decode payload
95
- @min = message[:'min']
96
- @n = message[:'n']
97
- @max = message[:'max']
105
+ Message::SSH_MSG_KEX_DH_GEX_REQUEST.new(logger: logger).decode payload
98
106
  end
99
107
 
100
108
  def send_kex_dh_gex_group transport
101
109
  message = {
102
110
  :'message number' => Message::SSH_MSG_KEX_DH_GEX_GROUP::VALUE,
103
- :'p' => @dh.p.to_i,
104
- :'g' => @dh.g.to_i,
111
+ :'p' => @p,
112
+ :'g' => @g,
105
113
  }
106
- payload = Message::SSH_MSG_KEX_DH_GEX_GROUP.encode message
114
+ payload = Message::SSH_MSG_KEX_DH_GEX_GROUP.new(logger: logger).encode message
107
115
  transport.send payload
108
116
  end
109
117
 
110
118
  def receive_kex_dh_gex_init payload
111
- message = Message::SSH_MSG_KEX_DH_GEX_INIT.decode payload
112
- set_e message[:'e']
119
+ Message::SSH_MSG_KEX_DH_GEX_INIT.new(logger: logger).decode payload
113
120
  end
114
121
 
115
122
  def send_kex_dh_gex_reply transport
116
123
  message = {
117
124
  :'message number' => Message::SSH_MSG_KEX_DH_GEX_REPLY::VALUE,
118
- :'server public host key and certificates (K_S)' => transport.server_host_key_algorithm.server_public_host_key,
119
- :'f' => pub_key,
125
+ :'server public host key and certificates (K_S)' => @k_s,
126
+ :'f' => @f,
120
127
  :'signature of H' => sign(transport),
121
128
  }
122
- payload = Message::SSH_MSG_KEX_DH_GEX_REPLY.encode message
129
+ payload = Message::SSH_MSG_KEX_DH_GEX_REPLY.new(logger: logger).encode message
130
+ transport.send payload
131
+ end
132
+
133
+ def send_kex_dh_gex_request transport
134
+ message = {
135
+ :'message number' => Message::SSH_MSG_KEX_DH_GEX_REQUEST::VALUE,
136
+ :'min' => @min,
137
+ :'n' => @n,
138
+ :'max' => @max,
139
+ }
140
+ payload = Message::SSH_MSG_KEX_DH_GEX_REQUEST.new(logger: logger).encode message
141
+ transport.send payload
142
+ end
143
+
144
+ def receive_kex_dh_gex_group payload
145
+ Message::SSH_MSG_KEX_DH_GEX_GROUP.new(logger: logger).decode payload
146
+ end
147
+
148
+ def send_kex_dh_gex_init transport
149
+ message = {
150
+ :'message number' => Message::SSH_MSG_KEX_DH_GEX_INIT::VALUE,
151
+ :'e' => @e,
152
+ }
153
+ payload = Message::SSH_MSG_KEX_DH_GEX_INIT.new(logger: logger).encode message
123
154
  transport.send payload
124
155
  end
156
+
157
+ def receive_kex_dh_gex_reply payload
158
+ Message::SSH_MSG_KEX_DH_GEX_REPLY.new(logger: logger).decode payload
159
+ end
125
160
  end
126
161
  end
127
162
  end