The AlgorithmNegotiator is used for negotiating the algorithms to be employed for a specific SSH session.

Methods
Included Modules
Constants
Algorithms = Struct.new( :server_packet, :client_packet, :kex, :host_key, :encryption_c2s, :encryption_s2c, :mac_c2s, :mac_s2c, :compression_c2s, :compression_s2c, :language_c2s, :language_s2c, :compression_level )
Public Class methods
new( logger, algorithms, buffers )

Create a new AlgorithmNegotiator instance, using the given logger, set of default algorithms, and buffer factory.

    # File lib/net/ssh/transport/algorithm-negotiator.rb, line 46
46:         def initialize( logger, algorithms, buffers )
47:           @default_algorithms = algorithms
48:           @buffers = buffers
49:           @logger = logger
50:         end
Public Instance methods
negotiate( session, options )

Negotiate the supported algorithms with the server. If a compromise cannot be reached between what the client wants and what the server can provide, this will fail.

     # File lib/net/ssh/transport/algorithm-negotiator.rb, line 109
109:         def negotiate( session, options )
110:           prepare_preferred_algorithms session, options
111: 
112:           # first, discover what the server can do
113:           type, buffer = session.wait_for_message
114:           raise Net::SSH::Exception, "expected KEXINIT" unless type == KEXINIT
115: 
116:           server_algorithm_packet = buffer.content
117: 
118:           cookie = buffer.read( 16 )
119:           kex_algorithms = buffer.read_string
120:           server_host_key_algorithms = buffer.read_string
121:           encryption_algorithms_client_to_server = buffer.read_string
122:           encryption_algorithms_server_to_client = buffer.read_string
123:           mac_algorithms_client_to_server = buffer.read_string
124:           mac_algorithms_server_to_client = buffer.read_string
125:           compression_algorithms_client_to_server = buffer.read_string
126:           compression_algorithms_server_to_client = buffer.read_string
127:           languages_client_to_server = buffer.read_string
128:           languages_server_to_client = buffer.read_string
129:           first_kex_packet_follows = buffer.read_bool
130:           zero = buffer.read_long
131: 
132:           # TODO: if first_kex_packet_follows, we need to try to skip the
133:           # actual kexinit stuff and try to guess what the server is doing...
134:           # need to read more about this scenario.
135: 
136:           # next, tell the server what we can do
137: 
138:           my_kex = @algorithms[ :kex ].join( "," )
139:           my_server_host_key_algorithms = @algorithms[ :host_key ].join( "," )
140:           my_encryption_algorithms = @algorithms[ :encryption ].join( "," )
141:           my_mac_algorithms = @algorithms[ :hmac ].join( "," )
142:           my_compression_algorithms = @algorithms[ :compression ].join( "," )
143:           my_languages = @algorithms[ :languages ].join( "," )
144: 
145:           msg = @buffers.writer
146:           msg.write_byte KEXINIT
147:           msg.write_long rand(0xFFFFFFFF), rand(0xFFFFFFFF), rand(0xFFFFFFFF),
148:             rand(0xFFFFFFFF)
149:           msg.write_string my_kex, my_server_host_key_algorithms
150:           msg.write_string my_encryption_algorithms, my_encryption_algorithms
151:           msg.write_string my_mac_algorithms, my_mac_algorithms
152:           msg.write_string my_compression_algorithms, my_compression_algorithms
153:           msg.write_string my_languages, my_languages
154:           msg.write_bool false
155:           msg.write_long 0
156: 
157:           client_algorithm_packet = msg.to_s
158:           session.send_message msg
159: 
160:           # negotiate algorithms
161: 
162:           kex_algorithm = first_matching_element( @algorithms[ :kex ],
163:             kex_algorithms )
164:           raise Net::SSH::Exception,
165:             "could not settle on kex algorithm" unless kex_algorithm
166:           @logger.debug "kex algorithm: #{kex_algorithm}" if @logger.debug?
167: 
168:           host_key_algorithm = first_matching_element(
169:             @algorithms[ :host_key ], server_host_key_algorithms )
170:           raise Net::SSH::Exception,
171:             "could not settle on host key algorithm" unless host_key_algorithm
172:           if @logger.debug?
173:             @logger.debug "host key algorithm: #{host_key_algorithm}"
174:           end
175: 
176:           encryption_algorithm_c2s = first_matching_element(
177:             @algorithms[ :encryption ], encryption_algorithms_client_to_server )
178:           unless encryption_algorithm_c2s
179:             raise Net::SSH::Exception,
180:               "could not settle on client-to-server encryption algorithm"
181:           end
182:           if @logger.debug?
183:             @logger.debug "encryption algorithm (client-to-server): " +
184:               encryption_algorithm_c2s
185:           end
186: 
187:           encryption_algorithm_s2c = first_matching_element(
188:             @algorithms[ :encryption ], encryption_algorithms_server_to_client )
189:           unless encryption_algorithm_s2c
190:             raise Net::SSH::Exception,
191:               "could not settle on server-to-client encryption algorithm"
192:           end
193:           if @logger.debug?
194:             @logger.debug "encryption algorithm (server-to-client): " +
195:               encryption_algorithm_s2c
196:           end
197: 
198:           mac_algorithm_c2s = first_matching_element(
199:             @algorithms[ :hmac ], mac_algorithms_client_to_server )
200:           unless mac_algorithm_c2s
201:             raise Net::SSH::Exception,
202:               "could not settle on client-to-server HMAC algorithm"
203:           end
204:           if @logger.debug?
205:             @logger.debug "hmac algorithm (client-to-server): " +
206:               mac_algorithm_c2s
207:           end
208: 
209:           mac_algorithm_s2c = first_matching_element( @algorithms[ :hmac ],
210:             mac_algorithms_server_to_client )
211:           unless mac_algorithm_s2c
212:             raise Net::SSH::Exception,
213:               "could not settle on server-to-client HMAC algorithm"
214:           end
215:           if @logger.debug?
216:             @logger.debug "hmac algorithm (server-to-client): " +
217:               mac_algorithm_s2c
218:           end
219: 
220:           compression_algorithm_c2s = first_matching_element(
221:             @algorithms[ :compression ],
222:             compression_algorithms_client_to_server )
223:           unless compression_algorithm_c2s
224:             raise Net::SSH::Exception,
225:               "could not settle on client-to-server compression algorithm"
226:           end
227:           if @logger.debug?
228:             @logger.debug "compression algorithm (client-to-server): " +
229:               compression_algorithm_c2s
230:           end
231: 
232:           compression_algorithm_s2c = first_matching_element(
233:             @algorithms[ :compression ],
234:             compression_algorithms_server_to_client )
235:           unless compression_algorithm_s2c
236:             raise Net::SSH::Exception,
237:               "could not settle on server-to-client compression algorithm"
238:           end
239:           if @logger.debug?
240:             @logger.debug "compression algorithm (server-to-client): " +
241:               compression_algorithm_s2c
242:           end
243: 
244:           language_c2s = first_matching_element( @algorithms[ :languages ],
245:             languages_client_to_server ) || ""
246:           if @logger.debug?
247:             @logger.debug "language (client-to-server): #{language_c2s}"
248:           end
249: 
250:           language_s2c = first_matching_element( @algorithms[ :languages ],
251:             languages_server_to_client ) || ""
252:           if @logger.debug?
253:             @logger.debug "language (server-to-client): #{language_s2c}"
254:           end
255: 
256:           return Algorithms.new( server_algorithm_packet,
257:                                  client_algorithm_packet,
258:                                  kex_algorithm,
259:                                  host_key_algorithm,
260:                                  encryption_algorithm_c2s,
261:                                  encryption_algorithm_s2c,
262:                                  mac_algorithm_c2s,
263:                                  mac_algorithm_s2c,
264:                                  compression_algorithm_c2s,
265:                                  compression_algorithm_s2c,
266:                                  language_c2s,
267:                                  language_s2c,
268:                                  @compression_level )
269:         end