net-ssh 4.1.0 → 6.1.0

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 (111) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/.gitignore +5 -0
  5. data/.rubocop.yml +8 -2
  6. data/.rubocop_todo.yml +405 -552
  7. data/.travis.yml +23 -22
  8. data/CHANGES.txt +112 -1
  9. data/Gemfile +1 -7
  10. data/{Gemfile.norbnacl → Gemfile.noed25519} +1 -1
  11. data/Manifest +4 -5
  12. data/README.md +287 -0
  13. data/Rakefile +40 -29
  14. data/appveyor.yml +12 -6
  15. data/lib/net/ssh.rb +68 -32
  16. data/lib/net/ssh/authentication/agent.rb +234 -222
  17. data/lib/net/ssh/authentication/certificate.rb +175 -164
  18. data/lib/net/ssh/authentication/constants.rb +17 -14
  19. data/lib/net/ssh/authentication/ed25519.rb +162 -141
  20. data/lib/net/ssh/authentication/ed25519_loader.rb +32 -29
  21. data/lib/net/ssh/authentication/key_manager.rb +40 -9
  22. data/lib/net/ssh/authentication/methods/abstract.rb +53 -47
  23. data/lib/net/ssh/authentication/methods/hostbased.rb +32 -33
  24. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +1 -1
  25. data/lib/net/ssh/authentication/methods/none.rb +10 -10
  26. data/lib/net/ssh/authentication/methods/password.rb +13 -13
  27. data/lib/net/ssh/authentication/methods/publickey.rb +56 -55
  28. data/lib/net/ssh/authentication/pageant.rb +468 -465
  29. data/lib/net/ssh/authentication/pub_key_fingerprint.rb +43 -0
  30. data/lib/net/ssh/authentication/session.rb +130 -122
  31. data/lib/net/ssh/buffer.rb +345 -312
  32. data/lib/net/ssh/buffered_io.rb +163 -163
  33. data/lib/net/ssh/config.rb +316 -238
  34. data/lib/net/ssh/connection/channel.rb +670 -650
  35. data/lib/net/ssh/connection/constants.rb +30 -26
  36. data/lib/net/ssh/connection/event_loop.rb +108 -105
  37. data/lib/net/ssh/connection/keepalive.rb +54 -50
  38. data/lib/net/ssh/connection/session.rb +682 -671
  39. data/lib/net/ssh/connection/term.rb +180 -176
  40. data/lib/net/ssh/errors.rb +101 -99
  41. data/lib/net/ssh/key_factory.rb +195 -108
  42. data/lib/net/ssh/known_hosts.rb +161 -152
  43. data/lib/net/ssh/loggable.rb +57 -55
  44. data/lib/net/ssh/packet.rb +82 -78
  45. data/lib/net/ssh/prompt.rb +55 -53
  46. data/lib/net/ssh/proxy/command.rb +104 -89
  47. data/lib/net/ssh/proxy/errors.rb +12 -8
  48. data/lib/net/ssh/proxy/http.rb +93 -91
  49. data/lib/net/ssh/proxy/https.rb +42 -39
  50. data/lib/net/ssh/proxy/jump.rb +50 -47
  51. data/lib/net/ssh/proxy/socks4.rb +0 -2
  52. data/lib/net/ssh/proxy/socks5.rb +11 -12
  53. data/lib/net/ssh/service/forward.rb +370 -317
  54. data/lib/net/ssh/test.rb +83 -77
  55. data/lib/net/ssh/test/channel.rb +146 -142
  56. data/lib/net/ssh/test/extensions.rb +150 -146
  57. data/lib/net/ssh/test/kex.rb +35 -31
  58. data/lib/net/ssh/test/local_packet.rb +48 -44
  59. data/lib/net/ssh/test/packet.rb +87 -84
  60. data/lib/net/ssh/test/remote_packet.rb +35 -31
  61. data/lib/net/ssh/test/script.rb +173 -171
  62. data/lib/net/ssh/test/socket.rb +59 -55
  63. data/lib/net/ssh/transport/algorithms.rb +430 -364
  64. data/lib/net/ssh/transport/cipher_factory.rb +95 -91
  65. data/lib/net/ssh/transport/constants.rb +33 -25
  66. data/lib/net/ssh/transport/ctr.rb +33 -11
  67. data/lib/net/ssh/transport/hmac.rb +15 -13
  68. data/lib/net/ssh/transport/hmac/abstract.rb +82 -63
  69. data/lib/net/ssh/transport/hmac/sha2_256.rb +7 -11
  70. data/lib/net/ssh/transport/hmac/sha2_256_96.rb +4 -8
  71. data/lib/net/ssh/transport/hmac/sha2_256_etm.rb +12 -0
  72. data/lib/net/ssh/transport/hmac/sha2_512.rb +6 -9
  73. data/lib/net/ssh/transport/hmac/sha2_512_96.rb +4 -8
  74. data/lib/net/ssh/transport/hmac/sha2_512_etm.rb +12 -0
  75. data/lib/net/ssh/transport/identity_cipher.rb +55 -51
  76. data/lib/net/ssh/transport/kex.rb +14 -13
  77. data/lib/net/ssh/transport/kex/abstract.rb +123 -0
  78. data/lib/net/ssh/transport/kex/abstract5656.rb +72 -0
  79. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +38 -0
  80. data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +30 -0
  81. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +33 -40
  82. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +112 -217
  83. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +53 -62
  84. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +5 -9
  85. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +36 -90
  86. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +18 -10
  87. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +18 -10
  88. data/lib/net/ssh/transport/key_expander.rb +29 -25
  89. data/lib/net/ssh/transport/openssl.rb +116 -116
  90. data/lib/net/ssh/transport/packet_stream.rb +223 -190
  91. data/lib/net/ssh/transport/server_version.rb +64 -66
  92. data/lib/net/ssh/transport/session.rb +306 -257
  93. data/lib/net/ssh/transport/state.rb +198 -196
  94. data/lib/net/ssh/verifiers/accept_new.rb +35 -0
  95. data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +34 -0
  96. data/lib/net/ssh/verifiers/always.rb +56 -0
  97. data/lib/net/ssh/verifiers/never.rb +21 -0
  98. data/lib/net/ssh/version.rb +55 -53
  99. data/net-ssh-public_cert.pem +18 -19
  100. data/net-ssh.gemspec +12 -11
  101. data/support/ssh_tunnel_bug.rb +2 -2
  102. metadata +86 -75
  103. metadata.gz.sig +0 -0
  104. data/Gemfile.norbnacl.lock +0 -41
  105. data/README.rdoc +0 -169
  106. data/lib/net/ssh/ruby_compat.rb +0 -24
  107. data/lib/net/ssh/verifiers/lenient.rb +0 -30
  108. data/lib/net/ssh/verifiers/null.rb +0 -12
  109. data/lib/net/ssh/verifiers/secure.rb +0 -52
  110. data/lib/net/ssh/verifiers/strict.rb +0 -24
  111. data/support/arcfour_check.rb +0 -20
