hrr_rb_ssh 0.3.0.pre3 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -11,12 +11,14 @@ module HrrRbSsh
11
11
  attr_reader \
12
12
  :username,
13
13
  :variables,
14
- :options
14
+ :options,
15
+ :mode
15
16
 
16
- def initialize authentication, options={}
17
+ def initialize authentication, mode, options={}
17
18
  @logger = Logger.new self.class.name
18
19
 
19
20
  @authentication = authentication
21
+ @mode = mode
20
22
  @options = options
21
23
 
22
24
  @global_request_handler = GlobalRequestHandler.new self
@@ -38,21 +40,31 @@ module HrrRbSsh
38
40
  def assign_channel
39
41
  i = 0
40
42
  res = nil
41
- loop do
43
+ while true
42
44
  break unless @channels.keys.include?(i)
43
45
  i += 1
44
46
  end
45
47
  i
46
48
  end
47
49
 
48
- def start
50
+ def start foreground: true
51
+ @logger.info { "start connection" }
49
52
  @authentication.start
50
53
  @closed = false
51
- connection_loop
54
+ @connection_loop_thread = connection_loop_thread
55
+ if foreground
56
+ @connection_loop_thread.join
57
+ end
58
+ end
59
+
60
+ def loop
61
+ @connection_loop_thread.join
52
62
  end
53
63
 
54
64
  def close
65
+ @logger.info { "closing connection" }
55
66
  @closed = true
67
+ @authentication.close
56
68
  @channels.values.each do |channel|
57
69
  begin
58
70
  channel.close
@@ -62,47 +74,58 @@ module HrrRbSsh
62
74
  end
63
75
  @channels.clear
64
76
  @global_request_handler.close
77
+ @connection_loop_thread.join unless @connection_loop_thread == Thread.current
78
+ @logger.info { "connection closed" }
65
79
  end
66
80
 
67
81
  def closed?
68
82
  @closed
69
83
  end
70
84
 
71
- def connection_loop
72
- @logger.info { "start connection" }
73
- loop do
85
+ def connection_loop_thread
86
+ @logger.info { "start connection loop" }
87
+ Thread.new do
74
88
  begin
75
- payload = @authentication.receive
76
- rescue Error::ClosedAuthentication => e
89
+ while true
90
+ begin
91
+ payload = @authentication.receive
92
+ rescue Error::ClosedAuthentication => e
93
+ @logger.info { "authentication closed" }
94
+ break
95
+ end
96
+ @username ||= @authentication.username
97
+ @variables ||= @authentication.variables
98
+ case payload[0,1].unpack("C")[0]
99
+ when Message::SSH_MSG_GLOBAL_REQUEST::VALUE
100
+ global_request payload
101
+ when Message::SSH_MSG_CHANNEL_OPEN::VALUE
102
+ channel_open payload
103
+ when Message::SSH_MSG_CHANNEL_OPEN_CONFIRMATION::VALUE
104
+ channel_open_confirmation payload
105
+ when Message::SSH_MSG_CHANNEL_REQUEST::VALUE
106
+ channel_request payload
107
+ when Message::SSH_MSG_CHANNEL_WINDOW_ADJUST::VALUE
108
+ channel_window_adjust payload
109
+ when Message::SSH_MSG_CHANNEL_DATA::VALUE
110
+ channel_data payload
111
+ when Message::SSH_MSG_CHANNEL_EXTENDED_DATA::VALUE
112
+ channel_extended_data payload
113
+ when Message::SSH_MSG_CHANNEL_EOF::VALUE
114
+ channel_eof payload
115
+ when Message::SSH_MSG_CHANNEL_CLOSE::VALUE
116
+ channel_close payload
117
+ else
118
+ @logger.warn { "received unsupported message: id: #{payload[0,1].unpack("C")[0]}" }
119
+ end
120
+ end
121
+ rescue => e
122
+ @logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
123
+ ensure
77
124
  @logger.info { "closing connection loop" }
