def negotiate( session, options )
prepare_preferred_algorithms options
type, buffer = session.wait_for_message
raise Net::SSH::Exception, "expected KEXINIT" unless type == KEXINIT
server_algorithm_packet = buffer.content
cookie = buffer.read( 16 )
kex_algorithms = buffer.read_string
server_host_key_algorithms = buffer.read_string
encryption_algorithms_client_to_server = buffer.read_string
encryption_algorithms_server_to_client = buffer.read_string
mac_algorithms_client_to_server = buffer.read_string
mac_algorithms_server_to_client = buffer.read_string
compression_algorithms_client_to_server = buffer.read_string
compression_algorithms_server_to_client = buffer.read_string
languages_client_to_server = buffer.read_string
languages_server_to_client = buffer.read_string
first_kex_packet_follows = buffer.read_bool
zero = buffer.read_long
my_kex = @algorithms[ :kex ].join( "," )
my_server_host_key_algorithms = @algorithms[ :host_key ].join( "," )
my_encryption_algorithms = @algorithms[ :encryption ].join( "," )
my_mac_algorithms = @algorithms[ :hmac ].join( "," )
my_compression_algorithms = @algorithms[ :compression ].join( "," )
my_languages = @algorithms[ :languages ].join( "," )
msg = @buffers.writer
msg.write_byte KEXINIT
msg.write_long rand(0xFFFFFFFF), rand(0xFFFFFFFF), rand(0xFFFFFFFF),
rand(0xFFFFFFFF)
msg.write_string my_kex, my_server_host_key_algorithms
msg.write_string my_encryption_algorithms, my_encryption_algorithms
msg.write_string my_mac_algorithms, my_mac_algorithms
msg.write_string my_compression_algorithms, my_compression_algorithms
msg.write_string my_languages, my_languages
msg.write_bool false
msg.write_long 0
client_algorithm_packet = msg.to_s
session.send_message msg
kex_algorithm = first_matching_element( @algorithms[ :kex ],
kex_algorithms )
raise Net::SSH::Exception,
"could not settle on kex algorithm" unless kex_algorithm
@logger.debug "kex algorithm: #{kex_algorithm}" if @logger.debug?
host_key_algorithm = first_matching_element(
@algorithms[ :host_key ], server_host_key_algorithms )
raise Net::SSH::Exception,
"could not settle on host key algorithm" unless host_key_algorithm
if @logger.debug?
@logger.debug "host key algorithm: #{host_key_algorithm}"
end
encryption_algorithm_c2s = first_matching_element(
@algorithms[ :encryption ], encryption_algorithms_client_to_server )
unless encryption_algorithm_c2s
raise Net::SSH::Exception,
"could not settle on client-to-server encryption algorithm"
end
if @logger.debug?
@logger.debug "encryption algorithm (client-to-server): " +
encryption_algorithm_c2s
end
encryption_algorithm_s2c = first_matching_element(
@algorithms[ :encryption ], encryption_algorithms_server_to_client )
unless encryption_algorithm_s2c
raise Net::SSH::Exception,
"could not settle on server-to-client encryption algorithm"
end
if @logger.debug?
@logger.debug "encryption algorithm (server-to-client): " +
encryption_algorithm_s2c
end
mac_algorithm_c2s = first_matching_element(
@algorithms[ :hmac ], mac_algorithms_client_to_server )
unless mac_algorithm_c2s
raise Net::SSH::Exception,
"could not settle on client-to-server HMAC algorithm"
end
if @logger.debug?
@logger.debug "hmac algorithm (client-to-server): " +
mac_algorithm_c2s
end
mac_algorithm_s2c = first_matching_element( @algorithms[ :hmac ],
mac_algorithms_server_to_client )
unless mac_algorithm_s2c
raise Net::SSH::Exception,
"could not settle on server-to-client HMAC algorithm"
end
if @logger.debug?
@logger.debug "hmac algorithm (server-to-client): " +
mac_algorithm_s2c
end
compression_algorithm_c2s = first_matching_element(
@algorithms[ :compression ],
compression_algorithms_client_to_server )
unless compression_algorithm_c2s
raise Net::SSH::Exception,
"could not settle on client-to-server compression algorithm"
end
if @logger.debug?
@logger.debug "compression algorithm (client-to-server): " +
compression_algorithm_c2s
end
compression_algorithm_s2c = first_matching_element(
@algorithms[ :compression ],
compression_algorithms_server_to_client )
unless compression_algorithm_s2c
raise Net::SSH::Exception,
"could not settle on server-to-client compression algorithm"
end
if @logger.debug?
@logger.debug "compression algorithm (server-to-client): " +
compression_algorithm_s2c
end
language_c2s = first_matching_element( @algorithms[ :languages ],
languages_client_to_server ) || ""
if @logger.debug?
@logger.debug "language (client-to-server): #{language_c2s}"
end
language_s2c = first_matching_element( @algorithms[ :languages ],
languages_server_to_client ) || ""
if @logger.debug?
@logger.debug "language (server-to-client): #{language_s2c}"
end
return Algorithms.new( server_algorithm_packet,
client_algorithm_packet,
kex_algorithm,
host_key_algorithm,
encryption_algorithm_c2s,
encryption_algorithm_s2c,
mac_algorithm_c2s,
mac_algorithm_s2c,
compression_algorithm_c2s,
compression_algorithm_s2c,
language_c2s,
language_s2c,
@compression_level )
end