@@ -2,205 +2,207 @@ require 'zlib'
2
2
  require 'net/ssh/transport/cipher_factory'
3
3
  require 'net/ssh/transport/hmac'
4
4
 
5
- module Net; module SSH; module Transport
6
-
7
- # Encapsulates state information about one end of an SSH connection. Such
8
- # state includes the packet sequence number, the algorithms in use, how
9
- # many packets and blocks have been processed since the last reset, and so
10
- # forth. This class will never be instantiated directly, but is used as
11
- # part of the internal state of the PacketStream module.
12
- class State
13
- # The socket object that owns this state object.
14
- attr_reader :socket
15
-
16
- # The next packet sequence number for this socket endpoint.
17
- attr_reader :sequence_number
18
-
19
- # The hmac algorithm in use for this endpoint.
20
- attr_reader :hmac
21
-
22
- # The compression algorithm in use for this endpoint.
23
- attr_reader :compression
24
-
25
- # The compression level to use when compressing data (or nil, for the default).
26
- attr_reader :compression_level
27
-
28
- # The number of packets processed since the last call to #reset!
29
- attr_reader :packets
30
-
31
- # The number of data blocks processed since the last call to #reset!
32
- attr_reader :blocks
33
-
34
- # The cipher algorithm in use for this socket endpoint.
35
- attr_reader :cipher
36
-
37
- # The block size for the cipher
38
- attr_reader :block_size
39
-
40
- # The role that this state plays (either :client or :server)
41
- attr_reader :role
42
-
43
- # The maximum number of packets that this endpoint wants to process before
44
- # needing a rekey.
45
- attr_accessor :max_packets
46
-
47
- # The maximum number of blocks that this endpoint wants to process before
48
- # needing a rekey.
49
- attr_accessor :max_blocks
50
-
51
- # The user-specified maximum number of bytes that this endpoint ought to
52
- # process before needing a rekey.
53
- attr_accessor :rekey_limit
54
-
55
- # Creates a new state object, belonging to the given socket. Initializes
56
- # the algorithms to "none".
57
- def initialize(socket, role)
58
- @socket = socket
59
- @role = role
60
- @sequence_number = @packets = @blocks = 0
61
- @cipher = CipherFactory.get("none")
62
- @block_size = 8
63
- @hmac = HMAC.get("none")
64
- @compression = nil
65
- @compressor = @decompressor = nil
66
- @next_iv = ""
67
- end
68
-
69
- # A convenience method for quickly setting multiple values in a single
70
- # command.
71
- def set(values)
72
- values.each do |key, value|
73
- instance_variable_set("@#{key}", value)
74
- end
75
- reset!
76
- end
77
-
78
- def update_cipher(data)
79
- result = cipher.update(data)
80
- update_next_iv(role == :client ? result : data)
81
- return result
82
- end
83
-
84
- def final_cipher
85
- result = cipher.final
86
- update_next_iv(role == :client ? result : "", true)
87
- return result
88
- end
89
-
90
- # Increments the counters. The sequence number is incremented (and remapped
91
- # so it always fits in a 32-bit integer). The number of packets and blocks
92
- # are also incremented.
93
- def increment(packet_length)
94
- @sequence_number = (@sequence_number + 1) & 0xFFFFFFFF
95
- @packets += 1
96
- @blocks += (packet_length + 4) / @block_size
97
- end
98
-
99
- # The compressor object to use when compressing data. This takes into account
100
- # the desired compression level.
101
- def compressor
102
- @compressor ||= Zlib::Deflate.new(compression_level || Zlib::DEFAULT_COMPRESSION)
103
- end
104
-
105
- # The decompressor object to use when decompressing data.
106
- def decompressor
107
- @decompressor ||= Zlib::Inflate.new(nil)
108
- end
109
-
110
- # Returns true if data compression/decompression is enabled. This will
111
- # return true if :standard compression is selected, or if :delayed
112
- # compression is selected and the :authenticated hint has been received
113
- # by the socket.
114
- def compression?
115
- compression == :standard || (compression == :delayed && socket.hints[:authenticated])
116
- end
117
-
118
- # Compresses the data. If no compression is in effect, this will just return
119
- # the data unmodified, otherwise it uses #compressor to compress the data.
120
- def compress(data)
121
- data = data.to_s
122
- return data unless compression?
123
- compressor.deflate(data, Zlib::SYNC_FLUSH)
124
- end
125
-
126
- # Deompresses the data. If no compression is in effect, this will just return
127
- # the data unmodified, otherwise it uses #decompressor to decompress the data.
128
- def decompress(data)
129
- data = data.to_s
130
- return data unless compression?
131
- decompressor.inflate(data)
132
- end
133
-
134
- # Resets the counters on the state object, but leaves the sequence_number
135
- # unchanged. It also sets defaults for and recomputes the max_packets and
136
- # max_blocks values.
137
- def reset!
138
- @packets = @blocks = 0
139
-
140
- @max_packets ||= 1 << 31
141
-
142
- @block_size = cipher.name == "RC4" ? 8 : cipher.block_size
143
-
144
- if max_blocks.nil?
145
- # cargo-culted from openssh. the idea is that "the 2^(blocksize*2)
146
- # limit is too expensive for 3DES, blowfish, etc., so enforce a 1GB
147
- # limit for small blocksizes."
148
- if @block_size >= 16
149
- @max_blocks = 1 << (@block_size * 2)
150
- else
151
- @max_blocks = (1 << 30) / @block_size
5
+ module Net
6
+ module SSH
7
+ module Transport
8
+
9
+ # Encapsulates state information about one end of an SSH connection. Such
10
+ # state includes the packet sequence number, the algorithms in use, how
11
+ # many packets and blocks have been processed since the last reset, and so
12
+ # forth. This class will never be instantiated directly, but is used as
13
+ # part of the internal state of the PacketStream module.
14
+ class State
15
+ # The socket object that owns this state object.
16
+ attr_reader :socket
17
+
18
+ # The next packet sequence number for this socket endpoint.
19
+ attr_reader :sequence_number
20
+
21
+ # The hmac algorithm in use for this endpoint.
22
+ attr_reader :hmac
23
+
24
+ # The compression algorithm in use for this endpoint.
25
+ attr_reader :compression
26
+
27
+ # The compression level to use when compressing data (or nil, for the default).
28
+ attr_reader :compression_level
29
+
30
+ # The number of packets processed since the last call to #reset!
31
+ attr_reader :packets
32
+
33
+ # The number of data blocks processed since the last call to #reset!
34
+ attr_reader :blocks
35
+
36
+ # The cipher algorithm in use for this socket endpoint.
37
+ attr_reader :cipher
38
+
39
+ # The block size for the cipher
40
+ attr_reader :block_size
41
+
42
+ # The role that this state plays (either :client or :server)
43
+ attr_reader :role
44
+
45
+ # The maximum number of packets that this endpoint wants to process before
46
+ # needing a rekey.
47
+ attr_accessor :max_packets
48
+
49
+ # The maximum number of blocks that this endpoint wants to process before
50
+ # needing a rekey.
51
+ attr_accessor :max_blocks
52
+
53
+ # The user-specified maximum number of bytes that this endpoint ought to
54
+ # process before needing a rekey.
55
+ attr_accessor :rekey_limit
56
+
57
+ # Creates a new state object, belonging to the given socket. Initializes
58
+ # the algorithms to "none".
59
+ def initialize(socket, role)
60
+ @socket = socket
61
+ @role = role
62
+ @sequence_number = @packets = @blocks = 0
63
+ @cipher = CipherFactory.get("none")
64
+ @block_size = 8
65
+ @hmac = HMAC.get("none")
66
+ @compression = nil
67
+ @compressor = @decompressor = nil
68
+ @next_iv = ""
152
69
  end