78
- break
79
- end
80
- @username ||= @authentication.username
81
- @variables ||= @authentication.variables
82
- case payload[0,1].unpack("C")[0]
83
- when Message::SSH_MSG_GLOBAL_REQUEST::VALUE
84
- global_request payload
85
- when Message::SSH_MSG_CHANNEL_OPEN::VALUE
86
- channel_open payload
87
- when Message::SSH_MSG_CHANNEL_OPEN_CONFIRMATION::VALUE
88
- channel_open_confirmation payload
89
- when Message::SSH_MSG_CHANNEL_REQUEST::VALUE
90
- channel_request payload
91
- when Message::SSH_MSG_CHANNEL_WINDOW_ADJUST::VALUE
92
- channel_window_adjust payload
93
- when Message::SSH_MSG_CHANNEL_DATA::VALUE
94
- channel_data payload
95
- when Message::SSH_MSG_CHANNEL_EOF::VALUE
96
- channel_eof payload
97
- when Message::SSH_MSG_CHANNEL_CLOSE::VALUE
98
- channel_close payload
99
- else
100
- @logger.warn { "received unsupported message: id: #{payload[0,1].unpack("C")[0]}" }
125
+ close
126
+ @logger.info { "connection loop closed" }
101
127
  end
102
128
  end
103
- @logger.info { "closing connection" }
104
- close
105
- @logger.info { "connection closed" }
106
129
  end
107
130
 
108
131
  def global_request payload
@@ -149,11 +172,40 @@ module HrrRbSsh
149
172
  channel.start
150
173
  send_channel_open_confirmation channel
151
174
  rescue => e
175
+ @logger.error { [e.backtrace[0], ": ", e.message, " (", e.class.to_s, ")\n\t", e.backtrace[1..-1].join("\n\t")].join }
152
176
  recipient_channel = message[:'sender channel']
153
177
  send_channel_open_failure recipient_channel, Message::SSH_MSG_CHANNEL_OPEN_FAILURE::ReasonCode::SSH_OPEN_CONNECT_FAILED, e.message
154
178
  end
155
179
  end
156
180
 
181
+ def request_channel_open channel_type, channel_specific_message={}, wait_response=true
182
+ @logger.info { 'request channel open' }
183
+ case channel_type
184
+ when "session"
185
+ channel = Channel.new self, {:'channel type' => channel_type}
186
+ @channels[channel.local_channel] = channel
187
+ end
188
+ message = {
189
+ :'message number' => Message::SSH_MSG_CHANNEL_OPEN::VALUE,
190
+ :'channel type' => channel_type,
191
+ :'sender channel' => channel.local_channel,
192
+ :'initial window size' => channel.local_window_size,
193
+ :'maximum packet size' => channel.local_maximum_packet_size,
194
+ }
195
+ send_channel_open message.merge(channel_specific_message)
196
+ @logger.info { 'sent channel open' }
197
+ if wait_response
198
+ @logger.info { 'wait response' }
199
+ channel.wait_until_started
200
+ end
201
+ unless channel.closed?
202
+ @logger.info { 'channel opened' }
203
+ channel
204
+ else
205
+ raise "Faild opening channel"
206
+ end
207
+ end
208
+
157
209
  def channel_open_confirmation payload
158
210
  @logger.info { 'received ' + Message::SSH_MSG_CHANNEL_OPEN_CONFIRMATION::ID }
159
211
  message = Message::SSH_MSG_CHANNEL_OPEN_CONFIRMATION.decode payload
@@ -183,12 +235,18 @@ module HrrRbSsh
183
235
  @channels[local_channel].receive_message_queue.enq message
184
236
  end
185
237
 
238
+ def channel_extended_data payload
239
+ @logger.info { 'received ' + Message::SSH_MSG_CHANNEL_EXTENDED_DATA::ID }
240
+ message = Message::SSH_MSG_CHANNEL_EXTENDED_DATA.decode payload
241
+ local_channel = message[:'recipient channel']
242
+ @channels[local_channel].receive_message_queue.enq message
243
+ end
244
+
186
245
  def channel_eof payload
187
246
  @logger.info { 'received ' + Message::SSH_MSG_CHANNEL_EOF::ID }
188
247
  message = Message::SSH_MSG_CHANNEL_EOF.decode payload
189
248
  local_channel = message[:'recipient channel']
190
- channel = @channels[local_channel]
191
- channel.receive_message_queue.close
249
+ @channels[local_channel].receive_message_queue.enq message
192
250
  end
193
251
 
194
252
  def channel_close payload
@@ -197,6 +255,9 @@ module HrrRbSsh
197
255
  local_channel = message[:'recipient channel']
198
256
  channel = @channels[local_channel]
199
257
  channel.close
