net-ssh 2.7.0 → 7.3.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 (199) hide show
  1. checksums.yaml +7 -0
  2. checksums.yaml.gz.sig +0 -0
  3. data/.dockerignore +6 -0
  4. data/.github/FUNDING.yml +1 -0
  5. data/.github/config/rubocop_linter_action.yml +4 -0
  6. data/.github/workflows/ci-with-docker.yml +44 -0
  7. data/.github/workflows/ci.yml +94 -0
  8. data/.github/workflows/rubocop.yml +16 -0
  9. data/.gitignore +15 -0
  10. data/.rubocop.yml +22 -0
  11. data/.rubocop_todo.yml +1081 -0
  12. data/CHANGES.txt +387 -0
  13. data/DEVELOPMENT.md +23 -0
  14. data/Dockerfile +29 -0
  15. data/Dockerfile.openssl3 +17 -0
  16. data/Gemfile +13 -0
  17. data/Gemfile.noed25519 +12 -0
  18. data/Gemfile.norbnacl +12 -0
  19. data/ISSUE_TEMPLATE.md +30 -0
  20. data/Manifest +4 -5
  21. data/README.md +303 -0
  22. data/Rakefile +174 -40
  23. data/SECURITY.md +4 -0
  24. data/THANKS.txt +25 -0
  25. data/appveyor.yml +58 -0
  26. data/docker-compose.yml +25 -0
  27. data/lib/net/ssh/authentication/agent.rb +279 -18
  28. data/lib/net/ssh/authentication/certificate.rb +183 -0
  29. data/lib/net/ssh/authentication/constants.rb +17 -15
  30. data/lib/net/ssh/authentication/ed25519.rb +184 -0
  31. data/lib/net/ssh/authentication/ed25519_loader.rb +31 -0
  32. data/lib/net/ssh/authentication/key_manager.rb +125 -54
  33. data/lib/net/ssh/authentication/methods/abstract.rb +67 -48
  34. data/lib/net/ssh/authentication/methods/hostbased.rb +34 -37
  35. data/lib/net/ssh/authentication/methods/keyboard_interactive.rb +19 -12
  36. data/lib/net/ssh/authentication/methods/none.rb +16 -19
  37. data/lib/net/ssh/authentication/methods/password.rb +56 -19
  38. data/lib/net/ssh/authentication/methods/publickey.rb +96 -55
  39. data/lib/net/ssh/authentication/pageant.rb +483 -246
  40. data/lib/net/ssh/authentication/pub_key_fingerprint.rb +43 -0
  41. data/lib/net/ssh/authentication/session.rb +138 -120
  42. data/lib/net/ssh/buffer.rb +399 -300
  43. data/lib/net/ssh/buffered_io.rb +154 -150
  44. data/lib/net/ssh/config.rb +361 -166
  45. data/lib/net/ssh/connection/channel.rb +640 -596
  46. data/lib/net/ssh/connection/constants.rb +29 -29
  47. data/lib/net/ssh/connection/event_loop.rb +123 -0
  48. data/lib/net/ssh/connection/keepalive.rb +59 -0
  49. data/lib/net/ssh/connection/session.rb +628 -548
  50. data/lib/net/ssh/connection/term.rb +125 -123
  51. data/lib/net/ssh/errors.rb +101 -95
  52. data/lib/net/ssh/key_factory.rb +198 -100
  53. data/lib/net/ssh/known_hosts.rb +221 -98
  54. data/lib/net/ssh/loggable.rb +50 -49
  55. data/lib/net/ssh/packet.rb +83 -79
  56. data/lib/net/ssh/prompt.rb +50 -81
  57. data/lib/net/ssh/proxy/command.rb +108 -60
  58. data/lib/net/ssh/proxy/errors.rb +12 -10
  59. data/lib/net/ssh/proxy/http.rb +82 -78
  60. data/lib/net/ssh/proxy/https.rb +50 -0
  61. data/lib/net/ssh/proxy/jump.rb +54 -0
  62. data/lib/net/ssh/proxy/socks4.rb +5 -8
  63. data/lib/net/ssh/proxy/socks5.rb +18 -20
  64. data/lib/net/ssh/service/forward.rb +383 -255
  65. data/lib/net/ssh/test/channel.rb +145 -136
  66. data/lib/net/ssh/test/extensions.rb +131 -110
  67. data/lib/net/ssh/test/kex.rb +34 -32
  68. data/lib/net/ssh/test/local_packet.rb +46 -44
  69. data/lib/net/ssh/test/packet.rb +89 -70
  70. data/lib/net/ssh/test/remote_packet.rb +32 -30
  71. data/lib/net/ssh/test/script.rb +156 -142
  72. data/lib/net/ssh/test/socket.rb +49 -48
  73. data/lib/net/ssh/test.rb +82 -77
  74. data/lib/net/ssh/transport/aes128_gcm.rb +40 -0
  75. data/lib/net/ssh/transport/aes256_gcm.rb +40 -0
  76. data/lib/net/ssh/transport/algorithms.rb +472 -348
  77. data/lib/net/ssh/transport/chacha20_poly1305_cipher.rb +117 -0
  78. data/lib/net/ssh/transport/chacha20_poly1305_cipher_loader.rb +17 -0
  79. data/lib/net/ssh/transport/cipher_factory.rb +124 -100
  80. data/lib/net/ssh/transport/constants.rb +32 -24
  81. data/lib/net/ssh/transport/ctr.rb +42 -22
  82. data/lib/net/ssh/transport/gcm_cipher.rb +207 -0
  83. data/lib/net/ssh/transport/hmac/abstract.rb +97 -63
  84. data/lib/net/ssh/transport/hmac/md5.rb +0 -2
  85. data/lib/net/ssh/transport/hmac/md5_96.rb +0 -2
  86. data/lib/net/ssh/transport/hmac/none.rb +0 -2
  87. data/lib/net/ssh/transport/hmac/ripemd160.rb +0 -2
  88. data/lib/net/ssh/transport/hmac/sha1.rb +0 -2
  89. data/lib/net/ssh/transport/hmac/sha1_96.rb +0 -2
  90. data/lib/net/ssh/transport/hmac/sha2_256.rb +7 -11
  91. data/lib/net/ssh/transport/hmac/sha2_256_96.rb +4 -8
  92. data/lib/net/ssh/transport/hmac/sha2_256_etm.rb +12 -0
  93. data/lib/net/ssh/transport/hmac/sha2_512.rb +6 -9
  94. data/lib/net/ssh/transport/hmac/sha2_512_96.rb +4 -8
  95. data/lib/net/ssh/transport/hmac/sha2_512_etm.rb +12 -0
  96. data/lib/net/ssh/transport/hmac.rb +14 -12
  97. data/lib/net/ssh/transport/identity_cipher.rb +54 -44
  98. data/lib/net/ssh/transport/kex/abstract.rb +130 -0
  99. data/lib/net/ssh/transport/kex/abstract5656.rb +72 -0
  100. data/lib/net/ssh/transport/kex/curve25519_sha256.rb +39 -0
  101. data/lib/net/ssh/transport/kex/curve25519_sha256_loader.rb +30 -0
  102. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb +33 -40
  103. data/lib/net/ssh/transport/kex/diffie_hellman_group14_sha256.rb +11 -0
  104. data/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb +119 -213
  105. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb +53 -61
  106. data/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb +5 -9
  107. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb +36 -90
  108. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb +18 -10
  109. data/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb +18 -10
  110. data/lib/net/ssh/transport/kex.rb +15 -12
  111. data/lib/net/ssh/transport/key_expander.rb +24 -20
  112. data/lib/net/ssh/transport/openssl.rb +161 -124
  113. data/lib/net/ssh/transport/openssl_cipher_extensions.rb +8 -0
  114. data/lib/net/ssh/transport/packet_stream.rb +246 -183
  115. data/lib/net/ssh/transport/server_version.rb +57 -51
  116. data/lib/net/ssh/transport/session.rb +307 -235
  117. data/lib/net/ssh/transport/state.rb +178 -176
  118. data/lib/net/ssh/verifiers/accept_new.rb +33 -0
  119. data/lib/net/ssh/verifiers/accept_new_or_local_tunnel.rb +33 -0
  120. data/lib/net/ssh/verifiers/always.rb +58 -0
  121. data/lib/net/ssh/verifiers/never.rb +19 -0
  122. data/lib/net/ssh/version.rb +57 -51
  123. data/lib/net/ssh.rb +140 -40
  124. data/net-ssh-public_cert.pem +21 -0
  125. data/net-ssh.gemspec +39 -184
  126. data/support/ssh_tunnel_bug.rb +5 -5
  127. data.tar.gz.sig +0 -0
  128. metadata +205 -99
  129. metadata.gz.sig +0 -0
  130. data/README.rdoc +0 -219
  131. data/Rudyfile +0 -96
  132. data/gem-public_cert.pem +0 -20
  133. data/lib/net/ssh/authentication/agent/java_pageant.rb +0 -85
  134. data/lib/net/ssh/authentication/agent/socket.rb +0 -170
  135. data/lib/net/ssh/ruby_compat.rb +0 -51
  136. data/lib/net/ssh/verifiers/lenient.rb +0 -30
  137. data/lib/net/ssh/verifiers/null.rb +0 -12
  138. data/lib/net/ssh/verifiers/secure.rb +0 -54
  139. data/lib/net/ssh/verifiers/strict.rb +0 -24
  140. data/setup.rb +0 -1585
  141. data/support/arcfour_check.rb +0 -20
  142. data/test/README.txt +0 -47
  143. data/test/authentication/methods/common.rb +0 -28
  144. data/test/authentication/methods/test_abstract.rb +0 -51
  145. data/test/authentication/methods/test_hostbased.rb +0 -114
  146. data/test/authentication/methods/test_keyboard_interactive.rb +0 -100
  147. data/test/authentication/methods/test_none.rb +0 -41
  148. data/test/authentication/methods/test_password.rb +0 -52
  149. data/test/authentication/methods/test_publickey.rb +0 -148
  150. data/test/authentication/test_agent.rb +0 -205
  151. data/test/authentication/test_key_manager.rb +0 -218
  152. data/test/authentication/test_session.rb +0 -108
  153. data/test/common.rb +0 -108
  154. data/test/configs/eqsign +0 -3
  155. data/test/configs/exact_match +0 -8
  156. data/test/configs/host_plus +0 -10
  157. data/test/configs/multihost +0 -4
  158. data/test/configs/nohost +0 -19
  159. data/test/configs/numeric_host +0 -4
  160. data/test/configs/send_env +0 -2
  161. data/test/configs/substitutes +0 -8
  162. data/test/configs/wild_cards +0 -14
  163. data/test/connection/test_channel.rb +0 -467
  164. data/test/connection/test_session.rb +0 -526
  165. data/test/known_hosts/github +0 -1
  166. data/test/manual/test_forward.rb +0 -223
  167. data/test/start/test_options.rb +0 -36
  168. data/test/start/test_transport.rb +0 -28
  169. data/test/test_all.rb +0 -11
  170. data/test/test_buffer.rb +0 -433
  171. data/test/test_buffered_io.rb +0 -63
  172. data/test/test_config.rb +0 -151
  173. data/test/test_key_factory.rb +0 -173
  174. data/test/test_known_hosts.rb +0 -13
  175. data/test/transport/hmac/test_md5.rb +0 -41
  176. data/test/transport/hmac/test_md5_96.rb +0 -27
  177. data/test/transport/hmac/test_none.rb +0 -34
  178. data/test/transport/hmac/test_ripemd160.rb +0 -36
  179. data/test/transport/hmac/test_sha1.rb +0 -36
  180. data/test/transport/hmac/test_sha1_96.rb +0 -27
  181. data/test/transport/hmac/test_sha2_256.rb +0 -37
  182. data/test/transport/hmac/test_sha2_256_96.rb +0 -27
  183. data/test/transport/hmac/test_sha2_512.rb +0 -37
  184. data/test/transport/hmac/test_sha2_512_96.rb +0 -27
  185. data/test/transport/kex/test_diffie_hellman_group14_sha1.rb +0 -13
  186. data/test/transport/kex/test_diffie_hellman_group1_sha1.rb +0 -146
  187. data/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb +0 -92
  188. data/test/transport/kex/test_diffie_hellman_group_exchange_sha256.rb +0 -34
  189. data/test/transport/kex/test_ecdh_sha2_nistp256.rb +0 -161
  190. data/test/transport/kex/test_ecdh_sha2_nistp384.rb +0 -38
  191. data/test/transport/kex/test_ecdh_sha2_nistp521.rb +0 -38
  192. data/test/transport/test_algorithms.rb +0 -330
  193. data/test/transport/test_cipher_factory.rb +0 -443
  194. data/test/transport/test_hmac.rb +0 -34
  195. data/test/transport/test_identity_cipher.rb +0 -40
  196. data/test/transport/test_packet_stream.rb +0 -1755
  197. data/test/transport/test_server_version.rb +0 -78
  198. data/test/transport/test_session.rb +0 -319
  199. data/test/transport/test_state.rb +0 -181
