net-ssh 4.1.0 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.
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