258
+ @logger.info { "wait until threads closed in channel" }
259
+ channel.wait_until_closed
260
+ @logger.info { "channel closed" }
200
261
  @logger.info { "deleting channel" }
201
262
  @channels.delete local_channel
202
263
  @logger.info { "channel deleted" }
@@ -25,31 +25,31 @@ module HrrRbSsh
25
25
 
26
26
  def fatal
27
27
  if @@logger
28
- @@logger.fatal { "#{@name}: #{yield}" }
28
+ @@logger.fatal { "p#{Process.pid}.t#{Thread.current.object_id}: #{@name}: #{yield}" }
29
29
  end
30
30
  end
31
31
 
32
32
  def error
33
33
  if @@logger
34
- @@logger.error { "#{@name}: #{yield}" }
34
+ @@logger.error { "p#{Process.pid}.t#{Thread.current.object_id}: #{@name}: #{yield}" }
35
35
  end
36
36
  end
37
37
 
38
38
  def warn
39
39
  if @@logger
40
- @@logger.warn { "#{@name}: #{yield}" }
40
+ @@logger.warn { "p#{Process.pid}.t#{Thread.current.object_id}: #{@name}: #{yield}" }
41
41
  end
42
42
  end
43
43
 
44
44
  def info
45
45
  if @@logger
46
- @@logger.info { "#{@name}: #{yield}" }
46
+ @@logger.info { "p#{Process.pid}.t#{Thread.current.object_id}: #{@name}: #{yield}" }
47
47
  end
48
48
  end
49
49
 
50
50
  def debug
51
51
  if @@logger
52
- @@logger.debug { "#{@name}: #{yield}" }
52
+ @@logger.debug { "p#{Process.pid}.t#{Thread.current.object_id}: #{@name}: #{yield}" }
53
53
  end
54
54
  end
55
55
  end
@@ -20,9 +20,9 @@ module HrrRbSsh
20
20
 
21
21
  def start io
22
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
23
+ transport = Transport.new io, Mode::SERVER, @options
24
+ authentication = Authentication.new transport, Mode::SERVER, @options
25
+ connection = Connection.new authentication, Mode::SERVER, @options
26
26
  connection.start
27
27
  end
28
28
  end
@@ -22,74 +22,79 @@ module HrrRbSsh
22
22
  @dh.g = OpenSSL::BN.new(self.class::G)
23
23
  end
24
24
  @dh.generate_key!
25
+ @public_key = @dh.pub_key.to_i
25
26
  end
26
27
 
27
- def start transport, mode
28
- case mode
28
+ def start transport
29
+ case transport.mode
29
30
  when Mode::SERVER
30
- receive_kexdh_init transport.receive
31
+ @k_s = transport.server_host_key_algorithm.server_public_host_key
32
+ @f = @public_key
33
+ message = receive_kexdh_init transport.receive
34
+ @e = message[:'e']
35
+ @shared_secret = OpenSSL::BN.new(@dh.compute_key(OpenSSL::BN.new(@e)), 2).to_i
31
36
  send_kexdh_reply transport
32
- else
33
- raise "unsupported mode"
37
+ when Mode::CLIENT
38
+ @e = @public_key
39
+ send_kexdh_init transport
40
+ message = receive_kexdh_reply transport.receive
41
+ @k_s = message[:'server public host key and certificates (K_S)']
42
+ @f = message[:'f']
43
+ @shared_secret = OpenSSL::BN.new(@dh.compute_key(OpenSSL::BN.new(@f)), 2).to_i
34
44
  end
35
45
  end
36
46
 
37
- def set_e e
38
- @e = e
39
- end
40
-
41
47
  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
48
+ @shared_secret
47
49
  end
48
50
 
49
51
  def hash transport
50
- e = @e
51
- k = shared_secret
52
- f = pub_key
53
-
54
52
  h0_payload = {
55
53
  :'V_C' => transport.v_c,
56
54
  :'V_S' => transport.v_s,
57
55
  :'I_C' => transport.i_c,
58
56
  :'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,
57
+ :'K_S' => @k_s,
58
+ :'e' => @e,
59
+ :'f' => @f,
60
+ :'k' => @shared_secret,
63
61
  }
64
62
  h0 = H0.encode h0_payload
65
-
66
- h = OpenSSL::Digest.digest self.class::DIGEST, h0
67
-
68
- h
63
+ h = OpenSSL::Digest.digest self.class::DIGEST, h0
69
64
  end