@@ -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
5
+ module Net
6
+ module SSH
7
+ module Transport
8
+ # Encapsulates state information about one end of an SSH connection. Such
9
+ # state includes the packet sequence number, the algorithms in use, how
10
+ # many packets and blocks have been processed since the last reset, and so
11
+ # forth. This class will never be instantiated directly, but is used as
12
+ # part of the internal state of the PacketStream module.
13
+ class State
14
+ # The socket object that owns this state object.
15
+ attr_reader :socket
16
+
17
+ # The next packet sequence number for this socket endpoint.
18
+ attr_reader :sequence_number
19
+
20
+ # The hmac algorithm in use for this endpoint.
21
+ attr_reader :hmac
22
+
23
+ # The compression algorithm in use for this endpoint.
24
+ attr_reader :compression
25
+
26
+ # The compression level to use when compressing data (or nil, for the default).
27
+ attr_reader :compression_level
28
+
29
+ # The number of packets processed since the last call to #reset!
30
+ attr_reader :packets
31
+
32
+ # The number of data blocks processed since the last call to #reset!
33
+ attr_reader :blocks
34
+
35
+ # The cipher algorithm in use for this socket endpoint.
36
+ attr_reader :cipher
37
+
38
+ # The block size for the cipher
39
+ attr_reader :block_size
40
+
41
+ # The role that this state plays (either :client or :server)
42
+ attr_reader :role
43
+
44
+ # The maximum number of packets that this endpoint wants to process before
45
+ # needing a rekey.
46
+ attr_accessor :max_packets
47
+
48
+ # The maximum number of blocks that this endpoint wants to process before
49
+ # needing a rekey.
50
+ attr_accessor :max_blocks
51
+
52
+ # The user-specified maximum number of bytes that this endpoint ought to
53
+ # process before needing a rekey.
54
+ attr_accessor :rekey_limit
55
+
56
+ # Creates a new state object, belonging to the given socket. Initializes
57
+ # the algorithms to "none".
58
+ def initialize(socket, role)
59
+ @socket = socket
60
+ @role = role
61
+ @sequence_number = @packets = @blocks = 0
62
+ @cipher = CipherFactory.get("none")
63
+ @block_size = 8
64
+ @hmac = HMAC.get("none")
65
+ @compression = nil
66
+ @compressor = @decompressor = nil
67
+ @next_iv = String.new
68
+ end
68
69
 
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
70
+ # A convenience method for quickly setting multiple values in a single
71
+ # command.
72
+ def set(values)
73
+ values.each do |key, value|
74
+ instance_variable_set("@#{key}", value)
75
+ end
76
+ reset!
77
+ end
77
78
 