153
-
154
- # if a limit on the # of bytes has been given, convert that into a
155
- # minimum number of blocks processed.
156
-
157
- if rekey_limit
158
- @max_blocks = [@max_blocks, rekey_limit / @block_size].min
70
+
71
+ # A convenience method for quickly setting multiple values in a single
72
+ # command.
73
+ def set(values)
74
+ values.each do |key, value|
75
+ instance_variable_set("@#{key}", value)
76
+ end
77
+ reset!
78
+ end
79
+
80
+ def update_cipher(data)
81
+ result = cipher.update(data)
82
+ update_next_iv(role == :client ? result : data)
83
+ return result
84
+ end
85
+
86
+ def final_cipher
87
+ result = cipher.final
88
+ update_next_iv(role == :client ? result : "", true)
89
+ return result
90
+ end
91
+
92
+ # Increments the counters. The sequence number is incremented (and remapped
93
+ # so it always fits in a 32-bit integer). The number of packets and blocks
94
+ # are also incremented.
95
+ def increment(packet_length)
96
+ @sequence_number = (@sequence_number + 1) & 0xFFFFFFFF
97
+ @packets += 1
98
+ @blocks += (packet_length + 4) / @block_size
99
+ end
100
+
101
+ # The compressor object to use when compressing data. This takes into account
102
+ # the desired compression level.
103
+ def compressor
104
+ @compressor ||= Zlib::Deflate.new(compression_level || Zlib::DEFAULT_COMPRESSION)
105
+ end
106
+
107
+ # The decompressor object to use when decompressing data.
108
+ def decompressor
109
+ @decompressor ||= Zlib::Inflate.new(nil)
110
+ end
111
+
112
+ # Returns true if data compression/decompression is enabled. This will
113
+ # return true if :standard compression is selected, or if :delayed
114
+ # compression is selected and the :authenticated hint has been received
115
+ # by the socket.
116
+ def compression?
117
+ compression == :standard || (compression == :delayed && socket.hints[:authenticated])
118
+ end
119
+
120
+ # Compresses the data. If no compression is in effect, this will just return
121
+ # the data unmodified, otherwise it uses #compressor to compress the data.
122
+ def compress(data)
123
+ data = data.to_s
124
+ return data unless compression?
125
+ compressor.deflate(data, Zlib::SYNC_FLUSH)
126
+ end
127
+
128
+ # Deompresses the data. If no compression is in effect, this will just return
129
+ # the data unmodified, otherwise it uses #decompressor to decompress the data.
130
+ def decompress(data)
131
+ data = data.to_s
132
+ return data unless compression?
133
+ decompressor.inflate(data)
134
+ end
135
+
136
+ # Resets the counters on the state object, but leaves the sequence_number
137
+ # unchanged. It also sets defaults for and recomputes the max_packets and
138
+ # max_blocks values.
139
+ def reset!
140
+ @packets = @blocks = 0
141
+
142
+ @max_packets ||= 1 << 31
143
+
144
+ @block_size = cipher.block_size
145
+
146
+ if max_blocks.nil?
147
+ # cargo-culted from openssh. the idea is that "the 2^(blocksize*2)
148
+ # limit is too expensive for 3DES, blowfish, etc., so enforce a 1GB
149
+ # limit for small blocksizes."
150
+ if @block_size >= 16
151
+ @max_blocks = 1 << (@block_size * 2)
152
+ else
153
+ @max_blocks = (1 << 30) / @block_size
154
+ end
155
+
156
+ # if a limit on the # of bytes has been given, convert that into a
157
+ # minimum number of blocks processed.
158
+
159
+ @max_blocks = [@max_blocks, rekey_limit / @block_size].min if rekey_limit
160
+ end
161
+
162
+ cleanup
163
+ end
164
+
165
+ # Closes any the compressor and/or decompressor objects that have been
166
+ # instantiated.
167
+ def cleanup
168
+ if @compressor
169
+ @compressor.finish if !@compressor.finished?
170
+ @compressor.close
171
+ end
172
+
173
+ if @decompressor
174
+ # we call reset here so that we don't get warnings when we try to
175
+ # close the decompressor
176
+ @decompressor.reset
177
+ @decompressor.close
178
+ end
179
+
180
+ @compressor = @decompressor = nil
181
+ end
182
+
183
+ # Returns true if the number of packets processed exceeds the maximum
184
+ # number of packets, or if the number of blocks processed exceeds the
185
+ # maximum number of blocks.
186
+ def needs_rekey?
187
+ max_packets && packets > max_packets ||
188
+ max_blocks && blocks > max_blocks
189
+ end
190
+
191
+ private
192
+
193
+ def update_next_iv(data, reset=false)
194
+ @next_iv << data
195
+ @next_iv = @next_iv[@next_iv.size - cipher.iv_len..-1]
196
+
197
+ if reset
198
+ cipher.reset
199
+ cipher.iv = @next_iv
200
+ end
201
+
202
+ return data
159
203
  end