70
65
 
71
66
  def sign transport
72
67
  h = hash transport
73
68
  s = transport.server_host_key_algorithm.sign h
74
-
75
- s
76
69
  end
77
70
 
78
71
  def receive_kexdh_init payload
79
- message = Message::SSH_MSG_KEXDH_INIT.decode payload
80
- set_e message[:'e']
72
+ Message::SSH_MSG_KEXDH_INIT.decode payload
81
73
  end
82
74
 
83
75
  def send_kexdh_reply transport
84
76
  message = {
85
77
  :'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,
78
+ :'server public host key and certificates (K_S)' => @k_s,
79
+ :'f' => @f,
88
80
  :'signature of H' => sign(transport),
89
81
  }
90
82
  payload = Message::SSH_MSG_KEXDH_REPLY.encode message
91
83
  transport.send payload
92
84
  end
85
+
86
+ def send_kexdh_init transport
87
+ message = {
88
+ :'message number' => Message::SSH_MSG_KEXDH_INIT::VALUE,
89
+ :'e' => @e,
90
+ }
91
+ payload = Message::SSH_MSG_KEXDH_INIT.encode message
92
+ transport.send payload
93
+ end
94
+
95
+ def receive_kexdh_reply payload
96
+ Message::SSH_MSG_KEXDH_REPLY.decode payload
97
+ end
93
98
  end
94
99
  end
95
100
  end
@@ -16,25 +16,50 @@ module HrrRbSsh
16
16
  @logger = Logger.new(self.class.name)
17
17
  end
18
18
 
19
- def start transport, mode
20
- case mode
19
+ def start transport
20
+ case transport.mode
21
21
  when Mode::SERVER
22
- receive_kex_dh_gex_request transport.receive
23
- set_dh
22
+ message = receive_kex_dh_gex_request transport.receive
23
+ @min = message[:'min']
24
+ @n = message[:'n']
25
+ @max = message[:'max']
26
+ initialize_dh
27
+ @p = @dh.p.to_i
28
+ @g = @dh.g.to_i
24
29
  send_kex_dh_gex_group transport
25
- receive_kex_dh_gex_init transport.receive
30
+ @k_s = transport.server_host_key_algorithm.server_public_host_key
31
+ @f = @public_key
32
+ message = receive_kex_dh_gex_init transport.receive
33
+ @e = message[:'e']
34
+ @shared_secret = OpenSSL::BN.new(@dh.compute_key(OpenSSL::BN.new(@e)), 2).to_i
26
35
  send_kex_dh_gex_reply transport
27
- else
28
- raise "unsupported mode"
36
+ when Mode::CLIENT
37
+ @min = 1024
38
+ @n = 2048
39
+ @max = 8192
40
+ send_kex_dh_gex_request transport
41
+ message = receive_kex_dh_gex_group transport.receive
42
+ @p = message[:'p']
43
+ @g = message[:'g']
44
+ initialize_dh [@p, @g]
45
+ @e = @public_key
46
+ send_kex_dh_gex_init transport
47
+ message = receive_kex_dh_gex_reply transport.receive
48
+ @k_s = message[:'server public host key and certificates (K_S)']
49
+ @f = message[:'f']
50
+ @shared_secret = OpenSSL::BN.new(@dh.compute_key(OpenSSL::BN.new(@f)), 2).to_i
29
51
  end
30
52
  end
31
53
 
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
54
+ def initialize_dh pg=nil
55
+ unless pg
56
+ 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
57
+ candidate = p_list.find{ |e| e[0] <= @n }
58
+ raise unless (@min .. @max).include?(candidate[0])
59
+ p, g = candidate[1], 2
60
+ else
61
+ p, g = pg
62
+ end
38
63
  @dh = OpenSSL::PKey::DH.new
39
64
  if @dh.respond_to?(:set_pqg)
40
65
  @dh.set_pqg OpenSSL::BN.new(p, 16), nil, OpenSSL::BN.new(g)
@@ -43,85 +68,94 @@ module HrrRbSsh
43
68
  @dh.g = OpenSSL::BN.new(g)
44
69
  end
45
70
  @dh.generate_key!
46
- end
47
-
48
- def set_e e
49
- @e = e
71
+ @public_key = @dh.pub_key.to_i
50
72
  end
51
73
 
52
74
  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
75
+ @shared_secret
58
76
  end
59
77
 
60
78
  def hash transport