78
- def update_cipher(data)
79
- result = cipher.update(data)
80
- update_next_iv(role == :client ? result : data)
81
- return result
82
- end
79
+ def update_cipher(data)
80
+ result = cipher.update(data)
81
+ update_next_iv(role == :client ? result : data)
82
+ return result
83
+ end
83
84
 
84
- def final_cipher
85
- result = cipher.final
86
- update_next_iv(role == :client ? result : "", true)
87
- return result
88
- end
85
+ def final_cipher
86
+ result = cipher.final
87
+ update_next_iv(role == :client ? result : "", true)
88
+ return result
89
+ end
89
90
 
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
91
+ # Increments the counters. The sequence number is incremented (and remapped
92
+ # so it always fits in a 32-bit integer). The number of packets and blocks
93
+ # are also incremented.
94
+ def increment(packet_length)
95
+ @sequence_number = (@sequence_number + 1) & 0xFFFFFFFF
96
+ @packets += 1
97
+ @blocks += (packet_length + 4) / @block_size
98
+ end
98
99
 
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
100
+ # The compressor object to use when compressing data. This takes into account
101
+ # the desired compression level.
102
+ def compressor
103
+ @compressor ||= Zlib::Deflate.new(compression_level || Zlib::DEFAULT_COMPRESSION)
104
+ end
104
105
 
