Class | Net::SSH::Transport::State |
In: |
lib/net/ssh/transport/state.rb
lib/net/ssh/transport/state.rb |
Parent: | Object |
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.
blocks | [R] | The number of data blocks processed since the last call to reset! |
blocks | [R] | The number of data blocks processed since the last call to reset! |
cipher | [R] | The cipher algorithm in use for this socket endpoint. |
cipher | [R] | The cipher algorithm in use for this socket endpoint. |
compression | [R] | The compression algorithm in use for this endpoint. |
compression | [R] | The compression algorithm in use for this endpoint. |
compression_level | [R] | The compression level to use when compressing data (or nil, for the default). |
compression_level | [R] | The compression level to use when compressing data (or nil, for the default). |
hmac | [R] | The hmac algorithm in use for this endpoint. |
hmac | [R] | The hmac algorithm in use for this endpoint. |
max_blocks | [RW] | The maximum number of blocks that this endpoint wants to process before needing a rekey. |
max_blocks | [RW] | The maximum number of blocks that this endpoint wants to process before needing a rekey. |
max_packets | [RW] | The maximum number of packets that this endpoint wants to process before needing a rekey. |
max_packets | [RW] | The maximum number of packets that this endpoint wants to process before needing a rekey. |
packets | [R] | The number of packets processed since the last call to reset! |
packets | [R] | The number of packets processed since the last call to reset! |
rekey_limit | [RW] | The user-specified maximum number of bytes that this endpoint ought to process before needing a rekey. |
rekey_limit | [RW] | The user-specified maximum number of bytes that this endpoint ought to process before needing a rekey. |
role | [R] | The role that this state plays (either :client or :server) |
role | [R] | The role that this state plays (either :client or :server) |
sequence_number | [R] | The next packet sequence number for this socket endpoint. |
sequence_number | [R] | The next packet sequence number for this socket endpoint. |
socket | [R] | The socket object that owns this state object. |
socket | [R] | The socket object that owns this state object. |
Creates a new state object, belonging to the given socket. Initializes the algorithms to "none".
# File lib/net/ssh/transport/state.rb, line 54 54: def initialize(socket, role) 55: @socket = socket 56: @role = role 57: @sequence_number = @packets = @blocks = 0 58: @cipher = CipherFactory.get("none") 59: @hmac = HMAC.get("none") 60: @compression = nil 61: @compressor = @decompressor = nil 62: @next_iv = "" 63: end
Creates a new state object, belonging to the given socket. Initializes the algorithms to "none".
# File lib/net/ssh/transport/state.rb, line 54 54: def initialize(socket, role) 55: @socket = socket 56: @role = role 57: @sequence_number = @packets = @blocks = 0 58: @cipher = CipherFactory.get("none") 59: @hmac = HMAC.get("none") 60: @compression = nil 61: @compressor = @decompressor = nil 62: @next_iv = "" 63: end
Closes any the compressor and/or decompressor objects that have been instantiated.
# File lib/net/ssh/transport/state.rb, line 162 162: def cleanup 163: if @compressor 164: @compressor.finish if !@compressor.finished? 165: @compressor.close 166: end 167: 168: if @decompressor 169: # we call reset here so that we don't get warnings when we try to 170: # close the decompressor 171: @decompressor.reset 172: @decompressor.close 173: end 174: 175: @compressor = @decompressor = nil 176: end
Closes any the compressor and/or decompressor objects that have been instantiated.
# File lib/net/ssh/transport/state.rb, line 162 162: def cleanup 163: if @compressor 164: @compressor.finish if !@compressor.finished? 165: @compressor.close 166: end 167: 168: if @decompressor 169: # we call reset here so that we don't get warnings when we try to 170: # close the decompressor 171: @decompressor.reset 172: @decompressor.close 173: end 174: 175: @compressor = @decompressor = nil 176: end
Compresses the data. If no compression is in effect, this will just return the data unmodified, otherwise it uses compressor to compress the data.
# File lib/net/ssh/transport/state.rb, line 116 116: def compress(data) 117: data = data.to_s 118: return data unless compression? 119: compressor.deflate(data, Zlib::SYNC_FLUSH) 120: end
Compresses the data. If no compression is in effect, this will just return the data unmodified, otherwise it uses compressor to compress the data.
# File lib/net/ssh/transport/state.rb, line 116 116: def compress(data) 117: data = data.to_s 118: return data unless compression? 119: compressor.deflate(data, Zlib::SYNC_FLUSH) 120: end
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.
# File lib/net/ssh/transport/state.rb, line 110 110: def compression? 111: compression == :standard || (compression == :delayed && socket.hints[:authenticated]) 112: end
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.
# File lib/net/ssh/transport/state.rb, line 110 110: def compression? 111: compression == :standard || (compression == :delayed && socket.hints[:authenticated]) 112: end
The compressor object to use when compressing data. This takes into account the desired compression level.
# File lib/net/ssh/transport/state.rb, line 97 97: def compressor 98: @compressor ||= Zlib::Deflate.new(compression_level || Zlib::DEFAULT_COMPRESSION) 99: end
The compressor object to use when compressing data. This takes into account the desired compression level.
# File lib/net/ssh/transport/state.rb, line 97 97: def compressor 98: @compressor ||= Zlib::Deflate.new(compression_level || Zlib::DEFAULT_COMPRESSION) 99: end
Deompresses the data. If no compression is in effect, this will just return the data unmodified, otherwise it uses decompressor to decompress the data.
# File lib/net/ssh/transport/state.rb, line 124 124: def decompress(data) 125: data = data.to_s 126: return data unless compression? 127: decompressor.inflate(data) 128: end
Deompresses the data. If no compression is in effect, this will just return the data unmodified, otherwise it uses decompressor to decompress the data.
# File lib/net/ssh/transport/state.rb, line 124 124: def decompress(data) 125: data = data.to_s 126: return data unless compression? 127: decompressor.inflate(data) 128: end
The decompressor object to use when decompressing data.
# File lib/net/ssh/transport/state.rb, line 102 102: def decompressor 103: @decompressor ||= Zlib::Inflate.new(nil) 104: end
The decompressor object to use when decompressing data.
# File lib/net/ssh/transport/state.rb, line 102 102: def decompressor 103: @decompressor ||= Zlib::Inflate.new(nil) 104: end
# File lib/net/ssh/transport/state.rb, line 80 80: def final_cipher 81: result = cipher.final 82: update_next_iv(role == :client ? result : "", true) 83: return result 84: end
# File lib/net/ssh/transport/state.rb, line 80 80: def final_cipher 81: result = cipher.final 82: update_next_iv(role == :client ? result : "", true) 83: return result 84: end
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.
# File lib/net/ssh/transport/state.rb, line 89 89: def increment(packet_length) 90: @sequence_number = (@sequence_number + 1) & 0xFFFFFFFF 91: @packets += 1 92: @blocks += (packet_length + 4) / cipher.block_size 93: end
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.
# File lib/net/ssh/transport/state.rb, line 89 89: def increment(packet_length) 90: @sequence_number = (@sequence_number + 1) & 0xFFFFFFFF 91: @packets += 1 92: @blocks += (packet_length + 4) / cipher.block_size 93: end
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.
# File lib/net/ssh/transport/state.rb, line 181 181: def needs_rekey? 182: max_packets && packets > max_packets || 183: max_blocks && blocks > max_blocks 184: end
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.
# File lib/net/ssh/transport/state.rb, line 181 181: def needs_rekey? 182: max_packets && packets > max_packets || 183: max_blocks && blocks > max_blocks 184: end
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.
# File lib/net/ssh/transport/state.rb, line 133 133: def reset! 134: @packets = @blocks = 0 135: 136: @max_packets ||= 1 << 31 137: 138: if max_blocks.nil? 139: # cargo-culted from openssh. the idea is that "the 2^(blocksize*2) 140: # limit is too expensive for 3DES, blowfish, etc., so enforce a 1GB 141: # limit for small blocksizes." 142: 143: if cipher.block_size >= 16 144: @max_blocks = 1 << (cipher.block_size * 2) 145: else 146: @max_blocks = (1 << 30) / cipher.block_size 147: end 148: 149: # if a limit on the # of bytes has been given, convert that into a 150: # minimum number of blocks processed. 151: 152: if rekey_limit 153: @max_blocks = [@max_blocks, rekey_limit / cipher.block_size].min 154: end 155: end 156: 157: cleanup 158: end
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.
# File lib/net/ssh/transport/state.rb, line 133 133: def reset! 134: @packets = @blocks = 0 135: 136: @max_packets ||= 1 << 31 137: 138: if max_blocks.nil? 139: # cargo-culted from openssh. the idea is that "the 2^(blocksize*2) 140: # limit is too expensive for 3DES, blowfish, etc., so enforce a 1GB 141: # limit for small blocksizes." 142: 143: if cipher.block_size >= 16 144: @max_blocks = 1 << (cipher.block_size * 2) 145: else 146: @max_blocks = (1 << 30) / cipher.block_size 147: end 148: 149: # if a limit on the # of bytes has been given, convert that into a 150: # minimum number of blocks processed. 151: 152: if rekey_limit 153: @max_blocks = [@max_blocks, rekey_limit / cipher.block_size].min 154: end 155: end 156: 157: cleanup 158: end
A convenience method for quickly setting multiple values in a single command.
# File lib/net/ssh/transport/state.rb, line 67 67: def set(values) 68: values.each do |key, value| 69: instance_variable_set("@#{key}", value) 70: end 71: reset! 72: end
A convenience method for quickly setting multiple values in a single command.
# File lib/net/ssh/transport/state.rb, line 67 67: def set(values) 68: values.each do |key, value| 69: instance_variable_set("@#{key}", value) 70: end 71: reset! 72: end
# File lib/net/ssh/transport/state.rb, line 74 74: def update_cipher(data) 75: result = cipher.update(data) 76: update_next_iv(role == :client ? result : data) 77: return result 78: end