61
- e = @e
62
- k = shared_secret
63
- f = pub_key
64
-
65
79
  h0_payload = {
66
80
  :'V_C' => transport.v_c,
67
81
  :'V_S' => transport.v_s,
68
82
  :'I_C' => transport.i_c,
69
83
  :'I_S' => transport.i_s,
70
- :'K_S' => transport.server_host_key_algorithm.server_public_host_key,
84
+ :'K_S' => @k_s,
71
85
  :'min' => @min,
72
86
  :'n' => @n,
73
87
  :'max' => @max,
74
- :'p' => @dh.p.to_i,
75
- :'g' => @dh.g.to_i,
76
- :'e' => e,
77
- :'f' => f,
78
- :'k' => k,
88
+ :'p' => @p,
89
+ :'g' => @g,
90
+ :'e' => @e,
91
+ :'f' => @f,
92
+ :'k' => @shared_secret,
79
93
  }
80
94
  h0 = H0.encode h0_payload
81
-
82
95
  h = OpenSSL::Digest.digest self.class::DIGEST, h0
83
-
84
- h
85
96
  end
86
97
 
87
98
  def sign transport
88
99
  h = hash transport
89
100
  s = transport.server_host_key_algorithm.sign h
90
- s
91
101
  end
92
102
 
93
103
  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']
104
+ Message::SSH_MSG_KEX_DH_GEX_REQUEST.decode payload
98
105
  end
99
106
 
100
107
  def send_kex_dh_gex_group transport
101
108
  message = {
102
109
  :'message number' => Message::SSH_MSG_KEX_DH_GEX_GROUP::VALUE,
103
- :'p' => @dh.p.to_i,
104
- :'g' => @dh.g.to_i,
110
+ :'p' => @p,
111
+ :'g' => @g,
105
112
  }
106
113
  payload = Message::SSH_MSG_KEX_DH_GEX_GROUP.encode message
107
114
  transport.send payload
108
115
  end
109
116
 
110
117
  def receive_kex_dh_gex_init payload
111
- message = Message::SSH_MSG_KEX_DH_GEX_INIT.decode payload
112
- set_e message[:'e']
118
+ Message::SSH_MSG_KEX_DH_GEX_INIT.decode payload
113
119
  end
114
120
 
115
121
  def send_kex_dh_gex_reply transport
116
122
  message = {
117
123
  :'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,
124
+ :'server public host key and certificates (K_S)' => @k_s,
125
+ :'f' => @f,
120
126
  :'signature of H' => sign(transport),
121
127
  }
122
128
  payload = Message::SSH_MSG_KEX_DH_GEX_REPLY.encode message
123
129
  transport.send payload
124
130
  end
131
+
132
+ def send_kex_dh_gex_request transport
133
+ message = {
134
+ :'message number' => Message::SSH_MSG_KEX_DH_GEX_REQUEST::VALUE,
135
+ :'min' => @min,
136
+ :'n' => @n,
137
+ :'max' => @max,
138
+ }
139
+ payload = Message::SSH_MSG_KEX_DH_GEX_REQUEST.encode message
140
+ transport.send payload
141
+ end
142
+
143
+ def receive_kex_dh_gex_group payload
144
+ Message::SSH_MSG_KEX_DH_GEX_GROUP.decode payload
145
+ end
146
+
147
+ def send_kex_dh_gex_init transport
148
+ message = {
149
+ :'message number' => Message::SSH_MSG_KEX_DH_GEX_INIT::VALUE,
150
+ :'e' => @e,
151
+ }
152
+ payload = Message::SSH_MSG_KEX_DH_GEX_INIT.encode message
153
+ transport.send payload
154
+ end
155
+
156
+ def receive_kex_dh_gex_reply payload
157
+ Message::SSH_MSG_KEX_DH_GEX_REPLY.decode payload
158
+ end
125
159
  end
126
160
  end
127
161
  end
@@ -16,74 +16,79 @@ module HrrRbSsh
16
16
  @logger = Logger.new(self.class.name)
17
17
  @dh = OpenSSL::PKey::EC.new(self.class::CURVE_NAME)
18
18
  @dh.generate_key
19
+ @public_key = @dh.public_key.to_bn.to_i
19
20
  end
20
21
 
21
- def start transport, mode
22
- case mode
22
+ def start transport
23
+ case transport.mode
23
24
  when Mode::SERVER