105
- # The decompressor object to use when decompressing data.
106
- def decompressor
107
- @decompressor ||= Zlib::Inflate.new(nil)
108
- end
106
+ # The decompressor object to use when decompressing data.
107
+ def decompressor
108
+ @decompressor ||= Zlib::Inflate.new(nil)
109
+ end
109
110
 
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
111
+ # Returns true if data compression/decompression is enabled. This will
112
+ # return true if :standard compression is selected, or if :delayed
113
+ # compression is selected and the :authenticated hint has been received
114
+ # by the socket.
115
+ def compression?
116
+ compression == :standard || (compression == :delayed && socket.hints[:authenticated])
117
+ end
117
118
 
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
119
+ # Compresses the data. If no compression is in effect, this will just return
120
+ # the data unmodified, otherwise it uses #compressor to compress the data.
121
+ def compress(data)
122
+ data = data.to_s
123
+ return data unless compression?
125
124
 
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
125
+ compressor.deflate(data, Zlib::SYNC_FLUSH)
126
+ end
133
127
 
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
128
+ # Decompresses 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?
139
133
 
140
- @max_packets ||= 1 << 31
134
+ decompressor.inflate(data)
135
+ end
141
136
 
142
- @block_size = cipher.name == "RC4" ? 8 : cipher.block_size
137
+ # Resets the counters on the state object, but leaves the sequence_number
138
+ # unchanged. It also sets defaults for and recomputes the max_packets and
139
+ # max_blocks values.
140
+ def reset!
141
+ @packets = @blocks = 0
143
142
 
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
152
- end
143
+ @max_packets ||= 1 << 31
153
144
 
