Class Net::SSH::Transport::State

  1. 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.

Attributes

block_size [R] The block size for the cipher
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.
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).
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_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!
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)
sequence_number [R] The next packet sequence number for this socket endpoint.
socket [R] The socket object that owns this state object.

Public class methods

new (socket, role)

Creates a new state object, belonging to the given socket. Initializes the algorithms to “none”.

[show source]
    # File lib/net/ssh/transport/state.rb, line 57
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

Public instance methods

cleanup ()

Closes any the compressor and/or decompressor objects that have been instantiated.

[show source]
     # File lib/net/ssh/transport/state.rb, line 167
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
compress (data)

Compresses the data. If no compression is in effect, this will just return the data unmodified, otherwise it uses compressor to compress the data.

[show source]
     # File lib/net/ssh/transport/state.rb, line 120
120:     def compress(data)
121:       data = data.to_s
122:       return data unless compression?
123:       compressor.deflate(data, Zlib::SYNC_FLUSH)
124:     end
compression? ()

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.

[show source]
     # File lib/net/ssh/transport/state.rb, line 114
114:     def compression?
115:       compression == :standard || (compression == :delayed && socket.hints[:authenticated])
116:     end
compressor ()

The compressor object to use when compressing data. This takes into account the desired compression level.

[show source]
     # File lib/net/ssh/transport/state.rb, line 101
101:     def compressor
102:       @compressor ||= Zlib::Deflate.new(compression_level || Zlib::DEFAULT_COMPRESSION)
103:     end
decompress (data)

Deompresses the data. If no compression is in effect, this will just return the data unmodified, otherwise it uses decompressor to decompress the data.

[show source]
     # File lib/net/ssh/transport/state.rb, line 128
128:     def decompress(data)
129:       data = data.to_s
130:       return data unless compression?
131:       decompressor.inflate(data)
132:     end
decompressor ()

The decompressor object to use when decompressing data.

[show source]
     # File lib/net/ssh/transport/state.rb, line 106
106:     def decompressor
107:       @decompressor ||= Zlib::Inflate.new(nil)
108:     end
final_cipher ()
[show source]
    # File lib/net/ssh/transport/state.rb, line 84
84:     def final_cipher
85:       result = cipher.final
86:       update_next_iv(role == :client ? result : "", true)
87:       return result
88:     end
increment (packet_length)

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.

[show source]
    # File lib/net/ssh/transport/state.rb, line 93
93:     def increment(packet_length)
94:       @sequence_number = (@sequence_number + 1) & 0xFFFFFFFF
95:       @packets += 1
96:       @blocks += (packet_length + 4) / @block_size
97:     end
needs_rekey? ()

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.

[show source]
     # File lib/net/ssh/transport/state.rb, line 186
186:     def needs_rekey?
187:       max_packets && packets > max_packets ||
188:       max_blocks && blocks > max_blocks
189:     end
reset! ()

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.

[show source]
     # File lib/net/ssh/transport/state.rb, line 137
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
152:         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
159:         end
160:       end
161: 
162:       cleanup
163:     end
set (values)

A convenience method for quickly setting multiple values in a single command.

[show source]
    # File lib/net/ssh/transport/state.rb, line 71
71:     def set(values)
72:       values.each do |key, value|
73:         instance_variable_set("@#{key}", value)
74:       end
75:       reset!
76:     end
update_cipher (data)
[show source]
    # File lib/net/ssh/transport/state.rb, line 78
78:     def update_cipher(data)
79:       result = cipher.update(data)
80:       update_next_iv(role == :client ? result : data)
81:       return result
82:     end