160
204
  end
161
205
 
162
- cleanup
163
- end
164
-
165
- # Closes any the compressor and/or decompressor objects that have been
166
- # instantiated.
167
- def cleanup
168
- if @compressor
169
- @compressor.finish if !@compressor.finished?
170
- @compressor.close
171
- end
172
-
173
- if @decompressor
174
- # we call reset here so that we don't get warnings when we try to
175
- # close the decompressor
176
- @decompressor.reset
177
- @decompressor.close
178
- end
179
-
180
- @compressor = @decompressor = nil
181
- end
182
-
183
- # Returns true if the number of packets processed exceeds the maximum
184
- # number of packets, or if the number of blocks processed exceeds the
185
- # maximum number of blocks.
186
- def needs_rekey?
187
- max_packets && packets > max_packets ||
188
- max_blocks && blocks > max_blocks
189
206
  end
190
-
191
- private
192
-
193
- def update_next_iv(data, reset=false)
194
- @next_iv << data
195
- @next_iv = @next_iv[@next_iv.size-cipher.iv_len..-1]
196
-
197
- if reset
198
- cipher.reset
199
- cipher.iv = @next_iv
200
- end
201
-
202
- return data
203
- end
204
207
  end
205
-
206
- end; end; end
208
+ end
@@ -0,0 +1,35 @@
1
+ require 'net/ssh/errors'
2
+ require 'net/ssh/known_hosts'
3
+ require 'net/ssh/verifiers/always'
4
+
5
+ module Net
6
+ module SSH
7
+ module Verifiers
8
+
9
+ # Does a strict host verification, looking the server up in the known
10
+ # host files to see if a key has already been seen for this server. If this
11
+ # server does not appear in any host file, this will silently add the
12
+ # server. If the server does appear at least once, but the key given does
13
+ # not match any known for the server, an exception will be raised (HostKeyMismatch).
14
+ # Otherwise, this returns true.
15
+ class AcceptNew < Always
16
+ def verify(arguments)
17
+ begin
18
+ super
19
+ rescue HostKeyUnknown => err
20
+ err.remember_host!
21
+ return true
22
+ end
23
+ end
24
+
25
+ def verify_signature(&block)
26
+ yield
27
+ rescue HostKeyUnknown => err
28
+ err.remember_host!
29
+ return true
30
+ end
31
+ end
32
+
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,34 @@
1
+ require 'net/ssh/verifiers/accept_new'
2
+
3
+ module Net
4
+ module SSH
5
+ module Verifiers
6
+
7
+ # Basically the same as the AcceptNew verifier, but does not try to actually
8
+ # verify a connection if the server is the localhost and the port is a
9
+ # nonstandard port number. Those two conditions will typically mean the
10
+ # connection is being tunnelled through a forwarded port, so the known-hosts
11
+ # file will not be helpful (in general).
12
+ class AcceptNewOrLocalTunnel < AcceptNew
13
+ # Tries to determine if the connection is being tunnelled, and if so,
14
+ # returns true. Otherwise, performs the standard strict verification.
15
+ def verify(arguments)
16
+ return true if tunnelled?(arguments)
17
+ super
18
+ end
19
+
20
+ private
21
+
22
+ # A connection is potentially being tunnelled if the port is not 22,
23
+ # and the ip refers to the localhost.
24
+ def tunnelled?(args)
25
+ return false if args[:session].port == Net::SSH::Transport::Session::DEFAULT_PORT
26
+
27
+ ip = args[:session].peer[:ip]
28
+ return ip == "127.0.0.1" || ip == "::1"
29
+ end
30
+ end
31
+
32
+ end
33
+ end
34
+ end