24
- receive_kexecdh_init transport.receive
25
+ @k_s = transport.server_host_key_algorithm.server_public_host_key
26
+ @q_s = @public_key
27
+ message = receive_kexecdh_init transport.receive
28
+ @q_c = message[:'Q_C']
29
+ @shared_secret = OpenSSL::BN.new(@dh.dh_compute_key(OpenSSL::PKey::EC::Point.new(OpenSSL::PKey::EC.new(self.class::CURVE_NAME).group, OpenSSL::BN.new(@q_c))), 2).to_i
25
30
  send_kexecdh_reply transport
26
- else
27
- raise "unsupported mode"
31
+ when Mode::CLIENT
32
+ @q_c = @public_key
33
+ send_kexecdh_init transport
34
+ message = receive_kexecdh_reply transport.receive
35
+ @k_s = message[:'K_S']
36
+ @q_s = message[:'Q_S']
37
+ @shared_secret = OpenSSL::BN.new(@dh.dh_compute_key(OpenSSL::PKey::EC::Point.new(OpenSSL::PKey::EC.new(self.class::CURVE_NAME).group, OpenSSL::BN.new(@q_s))), 2).to_i
28
38
  end
29
39
  end
30
40
 
31
- def set_q_c q_c
32
- @q_c = q_c
33
- end
34
-
35
41
  def shared_secret
36
- k = OpenSSL::BN.new(@dh.dh_compute_key(OpenSSL::PKey::EC::Point.new(OpenSSL::PKey::EC.new(self.class::CURVE_NAME).group, OpenSSL::BN.new(@q_c))), 2).to_i
37
- end
38
-
39
- def public_key
40
- f = @dh.public_key.to_bn.to_i
42
+ @shared_secret
41
43
  end
42
44
 
43
45
  def hash transport
44
- q_c = @q_c
45
- q_s = public_key
46
- k = shared_secret
47
-
48
46
  h0_payload = {
49
47
  :'V_C' => transport.v_c,
50
48
  :'V_S' => transport.v_s,
51
49
  :'I_C' => transport.i_c,
52
50
  :'I_S' => transport.i_s,
53
- :'K_S' => transport.server_host_key_algorithm.server_public_host_key,
54
- :'Q_C' => q_c,
55
- :'Q_S' => q_s,
56
- :'K' => k,
51
+ :'K_S' => @k_s,
52
+ :'Q_C' => @q_c,
53
+ :'Q_S' => @q_s,
54
+ :'K' => @shared_secret,
57
55
  }
58
56
  h0 = H0.encode h0_payload
59
-
60
- h = OpenSSL::Digest.digest self.class::DIGEST, h0
61
-
62
- h
57
+ h = OpenSSL::Digest.digest self.class::DIGEST, h0
63
58
  end
64
59
 
65
60
  def sign transport
66
61
  h = hash transport
67
62
  s = transport.server_host_key_algorithm.sign h
68
-
69
- s
70
63
  end
71
64
 
72
65
  def receive_kexecdh_init payload
73
- message = Message::SSH_MSG_KEXECDH_INIT.decode payload
74
- set_q_c message[:'Q_C']
66
+ Message::SSH_MSG_KEXECDH_INIT.decode payload
75
67
  end
76
68
 
77
69
  def send_kexecdh_reply transport
78
70
  message = {
79
71
  :'message number' => Message::SSH_MSG_KEXECDH_REPLY::VALUE,
80
- :'K_S' => transport.server_host_key_algorithm.server_public_host_key,
81
- :'Q_S' => public_key,
72
+ :'K_S' => @k_s,
73
+ :'Q_S' => @q_s,
82
74
  :'signature of H' => sign(transport),
83
75
  }
84
76
  payload = Message::SSH_MSG_KEXECDH_REPLY.encode message
85
77
  transport.send payload
86
78
  end
79
+
80
+ def send_kexecdh_init transport
81
+ message = {
82
+ :'message number' => Message::SSH_MSG_KEXECDH_INIT::VALUE,
83
+ :'Q_C' => @q_c,
84
+ }
85
+ payload = Message::SSH_MSG_KEXECDH_INIT.encode message
86
+ transport.send payload
87
+ end
88
+
89
+ def receive_kexecdh_reply payload
90
+ Message::SSH_MSG_KEXECDH_REPLY.decode payload
91
+ end
87
92
  end
88
93
  end
89
94
  end