154
- # if a limit on the # of bytes has been given, convert that into a
155
- # minimum number of blocks processed.
145
+ @block_size = cipher.block_size
156
146
 
157
- if rekey_limit
158
- @max_blocks = [@max_blocks, rekey_limit / @block_size].min
159
- end
160
- end
147
+ if max_blocks.nil?
148
+ # cargo-culted from openssh. the idea is that "the 2^(blocksize*2)
149
+ # limit is too expensive for 3DES, blowfish, etc., so enforce a 1GB
150
+ # limit for small blocksizes."
151
+ if @block_size >= 16
152
+ @max_blocks = 1 << (@block_size * 2)
153
+ else
154
+ @max_blocks = (1 << 30) / @block_size
155
+ end
161
156
 
162
- cleanup
163
- end
157
+ # if a limit on the # of bytes has been given, convert that into a
158
+ # minimum number of blocks processed.
164
159
 
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
160
+ @max_blocks = [@max_blocks, rekey_limit / @block_size].min if rekey_limit
161
+ end
172
162
 
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
163
+ cleanup
164
+ end
179
165
 
180
- @compressor = @decompressor = nil
181
- end
166
+ # Closes any the compressor and/or decompressor objects that have been
167
+ # instantiated.
168
+ def cleanup
169
+ if @compressor
170
+ @compressor.finish if !@compressor.finished?
171
+ @compressor.close
172
+ end
173
+
174
+ if @decompressor
175
+ # we call reset here so that we don't get warnings when we try to
176
+ # close the decompressor
177
+ @decompressor.reset
178
+ @decompressor.close
179
+ end
180
+
181
+ @compressor = @decompressor = nil
182
+ end
182
183
 
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
184
+ # Returns true if the number of packets processed exceeds the maximum
185
+ # number of packets, or if the number of blocks processed exceeds the
186
+ # maximum number of blocks.
187
+ def needs_rekey?
188
+ max_packets && packets > max_packets ||
189
+ max_blocks && blocks > max_blocks
190
+ end
190
191
 
191
- private
192
+ private
192
193
 
193
- def update_next_iv(data, reset=false)
194
- @next_iv << data
195
- @next_iv = @next_iv[-cipher.iv_len..-1]
194
+ def update_next_iv(data, reset = false)
195
+ @next_iv << data
196
+ @next_iv = @next_iv[@next_iv.size - cipher.iv_len..-1]
196
197
 
197
- if reset
198
- cipher.reset
199
- cipher.iv = @next_iv
200
- end
198
+ if reset
199
+ cipher.reset
200
+ cipher.iv = @next_iv
201
+ end
201
202
 
202
- return data
203
+ return data
204
+ end
203
205
  end
206
+ end
204
207
  end
