Class: Net::SSH::Transport::State
- Inherits:
-
Object
- Object
- Net::SSH::Transport::State
- Defined in:
- lib/net/ssh/transport/state.rb
Overview
Encapsulates state information about one end of an SSH connection. Such state includes the packet sequence number, the algorithms in use, how many packets and blocks have been processed since the last reset, and so forth. This class will never be instantiated directly, but is used as part of the internal state of the PacketStream module.
Instance Attribute Summary collapse
-
#block_size ⇒ Object
readonly
The block size for the cipher.
-
#blocks ⇒ Object
readonly
The number of data blocks processed since the last call to #reset!.
-
#cipher ⇒ Object
readonly
The cipher algorithm in use for this socket endpoint.
-
#compression ⇒ Object
readonly
The compression algorithm in use for this endpoint.
-
#compression_level ⇒ Object
readonly
The compression level to use when compressing data (or nil, for the default).
-
#hmac ⇒ Object
readonly
The hmac algorithm in use for this endpoint.
-
#max_blocks ⇒ Object
The maximum number of blocks that this endpoint wants to process before needing a rekey.
-
#max_packets ⇒ Object
The maximum number of packets that this endpoint wants to process before needing a rekey.
-
#packets ⇒ Object
readonly
The number of packets processed since the last call to #reset!.
-
#rekey_limit ⇒ Object
The user-specified maximum number of bytes that this endpoint ought to process before needing a rekey.
-
#role ⇒ Object
readonly
The role that this state plays (either :client or :server).
-
#sequence_number ⇒ Object
readonly
The next packet sequence number for this socket endpoint.
-
#socket ⇒ Object
readonly
The socket object that owns this state object.
Instance Method Summary collapse
-
#cleanup ⇒ Object
Closes any the compressor and/or decompressor objects that have been instantiated.
-
#compress(data) ⇒ Object
Compresses the data.
-
#compression? ⇒ Boolean
Returns true if data compression/decompression is enabled.
-
#compressor ⇒ Object
The compressor object to use when compressing data.
-
#decompress(data) ⇒ Object
Deompresses the data.
-
#decompressor ⇒ Object
The decompressor object to use when decompressing data.
- #final_cipher ⇒ Object
-
#increment(packet_length) ⇒ Object
Increments the counters.
-
#initialize(socket, role) ⇒ State
constructor
Creates a new state object, belonging to the given socket.
-
#needs_rekey? ⇒ Boolean
Returns true if the number of packets processed exceeds the maximum number of packets, or if the number of blocks processed exceeds the maximum number of blocks.
-
#reset! ⇒ Object
Resets the counters on the state object, but leaves the sequence_number unchanged.
-
#set(values) ⇒ Object
A convenience method for quickly setting multiple values in a single command.
- #update_cipher(data) ⇒ Object
Constructor Details
#initialize(socket, role) ⇒ State
Creates a new state object, belonging to the given socket. Initializes the algorithms to “none”.
57 58 59 60 61 62 63 64 65 66 67 |
# File 'lib/net/ssh/transport/state.rb', line 57 def initialize(socket, role) @socket = socket @role = role @sequence_number = @packets = @blocks = 0 @cipher = CipherFactory.get("none") @block_size = 8 @hmac = HMAC.get("none") @compression = nil @compressor = @decompressor = nil @next_iv = "" end |
Instance Attribute Details
#block_size ⇒ Object (readonly)
The block size for the cipher
38 39 40 |
# File 'lib/net/ssh/transport/state.rb', line 38 def block_size @block_size end |
#blocks ⇒ Object (readonly)
The number of data blocks processed since the last call to #reset!
32 33 34 |
# File 'lib/net/ssh/transport/state.rb', line 32 def blocks @blocks end |
#cipher ⇒ Object (readonly)
The cipher algorithm in use for this socket endpoint.
35 36 37 |
# File 'lib/net/ssh/transport/state.rb', line 35 def cipher @cipher end |
#compression ⇒ Object (readonly)
The compression algorithm in use for this endpoint.
23 24 25 |
# File 'lib/net/ssh/transport/state.rb', line 23 def compression @compression end |
#compression_level ⇒ Object (readonly)
The compression level to use when compressing data (or nil, for the default).
26 27 28 |
# File 'lib/net/ssh/transport/state.rb', line 26 def compression_level @compression_level end |
#hmac ⇒ Object (readonly)
The hmac algorithm in use for this endpoint.
20 21 22 |
# File 'lib/net/ssh/transport/state.rb', line 20 def hmac @hmac end |
#max_blocks ⇒ Object
The maximum number of blocks that this endpoint wants to process before needing a rekey.
49 50 51 |
# File 'lib/net/ssh/transport/state.rb', line 49 def max_blocks @max_blocks end |
#max_packets ⇒ Object
The maximum number of packets that this endpoint wants to process before needing a rekey.
45 46 47 |
# File 'lib/net/ssh/transport/state.rb', line 45 def max_packets @max_packets end |
#packets ⇒ Object (readonly)
The number of packets processed since the last call to #reset!
29 30 31 |
# File 'lib/net/ssh/transport/state.rb', line 29 def packets @packets end |
#rekey_limit ⇒ Object
The user-specified maximum number of bytes that this endpoint ought to process before needing a rekey.
53 54 55 |
# File 'lib/net/ssh/transport/state.rb', line 53 def rekey_limit @rekey_limit end |
#role ⇒ Object (readonly)
The role that this state plays (either :client or :server)
41 42 43 |
# File 'lib/net/ssh/transport/state.rb', line 41 def role @role end |
#sequence_number ⇒ Object (readonly)
The next packet sequence number for this socket endpoint.
17 18 19 |
# File 'lib/net/ssh/transport/state.rb', line 17 def sequence_number @sequence_number end |
#socket ⇒ Object (readonly)
The socket object that owns this state object.
14 15 16 |
# File 'lib/net/ssh/transport/state.rb', line 14 def socket @socket end |
Instance Method Details
#cleanup ⇒ Object
Closes any the compressor and/or decompressor objects that have been instantiated.
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 |
# File 'lib/net/ssh/transport/state.rb', line 167 def cleanup if @compressor @compressor.finish if !@compressor.finished? @compressor.close end if @decompressor # we call reset here so that we don't get warnings when we try to # close the decompressor @decompressor.reset @decompressor.close end @compressor = @decompressor = nil end |
#compress(data) ⇒ Object
Compresses the data. If no compression is in effect, this will just return the data unmodified, otherwise it uses #compressor to compress the data.
120 121 122 123 124 |
# File 'lib/net/ssh/transport/state.rb', line 120 def compress(data) data = data.to_s return data unless compression? compressor.deflate(data, Zlib::SYNC_FLUSH) end |
#compression? ⇒ Boolean
Returns true if data compression/decompression is enabled. This will return true if :standard compression is selected, or if :delayed compression is selected and the :authenticated hint has been received by the socket.
114 115 116 |
# File 'lib/net/ssh/transport/state.rb', line 114 def compression? compression == :standard || (compression == :delayed && socket.hints[:authenticated]) end |
#compressor ⇒ Object
The compressor object to use when compressing data. This takes into account the desired compression level.
101 102 103 |
# File 'lib/net/ssh/transport/state.rb', line 101 def compressor @compressor ||= Zlib::Deflate.new(compression_level || Zlib::DEFAULT_COMPRESSION) end |
#decompress(data) ⇒ Object
Deompresses the data. If no compression is in effect, this will just return the data unmodified, otherwise it uses #decompressor to decompress the data.
128 129 130 131 132 |
# File 'lib/net/ssh/transport/state.rb', line 128 def decompress(data) data = data.to_s return data unless compression? decompressor.inflate(data) end |
#decompressor ⇒ Object
The decompressor object to use when decompressing data.
106 107 108 |
# File 'lib/net/ssh/transport/state.rb', line 106 def decompressor @decompressor ||= Zlib::Inflate.new(nil) end |
#final_cipher ⇒ Object
84 85 86 87 88 |
# File 'lib/net/ssh/transport/state.rb', line 84 def final_cipher result = cipher.final update_next_iv(role == :client ? result : "", true) return result end |
#increment(packet_length) ⇒ Object
Increments the counters. The sequence number is incremented (and remapped so it always fits in a 32-bit integer). The number of packets and blocks are also incremented.
93 94 95 96 97 |
# File 'lib/net/ssh/transport/state.rb', line 93 def increment(packet_length) @sequence_number = (@sequence_number + 1) & 0xFFFFFFFF @packets += 1 @blocks += (packet_length + 4) / @block_size end |
#needs_rekey? ⇒ Boolean
Returns true if the number of packets processed exceeds the maximum number of packets, or if the number of blocks processed exceeds the maximum number of blocks.
186 187 188 189 |
# File 'lib/net/ssh/transport/state.rb', line 186 def needs_rekey? max_packets && packets > max_packets || max_blocks && blocks > max_blocks end |
#reset! ⇒ Object
Resets the counters on the state object, but leaves the sequence_number unchanged. It also sets defaults for and recomputes the max_packets and max_blocks values.
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 |
# File 'lib/net/ssh/transport/state.rb', line 137 def reset! @packets = @blocks = 0 @max_packets ||= 1 << 31 @block_size = cipher.name == "RC4" ? 8 : cipher.block_size if max_blocks.nil? # cargo-culted from openssh. the idea is that "the 2^(blocksize*2) # limit is too expensive for 3DES, blowfish, etc., so enforce a 1GB # limit for small blocksizes." if @block_size >= 16 @max_blocks = 1 << (@block_size * 2) else @max_blocks = (1 << 30) / @block_size end # if a limit on the # of bytes has been given, convert that into a # minimum number of blocks processed. if rekey_limit @max_blocks = [@max_blocks, rekey_limit / @block_size].min end end cleanup end |
#set(values) ⇒ Object
A convenience method for quickly setting multiple values in a single command.
71 72 73 74 75 76 |
# File 'lib/net/ssh/transport/state.rb', line 71 def set(values) values.each do |key, value| instance_variable_set("@#{key}", value) end reset! end |
#update_cipher(data) ⇒ Object
78 79 80 81 82 |
# File 'lib/net/ssh/transport/state.rb', line 78 def update_cipher(data) result = cipher.update(data) update_next_iv(role == :client ? result : data) return result end |