205
-
206
- end; end; end
208
+ end
@@ -0,0 +1,33 @@
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
+ # Does a strict host verification, looking the server up in the known
9
+ # host files to see if a key has already been seen for this server. If this
10
+ # server does not appear in any host file, this will silently add the
11
+ # server. If the server does appear at least once, but the key given does
12
+ # not match any known for the server, an exception will be raised (HostKeyMismatch).
13
+ # Otherwise, this returns true.
14
+ class AcceptNew < Always
15
+ def verify(arguments)
16
+ begin
17
+ super
18
+ rescue HostKeyUnknown => err
19
+ err.remember_host!
20
+ return true
21
+ end
22
+ end
23
+
24
+ def verify_signature(&block)
25
+ yield
26
+ rescue HostKeyUnknown => err
27
+ err.remember_host!
28
+ return true
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,33 @@
1
+ require 'net/ssh/verifiers/accept_new'
2
+
3
+ module Net
4
+ module SSH
5
+ module Verifiers
6
+ # Basically the same as the AcceptNew verifier, but does not try to actually
7
+ # verify a connection if the server is the localhost and the port is a
8
+ # nonstandard port number. Those two conditions will typically mean the
9
+ # connection is being tunnelled through a forwarded port, so the known-hosts
10
+ # file will not be helpful (in general).
11
+ class AcceptNewOrLocalTunnel < AcceptNew
12
+ # Tries to determine if the connection is being tunnelled, and if so,
13
+ # returns true. Otherwise, performs the standard strict verification.
14
+ def verify(arguments)
15
+ return true if tunnelled?(arguments)
16
+
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
+ end
32
+ end
33
+ end
@@ -0,0 +1,58 @@
1
+ require 'net/ssh/errors'
2
+ require 'net/ssh/known_hosts'
3
+
4
+ module Net
5
+ module SSH
6
+ module Verifiers
7
+ # Does a strict host verification, looking the server up in the known
8
+ # host files to see if a key has already been seen for this server. If this
9
+ # server does not appear in any host file, an exception will be raised
10
+ # (HostKeyUnknown). This is in contrast to the "Strict" class, which will
11
+ # silently add the key to your known_hosts file. If the server does appear at
12
+ # least once, but the key given does not match any known for the server, an
13
+ # exception will be raised (HostKeyMismatch).
14
+ # Otherwise, this returns true.
15
+ class Always
16
+ def verify(arguments)
17
+ host_keys = arguments[:session].host_keys
18
+
19
+ # We've never seen this host before, so raise an exception.
20
+ process_cache_miss(host_keys, arguments, HostKeyUnknown, "is unknown") if host_keys.empty?
21
+
22
+ # If we found any matches, check to see that the key type and
23
+ # blob also match.
24
+
25
+ found = host_keys.any? do |key|
26
+ if key.respond_to?(:matches_key?)
27
+ key.matches_key?(arguments[:key])
28
+ else
29
+ key.ssh_type == arguments[:key].ssh_type && key.to_blob == arguments[:key].to_blob
30
+ end
31
+ end
32
+
33
+ # If a match was found, return true. Otherwise, raise an exception
34
+ # indicating that the key was not recognized.
35
+ process_cache_miss(host_keys, arguments, HostKeyMismatch, "does not match") unless found
36
+
37
+ found
38
+ end
39
+
40
+ def verify_signature(&block)
41
+ yield
42
+ end
43
+
44
+ private
45
+
46
+ def process_cache_miss(host_keys, args, exc_class, message)
47
+ exception = exc_class.new("fingerprint #{args[:fingerprint]} " +
48
+ "#{message} for #{host_keys.host.inspect}")
49
+ exception.data = args
50
+ exception.callback = Proc.new do
51
+ host_keys.add_host_key(args[:key])
52
+ end
53
+ raise exception
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,19 @@
1
+ module Net
2
+ module SSH
3
+ module Verifiers
4
+ # This host key verifier simply allows every key it sees, without
5
+ # any verification. This is simple, but very insecure because it
6
+ # exposes you to MiTM attacks.
7
+ class Never
8
+ # Returns true.
9
+ def verify(arguments)
10
+ true
11
+ end
12
+
13
+ def verify_signature(&block)
14
+ true
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -1,62 +1,68 @@
1
- module Net; module SSH
2
- # A class for describing the current version of a library. The version
3
- # consists of three parts: the +major+ number, the +minor+ number, and the
4
- # +tiny+ (or +patch+) number.
5
- #
6
- # Two Version instances may be compared, so that you can test that a version
7
- # of a library is what you require:
8
- #
9
- # require 'net/ssh/version'
10
- #
11
- # if Net::SSH::Version::CURRENT < Net::SSH::Version[2,1,0]
12
- # abort "your software is too old!"
13
- # end
14
- class Version
15
- include Comparable
16
-
17
- # A convenience method for instantiating a new Version instance with the
18
- # given +major+, +minor+, and +tiny+ components.
19
- def self.[](major, minor, tiny)
20
- new(major, minor, tiny)
21
- end
1
+ module Net
2
+ module SSH
3
+ # A class for describing the current version of a library. The version
4
+ # consists of three parts: the +major+ number, the +minor+ number, and the
5
+ # +tiny+ (or +patch+) number.
6
+ #
7
+ # Two Version instances may be compared, so that you can test that a version
8
+ # of a library is what you require:
9
+ #
10
+ # require 'net/ssh/version'
11
+ #
12
+ # if Net::SSH::Version::CURRENT < Net::SSH::Version[2,1,0]
13
+ # abort "your software is too old!"
14
+ # end
15
+ class Version
16
+ include Comparable
22
17
 
23
- attr_reader :major, :minor, :tiny
18
+ # A convenience method for instantiating a new Version instance with the
19
+ # given +major+, +minor+, and +tiny+ components.
20
+ def self.[](major, minor, tiny, pre = nil)
21
+ new(major, minor, tiny, pre)
22
+ end
24
23
 
25
- # Create a new Version object with the given components.
26
- def initialize(major, minor, tiny)
27
- @major, @minor, @tiny = major, minor, tiny
28
- end
24
+ attr_reader :major, :minor, :tiny
29
25
 
30
- # Compare this version to the given +version+ object.
31
- def <=>(version)
32
- to_i <=> version.to_i
33
- end
26
+ # Create a new Version object with the given components.
27
+ def initialize(major, minor, tiny, pre = nil)
28
+ @major, @minor, @tiny, @pre = major, minor, tiny, pre
29
+ end
34
30
 
35
- # Converts this version object to a string, where each of the three
36
- # version components are joined by the '.' character. E.g., 2.0.0.
37
- def to_s
38
- @to_s ||= [@major, @minor, @tiny].join(".")
39
- end
31
+ # Compare this version to the given +version+ object.
32
+ def <=>(version)
33
+ to_i <=> version.to_i
34
+ end
40
35
 
41
- # Converts this version to a canonical integer that may be compared
42
- # against other version objects.
43
- def to_i
44
- @to_i ||= @major * 1_000_000 + @minor * 1_000 + @tiny
45
- end
36
+ # Converts this version object to a string, where each of the three
37
+ # version components are joined by the '.' character. E.g., 2.0.0.
38
+ def to_s
39
+ @to_s ||= [@major, @minor, @tiny, @pre].compact.join(".")
40
+ end
41
+
42
+ # Converts this version to a canonical integer that may be compared
43
+ # against other version objects.
44
+ def to_i
45
+ @to_i ||= @major * 1_000_000 + @minor * 1_000 + @tiny
46
+ end
46
47
 
47
- # The major component of this version of the Net::SSH library
48
- MAJOR = 2
48
+ # The major component of this version of the Net::SSH library
49
+ MAJOR = 7
49
50
 
50
- # The minor component of this version of the Net::SSH library
51
- MINOR = 7
51
+ # The minor component of this version of the Net::SSH library
52
+ MINOR = 3
52
53
 
53
- # The tiny component of this version of the Net::SSH library
54
- TINY = 0
54
+ # The tiny component of this version of the Net::SSH library
55
+ TINY = 0
55
56
 
56
- # The current version of the Net::SSH library as a Version instance
57
- CURRENT = new(MAJOR, MINOR, TINY)
57
+ # The prerelease component of this version of the Net::SSH library
58
+ # nil allowed
59
+ PRE = nil
58
60
 
59
- # The current version of the Net::SSH library as a String
60
- STRING = CURRENT.to_s
61
+ # The current version of the Net::SSH library as a Version instance
62
+ CURRENT = new(*[MAJOR, MINOR, TINY, PRE].compact)
63
+
64
+ # The current version of the Net::SSH library as a String
65
+ STRING = CURRENT.to_s
66
+ end
61
67
  end
62
- end; end
68
+ end