net-ssh-2.6.8/0000755000004100000410000000000012166626376013157 5ustar www-datawww-datanet-ssh-2.6.8/CHANGES.txt0000644000004100000410000002546712166626376015006 0ustar www-datawww-data === 2.6.8 / 6 Jul 2013 * Added support for host wildcard substitution [GabKlein] * Added a wait to the loop in close to help fix possible blocks [Josh Kalderimis] * Fixed test file encoding issues with Ruby 2.0 (#87) [voxik] === 2.6.7 / 11 Apr 2013 * Decreased default packet size to 32768 as described in RFC 4253 [Olipro] * Added max_pkt_size and max_win_size options to Net::SSH.start [Olipro] === 2.6.6 / 03 Mar 2013 * Fix for ruby 2.0 in windows [jansegre] === 2.6.5 / 06 Feb 2013 * Fixed path in gemspec [thanks priteau] === 2.6.4 / 06 Feb 2013 * Added license info to gemspec [jordimassaguerpla] * Added public cert. All gem releases are now signed. === 2.6.3 / 10 Jan 2013 * Small doc fix and correct error class for PKey::EC key type [Andreas Wolff] * Improve test dependencies [Kenichi Kamiya] === 2.6.2 / 22 Nov 2012 * Net::SSH.start now returns result of block [mhuffnagle] * Add stderr handling to Net::SSH::Test [ohrite] * Fix Invalid key size in JRuby [ohrite] === 2.6.1 / 18 Oct 2012 * Remove platform specific jruby dependency from gemspec * Changed encoding of file to prevent warnings when generating docs [iltempo] === 2.6.0 / 19 Sep 2012 * Use OpenSSL::PKey.read to read arbitrary private key. [nagachika] * Check availability of UNIXSocket and UNIXServer for Windows [Nobuhiro IMAI] * Bump version to 2.5.3 and depend on newer jruby-pageant version for Java 1.5 compat. [arturaz] * Implementation of the "none"-authentication method [dubspeed] * Add class for stricter host key verification [Andy Brody] === 2.5.2 / 25 May 2012 * Fix for Net::SSH::KnownHosts::SUPPORTED_TYPE [Marco Sandrini] === 2.5.1 / 24 May 2012 * Added missing file to manifest [Marco Sandrini] === 2.5.0 / 24 May 2012 * Implement many algorithms [Ryosuke Yamazaki] * Key Exchange * diffie-hellman-group14-sha1 * ecdh-sha2-nistp{256,384,521} * Host Key * ecdsa-sha2-nistp{256,384,521} * Authentication * ecdsa-sha2-nistp{256,384,521} * HMAC * hmac-ripemd160 * Cipher: * aes{128,192,256}-ctr * camellia{128,192,256}-ctr * blowfish-ctr * cast128-ctr * 3des-ctr * arcfour (has problems with weak keys, and should be used with caution) * camellia{128,192,256}-cbc === 2.4.0 / 17 May 2012 * Support for JRuby + Pageant + Windows [arturaz] === 2.3.0 / 11 Jan 2012 * Support for hmac-sha2 and diffie-hellman-group-exchange-sha256 [Ryosuke Yamazaki] === 2.2.2 / 04 Jan 2012 * Fixed: Connection hangs on ServerVersion.new(socket, logger) [muffl0n] * Avoid dying when unsupported auth mechanisms are defined [pcn] === 2.2.1 / 24 Aug 2011 * Do not prompt any passphrases before trying all identities from agent. [musybite] (see: http://net-ssh.lighthouseapp.com/projects/36253-net-ssh/tickets/30) === 2.2.0 / 16 Aug 2011 * Add support for forward a local UNIX domain socket to a remote TCP socket. [Mark Imbriaco] === 2.1.4 / 3 Apr 2011 * Add ConnectionTimeout exception class. [Joel Watson] See: https://github.com/net-ssh/net-ssh-multi/pull/1 === 2.1.3 / 2 Mar 2011 * Call to transport.closed should be transport.close [Woon Jung] === 2.1.2 / 1 Mar 2011 * Fix for Net::SSH Continues to attempt authentication when notified it is not allowed [Eric Hodel] (see: http://net-ssh.lighthouseapp.com/projects/36253-net-ssh/tickets/26) * Fix for transport won't be closed if authentication fails [Patrick Marchi] === 2.1 / 19 Jan 2011 * Support "IdentitiesOnly" directive (LH-24) [Musy Bite, Edmund Haselwanter] * Speeding up the Loggable module (LH-23) [robbebob] === 2.0.24 / 14 Jan 2011 * Fix for process code to correctly wait until remote_id is set before sending any output, including eof. [Daniel Pittman, Markus Roberts] * Fix circular require warning in Ruby 1.9.2 [Gavin Brock] === 2.0.23 / 03 Jun 2010 * delay CHANNEL_EOF packet until output buffer is empty [Rich Lane] Previously, calling #eof! after #send_data would result in the CHANNEL_EOF packet being sent immediately, ahead of the data in the output buffer. Now buffer becomes empty. === 2.0.22 / 20 Apr 2010 * Fix for: "Parsing the config errors out because it coerces the "1" into an integer and then tries to split it on spaces for multiple host checking." (http://net-ssh.lighthouseapp.com/projects/36253/tickets/10) [Lee Marlow] === 2.0.21 / 20 Mar 2010 * Fix for "IdentifyFile" in ~/.ssh/config does not work if no "Host" statement is given (http://net-ssh.lighthouseapp.com/projects/36253/tickets/9-identifyfile-in-sshconfig-does-not-work-if-no-host-statement-is-given#ticket-9-5) [xbaldauf, Delano Mandelbaum] * Fix for client closes a forwarded connection, but the server is reading, net-ssh terminates with IOError socket closed (http://net-ssh.lighthouseapp.com/projects/36253/tickets/7) [Miklós Fazekas] * Fix for client force closes (RST) a forwarded connection, but server is reading, net-ssh terminates with exception [Miklós Fazekas] * Fix for server closes the sending side, the on_eof is not handled. [Miklós Fazekas] * Removed Hanna dependency in Rakefile [Delano Mandelbaum] === 2.0.20 / 10 Feb 2010 * Support "ProxyCommand none" directive [Andy Lo-A-Foe] === 2.0.19 / 16 Jan 2010 * Support plus sign in sshconfig hostname [Jason Weathered] === 2.0.18 / 15 Jan 2010 * Fix related to #recv(1) to #readpartial change in 2.0.16 [Hans de Graaff, Delano Mandelbaum] === 2.0.17 / 14 Dec 2009 * Don't load net/ssh/authentication/pageant on Windows with Ruby 1.9 [Travis Reeder, Delano Mandelbaum] === 2.0.16 / 28 Nov 2009 * Fix for "multiple hosts are separated by whitespace" [Akinori MUSHA] * Add support for the ProxyCommand directive [Akinori MUSHA] * Switched from #recv(1) to #readpartial in lib/net/ssh/transport/server_version.rb, so that closed sockets are recognized [Alex Peuchert] === 2.0.15 / 03 Sep 2009 * Scale back IO#select patch so it mutexes only zero-timeout calls [Daniel Azuma, Will Bryant] === 2.0.14 / 28 Aug 2009 * Fix for IO#select threading bug in Ruby 1.8 (LH-1) [Daniel Azuma] * Fix for "uninitialized constant OpenSSL::Digest::MD5" exception in Net::SFTP [DL Redden] === 2.0.13 / 17 Aug 2009 * Added fix for hanging in ServerVersion#negotiate! when using SOCKS5 proxy (GH-9) [Gerald Talton] * Added support for specifying a list of hosts in .ssh/config, with tests (GH-6) [ckoehler, Delano Mandelbaum] * Added tests for arcfour128/256/512 lengths, encryption, and decryption [Delano Mandelbaum] * Skip packet stream tests for arcfour128/256/512 [Delano Mandelbaum] * Fix for OpenSSL cipher key length because it always returns 16, even when 32 byte keys are required, e.g. for arcfour256 and arcfour512 ciphers [Karl Varga] === 2.0.12 / 08 Jun 2009 * Applied patch for arcfour128 and arcfour256 support [Denis Bernard] * Use unbuffered reads when negotiating the protocol version [Steven Hazel] === 2.0.11 / 24 Feb 2009 * Add :key_data option for specifying raw private keys in PEM format [Alex Holems, Andrew Babkin] === 2.0.10 / 4 Feb 2009 * Added Net::SSH.configuration_for to make it easier to query the SSH configuration file(s) [Jamis Buck] === 2.0.9 / 1 Feb 2009 * Specifying non-nil user argument overrides user in .ssh/config [Jamis Buck] * Ignore requests for non-existent channels (workaround ssh server bug) [Jamis Buck] * Add terminate! method for hard shutdown scenarios [Jamis Buck] * Revert to pre-2.0.7 key-loading behavior by default, but load private-key if public-key doesn't exist [Jamis Buck] * Make sure :passphrase option gets passed to key manager [Bob Cotton] === 2.0.8 / 29 December 2008 * Fix private key change from 2.0.7 so that keys are loaded just-in-time, avoiding unecessary prompts from encrypted keys. [Jamis Buck] === 2.0.7 / 29 December 2008 * Make key manager use private keys instead of requiring public key to exist [arilerner@mac.com] * Fix failing tests [arilerner@mac.com] * Don't include pageant when running under JRuby [Angel N. Sciortino] === 2.0.6 / 6 December 2008 * Update the Manifest file so that the gem includes all necessary files [Jamis Buck] === 2.0.5 / 6 December 2008 * Make the Pageant interface comply with more of the Socket interface to avoid related errors [Jamis Buck] * Don't busy-wait on session close for remaining channels to close [Will Bryant] * Ruby 1.9 compatibility [Jamis Buck] * Fix Cipher#final to correctly flag a need for a cipher reset [Jamis Buck] === 2.0.4 / 27 Aug 2008 * Added Connection::Session#closed? and Transport::Session#closed? [Jamis Buck] * Numeric host names in .ssh/config are now parsed correct [Yanko Ivanov] * Make sure the error raised when a public key file is malformed is more informative than a MethodMissing error [Jamis Buck] * Cipher#reset is now called after Cipher#final, with the last n bytes used as the next initialization vector [Jamis Buck] === 2.0.3 / 27 Jun 2008 * Make Net::SSH::Version comparable [Brian Candler] * Fix errors in port forwarding when a channel could not be opened due to a typo in the exception name [Matthew Todd] * Use #chomp instead of #strip when cleaning the version string reported by the remote host, so that trailing whitespace is preserved (this is to play nice with servers like Mocana SSH) [Timo Gatsonides] * Correctly parse ssh_config entries with eq-sign delimiters [Jamis Buck] * Ignore malformed ssh_config entries [Jamis Buck] === 2.0.2 / 29 May 2008 * Make sure the agent client understands both RSA "identities answers" [Jamis Buck] * Fixed key truncation bug that caused hmacs other than SHA1 to fail with "corrupt hmac" errors [Jamis Buck] * Fix detection and loading of public keys when the keys don't actually exist [David Dollar] === 2.0.1 / 5 May 2008 * Teach Net::SSH about a handful of default key names [Jamis Buck] === 2.0.0 / 1 May 2008 * Allow the :verbose argument to accept symbols (:debug, etc.) as well as Logger level constants (Logger::DEBUG, etc.) [Jamis Buck] === 2.0 Preview Release 4 (1.99.3) / 19 Apr 2008 * Make sure HOME is set to something sane, even on OS's that don't set it by default [Jamis Buck] * Add a :passphrase option to specify the passphrase to use with private keys [Francis Sullivan] * Open a new auth agent connection for every auth-agent channel request [Jamis Buck] === 2.0 Preview Release 3 (1.99.2) / 10 Apr 2008 * Session properties [Jamis Buck] * Make channel open failure work with a callback so that failures can be handled similarly to successes [Jamis Buck] === 2.0 Preview Release 2 (1.99.1) / 22 Mar 2008 * Partial support for ~/.ssh/config (and related) SSH configuration files [Daniel J. Berger, Jamis Buck] * Added Net::SSH::Test to facilitate testing complex SSH state machines [Jamis Buck] * Reworked Net::SSH::Prompt to use conditionally-selected modules [Jamis Buck, suggested by James Rosen] * Added Channel#eof? and Channel#eof! [Jamis Buck] * Fixed bug in strict host key verifier on cache miss [Mike Timm] === 2.0 Preview Release 1 (1.99.0) / 21 Aug 2007 * First preview release of Net::SSH v2 net-ssh-2.6.8/test/0000755000004100000410000000000012166626376014136 5ustar www-datawww-datanet-ssh-2.6.8/test/configs/0000755000004100000410000000000012166626376015566 5ustar www-datawww-datanet-ssh-2.6.8/test/configs/exact_match0000644000004100000410000000015512166626376017772 0ustar www-datawww-dataHost other.host Compression no Port 1231 Host test.host Compression yes ForwardAgent yes Port 1234net-ssh-2.6.8/test/configs/numeric_host0000644000004100000410000000007012166626376020205 0ustar www-datawww-dataHost 1234 Compression yes Port 1980 RekeyLimit 2G net-ssh-2.6.8/test/configs/eqsign0000644000004100000410000000005612166626376017000 0ustar www-datawww-dataHost=test.test Port =1234 Compression yes net-ssh-2.6.8/test/configs/multihost0000644000004100000410000000011012166626376017531 0ustar www-datawww-dataHost other.host test.host Compression yes Port 1980 RekeyLimit 2G net-ssh-2.6.8/test/configs/host_plus0000644000004100000410000000053312166626376017532 0ustar www-datawww-data# Jump through hosts with one SSH call # via Host *+* ProxyCommand ssh $(echo %h | sed 's/+[^+]*$//;s/\([^+%%]*\)%%\([^+]*\)$/\2 -l \1/;s/:/ -p /') PATH=.:\$PATH nc -w1 $(echo %h | sed 's/^.*+//;/:/!s/$/ %p/;s/:/ /') Host office-offsite HostName work-gateway+office-workstation Host test.host Compression yesnet-ssh-2.6.8/test/configs/substitutes0000644000004100000410000000013112166626376020102 0ustar www-datawww-dataHost test HostName %h.sufix Host 1234 HostName prefix.%h.sufix Host * HostName %hnet-ssh-2.6.8/test/configs/wild_cards0000644000004100000410000000026112166626376017623 0ustar www-datawww-dataHost test.* Port 1234 Compression no Host tes?.host Port 4321 ForwardAgent yes Host *.hos? IdentityFile ~/.ssh/id_dsa Compression yes Host k*.host RekeyLimit 1Gnet-ssh-2.6.8/test/configs/nohost0000644000004100000410000000023012166626376017016 0ustar www-datawww-data IdentityFile ~/.ssh/id_dsa IdentityFile ~/.ssh/id_rsa Port 1980 Host test.host Port 1985 net-ssh-2.6.8/test/connection/0000755000004100000410000000000012166626376016275 5ustar www-datawww-datanet-ssh-2.6.8/test/connection/test_session.rb0000644000004100000410000004506012166626376021351 0ustar www-datawww-datarequire 'common' require 'net/ssh/connection/session' module Connection class TestSession < Test::Unit::TestCase include Net::SSH::Connection::Constants def test_constructor_should_set_defaults assert session.channels.empty? assert session.pending_requests.empty? assert_equal({ socket => nil }, session.listeners) end def test_on_open_channel_should_register_block_with_given_channel_type flag = false session.on_open_channel("testing") { flag = true } assert_not_nil session.channel_open_handlers["testing"] session.channel_open_handlers["testing"].call assert flag, "callback should have been invoked" end def test_forward_should_create_and_cache_instance_of_forward_service assert_instance_of Net::SSH::Service::Forward, session.forward assert_equal session.forward.object_id, session.forward.object_id end def test_listen_to_without_callback_should_add_argument_as_listener io = stub("io") session.listen_to(io) assert session.listeners.key?(io) assert_nil session.listeners[io] end def test_listen_to_should_add_argument_to_listeners_list_if_block_is_given io = stub("io", :pending_write? => true) flag = false session.listen_to(io) { flag = true } assert !flag, "callback should not be invoked immediately" assert session.listeners.key?(io) session.listeners[io].call assert flag, "callback should have been invoked" end def test_stop_listening_to_should_remove_argument_from_listeners io = stub("io", :pending_write? => true) session.listen_to(io) assert session.listeners.key?(io) session.stop_listening_to(io) assert !session.listeners.key?(io) end def test_send_message_should_enqueue_message_at_transport_layer packet = P(:byte, REQUEST_SUCCESS) session.send_message(packet) assert_equal packet.to_s, socket.write_buffer end def test_open_channel_defaults_should_use_session_channel flag = false channel = session.open_channel { flag = true } assert !flag, "callback should not be invoked immediately" channel.do_open_confirmation(1,2,3) assert flag, "callback should have been invoked" assert_equal "session", channel.type assert_equal 0, channel.local_id assert_equal channel, session.channels[channel.local_id] packet = P(:byte, CHANNEL_OPEN, :string, "session", :long, channel.local_id, :long, channel.local_maximum_window_size, :long, channel.local_maximum_packet_size) assert_equal packet.to_s, socket.write_buffer end def test_open_channel_with_type_should_use_type channel = session.open_channel("direct-tcpip") assert_equal "direct-tcpip", channel.type packet = P(:byte, CHANNEL_OPEN, :string, "direct-tcpip", :long, channel.local_id, :long, channel.local_maximum_window_size, :long, channel.local_maximum_packet_size) assert_equal packet.to_s, socket.write_buffer end def test_open_channel_with_extras_should_append_extras_to_packet channel = session.open_channel("direct-tcpip", :string, "other.host", :long, 1234) packet = P(:byte, CHANNEL_OPEN, :string, "direct-tcpip", :long, channel.local_id, :long, channel.local_maximum_window_size, :long, channel.local_maximum_packet_size, :string, "other.host", :long, 1234) assert_equal packet.to_s, socket.write_buffer end def test_send_global_request_without_callback_should_not_expect_reply packet = P(:byte, GLOBAL_REQUEST, :string, "testing", :bool, false) session.send_global_request("testing") assert_equal packet.to_s, socket.write_buffer assert session.pending_requests.empty? end def test_send_global_request_with_callback_should_expect_reply packet = P(:byte, GLOBAL_REQUEST, :string, "testing", :bool, true) proc = Proc.new {} session.send_global_request("testing", &proc) assert_equal packet.to_s, socket.write_buffer assert_equal [proc], session.pending_requests end def test_send_global_request_with_extras_should_append_extras_to_packet packet = P(:byte, GLOBAL_REQUEST, :string, "testing", :bool, false, :string, "other.host", :long, 1234) session.send_global_request("testing", :string, "other.host", :long, 1234) assert_equal packet.to_s, socket.write_buffer end def test_process_should_exit_immediately_if_block_is_false session.channels[0] = stub("channel", :closing? => false) session.channels[0].expects(:process).never process_times(0) end def test_process_should_exit_after_processing_if_block_is_true_then_false session.channels[0] = stub("channel", :closing? => false) session.channels[0].expects(:process) IO.expects(:select).never process_times(2) end def test_process_should_not_process_channels_that_are_closing session.channels[0] = stub("channel", :closing? => true) session.channels[0].expects(:process).never IO.expects(:select).never process_times(2) end def test_global_request_packets_should_be_silently_handled_if_no_handler_exists_for_them transport.return(GLOBAL_REQUEST, :string, "testing", :bool, false) process_times(2) assert transport.queue.empty? assert !socket.pending_write? end def test_global_request_packets_should_be_auto_replied_to_even_if_no_handler_exists transport.return(GLOBAL_REQUEST, :string, "testing", :bool, true) process_times(2) assert_equal P(:byte, REQUEST_FAILURE).to_s, socket.write_buffer end def test_global_request_handler_should_not_trigger_auto_reply_if_no_reply_is_wanted flag = false session.on_global_request("testing") { flag = true } assert !flag, "callback should not be invoked yet" transport.return(GLOBAL_REQUEST, :string, "testing", :bool, false) process_times(2) assert transport.queue.empty? assert !socket.pending_write? assert flag, "callback should have been invoked" end def test_global_request_handler_returning_true_should_trigger_success_auto_reply flag = false session.on_global_request("testing") { flag = true } transport.return(GLOBAL_REQUEST, :string, "testing", :bool, true) process_times(2) assert_equal P(:byte, REQUEST_SUCCESS).to_s, socket.write_buffer assert flag end def test_global_request_handler_returning_false_should_trigger_failure_auto_reply flag = false session.on_global_request("testing") { flag = true; false } transport.return(GLOBAL_REQUEST, :string, "testing", :bool, true) process_times(2) assert_equal P(:byte, REQUEST_FAILURE).to_s, socket.write_buffer assert flag end def test_global_request_handler_returning_sent_should_not_trigger_auto_reply flag = false session.on_global_request("testing") { flag = true; :sent } transport.return(GLOBAL_REQUEST, :string, "testing", :bool, true) process_times(2) assert !socket.pending_write? assert flag end def test_global_request_handler_returning_other_value_should_raise_error session.on_global_request("testing") { "bug" } transport.return(GLOBAL_REQUEST, :string, "testing", :bool, true) assert_raises(RuntimeError) { process_times(2) } end def test_request_success_packets_should_invoke_next_pending_request_with_true result = nil session.pending_requests << Proc.new { |*args| result = args } transport.return(REQUEST_SUCCESS) process_times(2) assert_equal [true, P(:byte, REQUEST_SUCCESS)], result assert session.pending_requests.empty? end def test_request_failure_packets_should_invoke_next_pending_request_with_false result = nil session.pending_requests << Proc.new { |*args| result = args } transport.return(REQUEST_FAILURE) process_times(2) assert_equal [false, P(:byte, REQUEST_FAILURE)], result assert session.pending_requests.empty? end def test_channel_open_packet_without_corresponding_channel_open_handler_should_result_in_channel_open_failure transport.return(CHANNEL_OPEN, :string, "auth-agent", :long, 14, :long, 0x20000, :long, 0x10000) process_times(2) assert_equal P(:byte, CHANNEL_OPEN_FAILURE, :long, 14, :long, 3, :string, "unknown channel type auth-agent", :string, "").to_s, socket.write_buffer end def test_channel_open_packet_with_corresponding_handler_should_result_in_channel_open_failure_when_handler_returns_an_error transport.return(CHANNEL_OPEN, :string, "auth-agent", :long, 14, :long, 0x20000, :long, 0x10000) session.on_open_channel "auth-agent" do |s, ch, p| raise Net::SSH::ChannelOpenFailed.new(1234, "we iz in ur channelz!") end process_times(2) assert_equal P(:byte, CHANNEL_OPEN_FAILURE, :long, 14, :long, 1234, :string, "we iz in ur channelz!", :string, "").to_s, socket.write_buffer end def test_channel_open_packet_with_corresponding_handler_should_result_in_channel_open_confirmation_when_handler_succeeds transport.return(CHANNEL_OPEN, :string, "auth-agent", :long, 14, :long, 0x20001, :long, 0x10001) result = nil session.on_open_channel("auth-agent") { |*args| result = args } process_times(2) assert_equal P(:byte, CHANNEL_OPEN_CONFIRMATION, :long, 14, :long, 0, :long, 0x20000, :long, 0x8000).to_s, socket.write_buffer assert_not_nil(ch = session.channels[0]) assert_equal [session, ch, P(:byte, CHANNEL_OPEN, :string, "auth-agent", :long, 14, :long, 0x20001, :long, 0x10001)], result assert_equal 0, ch.local_id assert_equal 14, ch.remote_id assert_equal 0x20001, ch.remote_maximum_window_size assert_equal 0x10001, ch.remote_maximum_packet_size assert_equal 0x20000, ch.local_maximum_window_size assert_equal 0x8000, ch.local_maximum_packet_size assert_equal "auth-agent", ch.type end def test_channel_open_failure_should_remove_channel_and_tell_channel_that_open_failed session.channels[1] = stub("channel") session.channels[1].expects(:do_open_failed).with(1234, "some reason") transport.return(CHANNEL_OPEN_FAILURE, :long, 1, :long, 1234, :string, "some reason", :string, "lang tag") process_times(2) assert session.channels.empty? end def test_channel_open_confirmation_packet_should_be_routed_to_corresponding_channel channel_at(14).expects(:do_open_confirmation).with(1234, 0x20001, 0x10001) transport.return(CHANNEL_OPEN_CONFIRMATION, :long, 14, :long, 1234, :long, 0x20001, :long, 0x10001) process_times(2) end def test_channel_window_adjust_packet_should_be_routed_to_corresponding_channel channel_at(14).expects(:do_window_adjust).with(5000) transport.return(CHANNEL_WINDOW_ADJUST, :long, 14, :long, 5000) process_times(2) end def test_channel_request_for_nonexistant_channel_should_be_ignored transport.return(CHANNEL_REQUEST, :long, 14, :string, "testing", :bool, false) assert_nothing_raised { process_times(2) } end def test_channel_request_packet_should_be_routed_to_corresponding_channel channel_at(14).expects(:do_request).with("testing", false, Net::SSH::Buffer.new) transport.return(CHANNEL_REQUEST, :long, 14, :string, "testing", :bool, false) process_times(2) end def test_channel_data_packet_should_be_routed_to_corresponding_channel channel_at(14).expects(:do_data).with("bring it on down") transport.return(CHANNEL_DATA, :long, 14, :string, "bring it on down") process_times(2) end def test_channel_extended_data_packet_should_be_routed_to_corresponding_channel channel_at(14).expects(:do_extended_data).with(1, "bring it on down") transport.return(CHANNEL_EXTENDED_DATA, :long, 14, :long, 1, :string, "bring it on down") process_times(2) end def test_channel_eof_packet_should_be_routed_to_corresponding_channel channel_at(14).expects(:do_eof).with() transport.return(CHANNEL_EOF, :long, 14) process_times(2) end def test_channel_success_packet_should_be_routed_to_corresponding_channel channel_at(14).expects(:do_success).with() transport.return(CHANNEL_SUCCESS, :long, 14) process_times(2) end def test_channel_failure_packet_should_be_routed_to_corresponding_channel channel_at(14).expects(:do_failure).with() transport.return(CHANNEL_FAILURE, :long, 14) process_times(2) end def test_channel_close_packet_should_be_routed_to_corresponding_channel_and_channel_should_be_closed_and_removed channel_at(14).expects(:do_close).with() session.channels[14].expects(:close).with() transport.return(CHANNEL_CLOSE, :long, 14) process_times(2) assert session.channels.empty? end def test_multiple_pending_dispatches_should_be_dispatched_together channel_at(14).expects(:do_eof).with() session.channels[14].expects(:do_success).with() transport.return(CHANNEL_SUCCESS, :long, 14) transport.return(CHANNEL_EOF, :long, 14) process_times(2) end def test_writers_without_pending_writes_should_not_be_considered_for_select IO.expects(:select).with([socket],[],nil,nil).returns([[],[],[]]) session.process end def test_writers_with_pending_writes_should_be_considered_for_select socket.enqueue("laksdjflasdkf") IO.expects(:select).with([socket],[socket],nil,nil).returns([[],[],[]]) session.process end def test_ready_readers_should_be_filled socket.expects(:recv).returns("this is some data") IO.expects(:select).with([socket],[],nil,nil).returns([[socket],[],[]]) session.process assert_equal [socket], session.listeners.keys end def test_ready_readers_that_cant_be_filled_should_be_removed socket.expects(:recv).returns("") socket.expects(:close) IO.expects(:select).with([socket],[],nil,nil).returns([[socket],[],[]]) session.process assert session.listeners.empty? end def test_ready_readers_that_are_registered_with_a_block_should_call_block_instead_of_fill io = stub("io", :pending_write? => false) flag = false session.stop_listening_to(socket) # so that we only have to test the presence of a single IO object session.listen_to(io) { flag = true } IO.expects(:select).with([io],[],nil,nil).returns([[io],[],[]]) session.process assert flag, "callback should have been invoked" end def test_ready_writers_should_call_send_pending socket.enqueue("laksdjflasdkf") socket.expects(:send).with("laksdjflasdkf", 0).returns(13) IO.expects(:select).with([socket],[socket],nil,nil).returns([[],[socket],[]]) session.process end def test_process_should_call_rekey_as_needed transport.expects(:rekey_as_needed) IO.expects(:select).with([socket],[],nil,nil).returns([[],[],[]]) session.process end def test_loop_should_call_process_until_process_returns_false IO.stubs(:select).with([socket],[],nil,nil).returns([[],[],[]]) session.expects(:process).with(nil).times(4).returns(true,true,true,false).yields n = 0 session.loop { n += 1 } assert_equal 4, n end def test_exec_should_open_channel_and_configure_default_callbacks prep_exec("ls", :stdout, "data packet", :stderr, "extended data packet") call = :first session.exec "ls" do |channel, type, data| if call == :first assert_equal :stdout, type assert_equal "data packet", data call = :second elsif call == :second assert_equal :stderr, type assert_equal "extended data packet", data call = :third else flunk "should never get here, call == #{call.inspect}" end end session.loop assert_equal :third, call end def test_exec_without_block_should_use_print_to_display_result prep_exec("ls", :stdout, "data packet", :stderr, "extended data packet") $stdout.expects(:print).with("data packet") $stderr.expects(:print).with("extended data packet") session.exec "ls" session.loop end def test_exec_bang_should_block_until_command_finishes prep_exec("ls", :stdout, "some data") called = false session.exec! "ls" do |channel, type, data| called = true assert_equal :stdout, type assert_equal "some data", data end assert called end def test_exec_bang_without_block_should_return_data_as_string prep_exec("ls", :stdout, "some data") assert_equal "some data", session.exec!("ls") end private def prep_exec(command, *data) transport.mock_enqueue = true transport.expect do |t, p| assert_equal CHANNEL_OPEN, p.type t.return(CHANNEL_OPEN_CONFIRMATION, :long, p[:remote_id], :long, 0, :long, 0x20000, :long, 0x10000) t.expect do |t2, p2| assert_equal CHANNEL_REQUEST, p2.type assert_equal "exec", p2[:request] assert_equal true, p2[:want_reply] assert_equal "ls", p2.read_string t2.return(CHANNEL_SUCCESS, :long, p[:remote_id]) 0.step(data.length-1, 2) do |index| type = data[index] datum = data[index+1] if type == :stdout t2.return(CHANNEL_DATA, :long, p[:remote_id], :string, datum) else t2.return(CHANNEL_EXTENDED_DATA, :long, p[:remote_id], :long, 1, :string, datum) end end t2.return(CHANNEL_CLOSE, :long, p[:remote_id]) t2.expect { |t3,p3| assert_equal CHANNEL_CLOSE, p3.type } end end end module MockSocket # so that we can easily test the contents that were enqueued, without # worrying about all the packet stream overhead def enqueue_packet(message) enqueue(message.to_s) end end def socket @socket ||= begin socket ||= Object.new socket.extend(Net::SSH::Transport::PacketStream) socket.extend(MockSocket) socket end end def channel_at(local_id) session.channels[local_id] = stub("channel", :process => true, :closing? => false) end def transport(options={}) @transport ||= MockTransport.new(options.merge(:socket => socket)) end def session(options={}) @session ||= Net::SSH::Connection::Session.new(transport, options) end def process_times(n) i = 0 session.process { (i += 1) < n } end end end net-ssh-2.6.8/test/connection/test_channel.rb0000644000004100000410000004020012166626376021265 0ustar www-datawww-datarequire 'common' require 'net/ssh/connection/channel' module Connection class TestChannel < Test::Unit::TestCase include Net::SSH::Connection::Constants def teardown connection.test! end def test_constructor_should_set_defaults assert_equal 0x8000, channel.local_maximum_packet_size assert_equal 0x20000, channel.local_maximum_window_size assert channel.pending_requests.empty? end def test_channel_properties channel[:hello] = "some value" assert_equal "some value", channel[:hello] end def test_exec_should_be_syntactic_sugar_for_a_channel_request channel.expects(:send_channel_request).with("exec", :string, "ls").yields found_block = false channel.exec("ls") { found_block = true } assert found_block, "expected block to be passed to send_channel_request" end def test_subsystem_should_be_syntactic_sugar_for_a_channel_request channel.expects(:send_channel_request).with("subsystem", :string, "sftp").yields found_block = false channel.subsystem("sftp") { found_block = true } assert found_block, "expected block to be passed to send_channel_request" end def test_request_pty_with_invalid_option_should_raise_error assert_raises(ArgumentError) do channel.request_pty(:bogus => "thing") end end def test_request_pty_without_options_should_use_defaults channel.expects(:send_channel_request).with("pty-req", :string, "xterm", :long, 80, :long, 24, :long, 640, :long, 480, :string, "\0").yields found_block = false channel.request_pty { found_block = true } assert found_block, "expected block to be passed to send_channel_request" end def test_request_pty_with_options_should_honor_options channel.expects(:send_channel_request).with("pty-req", :string, "vanilla", :long, 60, :long, 15, :long, 400, :long, 200, :string, "\5\0\0\0\1\0") channel.request_pty :term => "vanilla", :chars_wide => 60, :chars_high => 15, :pixels_wide => 400, :pixels_high => 200, :modes => { 5 => 1 } end def test_send_data_should_append_to_channels_output_buffer channel.send_data("hello") assert_equal "hello", channel.output.to_s channel.send_data("world") assert_equal "helloworld", channel.output.to_s end def test_close_before_channel_has_been_confirmed_should_do_nothing assert !channel.closing? channel.close assert !channel.closing? end def test_close_should_set_closing_and_send_message channel.do_open_confirmation(0, 100, 100) assert !channel.closing? connection.expect { |t,packet| assert_equal CHANNEL_CLOSE, packet.type } channel.close assert channel.closing? end def test_close_while_closing_should_do_nothing test_close_should_set_closing_and_send_message assert_nothing_raised { channel.close } end def test_process_when_process_callback_is_not_set_should_just_enqueue_data channel.expects(:enqueue_pending_output) channel.process end def test_process_when_process_callback_is_set_should_yield_self_before_enqueuing_data channel.expects(:enqueue_pending_output).never channel.on_process { |ch| ch.expects(:enqueue_pending_output).once } channel.process end def test_enqueue_pending_output_should_have_no_effect_if_channel_has_not_been_confirmed channel.send_data("hello") assert_nothing_raised { channel.enqueue_pending_output } end def test_enqueue_pending_output_should_have_no_effect_if_there_is_no_output channel.do_open_confirmation(0, 100, 100) assert_nothing_raised { channel.enqueue_pending_output } end def test_enqueue_pending_output_should_not_enqueue_more_than_output_length channel.do_open_confirmation(0, 100, 100) channel.send_data("hello world") connection.expect do |t,packet| assert_equal CHANNEL_DATA, packet.type assert_equal 0, packet[:local_id] assert_equal 11, packet[:data].length end channel.enqueue_pending_output end def test_enqueue_pending_output_should_not_enqueue_more_than_max_packet_length_at_once channel.do_open_confirmation(0, 100, 8) channel.send_data("hello world") connection.expect do |t,packet| assert_equal CHANNEL_DATA, packet.type assert_equal 0, packet[:local_id] assert_equal "hello wo", packet[:data] t.expect do |t2,packet2| assert_equal CHANNEL_DATA, packet2.type assert_equal 0, packet2[:local_id] assert_equal "rld", packet2[:data] end end channel.enqueue_pending_output end def test_enqueue_pending_output_should_not_enqueue_more_than_max_window_size channel.do_open_confirmation(0, 8, 100) channel.send_data("hello world") connection.expect do |t,packet| assert_equal CHANNEL_DATA, packet.type assert_equal 0, packet[:local_id] assert_equal "hello wo", packet[:data] end channel.enqueue_pending_output end def test_on_data_with_block_should_set_callback flag = false channel.on_data { flag = !flag } channel.do_data("") assert(flag, "callback should have been invoked") channel.on_data channel.do_data("") assert(flag, "callback should have been removed") end def test_on_extended_data_with_block_should_set_callback flag = false channel.on_extended_data { flag = !flag } channel.do_extended_data(0, "") assert(flag, "callback should have been invoked") channel.on_extended_data channel.do_extended_data(0, "") assert(flag, "callback should have been removed") end def test_on_process_with_block_should_set_callback flag = false channel.on_process { flag = !flag } channel.process assert(flag, "callback should have been invoked") channel.on_process channel.process assert(flag, "callback should have been removed") end def test_on_close_with_block_should_set_callback flag = false channel.on_close { flag = !flag } channel.do_close assert(flag, "callback should have been invoked") channel.on_close channel.do_close assert(flag, "callback should have been removed") end def test_on_eof_with_block_should_set_callback flag = false channel.on_eof { flag = !flag } channel.do_eof assert(flag, "callback should have been invoked") channel.on_eof channel.do_eof assert(flag, "callback should have been removed") end def test_do_request_for_unhandled_request_should_do_nothing_if_not_wants_reply channel.do_open_confirmation(0, 100, 100) assert_nothing_raised { channel.do_request "exit-status", false, nil } end def test_do_request_for_unhandled_request_should_send_CHANNEL_FAILURE_if_wants_reply channel.do_open_confirmation(0, 100, 100) connection.expect { |t,packet| assert_equal CHANNEL_FAILURE, packet.type } channel.do_request "keepalive@openssh.com", true, nil end def test_do_request_for_handled_request_should_invoke_callback_and_do_nothing_if_returns_true_and_not_wants_reply channel.do_open_confirmation(0, 100, 100) flag = false channel.on_request("exit-status") { flag = true; true } assert_nothing_raised { channel.do_request "exit-status", false, nil } assert flag, "callback should have been invoked" end def test_do_request_for_handled_request_should_invoke_callback_and_do_nothing_if_fails_and_not_wants_reply channel.do_open_confirmation(0, 100, 100) flag = false channel.on_request("exit-status") { flag = true; raise Net::SSH::ChannelRequestFailed } assert_nothing_raised { channel.do_request "exit-status", false, nil } assert flag, "callback should have been invoked" end def test_do_request_for_handled_request_should_invoke_callback_and_send_CHANNEL_SUCCESS_if_returns_true_and_wants_reply channel.do_open_confirmation(0, 100, 100) flag = false channel.on_request("exit-status") { flag = true; true } connection.expect { |t,p| assert_equal CHANNEL_SUCCESS, p.type } assert_nothing_raised { channel.do_request "exit-status", true, nil } assert flag, "callback should have been invoked" end def test_do_request_for_handled_request_should_invoke_callback_and_send_CHANNEL_FAILURE_if_returns_false_and_wants_reply channel.do_open_confirmation(0, 100, 100) flag = false channel.on_request("exit-status") { flag = true; raise Net::SSH::ChannelRequestFailed } connection.expect { |t,p| assert_equal CHANNEL_FAILURE, p.type } assert_nothing_raised { channel.do_request "exit-status", true, nil } assert flag, "callback should have been invoked" end def test_send_channel_request_without_callback_should_not_want_reply channel.do_open_confirmation(0, 100, 100) connection.expect do |t,p| assert_equal CHANNEL_REQUEST, p.type assert_equal 0, p[:local_id] assert_equal "exec", p[:request] assert_equal false, p[:want_reply] assert_equal "ls", p[:request_data].read_string end channel.send_channel_request("exec", :string, "ls") assert channel.pending_requests.empty? end def test_send_channel_request_with_callback_should_want_reply channel.do_open_confirmation(0, 100, 100) connection.expect do |t,p| assert_equal CHANNEL_REQUEST, p.type assert_equal 0, p[:local_id] assert_equal "exec", p[:request] assert_equal true, p[:want_reply] assert_equal "ls", p[:request_data].read_string end callback = Proc.new {} channel.send_channel_request("exec", :string, "ls", &callback) assert_equal [callback], channel.pending_requests end def test_do_open_confirmation_should_set_remote_parameters channel.do_open_confirmation(1, 2, 3) assert_equal 1, channel.remote_id assert_equal 2, channel.remote_window_size assert_equal 2, channel.remote_maximum_window_size assert_equal 3, channel.remote_maximum_packet_size end def test_do_open_confirmation_should_call_open_confirmation_callback flag = false channel { flag = true } assert !flag, "callback should not have been invoked yet" channel.do_open_confirmation(1,2,3) assert flag, "callback should have been invoked" end def test_do_open_confirmation_with_session_channel_should_invoke_agent_forwarding_if_agent_forwarding_requested connection :forward_agent => true forward = mock("forward") forward.expects(:agent).with(channel) connection.expects(:forward).returns(forward) channel.do_open_confirmation(1,2,3) end def test_do_open_confirmation_with_non_session_channel_should_not_invoke_agent_forwarding_even_if_agent_forwarding_requested connection :forward_agent => true channel :type => "direct-tcpip" connection.expects(:forward).never channel.do_open_confirmation(1,2,3) end def test_do_window_adjust_should_adjust_remote_window_size_by_the_given_amount channel.do_open_confirmation(0, 1000, 1000) assert_equal 1000, channel.remote_window_size assert_equal 1000, channel.remote_maximum_window_size channel.do_window_adjust(500) assert_equal 1500, channel.remote_window_size assert_equal 1500, channel.remote_maximum_window_size end def test_do_data_should_update_local_window_size assert_equal 0x20000, channel.local_maximum_window_size assert_equal 0x20000, channel.local_window_size channel.do_data("here is some data") assert_equal 0x20000, channel.local_maximum_window_size assert_equal 0x1FFEF, channel.local_window_size end def test_do_extended_data_should_update_local_window_size assert_equal 0x20000, channel.local_maximum_window_size assert_equal 0x20000, channel.local_window_size channel.do_extended_data(1, "here is some data") assert_equal 0x20000, channel.local_maximum_window_size assert_equal 0x1FFEF, channel.local_window_size end def test_do_data_when_local_window_size_drops_below_threshold_should_trigger_WINDOW_ADJUST_message channel.do_open_confirmation(0, 1000, 1000) assert_equal 0x20000, channel.local_maximum_window_size assert_equal 0x20000, channel.local_window_size connection.expect do |t,p| assert_equal CHANNEL_WINDOW_ADJUST, p.type assert_equal 0, p[:local_id] assert_equal 0x20000, p[:extra_bytes] end channel.do_data("." * 0x10001) assert_equal 0x40000, channel.local_maximum_window_size assert_equal 0x2FFFF, channel.local_window_size end def test_do_failure_should_grab_next_pending_request_and_call_it result = nil channel.pending_requests << Proc.new { |*args| result = args } channel.do_failure assert_equal [channel, false], result assert channel.pending_requests.empty? end def test_do_success_should_grab_next_pending_request_and_call_it result = nil channel.pending_requests << Proc.new { |*args| result = args } channel.do_success assert_equal [channel, true], result assert channel.pending_requests.empty? end def test_active_should_be_true_when_channel_appears_in_channel_list connection.channels[channel.local_id] = channel assert channel.active? end def test_active_should_be_false_when_channel_is_not_in_channel_list assert !channel.active? end def test_wait_should_block_while_channel_is_active? channel.expects(:active?).times(3).returns(true,true,false) channel.wait end def test_eof_bang_should_send_eof_to_server channel.do_open_confirmation(0, 1000, 1000) connection.expect { |t,p| assert_equal CHANNEL_EOF, p.type } channel.eof! channel.process end def test_eof_bang_should_not_send_eof_if_eof_was_already_declared channel.do_open_confirmation(0, 1000, 1000) connection.expect { |t,p| assert_equal CHANNEL_EOF, p.type } channel.eof! assert_nothing_raised { channel.eof! } channel.process end def test_eof_q_should_return_true_if_eof_declared channel.do_open_confirmation(0, 1000, 1000) connection.expect { |t,p| assert_equal CHANNEL_EOF, p.type } assert !channel.eof? channel.eof! assert channel.eof? channel.process end def test_send_data_should_raise_exception_if_eof_declared channel.do_open_confirmation(0, 1000, 1000) connection.expect { |t,p| assert_equal CHANNEL_EOF, p.type } channel.eof! channel.process assert_raises(EOFError) { channel.send_data("die! die! die!") } end def test_data_should_precede_eof channel.do_open_confirmation(0, 1000, 1000) connection.expect do |t,p| assert_equal CHANNEL_DATA, p.type connection.expect { |t,p| assert_equal CHANNEL_EOF, p.type } end channel.send_data "foo" channel.eof! channel.process end private class MockConnection attr_reader :logger attr_reader :options attr_reader :channels def initialize(options={}) @expectation = nil @options = options @channels = {} end def expect(&block) @expectation = block end def send_message(msg) raise "#{msg.to_s.inspect} recieved but no message was expected" unless @expectation packet = Net::SSH::Packet.new(msg.to_s) callback, @expectation = @expectation, nil callback.call(self, packet) end alias loop_forever loop def loop(&block) loop_forever { break unless block.call } end def test! raise "expected a packet but none were sent" if @expectation end end def connection(options={}) @connection ||= MockConnection.new(options) end def channel(options={}, &block) @channel ||= Net::SSH::Connection::Channel.new(connection(options), options[:type] || "session", options[:local_id] || 0, &block) end end end net-ssh-2.6.8/test/transport/0000755000004100000410000000000012166626376016172 5ustar www-datawww-datanet-ssh-2.6.8/test/transport/test_session.rb0000644000004100000410000002553112166626376021247 0ustar www-datawww-datarequire 'common' require 'net/ssh/transport/session' # mocha adds #verify to Object, which throws off the host-key-verifier part of # these tests. # can't use .include? because ruby18 uses strings and ruby19 uses symbols :/ if Object.instance_methods.any? { |v| v.to_sym == :verify } Object.send(:undef_method, :verify) end module Transport class TestSession < Test::Unit::TestCase include Net::SSH::Transport::Constants def test_constructor_defaults assert_equal "net.ssh.test", session.host assert_equal 22, session.port assert_instance_of Net::SSH::Verifiers::Lenient, session.host_key_verifier end def test_paranoid_true_uses_lenient_verifier assert_instance_of Net::SSH::Verifiers::Lenient, session(:paranoid => true).host_key_verifier end def test_paranoid_very_uses_strict_verifier assert_instance_of Net::SSH::Verifiers::Strict, session(:paranoid => :very).host_key_verifier end def test_paranoid_secure_uses_secure_verifier assert_instance_of Net::SSH::Verifiers::Secure, session(:paranoid => :secure).host_key_verifier end def test_paranoid_false_uses_null_verifier assert_instance_of Net::SSH::Verifiers::Null, session(:paranoid => false).host_key_verifier end def test_unknown_paranoid_value_raises_exception_if_value_does_not_respond_to_verify assert_raises(ArgumentError) { session(:paranoid => :bogus).host_key_verifier } end def test_paranoid_value_responding_to_verify_should_pass_muster object = stub("thingy", :verify => true) assert_equal object, session(:paranoid => object).host_key_verifier end def test_host_as_string_should_return_host_and_ip_when_port_is_default session! socket.stubs(:peer_ip).returns("1.2.3.4") assert_equal "net.ssh.test,1.2.3.4", session.host_as_string end def test_host_as_string_should_return_host_and_ip_with_port_when_port_is_not_default session(:port => 1234) # force session to be instantiated socket.stubs(:peer_ip).returns("1.2.3.4") assert_equal "[net.ssh.test]:1234,[1.2.3.4]:1234", session.host_as_string end def test_host_as_string_should_return_only_host_when_host_is_ip session!(:host => "1.2.3.4") socket.stubs(:peer_ip).returns("1.2.3.4") assert_equal "1.2.3.4", session.host_as_string end def test_host_as_string_should_return_only_host_and_port_when_host_is_ip_and_port_is_not_default session!(:host => "1.2.3.4", :port => 1234) socket.stubs(:peer_ip).returns("1.2.3.4") assert_equal "[1.2.3.4]:1234", session.host_as_string end def test_close_should_cleanup_and_close_socket session! socket.expects(:cleanup) socket.expects(:close) session.close end def test_service_request_should_return_buffer assert_equal "\005\000\000\000\004sftp", session.service_request('sftp').to_s end def test_rekey_when_kex_is_pending_should_do_nothing algorithms.stubs(:pending? => true) algorithms.expects(:rekey!).never session.rekey! end def test_rekey_when_no_kex_is_pending_should_initiate_rekey_and_block_until_it_completes algorithms.stubs(:pending? => false) algorithms.expects(:rekey!) session.expects(:wait).yields algorithms.expects(:initialized?).returns(true) session.rekey! end def test_rekey_as_needed_when_kex_is_pending_should_do_nothing session! algorithms.stubs(:pending? => true) socket.expects(:if_needs_rekey?).never session.rekey_as_needed end def test_rekey_as_needed_when_no_kex_is_pending_and_no_rekey_is_needed_should_do_nothing session! algorithms.stubs(:pending? => false) socket.stubs(:if_needs_rekey? => false) session.expects(:rekey!).never session.rekey_as_needed end def test_rekey_as_needed_when_no_kex_is_pending_and_rekey_is_needed_should_initiate_rekey_and_block session! algorithms.stubs(:pending? => false) socket.expects(:if_needs_rekey?).yields session.expects(:rekey!) session.rekey_as_needed end def test_peer_should_return_hash_of_info_about_peer session! socket.stubs(:peer_ip => "1.2.3.4") assert_equal({:ip => "1.2.3.4", :port => 22, :host => "net.ssh.test", :canonized => "net.ssh.test,1.2.3.4"}, session.peer) end def test_next_message_should_block_until_next_message_is_available session.expects(:poll_message).with(:block) session.next_message end def test_poll_message_should_query_next_packet_using_the_given_blocking_parameter session! socket.expects(:next_packet).with(:blocking_parameter).returns(nil) session.poll_message(:blocking_parameter) end def test_poll_message_should_default_to_non_blocking session! socket.expects(:next_packet).with(:nonblock).returns(nil) session.poll_message end def test_poll_message_should_silently_handle_disconnect_packets session! socket.expects(:next_packet).returns(P(:byte, DISCONNECT, :long, 1, :string, "testing", :string, "")) assert_raises(Net::SSH::Disconnect) { session.poll_message } end def test_poll_message_should_silently_handle_ignore_packets session! socket.expects(:next_packet).times(2).returns(P(:byte, IGNORE, :string, "test"), nil) assert_nil session.poll_message end def test_poll_message_should_silently_handle_unimplemented_packets session! socket.expects(:next_packet).times(2).returns(P(:byte, UNIMPLEMENTED, :long, 15), nil) assert_nil session.poll_message end def test_poll_message_should_silently_handle_debug_packets_with_always_display session! socket.expects(:next_packet).times(2).returns(P(:byte, DEBUG, :bool, true, :string, "testing", :string, ""), nil) assert_nil session.poll_message end def test_poll_message_should_silently_handle_debug_packets_without_always_display session! socket.expects(:next_packet).times(2).returns(P(:byte, DEBUG, :bool, false, :string, "testing", :string, ""), nil) assert_nil session.poll_message end def test_poll_message_should_silently_handle_kexinit_packets session! packet = P(:byte, KEXINIT, :raw, "lasdfalksdjfa;slkdfja;slkfjsdfaklsjdfa;df") socket.expects(:next_packet).times(2).returns(packet, nil) algorithms.expects(:accept_kexinit).with(packet) assert_nil session.poll_message end def test_poll_message_should_return_other_packets session! packet = P(:byte, SERVICE_ACCEPT, :string, "test") socket.expects(:next_packet).returns(packet) assert_equal packet, session.poll_message end def test_poll_message_should_enqueue_packets_when_algorithm_disallows_packet session! packet = P(:byte, SERVICE_ACCEPT, :string, "test") algorithms.stubs(:allow?).with(packet).returns(false) socket.expects(:next_packet).times(2).returns(packet, nil) assert_nil session.poll_message assert_equal [packet], session.queue end def test_poll_message_should_read_from_queue_when_next_in_queue_is_allowed_and_consume_queue_is_true session! packet = P(:byte, SERVICE_ACCEPT, :string, "test") session.push(packet) socket.expects(:next_packet).never assert_equal packet, session.poll_message assert session.queue.empty? end def test_poll_message_should_not_read_from_queue_when_next_in_queue_is_not_allowed session! packet = P(:byte, SERVICE_ACCEPT, :string, "test") algorithms.stubs(:allow?).with(packet).returns(false) session.push(packet) socket.expects(:next_packet).returns(nil) assert_nil session.poll_message assert_equal [packet], session.queue end def test_poll_message_should_not_read_from_queue_when_consume_queue_is_false session! packet = P(:byte, SERVICE_ACCEPT, :string, "test") session.push(packet) socket.expects(:next_packet).returns(nil) assert_nil session.poll_message(:nonblock, false) assert_equal [packet], session.queue end def test_wait_with_block_should_return_immediately_if_block_returns_truth session.expects(:poll_message).never session.wait { true } end def test_wait_should_not_consume_queue_on_reads n = 0 session.expects(:poll_message).with(:nonblock, false).returns(nil) session.wait { (n += 1) > 1 } end def test_wait_without_block_should_return_after_first_read session.expects(:poll_message).returns(nil) session.wait end def test_wait_should_enqueue_packets session! p1 = P(:byte, SERVICE_REQUEST, :string, "test") p2 = P(:byte, SERVICE_ACCEPT, :string, "test") socket.expects(:next_packet).times(2).returns(p1, p2) n = 0 session.wait { (n += 1) > 2 } assert_equal [p1, p2], session.queue end def test_push_should_enqueue_packet packet = P(:byte, SERVICE_ACCEPT, :string, "test") session.push(packet) assert_equal [packet], session.queue end def test_send_message_should_delegate_to_socket session! packet = P(:byte, SERVICE_ACCEPT, :string, "test") socket.expects(:send_packet).with(packet) session.send_message(packet) end def test_enqueue_message_should_delegate_to_socket session! packet = P(:byte, SERVICE_ACCEPT, :string, "test") socket.expects(:enqueue_packet).with(packet) session.enqueue_message(packet) end def test_configure_client_should_pass_options_to_socket_client_state session.configure_client :compression => :standard assert_equal :standard, socket.client.compression end def test_configure_server_should_pass_options_to_socket_server_state session.configure_server :compression => :standard assert_equal :standard, socket.server.compression end def test_hint_should_set_hint_on_socket assert !socket.hints[:authenticated] session.hint :authenticated assert socket.hints[:authenticated] end private def socket @socket ||= stub("socket", :hints => {}) end def server_version @server_version ||= stub("server_version") end def algorithms @algorithms ||= stub("algorithms", :initialized? => true, :allow? => true) end def session(options={}) @session ||= begin host = options.delete(:host) || "net.ssh.test" TCPSocket.stubs(:open).with(host, options[:port] || 22).returns(socket) Net::SSH::Transport::ServerVersion.stubs(:new).returns(server_version) Net::SSH::Transport::Algorithms.stubs(:new).returns(algorithms) Net::SSH::Transport::Session.new(host, options) end end # a simple alias to make the tests more self-documenting. the bang # version makes it look more like the session is being instantiated alias session! session end end net-ssh-2.6.8/test/transport/test_algorithms.rb0000644000004100000410000004307012166626376021733 0ustar www-datawww-datarequire 'common' require 'net/ssh/transport/algorithms' module Transport class TestAlgorithms < Test::Unit::TestCase include Net::SSH::Transport::Constants def test_allowed_packets (0..255).each do |type| packet = stub("packet", :type => type) case type when 1..4, 6..19, 21..49 then assert(Net::SSH::Transport::Algorithms.allowed_packet?(packet), "#{type} should be allowed during key exchange") else assert(!Net::SSH::Transport::Algorithms.allowed_packet?(packet), "#{type} should not be allowed during key exchange") end end end def test_constructor_should_build_default_list_of_preferred_algorithms if defined?(OpenSSL::PKey::EC) assert_equal %w(ssh-rsa ssh-dss ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521), algorithms[:host_key] assert_equal %w(diffie-hellman-group-exchange-sha1 diffie-hellman-group1-sha1 diffie-hellman-group14-sha1 diffie-hellman-group-exchange-sha256 ecdh-sha2-nistp256 ecdh-sha2-nistp384 ecdh-sha2-nistp521), algorithms[:kex] else assert_equal %w(ssh-rsa ssh-dss), algorithms[:host_key] assert_equal %w(diffie-hellman-group-exchange-sha1 diffie-hellman-group1-sha1 diffie-hellman-group14-sha1 diffie-hellman-group-exchange-sha256), algorithms[:kex] end assert_equal %w(aes128-cbc 3des-cbc blowfish-cbc cast128-cbc aes192-cbc aes256-cbc rijndael-cbc@lysator.liu.se idea-cbc none arcfour128 arcfour256 arcfour aes128-ctr aes192-ctr aes256-ctr camellia128-cbc camellia192-cbc camellia256-cbc camellia128-cbc@openssh.org camellia192-cbc@openssh.org camellia256-cbc@openssh.org camellia128-ctr camellia192-ctr camellia256-ctr camellia128-ctr@openssh.org camellia192-ctr@openssh.org camellia256-ctr@openssh.org cast128-ctr blowfish-ctr 3des-ctr), algorithms[:encryption] if defined?(OpenSSL::Digest::SHA256) assert_equal %w(hmac-sha1 hmac-md5 hmac-sha1-96 hmac-md5-96 hmac-ripemd160 hmac-ripemd160@openssh.com hmac-sha2-256 hmac-sha2-512 hmac-sha2-256-96 hmac-sha2-512-96 none), algorithms[:hmac] else assert_equal %w(hmac-sha1 hmac-md5 hmac-sha1-96 hmac-md5-96 hmac-ripemd160 hmac-ripemd160@openssh.com none), algorithms[:hmac] end assert_equal %w(none zlib@openssh.com zlib), algorithms[:compression] assert_equal %w(), algorithms[:language] end def test_constructor_should_set_client_and_server_prefs_identically %w(encryption hmac compression language).each do |key| assert_equal algorithms[key.to_sym], algorithms[:"#{key}_client"], key assert_equal algorithms[key.to_sym], algorithms[:"#{key}_server"], key end end def test_constructor_with_preferred_host_key_type_should_put_preferred_host_key_type_first if defined?(OpenSSL::PKey::EC) assert_equal %w(ssh-dss ssh-rsa ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521), algorithms(:host_key => "ssh-dss")[:host_key] else assert_equal %w(ssh-dss ssh-rsa), algorithms(:host_key => "ssh-dss")[:host_key] end end def test_constructor_with_known_hosts_reporting_known_host_key_should_use_that_host_key_type Net::SSH::KnownHosts.expects(:search_for).with("net.ssh.test,127.0.0.1", {}).returns([stub("key", :ssh_type => "ssh-dss")]) if defined?(OpenSSL::PKey::EC) assert_equal %w(ssh-dss ssh-rsa ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521), algorithms[:host_key] else assert_equal %w(ssh-dss ssh-rsa), algorithms[:host_key] end end def test_constructor_with_unrecognized_host_key_type_should_raise_exception assert_raises(NotImplementedError) { algorithms(:host_key => "bogus") } end def test_constructor_with_preferred_kex_should_put_preferred_kex_first if defined?(OpenSSL::PKey::EC) assert_equal %w(diffie-hellman-group1-sha1 diffie-hellman-group-exchange-sha1 diffie-hellman-group14-sha1 diffie-hellman-group-exchange-sha256 ecdh-sha2-nistp256 ecdh-sha2-nistp384 ecdh-sha2-nistp521), algorithms(:kex => "diffie-hellman-group1-sha1")[:kex] else assert_equal %w(diffie-hellman-group1-sha1 diffie-hellman-group-exchange-sha1 diffie-hellman-group14-sha1 diffie-hellman-group-exchange-sha256), algorithms(:kex => "diffie-hellman-group1-sha1")[:kex] end end def test_constructor_with_unrecognized_kex_should_raise_exception assert_raises(NotImplementedError) { algorithms(:kex => "bogus") } end def test_constructor_with_preferred_encryption_should_put_preferred_encryption_first assert_equal %w(aes256-cbc aes128-cbc 3des-cbc blowfish-cbc cast128-cbc aes192-cbc rijndael-cbc@lysator.liu.se idea-cbc none arcfour128 arcfour256 arcfour aes128-ctr aes192-ctr aes256-ctr camellia128-cbc camellia192-cbc camellia256-cbc camellia128-cbc@openssh.org camellia192-cbc@openssh.org camellia256-cbc@openssh.org camellia128-ctr camellia192-ctr camellia256-ctr camellia128-ctr@openssh.org camellia192-ctr@openssh.org camellia256-ctr@openssh.org cast128-ctr blowfish-ctr 3des-ctr), algorithms(:encryption => "aes256-cbc")[:encryption] end def test_constructor_with_multiple_preferred_encryption_should_put_all_preferred_encryption_first assert_equal %w(aes256-cbc 3des-cbc idea-cbc aes128-cbc blowfish-cbc cast128-cbc aes192-cbc rijndael-cbc@lysator.liu.se none arcfour128 arcfour256 arcfour aes128-ctr aes192-ctr aes256-ctr camellia128-cbc camellia192-cbc camellia256-cbc camellia128-cbc@openssh.org camellia192-cbc@openssh.org camellia256-cbc@openssh.org camellia128-ctr camellia192-ctr camellia256-ctr camellia128-ctr@openssh.org camellia192-ctr@openssh.org camellia256-ctr@openssh.org cast128-ctr blowfish-ctr 3des-ctr), algorithms(:encryption => %w(aes256-cbc 3des-cbc idea-cbc))[:encryption] end def test_constructor_with_unrecognized_encryption_should_raise_exception assert_raises(NotImplementedError) { algorithms(:encryption => "bogus") } end def test_constructor_with_preferred_hmac_should_put_preferred_hmac_first assert_equal %w(hmac-md5-96 hmac-sha1 hmac-md5 hmac-sha1-96 hmac-ripemd160 hmac-ripemd160@openssh.com hmac-sha2-256 hmac-sha2-512 hmac-sha2-256-96 hmac-sha2-512-96 none), algorithms(:hmac => "hmac-md5-96")[:hmac] end def test_constructor_with_multiple_preferred_hmac_should_put_all_preferred_hmac_first assert_equal %w(hmac-md5-96 hmac-sha1-96 hmac-sha1 hmac-md5 hmac-ripemd160 hmac-ripemd160@openssh.com hmac-sha2-256 hmac-sha2-512 hmac-sha2-256-96 hmac-sha2-512-96 none), algorithms(:hmac => %w(hmac-md5-96 hmac-sha1-96))[:hmac] end def test_constructor_with_unrecognized_hmac_should_raise_exception assert_raises(NotImplementedError) { algorithms(:hmac => "bogus") } end def test_constructor_with_preferred_compression_should_put_preferred_compression_first assert_equal %w(zlib none zlib@openssh.com), algorithms(:compression => "zlib")[:compression] end def test_constructor_with_multiple_preferred_compression_should_put_all_preferred_compression_first assert_equal %w(zlib@openssh.com zlib none), algorithms(:compression => %w(zlib@openssh.com zlib))[:compression] end def test_constructor_with_general_preferred_compression_should_put_none_last assert_equal %w(zlib@openssh.com zlib none), algorithms(:compression => true)[:compression] end def test_constructor_with_unrecognized_compression_should_raise_exception assert_raises(NotImplementedError) { algorithms(:compression => "bogus") } end def test_initial_state_should_be_neither_pending_nor_initialized assert !algorithms.pending? assert !algorithms.initialized? end def test_key_exchange_when_initiated_by_server transport.expect do |t, buffer| assert_kexinit(buffer) install_mock_key_exchange(buffer) end install_mock_algorithm_lookups algorithms.accept_kexinit(kexinit) assert_exchange_results end def test_key_exchange_when_initiated_by_client state = nil transport.expect do |t, buffer| assert_kexinit(buffer) state = :sent_kexinit install_mock_key_exchange(buffer) end algorithms.rekey! assert_equal state, :sent_kexinit assert algorithms.pending? install_mock_algorithm_lookups algorithms.accept_kexinit(kexinit) assert_exchange_results end def test_key_exchange_when_server_does_not_support_preferred_kex_should_fallback_to_secondary kexinit :kex => "diffie-hellman-group1-sha1" transport.expect do |t,buffer| assert_kexinit(buffer) install_mock_key_exchange(buffer, :kex => Net::SSH::Transport::Kex::DiffieHellmanGroup1SHA1) end algorithms.accept_kexinit(kexinit) end def test_key_exchange_when_server_does_not_support_any_preferred_kex_should_raise_error kexinit :kex => "something-obscure" transport.expect { |t,buffer| assert_kexinit(buffer) } assert_raises(Net::SSH::Exception) { algorithms.accept_kexinit(kexinit) } end def test_allow_when_not_pending_should_be_true_for_all_packets (0..255).each do |type| packet = stub("packet", :type => type) assert algorithms.allow?(packet), type.to_s end end def test_allow_when_pending_should_be_true_only_for_packets_valid_during_key_exchange transport.expect! algorithms.rekey! assert algorithms.pending? (0..255).each do |type| packet = stub("packet", :type => type) case type when 1..4, 6..19, 21..49 then assert(algorithms.allow?(packet), "#{type} should be allowed during key exchange") else assert(!algorithms.allow?(packet), "#{type} should not be allowed during key exchange") end end end def test_exchange_with_zlib_compression_enabled_sets_compression_to_standard algorithms :compression => "zlib" transport.expect do |t, buffer| assert_kexinit(buffer, :compression_client => "zlib,none,zlib@openssh.com", :compression_server => "zlib,none,zlib@openssh.com") install_mock_key_exchange(buffer) end install_mock_algorithm_lookups algorithms.accept_kexinit(kexinit) assert_equal :standard, transport.client_options[:compression] assert_equal :standard, transport.server_options[:compression] end def test_exchange_with_zlib_at_openssh_dot_com_compression_enabled_sets_compression_to_delayed algorithms :compression => "zlib@openssh.com" transport.expect do |t, buffer| assert_kexinit(buffer, :compression_client => "zlib@openssh.com,none,zlib", :compression_server => "zlib@openssh.com,none,zlib") install_mock_key_exchange(buffer) end install_mock_algorithm_lookups algorithms.accept_kexinit(kexinit) assert_equal :delayed, transport.client_options[:compression] assert_equal :delayed, transport.server_options[:compression] end private def install_mock_key_exchange(buffer, options={}) kex = options[:kex] || Net::SSH::Transport::Kex::DiffieHellmanGroupExchangeSHA1 Net::SSH::Transport::Kex::MAP.each do |name, klass| next if klass == kex klass.expects(:new).never end kex.expects(:new). with(algorithms, transport, :client_version_string => Net::SSH::Transport::ServerVersion::PROTO_VERSION, :server_version_string => transport.server_version.version, :server_algorithm_packet => kexinit.to_s, :client_algorithm_packet => buffer.to_s, :need_bytes => 20, :logger => nil). returns(stub("kex", :exchange_keys => { :shared_secret => shared_secret, :session_id => session_id, :hashing_algorithm => hashing_algorithm })) end def install_mock_algorithm_lookups(options={}) params = { :shared => shared_secret.to_ssh, :hash => session_id, :digester => hashing_algorithm } Net::SSH::Transport::CipherFactory.expects(:get). with(options[:client_cipher] || "aes128-cbc", params.merge(:iv => key("A"), :key => key("C"), :encrypt => true)). returns(:client_cipher) Net::SSH::Transport::CipherFactory.expects(:get). with(options[:server_cipher] || "aes128-cbc", params.merge(:iv => key("B"), :key => key("D"), :decrypt => true)). returns(:server_cipher) Net::SSH::Transport::HMAC.expects(:get).with(options[:client_hmac] || "hmac-sha1", key("E"), params).returns(:client_hmac) Net::SSH::Transport::HMAC.expects(:get).with(options[:server_hmac] || "hmac-sha1", key("F"), params).returns(:server_hmac) end def shared_secret @shared_secret ||= OpenSSL::BN.new("1234567890", 10) end def session_id @session_id ||= "this is the session id" end def hashing_algorithm OpenSSL::Digest::SHA1 end def key(salt) hashing_algorithm.digest(shared_secret.to_ssh + session_id + salt + session_id) end def cipher(type, options={}) Net::SSH::Transport::CipherFactory.get(type, options) end def kexinit(options={}) @kexinit ||= P(:byte, KEXINIT, :long, rand(0xFFFFFFFF), :long, rand(0xFFFFFFFF), :long, rand(0xFFFFFFFF), :long, rand(0xFFFFFFFF), :string, options[:kex] || "diffie-hellman-group-exchange-sha1,diffie-hellman-group14-sha1,diffie-hellman-group1-sha1,diffie-hellman-group-exchange-sha256", :string, options[:host_key] || "ssh-rsa,ssh-dss", :string, options[:encryption_client] || "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se,idea-cbc", :string, options[:encryption_server] || "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se,idea-cbc", :string, options[:hmac_client] || "hmac-sha1,hmac-md5,hmac-sha1-96,hmac-md5-96", :string, options[:hmac_server] || "hmac-sha1,hmac-md5,hmac-sha1-96,hmac-md5-96", :string, options[:compmression_client] || "none,zlib@openssh.com,zlib", :string, options[:compmression_server] || "none,zlib@openssh.com,zlib", :string, options[:language_client] || "", :string, options[:langauge_server] || "", :bool, options[:first_kex_follows]) end def assert_kexinit(buffer, options={}) assert_equal KEXINIT, buffer.type assert_equal 16, buffer.read(16).length if defined?(OpenSSL::PKey::EC) assert_equal options[:kex] || "diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha256,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521", buffer.read_string assert_equal options[:host_key] || "ssh-rsa,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521", buffer.read_string else assert_equal options[:kex] || "diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha256", buffer.read_string assert_equal options[:host_key] || "ssh-rsa,ssh-dss", buffer.read_string end assert_equal options[:encryption_client] || "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se,idea-cbc,none,arcfour128,arcfour256,arcfour,aes128-ctr,aes192-ctr,aes256-ctr,camellia128-cbc,camellia192-cbc,camellia256-cbc,camellia128-cbc@openssh.org,camellia192-cbc@openssh.org,camellia256-cbc@openssh.org,camellia128-ctr,camellia192-ctr,camellia256-ctr,camellia128-ctr@openssh.org,camellia192-ctr@openssh.org,camellia256-ctr@openssh.org,cast128-ctr,blowfish-ctr,3des-ctr", buffer.read_string assert_equal options[:encryption_server] || "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,aes256-cbc,rijndael-cbc@lysator.liu.se,idea-cbc,none,arcfour128,arcfour256,arcfour,aes128-ctr,aes192-ctr,aes256-ctr,camellia128-cbc,camellia192-cbc,camellia256-cbc,camellia128-cbc@openssh.org,camellia192-cbc@openssh.org,camellia256-cbc@openssh.org,camellia128-ctr,camellia192-ctr,camellia256-ctr,camellia128-ctr@openssh.org,camellia192-ctr@openssh.org,camellia256-ctr@openssh.org,cast128-ctr,blowfish-ctr,3des-ctr", buffer.read_string assert_equal options[:hmac_client] || "hmac-sha1,hmac-md5,hmac-sha1-96,hmac-md5-96,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha2-256-96,hmac-sha2-512-96,none", buffer.read_string assert_equal options[:hmac_server] || "hmac-sha1,hmac-md5,hmac-sha1-96,hmac-md5-96,hmac-ripemd160,hmac-ripemd160@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha2-256-96,hmac-sha2-512-96,none", buffer.read_string assert_equal options[:compression_client] || "none,zlib@openssh.com,zlib", buffer.read_string assert_equal options[:compression_server] || "none,zlib@openssh.com,zlib", buffer.read_string assert_equal options[:language_client] || "", buffer.read_string assert_equal options[:language_server] || "", buffer.read_string assert_equal options[:first_kex_follows] || false, buffer.read_bool end def assert_exchange_results assert algorithms.initialized? assert !algorithms.pending? assert !transport.client_options[:compression] assert !transport.server_options[:compression] assert_equal :client_cipher, transport.client_options[:cipher] assert_equal :server_cipher, transport.server_options[:cipher] assert_equal :client_hmac, transport.client_options[:hmac] assert_equal :server_hmac, transport.server_options[:hmac] end def algorithms(options={}) @algorithms ||= Net::SSH::Transport::Algorithms.new(transport, options) end def transport @transport ||= MockTransport.new end end end net-ssh-2.6.8/test/transport/test_hmac.rb0000644000004100000410000000230412166626376020465 0ustar www-datawww-datarequire 'common' require 'net/ssh/transport/hmac' module Transport class TestHMAC < Test::Unit::TestCase Net::SSH::Transport::HMAC::MAP.each do |name, value| method = name.tr("-", "_") define_method("test_get_with_#{method}_returns_new_hmac_instance") do key = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!&$%"[0,Net::SSH::Transport::HMAC::MAP[name].key_length] hmac = Net::SSH::Transport::HMAC.get(name, key, { :shared => "123", :hash => "^&*", :digester => OpenSSL::Digest::SHA1 }) assert_instance_of Net::SSH::Transport::HMAC::MAP[name], hmac assert_equal key, hmac.key end define_method("test_key_length_with_#{method}_returns_correct_key_length") do assert_equal Net::SSH::Transport::HMAC::MAP[name].key_length, Net::SSH::Transport::HMAC.key_length(name) end end def test_get_with_unrecognized_hmac_raises_argument_error assert_raises(ArgumentError) do Net::SSH::Transport::HMAC.get("bogus") end end def test_key_length_with_unrecognized_hmac_raises_argument_error assert_raises(ArgumentError) do Net::SSH::Transport::HMAC.get("bogus") end end end end net-ssh-2.6.8/test/transport/test_identity_cipher.rb0000644000004100000410000000142712166626376022745 0ustar www-datawww-datarequire 'common' require 'net/ssh/transport/identity_cipher' module Transport class TestIdentityCipher < Test::Unit::TestCase def test_block_size_should_be_8 assert_equal 8, cipher.block_size end def test_encrypt_should_return_self assert_equal cipher, cipher.encrypt end def test_decrypt_should_return_self assert_equal cipher, cipher.decrypt end def test_update_should_return_argument assert_equal "hello, world", cipher.update("hello, world") end def test_final_should_return_empty_string assert_equal "", cipher.final end def test_name_should_be_identity assert_equal "identity", cipher.name end private def cipher Net::SSH::Transport::IdentityCipher end end end net-ssh-2.6.8/test/transport/test_server_version.rb0000644000004100000410000000525712166626376022642 0ustar www-datawww-datarequire 'common' require 'net/ssh/transport/server_version' module Transport class TestServerVersion < Test::Unit::TestCase def test_1_99_server_version_should_be_acceptible s = subject(socket(true, "SSH-1.99-Testing_1.0\r\n")) assert s.header.empty? assert_equal "SSH-1.99-Testing_1.0", s.version end def test_2_0_server_version_should_be_acceptible s = subject(socket(true, "SSH-2.0-Testing_1.0\r\n")) assert s.header.empty? assert_equal "SSH-2.0-Testing_1.0", s.version end def test_trailing_whitespace_should_be_preserved # some servers, like Mocana, send a version string with trailing # spaces, which are significant when exchanging keys later. s = subject(socket(true, "SSH-2.0-Testing_1.0 \r\n")) assert_equal "SSH-2.0-Testing_1.0 ", s.version end def test_unacceptible_server_version_should_raise_exception assert_raises(Net::SSH::Exception) { subject(socket(false, "SSH-1.4-Testing_1.0\r\n")) } end def test_unexpected_server_close_should_raise_exception assert_raises(Net::SSH::Disconnect) { subject(socket(false, "\r\nDestination server does not have Ssh activated.\r\nContact Cisco Systems, Inc to purchase a\r\nlicense key to activate Ssh.\r\n", true)) } end def test_header_lines_should_be_accumulated s = subject(socket(true, "Welcome\r\nAnother line\r\nSSH-2.0-Testing_1.0\r\n")) assert_equal "Welcome\r\nAnother line\r\n", s.header assert_equal "SSH-2.0-Testing_1.0", s.version end def test_server_disconnect_should_raise_exception assert_raises(Net::SSH::Disconnect) { subject(socket(false, "SSH-2.0-Aborting")) } end private def socket(good, version_header, raise_eot=false) socket = mock("socket") data = version_header.split('') recv_times = data.length recv_times += 1 if data[-1] != "\n" unless raise_eot # socket.expects(:recv).with(1).times(recv_times).returns(*data).then.returns(nil) # socket.expects(:readchar).times(recv_times).returns(*data).then.returns(nil) socket.expects(:readpartial).with(1).times(recv_times).returns(*data).then.returns(nil) else socket.expects(:readpartial).with(1).times(recv_times+1).returns(*data).then.raises(EOFError, "end of file reached") end if good socket.expects(:write).with("#{Net::SSH::Transport::ServerVersion::PROTO_VERSION}\r\n") socket.expects(:flush) else socket.expects(:write).never end socket end def subject(socket) Net::SSH::Transport::ServerVersion.new(socket, nil) end end end net-ssh-2.6.8/test/transport/test_packet_stream.rb0000644000004100000410000046571512166626376022422 0ustar www-datawww-data# encoding: ASCII-8BIT require 'common' require 'net/ssh/transport/packet_stream' module Transport class TestPacketStream < Test::Unit::TestCase include Net::SSH::Transport::Constants def test_client_name_when_getnameinfo_works stream.expects(:getsockname).returns(:sockaddr) Socket.expects(:getnameinfo).with(:sockaddr, Socket::NI_NAMEREQD).returns(["net.ssh.test"]) assert_equal "net.ssh.test", stream.client_name end def test_client_name_when_getnameinfo_fails_first_and_then_works stream.expects(:getsockname).returns(:sockaddr) Socket.expects(:getnameinfo).with(:sockaddr, Socket::NI_NAMEREQD).raises(SocketError) Socket.expects(:getnameinfo).with(:sockaddr).returns(["1.2.3.4"]) assert_equal "1.2.3.4", stream.client_name end def test_client_name_when_getnameinfo_fails_but_gethostbyname_works stream.expects(:getsockname).returns(:sockaddr) Socket.expects(:getnameinfo).with(:sockaddr, Socket::NI_NAMEREQD).raises(SocketError) Socket.expects(:getnameinfo).with(:sockaddr).raises(SocketError) Socket.expects(:gethostname).returns(:hostname) Socket.expects(:gethostbyname).with(:hostname).returns(["net.ssh.test"]) assert_equal "net.ssh.test", stream.client_name end def test_client_name_when_getnameinfo_and_gethostbyname_all_fail stream.expects(:getsockname).returns(:sockaddr) Socket.expects(:getnameinfo).with(:sockaddr, Socket::NI_NAMEREQD).raises(SocketError) Socket.expects(:getnameinfo).with(:sockaddr).raises(SocketError) Socket.expects(:gethostname).returns(:hostname) Socket.expects(:gethostbyname).with(:hostname).raises(SocketError) assert_equal "unknown", stream.client_name end def test_peer_ip_should_query_socket_for_info_about_peer stream.expects(:getpeername).returns(:sockaddr) Socket.expects(:getnameinfo).with(:sockaddr, Socket::NI_NUMERICHOST | Socket::NI_NUMERICSERV).returns(["1.2.3.4"]) assert_equal "1.2.3.4", stream.peer_ip end def test_available_for_read_should_return_nontrue_when_select_fails IO.expects(:select).returns(nil) assert !stream.available_for_read? end def test_available_for_read_should_return_nontrue_when_self_is_not_ready IO.expects(:select).with([stream], nil, nil, 0).returns([[],[],[]]) assert !stream.available_for_read? end def test_available_for_read_should_return_true_when_self_is_ready IO.expects(:select).with([stream], nil, nil, 0).returns([[self],[],[]]) assert stream.available_for_read? end def test_cleanup_should_delegate_cleanup_to_client_and_server_states stream.client.expects(:cleanup) stream.server.expects(:cleanup) stream.cleanup end def test_if_needs_rekey_should_not_yield_if_neither_client_nor_server_states_need_rekey stream.if_needs_rekey? { flunk "shouldn't need rekey" } assert(true) end def test_if_needs_rekey_should_yield_and_cleanup_if_client_needs_rekey stream.client.stubs(:needs_rekey?).returns(true) stream.client.expects(:reset!) stream.server.expects(:reset!).never rekeyed = false stream.if_needs_rekey? { rekeyed = true } assert(rekeyed) end def test_if_needs_rekey_should_yield_and_cleanup_if_server_needs_rekey stream.server.stubs(:needs_rekey?).returns(true) stream.server.expects(:reset!) stream.client.expects(:reset!).never rekeyed = false stream.if_needs_rekey? { rekeyed = true } assert(rekeyed) end def test_if_needs_rekey_should_yield_and_cleanup_if_both_need_rekey stream.server.stubs(:needs_rekey?).returns(true) stream.client.stubs(:needs_rekey?).returns(true) stream.server.expects(:reset!) stream.client.expects(:reset!) rekeyed = false stream.if_needs_rekey? { rekeyed = true } assert(rekeyed) end def test_next_packet_should_not_block_by_default IO.expects(:select).returns(nil) assert_nothing_raised do timeout(1) { stream.next_packet } end end def test_next_packet_should_return_nil_when_non_blocking_and_not_ready IO.expects(:select).returns(nil) assert_nil stream.next_packet(:nonblock) end def test_next_packet_should_return_nil_when_non_blocking_and_partial_read IO.expects(:select).returns([[stream]]) stream.expects(:recv).returns([8].pack("N")) assert_nil stream.next_packet(:nonblock) assert !stream.read_buffer.empty? end def test_next_packet_should_return_packet_when_non_blocking_and_full_read IO.expects(:select).returns([[stream]]) stream.expects(:recv).returns(packet) packet = stream.next_packet(:nonblock) assert_not_nil packet assert_equal DEBUG, packet.type end def test_next_packet_should_eventually_return_packet_when_non_blocking_and_partial_read IO.stubs(:select).returns([[stream]]) stream.stubs(:recv).returns(packet[0,10], packet[10..-1]) assert_nil stream.next_packet(:nonblock) packet = stream.next_packet(:nonblock) assert_not_nil packet assert_equal DEBUG, packet.type end def test_next_packet_should_block_when_requested_until_entire_packet_is_available IO.stubs(:select).returns([[stream]]) stream.stubs(:recv).returns(packet[0,10], packet[10,20], packet[20..-1]) packet = stream.next_packet(:block) assert_not_nil packet assert_equal DEBUG, packet.type end def test_next_packet_when_blocking_should_fail_when_fill_could_not_read_any_data IO.stubs(:select).returns([[stream]]) stream.stubs(:recv).returns("") assert_raises(Net::SSH::Disconnect) { stream.next_packet(:block) } end def test_next_packet_fails_with_invalid_argument assert_raises(ArgumentError) { stream.next_packet("invalid") } end def test_send_packet_should_enqueue_and_send_data_immediately stream.expects(:send).times(3).with { |a,b| a == stream.write_buffer && b == 0 }.returns(15) IO.expects(:select).times(2).returns([[], [stream]]) stream.send_packet(ssh_packet) assert !stream.pending_write? end def test_enqueue_short_packet_should_ensure_packet_is_at_least_16_bytes_long packet = Net::SSH::Buffer.from(:byte, 0) stream.enqueue_packet(packet) # 12 originally, plus the block-size (8), plus the 4-byte length field assert_equal 24, stream.write_buffer.length end def test_enqueue_utf_8_packet_should_ensure_packet_length_is_in_bytes_and_multiple_of_block_length packet = Net::SSH::Buffer.from(:string, "\u2603") # Snowman is 3 bytes stream.enqueue_packet(packet) # When bytesize is measured wrong using length, the result is off by 2. # With length instead of bytesize, you get 26 length buffer. assert_equal 0, stream.write_buffer.length % 8 end PACKETS = { "3des-cbc" => { "hmac-md5" => { false => "\003\352\031\261k\243\200\204\301\203]!\a\306\217\201\a[^\304\317\322\264\265~\361\017\n\205\272, \000\032w\312\t\306\374\271\345p\215\224\373\363\v\261", :standard => "\317\222v\316\234<\310\377\310\034\346\351\020:\025{\372PDS\246\344\312J\364\301\n\262\r<\037\231Mu\031\240\255\026\362\200\354=g\361\271[E\265\217\316\314\b\202\235\226\334", }, "hmac-md5-96" => { false => "\003\352\031\261k\243\200\204\301\203]!\a\306\217\201\a[^\304\317\322\264\265~\361\017\n\205\272, \000\032w\312\t\306\374\271\345p\215\224", :standard => "\317\222v\316\234<\310\377\310\034\346\351\020:\025{\372PDS\246\344\312J\364\301\n\262\r<\037\231Mu\031\240\255\026\362\200\354=g\361\271[E\265\217\316\314\b", }, "hmac-sha1" => { false => "\003\352\031\261k\243\200\204\301\203]!\a\306\217\201\a[^\304\317\322\264\265~\361\017\n\205\272, \004\a\200\n\004\202z\270\236\261\330m\275\005\f\202g\260g\376", :standard => "\317\222v\316\234<\310\377\310\034\346\351\020:\025{\372PDS\246\344\312J\364\301\n\262\r<\037\231Mu\031\240\255\026\362\200\2117U\266\3444(\235\034\023\377\376\335\301\253rI\215W\311", }, "hmac-sha1-96" => { false => "\003\352\031\261k\243\200\204\301\203]!\a\306\217\201\a[^\304\317\322\264\265~\361\017\n\205\272, \004\a\200\n\004\202z\270\236\261\330m", :standard => "\317\222v\316\234<\310\377\310\034\346\351\020:\025{\372PDS\246\344\312J\364\301\n\262\r<\037\231Mu\031\240\255\026\362\200\2117U\266\3444(\235\034\023\377\376", }, "hmac-ripemd160" => { false => "\003\352\031\261k\243\200\204\301\203]!\a\306\217\201\a[^\304\317\322\264\265~\361\017\n\205\272, F\303\307\207\245\206\325~\315(\370\331\313\305\vHI\312L\216", :standard => "\317\222v\316\234<\310\377\310\034\346\351\020:\025{\372PDS\246\344\312J\364\301\n\262\r<\037\231Mu\031\240\255\026\362\200)U\275\003U\333\225\221Y)\317\256\240\246\0000\351\032\363Y", }, "hmac-ripemd160@openssh.com" => { false => "\003\352\031\261k\243\200\204\301\203]!\a\306\217\201\a[^\304\317\322\264\265~\361\017\n\205\272, F\303\307\207\245\206\325~\315(\370\331\313\305\vHI\312L\216", :standard => "\317\222v\316\234<\310\377\310\034\346\351\020:\025{\372PDS\246\344\312J\364\301\n\262\r<\037\231Mu\031\240\255\026\362\200)U\275\003U\333\225\221Y)\317\256\240\246\0000\351\032\363Y", }, "none" => { false => "\003\352\031\261k\243\200\204\301\203]!\a\306\217\201\a[^\304\317\322\264\265~\361\017\n\205\272, ", :standard => "\317\222v\316\234<\310\377\310\034\346\351\020:\025{\372PDS\246\344\312J\364\301\n\262\r<\037\231Mu\031\240\255\026\362\200", }, }, "aes128-cbc" => { "hmac-md5" => { false => "\240\016\243k]0\330\253\030\320\334\261(\034E\211\230#\326\374\267\311O\211E(\234\325n\306NY\000\032w\312\t\306\374\271\345p\215\224\373\363\v\261", :standard => "\273\367\324\032\3762\334\026\r\246\342\022\016\325\024\270.\273\005\314\036\312\211\261\037A\361\362:W\316\352K\204\216b\2124>A\265g\331\177\233dK\251-\345\b\025\242#\336P8\343\361\263\\\241\326\311", }, "hmac-md5-96" => { false => "\240\016\243k]0\330\253\030\320\334\261(\034E\211\230#\326\374\267\311O\211E(\234\325n\306NY\000\032w\312\t\306\374\271\345p\215\224", :standard => "\273\367\324\032\3762\334\026\r\246\342\022\016\325\024\270.\273\005\314\036\312\211\261\037A\361\362:W\316\352K\204\216b\2124>A\265g\331\177\233dK\251-\345\b\025\242#\336P8\343\361\263", }, "hmac-sha1" => { false => "\240\016\243k]0\330\253\030\320\334\261(\034E\211\230#\326\374\267\311O\211E(\234\325n\306NY\004\a\200\n\004\202z\270\236\261\330m\275\005\f\202g\260g\376", :standard => "\273\367\324\032\3762\334\026\r\246\342\022\016\325\024\270.\273\005\314\036\312\211\261\037A\361\362:W\316\352K\204\216b\2124>A\265g\331\177\233dK\251yC\272\314@\301\n\346$\223\367\r\026\366\375(i'\212\351", }, "hmac-sha1-96" => { false => "\240\016\243k]0\330\253\030\320\334\261(\034E\211\230#\326\374\267\311O\211E(\234\325n\306NY\004\a\200\n\004\202z\270\236\261\330m", :standard => "\273\367\324\032\3762\334\026\r\246\342\022\016\325\024\270.\273\005\314\036\312\211\261\037A\361\362:W\316\352K\204\216b\2124>A\265g\331\177\233dK\251yC\272\314@\301\n\346$\223\367\r", }, "hmac-ripemd160" => { false => "\240\016\243k]0\330\253\030\320\334\261(\034E\211\230#\326\374\267\311O\211E(\234\325n\306NYF\303\307\207\245\206\325~\315(\370\331\313\305\vHI\312L\216", :standard => "\273\367\324\032\3762\334\026\r\246\342\022\016\325\024\270.\273\005\314\036\312\211\261\037A\361\362:W\316\352K\204\216b\2124>A\265g\331\177\233dK\251\3044\024\343q\356\023\032\262\201\e9\213d\265>^{\300\320", }, "hmac-ripemd160@openssh.com" => { false => "\240\016\243k]0\330\253\030\320\334\261(\034E\211\230#\326\374\267\311O\211E(\234\325n\306NYF\303\307\207\245\206\325~\315(\370\331\313\305\vHI\312L\216", :standard => "\273\367\324\032\3762\334\026\r\246\342\022\016\325\024\270.\273\005\314\036\312\211\261\037A\361\362:W\316\352K\204\216b\2124>A\265g\331\177\233dK\251\3044\024\343q\356\023\032\262\201\e9\213d\265>^{\300\320", }, "none" => { false => "\240\016\243k]0\330\253\030\320\334\261(\034E\211\230#\326\374\267\311O\211E(\234\325n\306NY", :standard => "\273\367\324\032\3762\334\026\r\246\342\022\016\325\024\270.\273\005\314\036\312\211\261\037A\361\362:W\316\352K\204\216b\2124>A\265g\331\177\233dK\251", }, }, "aes192-cbc" => { "hmac-md5" => { false => "P$\377\302\326\262\276\215\206\343&\257#\315>Mp\232P\345o\215\330\213\t\027\300\360\300\037\267\003\000\032w\312\t\306\374\271\345p\215\224\373\363\v\261", :standard => "se\347\230\026\311\212\250yH\241\302n\364:\276\270M=H1\317\222^\362\237D\225N\354:\343\205M\006[\313$U/yZ\330\235\032\307\320D-\345\b\025\242#\336P8\343\361\263\\\241\326\311", }, "hmac-md5-96" => { false => "P$\377\302\326\262\276\215\206\343&\257#\315>Mp\232P\345o\215\330\213\t\027\300\360\300\037\267\003\000\032w\312\t\306\374\271\345p\215\224", :standard => "se\347\230\026\311\212\250yH\241\302n\364:\276\270M=H1\317\222^\362\237D\225N\354:\343\205M\006[\313$U/yZ\330\235\032\307\320D-\345\b\025\242#\336P8\343\361\263", }, "hmac-sha1" => { false => "P$\377\302\326\262\276\215\206\343&\257#\315>Mp\232P\345o\215\330\213\t\027\300\360\300\037\267\003\004\a\200\n\004\202z\270\236\261\330m\275\005\f\202g\260g\376", :standard => "se\347\230\026\311\212\250yH\241\302n\364:\276\270M=H1\317\222^\362\237D\225N\354:\343\205M\006[\313$U/yZ\330\235\032\307\320DyC\272\314@\301\n\346$\223\367\r\026\366\375(i'\212\351", }, "hmac-sha1-96" => { false => "P$\377\302\326\262\276\215\206\343&\257#\315>Mp\232P\345o\215\330\213\t\027\300\360\300\037\267\003\004\a\200\n\004\202z\270\236\261\330m", :standard => "se\347\230\026\311\212\250yH\241\302n\364:\276\270M=H1\317\222^\362\237D\225N\354:\343\205M\006[\313$U/yZ\330\235\032\307\320DyC\272\314@\301\n\346$\223\367\r", }, "hmac-ripemd160" => { false => "P$\377\302\326\262\276\215\206\343&\257#\315>Mp\232P\345o\215\330\213\t\027\300\360\300\037\267\003F\303\307\207\245\206\325~\315(\370\331\313\305\vHI\312L\216", :standard => "se\347\230\026\311\212\250yH\241\302n\364:\276\270M=H1\317\222^\362\237D\225N\354:\343\205M\006[\313$U/yZ\330\235\032\307\320D\3044\024\343q\356\023\032\262\201\e9\213d\265>^{\300\320", }, "hmac-ripemd160@openssh.com" => { false => "P$\377\302\326\262\276\215\206\343&\257#\315>Mp\232P\345o\215\330\213\t\027\300\360\300\037\267\003F\303\307\207\245\206\325~\315(\370\331\313\305\vHI\312L\216", :standard => "se\347\230\026\311\212\250yH\241\302n\364:\276\270M=H1\317\222^\362\237D\225N\354:\343\205M\006[\313$U/yZ\330\235\032\307\320D\3044\024\343q\356\023\032\262\201\e9\213d\265>^{\300\320", }, "none" => { false => "P$\377\302\326\262\276\215\206\343&\257#\315>Mp\232P\345o\215\330\213\t\027\300\360\300\037\267\003", :standard => "se\347\230\026\311\212\250yH\241\302n\364:\276\270M=H1\317\222^\362\237D\225N\354:\343\205M\006[\313$U/yZ\330\235\032\307\320D", }, }, "aes256-cbc" => { "hmac-md5" => { false => "\266\001oG(\201s\255[\202j\031-\354\353]\022\374\367j2\257\b#\273r\275\341\232\264\255\340\000\032w\312\t\306\374\271\345p\215\224\373\363\v\261", :standard => "\251!O/_\253\321\217e\225\202\202W\261p\r\357\357\375\231\264Y,nZ/\366\225G\256\3000\036\223\237\353\265vG\231\215cvY\236%\315\365-\345\b\025\242#\336P8\343\361\263\\\241\326\311", }, "hmac-md5-96" => { false => "\266\001oG(\201s\255[\202j\031-\354\353]\022\374\367j2\257\b#\273r\275\341\232\264\255\340\000\032w\312\t\306\374\271\345p\215\224", :standard => "\251!O/_\253\321\217e\225\202\202W\261p\r\357\357\375\231\264Y,nZ/\366\225G\256\3000\036\223\237\353\265vG\231\215cvY\236%\315\365-\345\b\025\242#\336P8\343\361\263", }, "hmac-sha1" => { false => "\266\001oG(\201s\255[\202j\031-\354\353]\022\374\367j2\257\b#\273r\275\341\232\264\255\340\004\a\200\n\004\202z\270\236\261\330m\275\005\f\202g\260g\376", :standard => "\251!O/_\253\321\217e\225\202\202W\261p\r\357\357\375\231\264Y,nZ/\366\225G\256\3000\036\223\237\353\265vG\231\215cvY\236%\315\365yC\272\314@\301\n\346$\223\367\r\026\366\375(i'\212\351", }, "hmac-sha1-96" => { false => "\266\001oG(\201s\255[\202j\031-\354\353]\022\374\367j2\257\b#\273r\275\341\232\264\255\340\004\a\200\n\004\202z\270\236\261\330m", :standard => "\251!O/_\253\321\217e\225\202\202W\261p\r\357\357\375\231\264Y,nZ/\366\225G\256\3000\036\223\237\353\265vG\231\215cvY\236%\315\365yC\272\314@\301\n\346$\223\367\r", }, "hmac-ripemd160" => { false => "\266\001oG(\201s\255[\202j\031-\354\353]\022\374\367j2\257\b#\273r\275\341\232\264\255\340F\303\307\207\245\206\325~\315(\370\331\313\305\vHI\312L\216", :standard => "\251!O/_\253\321\217e\225\202\202W\261p\r\357\357\375\231\264Y,nZ/\366\225G\256\3000\036\223\237\353\265vG\231\215cvY\236%\315\365\3044\024\343q\356\023\032\262\201\e9\213d\265>^{\300\320", }, "hmac-ripemd160@openssh.com" => { false => "\266\001oG(\201s\255[\202j\031-\354\353]\022\374\367j2\257\b#\273r\275\341\232\264\255\340F\303\307\207\245\206\325~\315(\370\331\313\305\vHI\312L\216", :standard => "\251!O/_\253\321\217e\225\202\202W\261p\r\357\357\375\231\264Y,nZ/\366\225G\256\3000\036\223\237\353\265vG\231\215cvY\236%\315\365\3044\024\343q\356\023\032\262\201\e9\213d\265>^{\300\320", }, "none" => { false => "\266\001oG(\201s\255[\202j\031-\354\353]\022\374\367j2\257\b#\273r\275\341\232\264\255\340", :standard => "\251!O/_\253\321\217e\225\202\202W\261p\r\357\357\375\231\264Y,nZ/\366\225G\256\3000\036\223\237\353\265vG\231\215cvY\236%\315\365", }, }, "blowfish-cbc" => { "hmac-md5" => { false => "vT\353\203\247\206L\255e\371\001 6B/\234g\332\371\224l\227\257\346\373E\237C2\212u)\000\032w\312\t\306\374\271\345p\215\224\373\363\v\261", :standard => "U\257\231e\347\274\bh\016X\232h\334\v\005\316e1G$-\367##\256$rW\000\210\335_\360\f\000\205#\370\201\006\354=g\361\271[E\265\217\316\314\b\202\235\226\334", }, "hmac-md5-96" => { false => "vT\353\203\247\206L\255e\371\001 6B/\234g\332\371\224l\227\257\346\373E\237C2\212u)\000\032w\312\t\306\374\271\345p\215\224", :standard => "U\257\231e\347\274\bh\016X\232h\334\v\005\316e1G$-\367##\256$rW\000\210\335_\360\f\000\205#\370\201\006\354=g\361\271[E\265\217\316\314\b", }, "hmac-sha1" => { false => "vT\353\203\247\206L\255e\371\001 6B/\234g\332\371\224l\227\257\346\373E\237C2\212u)\004\a\200\n\004\202z\270\236\261\330m\275\005\f\202g\260g\376", :standard => "U\257\231e\347\274\bh\016X\232h\334\v\005\316e1G$-\367##\256$rW\000\210\335_\360\f\000\205#\370\201\006\2117U\266\3444(\235\034\023\377\376\335\301\253rI\215W\311", }, "hmac-sha1-96" => { false => "vT\353\203\247\206L\255e\371\001 6B/\234g\332\371\224l\227\257\346\373E\237C2\212u)\004\a\200\n\004\202z\270\236\261\330m", :standard => "U\257\231e\347\274\bh\016X\232h\334\v\005\316e1G$-\367##\256$rW\000\210\335_\360\f\000\205#\370\201\006\2117U\266\3444(\235\034\023\377\376", }, "hmac-ripemd160" => { false => "vT\353\203\247\206L\255e\371\001 6B/\234g\332\371\224l\227\257\346\373E\237C2\212u)F\303\307\207\245\206\325~\315(\370\331\313\305\vHI\312L\216", :standard => "U\257\231e\347\274\bh\016X\232h\334\v\005\316e1G$-\367##\256$rW\000\210\335_\360\f\000\205#\370\201\006)U\275\003U\333\225\221Y)\317\256\240\246\0000\351\032\363Y", }, "hmac-ripemd160@openssh.com" => { false => "vT\353\203\247\206L\255e\371\001 6B/\234g\332\371\224l\227\257\346\373E\237C2\212u)F\303\307\207\245\206\325~\315(\370\331\313\305\vHI\312L\216", :standard => "U\257\231e\347\274\bh\016X\232h\334\v\005\316e1G$-\367##\256$rW\000\210\335_\360\f\000\205#\370\201\006)U\275\003U\333\225\221Y)\317\256\240\246\0000\351\032\363Y", }, "none" => { false => "vT\353\203\247\206L\255e\371\001 6B/\234g\332\371\224l\227\257\346\373E\237C2\212u)", :standard => "U\257\231e\347\274\bh\016X\232h\334\v\005\316e1G$-\367##\256$rW\000\210\335_\360\f\000\205#\370\201\006", }, }, "cast128-cbc" => { "hmac-md5" => { false => "\361\026\313!\31235|w~\n\261\257\277\e\277b\246b\342\333\eE\021N\345\343m\314\272\315\376\000\032w\312\t\306\374\271\345p\215\224\373\363\v\261", :standard => "\375i\253\004\311E\2011)\220$\251A\245\f(\371\263\314\242\353\260\272\367\276\"\031\224$\244\311W\307Oe\224\0017\336\325\354=g\361\271[E\265\217\316\314\b\202\235\226\334", }, "hmac-md5-96" => { false => "\361\026\313!\31235|w~\n\261\257\277\e\277b\246b\342\333\eE\021N\345\343m\314\272\315\376\000\032w\312\t\306\374\271\345p\215\224", :standard => "\375i\253\004\311E\2011)\220$\251A\245\f(\371\263\314\242\353\260\272\367\276\"\031\224$\244\311W\307Oe\224\0017\336\325\354=g\361\271[E\265\217\316\314\b", }, "hmac-sha1" => { false => "\361\026\313!\31235|w~\n\261\257\277\e\277b\246b\342\333\eE\021N\345\343m\314\272\315\376\004\a\200\n\004\202z\270\236\261\330m\275\005\f\202g\260g\376", :standard => "\375i\253\004\311E\2011)\220$\251A\245\f(\371\263\314\242\353\260\272\367\276\"\031\224$\244\311W\307Oe\224\0017\336\325\2117U\266\3444(\235\034\023\377\376\335\301\253rI\215W\311", }, "hmac-sha1-96" => { false => "\361\026\313!\31235|w~\n\261\257\277\e\277b\246b\342\333\eE\021N\345\343m\314\272\315\376\004\a\200\n\004\202z\270\236\261\330m", :standard => "\375i\253\004\311E\2011)\220$\251A\245\f(\371\263\314\242\353\260\272\367\276\"\031\224$\244\311W\307Oe\224\0017\336\325\2117U\266\3444(\235\034\023\377\376", }, "hmac-ripemd160" => { false => "\361\026\313!\31235|w~\n\261\257\277\e\277b\246b\342\333\eE\021N\345\343m\314\272\315\376F\303\307\207\245\206\325~\315(\370\331\313\305\vHI\312L\216", :standard => "\375i\253\004\311E\2011)\220$\251A\245\f(\371\263\314\242\353\260\272\367\276\"\031\224$\244\311W\307Oe\224\0017\336\325)U\275\003U\333\225\221Y)\317\256\240\246\0000\351\032\363Y", }, "hmac-ripemd160@openssh.com" => { false => "\361\026\313!\31235|w~\n\261\257\277\e\277b\246b\342\333\eE\021N\345\343m\314\272\315\376F\303\307\207\245\206\325~\315(\370\331\313\305\vHI\312L\216", :standard => "\375i\253\004\311E\2011)\220$\251A\245\f(\371\263\314\242\353\260\272\367\276\"\031\224$\244\311W\307Oe\224\0017\336\325)U\275\003U\333\225\221Y)\317\256\240\246\0000\351\032\363Y", }, "none" => { false => "\361\026\313!\31235|w~\n\261\257\277\e\277b\246b\342\333\eE\021N\345\343m\314\272\315\376", :standard => "\375i\253\004\311E\2011)\220$\251A\245\f(\371\263\314\242\353\260\272\367\276\"\031\224$\244\311W\307Oe\224\0017\336\325", }, }, "idea-cbc" => { "hmac-md5" => { false => "\342\255\202$\273\201\025#\245\2341F\263\005@{\000<\266&s\016\251NH=J\322/\220 H\000\032w\312\t\306\374\271\345p\215\224\373\363\v\261", :standard => "F\3048\360\357\265\215I\021)\a\254/\315%\354M\004\330\006\356\vFr\250K\225\223x\277+Q)\022\327\311K\025\322\317\354=g\361\271[E\265\217\316\314\b\202\235\226\334", }, "hmac-md5-96" => { false => "\342\255\202$\273\201\025#\245\2341F\263\005@{\000<\266&s\016\251NH=J\322/\220 H\000\032w\312\t\306\374\271\345p\215\224", :standard => "F\3048\360\357\265\215I\021)\a\254/\315%\354M\004\330\006\356\vFr\250K\225\223x\277+Q)\022\327\311K\025\322\317\354=g\361\271[E\265\217\316\314\b", }, "hmac-sha1" => { false => "\342\255\202$\273\201\025#\245\2341F\263\005@{\000<\266&s\016\251NH=J\322/\220 H\004\a\200\n\004\202z\270\236\261\330m\275\005\f\202g\260g\376", :standard => "F\3048\360\357\265\215I\021)\a\254/\315%\354M\004\330\006\356\vFr\250K\225\223x\277+Q)\022\327\311K\025\322\317\2117U\266\3444(\235\034\023\377\376\335\301\253rI\215W\311", }, "hmac-sha1-96" => { false => "\342\255\202$\273\201\025#\245\2341F\263\005@{\000<\266&s\016\251NH=J\322/\220 H\004\a\200\n\004\202z\270\236\261\330m", :standard => "F\3048\360\357\265\215I\021)\a\254/\315%\354M\004\330\006\356\vFr\250K\225\223x\277+Q)\022\327\311K\025\322\317\2117U\266\3444(\235\034\023\377\376", }, "hmac-ripemd160" => { false => "\342\255\202$\273\201\025#\245\2341F\263\005@{\000<\266&s\016\251NH=J\322/\220 HF\303\307\207\245\206\325~\315(\370\331\313\305\vHI\312L\216", :standard => "F\3048\360\357\265\215I\021)\a\254/\315%\354M\004\330\006\356\vFr\250K\225\223x\277+Q)\022\327\311K\025\322\317)U\275\003U\333\225\221Y)\317\256\240\246\0000\351\032\363Y", }, "hmac-ripemd160@openssh.com" => { false => "\342\255\202$\273\201\025#\245\2341F\263\005@{\000<\266&s\016\251NH=J\322/\220 HF\303\307\207\245\206\325~\315(\370\331\313\305\vHI\312L\216", :standard => "F\3048\360\357\265\215I\021)\a\254/\315%\354M\004\330\006\356\vFr\250K\225\223x\277+Q)\022\327\311K\025\322\317)U\275\003U\333\225\221Y)\317\256\240\246\0000\351\032\363Y", }, "none" => { false => "\342\255\202$\273\201\025#\245\2341F\263\005@{\000<\266&s\016\251NH=J\322/\220 H", :standard => "F\3048\360\357\265\215I\021)\a\254/\315%\354M\004\330\006\356\vFr\250K\225\223x\277+Q)\022\327\311K\025\322\317", }, }, "arcfour128" => { "hmac-md5" => { false => "e_\204\037\366\363>\024\263q\025\334\354AO.\026t\231nvD\030\226\234\263\257\335:\001\300\255\000\032w\312\t\306\374\271\345p\215\224\373\363\v\261", :standard => "e_\204'\367\217\243v\322\025|\330ios\004[P\270\306\272\017\037\344\214\253\354\272m\261\217/jW'V\277\341U\224\354=g\361\271[E\265\217\316\314\b\202\235\226\334", }, "hmac-md5-96" => { false => "e_\204\037\366\363>\024\263q\025\334\354AO.\026t\231nvD\030\226\234\263\257\335:\001\300\255\000\032w\312\t\306\374\271\345p\215\224", :standard => "e_\204'\367\217\243v\322\025|\330ios\004[P\270\306\272\017\037\344\214\253\354\272m\261\217/jW'V\277\341U\224\354=g\361\271[E\265\217\316\314\b", }, "hmac-sha1" => { false => "e_\204\037\366\363>\024\263q\025\334\354AO.\026t\231nvD\030\226\234\263\257\335:\001\300\255\004\a\200\n\004\202z\270\236\261\330m\275\005\f\202g\260g\376", :standard => "e_\204'\367\217\243v\322\025|\330ios\004[P\270\306\272\017\037\344\214\253\354\272m\261\217/jW'V\277\341U\224\2117U\266\3444(\235\034\023\377\376\335\301\253rI\215W\311", }, "hmac-sha1-96" => { false => "e_\204\037\366\363>\024\263q\025\334\354AO.\026t\231nvD\030\226\234\263\257\335:\001\300\255\004\a\200\n\004\202z\270\236\261\330m", :standard => "e_\204'\367\217\243v\322\025|\330ios\004[P\270\306\272\017\037\344\214\253\354\272m\261\217/jW'V\277\341U\224\2117U\266\3444(\235\034\023\377\376", }, "hmac-ripemd160" => { false => "e_\204\037\366\363>\024\263q\025\334\354AO.\026t\231nvD\030\226\234\263\257\335:\001\300\255F\303\307\207\245\206\325~\315(\370\331\313\305\vHI\312L\216", :standard => "e_\204'\367\217\243v\322\025|\330ios\004[P\270\306\272\017\037\344\214\253\354\272m\261\217/jW'V\277\341U\224)U\275\003U\333\225\221Y)\317\256\240\246\0000\351\032\363Y", }, "hmac-ripemd160@openssh.com" => { false => "e_\204\037\366\363>\024\263q\025\334\354AO.\026t\231nvD\030\226\234\263\257\335:\001\300\255F\303\307\207\245\206\325~\315(\370\331\313\305\vHI\312L\216", :standard => "e_\204'\367\217\243v\322\025|\330ios\004[P\270\306\272\017\037\344\214\253\354\272m\261\217/jW'V\277\341U\224)U\275\003U\333\225\221Y)\317\256\240\246\0000\351\032\363Y", }, "none" => { false => "e_\204\037\366\363>\024\263q\025\334\354AO.\026t\231nvD\030\226\234\263\257\335:\001\300\255", :standard => "e_\204'\367\217\243v\322\025|\330ios\004[P\270\306\272\017\037\344\214\253\354\272m\261\217/jW'V\277\341U\224", }, }, "arcfour256" => { "hmac-md5" => { false => "B\374\256V\035b\337\215\305h\031bE\271\312\361\017T+\302\024x\3016\315g%\032\331\004fr\000\032w\312\t\306\374\271\345p\215\224\373\363\v\261", :standard => "B\374\256n\034\036B\357\244\fpf\300\227\366\333Bp\nj\3303\306D\335\177f}\216\264)\360\325jU^M\357$\221\354=g\361\271[E\265\217\316\314\b\202\235\226\334", }, "hmac-md5-96" => { false => "B\374\256V\035b\337\215\305h\031bE\271\312\361\017T+\302\024x\3016\315g%\032\331\004fr\000\032w\312\t\306\374\271\345p\215\224", :standard => "B\374\256n\034\036B\357\244\fpf\300\227\366\333Bp\nj\3303\306D\335\177f}\216\264)\360\325jU^M\357$\221\354=g\361\271[E\265\217\316\314\b", }, "hmac-sha1" => { false => "B\374\256V\035b\337\215\305h\031bE\271\312\361\017T+\302\024x\3016\315g%\032\331\004fr\004\a\200\n\004\202z\270\236\261\330m\275\005\f\202g\260g\376", :standard => "B\374\256n\034\036B\357\244\fpf\300\227\366\333Bp\nj\3303\306D\335\177f}\216\264)\360\325jU^M\357$\221\2117U\266\3444(\235\034\023\377\376\335\301\253rI\215W\311", }, "hmac-sha1-96" => { false => "B\374\256V\035b\337\215\305h\031bE\271\312\361\017T+\302\024x\3016\315g%\032\331\004fr\004\a\200\n\004\202z\270\236\261\330m", :standard => "B\374\256n\034\036B\357\244\fpf\300\227\366\333Bp\nj\3303\306D\335\177f}\216\264)\360\325jU^M\357$\221\2117U\266\3444(\235\034\023\377\376", }, "hmac-ripemd160" => { false => "B\374\256V\035b\337\215\305h\031bE\271\312\361\017T+\302\024x\3016\315g%\032\331\004frF\303\307\207\245\206\325~\315(\370\331\313\305\vHI\312L\216", :standard => "B\374\256n\034\036B\357\244\fpf\300\227\366\333Bp\nj\3303\306D\335\177f}\216\264)\360\325jU^M\357$\221)U\275\003U\333\225\221Y)\317\256\240\246\0000\351\032\363Y", }, "hmac-ripemd160@openssh.com" => { false => "B\374\256V\035b\337\215\305h\031bE\271\312\361\017T+\302\024x\3016\315g%\032\331\004frF\303\307\207\245\206\325~\315(\370\331\313\305\vHI\312L\216", :standard => "B\374\256n\034\036B\357\244\fpf\300\227\366\333Bp\nj\3303\306D\335\177f}\216\264)\360\325jU^M\357$\221)U\275\003U\333\225\221Y)\317\256\240\246\0000\351\032\363Y", }, "none" => { false => "B\374\256V\035b\337\215\305h\031bE\271\312\361\017T+\302\024x\3016\315g%\032\331\004fr", :standard => "B\374\256n\034\036B\357\244\fpf\300\227\366\333Bp\nj\3303\306D\335\177f}\216\264)\360\325jU^M\357$\221", }, }, "arcfour512" => { "hmac-md5" => { false => "\n{\275\177Yw\307\f\277\221\247'\0318\237\223cR\340\361\356\017\357\235\342\374\005wL\267\330D\000\032w\312\t\306\374\271\345p\215\224\373\363\v\261", :standard => "\n{\275GX\vZn\336\365\316#\234\026\243\271.v\301Y\"D\350\357\362\344F\020\e\a\227\306\366\025:\246\2349\233\313\354=g\361\271[E\265\217\316\314\b\202\235\226\334", }, "hmac-md5-96" => { false => "\n{\275\177Yw\307\f\277\221\247'\0318\237\223cR\340\361\356\017\357\235\342\374\005wL\267\330D\000\032w\312\t\306\374\271\345p\215\224", :standard => "\n{\275GX\vZn\336\365\316#\234\026\243\271.v\301Y\"D\350\357\362\344F\020\e\a\227\306\366\025:\246\2349\233\313\354=g\361\271[E\265\217\316\314\b", }, "hmac-sha1" => { false => "\n{\275\177Yw\307\f\277\221\247'\0318\237\223cR\340\361\356\017\357\235\342\374\005wL\267\330D\004\a\200\n\004\202z\270\236\261\330m\275\005\f\202g\260g\376", :standard => "\n{\275GX\vZn\336\365\316#\234\026\243\271.v\301Y\"D\350\357\362\344F\020\e\a\227\306\366\025:\246\2349\233\313\2117U\266\3444(\235\034\023\377\376\335\301\253rI\215W\311", }, "hmac-sha1-96" => { false => "\n{\275\177Yw\307\f\277\221\247'\0318\237\223cR\340\361\356\017\357\235\342\374\005wL\267\330D\004\a\200\n\004\202z\270\236\261\330m", :standard => "\n{\275GX\vZn\336\365\316#\234\026\243\271.v\301Y\"D\350\357\362\344F\020\e\a\227\306\366\025:\246\2349\233\313\2117U\266\3444(\235\034\023\377\376", }, "hmac-ripemd160" => { false => "\n{\275\177Yw\307\f\277\221\247'\0318\237\223cR\340\361\356\017\357\235\342\374\005wL\267\330DF\303\307\207\245\206\325~\315(\370\331\313\305\vHI\312L\216", :standard => "\n{\275GX\vZn\336\365\316#\234\026\243\271.v\301Y\"D\350\357\362\344F\020\e\a\227\306\366\025:\246\2349\233\313)U\275\003U\333\225\221Y)\317\256\240\246\0000\351\032\363Y", }, "hmac-ripemd160@openssh.com" => { false => "\n{\275\177Yw\307\f\277\221\247'\0318\237\223cR\340\361\356\017\357\235\342\374\005wL\267\330DF\303\307\207\245\206\325~\315(\370\331\313\305\vHI\312L\216", :standard => "\n{\275GX\vZn\336\365\316#\234\026\243\271.v\301Y\"D\350\357\362\344F\020\e\a\227\306\366\025:\246\2349\233\313)U\275\003U\333\225\221Y)\317\256\240\246\0000\351\032\363Y", }, "none" => { false => "\n{\275\177Yw\307\f\277\221\247'\0318\237\223cR\340\361\356\017\357\235\342\374\005wL\267\330D", :standard => "\n{\275GX\vZn\336\365\316#\234\026\243\271.v\301Y\"D\350\357\362\344F\020\e\a\227\306\366\025:\246\2349\233\313", }, }, "camellia128-cbc@openssh.org" => { "hmac-md5" => { false => "vO\xD4Mst\xD2 } _\xE3e\xC4\x8A\xAA\xCD\x9E*\xE2\xA5\xC0\xED\xBB\xD5\x99\x12 ^2\xC3\x9D\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94\xFB\xF3\v\xB1", :standard => "\x1Du9\xC7\x12\xA4\x9B\r\b\x19e&\x04e\xCE\rp\xE8=\x87h\xBE2\xE0\xAE\x90\xFF\xB22az\x17\xA4IO7}\xE3h2Q\xB8S\x18+&\xFE\x13-\xE5\b\x15\xA2#\xDEP8\xE3\xF1\xB3\\\xA1\xD6\xC9", }, "hmac-md5-96" => { false => "vO\xD4Mst\xD2 } _\xE3e\xC4\x8A\xAA\xCD\x9E*\xE2\xA5\xC0\xED\xBB\xD5\x99\x12 ^2\xC3\x9D\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94", :standard => "\x1Du9\xC7\x12\xA4\x9B\r\b\x19e&\x04e\xCE\rp\xE8=\x87h\xBE2\xE0\xAE\x90\xFF\xB22az\x17\xA4IO7}\xE3h2Q\xB8S\x18+&\xFE\x13-\xE5\b\x15\xA2#\xDEP8\xE3\xF1\xB3", }, "hmac-sha1" => { false => "vO\xD4Mst\xD2 } _\xE3e\xC4\x8A\xAA\xCD\x9E*\xE2\xA5\xC0\xED\xBB\xD5\x99\x12 ^2\xC3\x9D\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m\xBD\x05\f\x82g\xB0g\xFE", :standard => "\x1Du9\xC7\x12\xA4\x9B\r\b\x19e&\x04e\xCE\rp\xE8=\x87h\xBE2\xE0\xAE\x90\xFF\xB22az\x17\xA4IO7}\xE3h2Q\xB8S\x18+&\xFE\x13yC\xBA\xCC@\xC1\n\xE6$\x93\xF7\r\x16\xF6\xFD(i'\x8A\xE9", }, "hmac-sha1-96" => { false => "vO\xD4Mst\xD2 } _\xE3e\xC4\x8A\xAA\xCD\x9E*\xE2\xA5\xC0\xED\xBB\xD5\x99\x12 ^2\xC3\x9D\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m", :standard => "\x1Du9\xC7\x12\xA4\x9B\r\b\x19e&\x04e\xCE\rp\xE8=\x87h\xBE2\xE0\xAE\x90\xFF\xB22az\x17\xA4IO7}\xE3h2Q\xB8S\x18+&\xFE\x13yC\xBA\xCC@\xC1\n\xE6$\x93\xF7\r", }, "hmac-ripemd160" => { false => "vO\xD4Mst\xD2 } _\xE3e\xC4\x8A\xAA\xCD\x9E*\xE2\xA5\xC0\xED\xBB\xD5\x99\x12 ^2\xC3\x9DF\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\x1Du9\xC7\x12\xA4\x9B\r\b\x19e&\x04e\xCE\rp\xE8=\x87h\xBE2\xE0\xAE\x90\xFF\xB22az\x17\xA4IO7}\xE3h2Q\xB8S\x18+&\xFE\x13\xC44\x14\xE3q\xEE\x13\x1A\xB2\x81\e9\x8Bd\xB5>^{\xC0\xD0", }, "hmac-ripemd160@openssh.com" => { false => "vO\xD4Mst\xD2 } _\xE3e\xC4\x8A\xAA\xCD\x9E*\xE2\xA5\xC0\xED\xBB\xD5\x99\x12 ^2\xC3\x9DF\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\x1Du9\xC7\x12\xA4\x9B\r\b\x19e&\x04e\xCE\rp\xE8=\x87h\xBE2\xE0\xAE\x90\xFF\xB22az\x17\xA4IO7}\xE3h2Q\xB8S\x18+&\xFE\x13\xC44\x14\xE3q\xEE\x13\x1A\xB2\x81\e9\x8Bd\xB5>^{\xC0\xD0", }, "none" => { false => "vO\xD4Mst\xD2 } _\xE3e\xC4\x8A\xAA\xCD\x9E*\xE2\xA5\xC0\xED\xBB\xD5\x99\x12 ^2\xC3\x9D", :standard => "\x1Du9\xC7\x12\xA4\x9B\r\b\x19e&\x04e\xCE\rp\xE8=\x87h\xBE2\xE0\xAE\x90\xFF\xB22az\x17\xA4IO7}\xE3h2Q\xB8S\x18+&\xFE\x13", }, }, "camellia192-cbc@openssh.org" => { "hmac-md5" => { false => "Nnl\x00\xD2\xBA\x89j-(\xDD\xF4\\\x19\xF4\xB7\x16,\x90\xEA,\xE26\x00I\xF9\xB5Z\x060\x83E\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94\xFB\xF3\v\xB1", :standard => "\x8Cm\x02.\x18\xFA\x87\x7F\x18a\xA8\xAC \x82u\xC7]\xE6rs/\xB3\xF5.>Aw\x96\xEF\xADLO\xDE[\x02\x14k\xCEn\x06\xF6\xBD^\"4';\x12-\xE5\b\x15\xA2#\xDEP8\xE3\xF1\xB3\\\xA1\xD6\xC9", }, "hmac-md5-96" => { false => "Nnl\x00\xD2\xBA\x89j-(\xDD\xF4\\\x19\xF4\xB7\x16,\x90\xEA,\xE26\x00I\xF9\xB5Z\x060\x83E\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94", :standard => "\x8Cm\x02.\x18\xFA\x87\x7F\x18a\xA8\xAC \x82u\xC7]\xE6rs/\xB3\xF5.>Aw\x96\xEF\xADLO\xDE[\x02\x14k\xCEn\x06\xF6\xBD^\"4';\x12-\xE5\b\x15\xA2#\xDEP8\xE3\xF1\xB3", }, "hmac-sha1" => { false => "Nnl\x00\xD2\xBA\x89j-(\xDD\xF4\\\x19\xF4\xB7\x16,\x90\xEA,\xE26\x00I\xF9\xB5Z\x060\x83E\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m\xBD\x05\f\x82g\xB0g\xFE", :standard => "\x8Cm\x02.\x18\xFA\x87\x7F\x18a\xA8\xAC \x82u\xC7]\xE6rs/\xB3\xF5.>Aw\x96\xEF\xADLO\xDE[\x02\x14k\xCEn\x06\xF6\xBD^\"4';\x12yC\xBA\xCC@\xC1\n\xE6$\x93\xF7\r\x16\xF6\xFD(i'\x8A\xE9", }, "hmac-sha1-96" => { false => "Nnl\x00\xD2\xBA\x89j-(\xDD\xF4\\\x19\xF4\xB7\x16,\x90\xEA,\xE26\x00I\xF9\xB5Z\x060\x83E\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m", :standard => "\x8Cm\x02.\x18\xFA\x87\x7F\x18a\xA8\xAC \x82u\xC7]\xE6rs/\xB3\xF5.>Aw\x96\xEF\xADLO\xDE[\x02\x14k\xCEn\x06\xF6\xBD^\"4';\x12yC\xBA\xCC@\xC1\n\xE6$\x93\xF7\r", }, "hmac-ripemd160" => { false => "Nnl\x00\xD2\xBA\x89j-(\xDD\xF4\\\x19\xF4\xB7\x16,\x90\xEA,\xE26\x00I\xF9\xB5Z\x060\x83EF\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\x8Cm\x02.\x18\xFA\x87\x7F\x18a\xA8\xAC \x82u\xC7]\xE6rs/\xB3\xF5.>Aw\x96\xEF\xADLO\xDE[\x02\x14k\xCEn\x06\xF6\xBD^\"4';\x12\xC44\x14\xE3q\xEE\x13\x1A\xB2\x81\e9\x8Bd\xB5>^{\xC0\xD0", }, "hmac-ripemd160@openssh.com" => { false => "Nnl\x00\xD2\xBA\x89j-(\xDD\xF4\\\x19\xF4\xB7\x16,\x90\xEA,\xE26\x00I\xF9\xB5Z\x060\x83EF\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\x8Cm\x02.\x18\xFA\x87\x7F\x18a\xA8\xAC \x82u\xC7]\xE6rs/\xB3\xF5.>Aw\x96\xEF\xADLO\xDE[\x02\x14k\xCEn\x06\xF6\xBD^\"4';\x12\xC44\x14\xE3q\xEE\x13\x1A\xB2\x81\e9\x8Bd\xB5>^{\xC0\xD0", }, "none" => { false => "Nnl\x00\xD2\xBA\x89j-(\xDD\xF4\\\x19\xF4\xB7\x16,\x90\xEA,\xE26\x00I\xF9\xB5Z\x060\x83E", :standard => "\x8Cm\x02.\x18\xFA\x87\x7F\x18a\xA8\xAC \x82u\xC7]\xE6rs/\xB3\xF5.>Aw\x96\xEF\xADLO\xDE[\x02\x14k\xCEn\x06\xF6\xBD^\"4';\x12", }, }, "camellia256-cbc@openssh.org" => { "hmac-md5" => { false => "\xE9\xAB&\x85*\x8B\x9C\xFF\xC9\xD2\x91\xE7\e\xE7P]\xD7\t\xA0\x99\a\xCD\x83K\x161\xA4\xBD\xCE\x82y|\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94\xFB\xF3\v\xB1", :standard => "\x9D\x87\e\x99\x80mG\ex-\xA1\xEFA\xBB\xBD+!\xF9s\xC1\xBA_\xA8\xE0\x82\xBEX\xA6\xE8\x85\x1E\xBA\xAFY\x0E\xAC\xCB\xE1\xBF\xD1\xFD\xC3X\x8A\xF1qFi-\xE5\b\x15\xA2#\xDEP8\xE3\xF1\xB3\\\xA1\xD6\xC9", }, "hmac-md5-96" => { false => "\xE9\xAB&\x85*\x8B\x9C\xFF\xC9\xD2\x91\xE7\e\xE7P]\xD7\t\xA0\x99\a\xCD\x83K\x161\xA4\xBD\xCE\x82y|\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94", :standard => "\x9D\x87\e\x99\x80mG\ex-\xA1\xEFA\xBB\xBD+!\xF9s\xC1\xBA_\xA8\xE0\x82\xBEX\xA6\xE8\x85\x1E\xBA\xAFY\x0E\xAC\xCB\xE1\xBF\xD1\xFD\xC3X\x8A\xF1qFi-\xE5\b\x15\xA2#\xDEP8\xE3\xF1\xB3", }, "hmac-sha1" => { false => "\xE9\xAB&\x85*\x8B\x9C\xFF\xC9\xD2\x91\xE7\e\xE7P]\xD7\t\xA0\x99\a\xCD\x83K\x161\xA4\xBD\xCE\x82y|\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m\xBD\x05\f\x82g\xB0g\xFE", :standard => "\x9D\x87\e\x99\x80mG\ex-\xA1\xEFA\xBB\xBD+!\xF9s\xC1\xBA_\xA8\xE0\x82\xBEX\xA6\xE8\x85\x1E\xBA\xAFY\x0E\xAC\xCB\xE1\xBF\xD1\xFD\xC3X\x8A\xF1qFiyC\xBA\xCC@\xC1\n\xE6$\x93\xF7\r\x16\xF6\xFD(i'\x8A\xE9", }, "hmac-sha1-96" => { false => "\xE9\xAB&\x85*\x8B\x9C\xFF\xC9\xD2\x91\xE7\e\xE7P]\xD7\t\xA0\x99\a\xCD\x83K\x161\xA4\xBD\xCE\x82y|\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m", :standard => "\x9D\x87\e\x99\x80mG\ex-\xA1\xEFA\xBB\xBD+!\xF9s\xC1\xBA_\xA8\xE0\x82\xBEX\xA6\xE8\x85\x1E\xBA\xAFY\x0E\xAC\xCB\xE1\xBF\xD1\xFD\xC3X\x8A\xF1qFiyC\xBA\xCC@\xC1\n\xE6$\x93\xF7\r", }, "hmac-ripemd160" => { false => "\xE9\xAB&\x85*\x8B\x9C\xFF\xC9\xD2\x91\xE7\e\xE7P]\xD7\t\xA0\x99\a\xCD\x83K\x161\xA4\xBD\xCE\x82y|F\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\x9D\x87\e\x99\x80mG\ex-\xA1\xEFA\xBB\xBD+!\xF9s\xC1\xBA_\xA8\xE0\x82\xBEX\xA6\xE8\x85\x1E\xBA\xAFY\x0E\xAC\xCB\xE1\xBF\xD1\xFD\xC3X\x8A\xF1qFi\xC44\x14\xE3q\xEE\x13\x1A\xB2\x81\e9\x8Bd\xB5>^{\xC0\xD0", }, "hmac-ripemd160@openssh.com" => { false => "\xE9\xAB&\x85*\x8B\x9C\xFF\xC9\xD2\x91\xE7\e\xE7P]\xD7\t\xA0\x99\a\xCD\x83K\x161\xA4\xBD\xCE\x82y|F\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\x9D\x87\e\x99\x80mG\ex-\xA1\xEFA\xBB\xBD+!\xF9s\xC1\xBA_\xA8\xE0\x82\xBEX\xA6\xE8\x85\x1E\xBA\xAFY\x0E\xAC\xCB\xE1\xBF\xD1\xFD\xC3X\x8A\xF1qFi\xC44\x14\xE3q\xEE\x13\x1A\xB2\x81\e9\x8Bd\xB5>^{\xC0\xD0", }, "none" => { false => "\xE9\xAB&\x85*\x8B\x9C\xFF\xC9\xD2\x91\xE7\e\xE7P]\xD7\t\xA0\x99\a\xCD\x83K\x161\xA4\xBD\xCE\x82y|", :standard => "\x9D\x87\e\x99\x80mG\ex-\xA1\xEFA\xBB\xBD+!\xF9s\xC1\xBA_\xA8\xE0\x82\xBEX\xA6\xE8\x85\x1E\xBA\xAFY\x0E\xAC\xCB\xE1\xBF\xD1\xFD\xC3X\x8A\xF1qFi", }, }, "camellia128-cbc" => { "hmac-md5" => { false => "vO\xD4Mst\xD2 } _\xE3e\xC4\x8A\xAA\xCD\x9E*\xE2\xA5\xC0\xED\xBB\xD5\x99\x12 ^2\xC3\x9D\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94\xFB\xF3\v\xB1", :standard => "\x1Du9\xC7\x12\xA4\x9B\r\b\x19e&\x04e\xCE\rp\xE8=\x87h\xBE2\xE0\xAE\x90\xFF\xB22az\x17\xA4IO7}\xE3h2Q\xB8S\x18+&\xFE\x13-\xE5\b\x15\xA2#\xDEP8\xE3\xF1\xB3\\\xA1\xD6\xC9", }, "hmac-md5-96" => { false => "vO\xD4Mst\xD2 } _\xE3e\xC4\x8A\xAA\xCD\x9E*\xE2\xA5\xC0\xED\xBB\xD5\x99\x12 ^2\xC3\x9D\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94", :standard => "\x1Du9\xC7\x12\xA4\x9B\r\b\x19e&\x04e\xCE\rp\xE8=\x87h\xBE2\xE0\xAE\x90\xFF\xB22az\x17\xA4IO7}\xE3h2Q\xB8S\x18+&\xFE\x13-\xE5\b\x15\xA2#\xDEP8\xE3\xF1\xB3", }, "hmac-sha1" => { false => "vO\xD4Mst\xD2 } _\xE3e\xC4\x8A\xAA\xCD\x9E*\xE2\xA5\xC0\xED\xBB\xD5\x99\x12 ^2\xC3\x9D\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m\xBD\x05\f\x82g\xB0g\xFE", :standard => "\x1Du9\xC7\x12\xA4\x9B\r\b\x19e&\x04e\xCE\rp\xE8=\x87h\xBE2\xE0\xAE\x90\xFF\xB22az\x17\xA4IO7}\xE3h2Q\xB8S\x18+&\xFE\x13yC\xBA\xCC@\xC1\n\xE6$\x93\xF7\r\x16\xF6\xFD(i'\x8A\xE9", }, "hmac-sha1-96" => { false => "vO\xD4Mst\xD2 } _\xE3e\xC4\x8A\xAA\xCD\x9E*\xE2\xA5\xC0\xED\xBB\xD5\x99\x12 ^2\xC3\x9D\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m", :standard => "\x1Du9\xC7\x12\xA4\x9B\r\b\x19e&\x04e\xCE\rp\xE8=\x87h\xBE2\xE0\xAE\x90\xFF\xB22az\x17\xA4IO7}\xE3h2Q\xB8S\x18+&\xFE\x13yC\xBA\xCC@\xC1\n\xE6$\x93\xF7\r", }, "hmac-ripemd160" => { false => "vO\xD4Mst\xD2 } _\xE3e\xC4\x8A\xAA\xCD\x9E*\xE2\xA5\xC0\xED\xBB\xD5\x99\x12 ^2\xC3\x9DF\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\x1Du9\xC7\x12\xA4\x9B\r\b\x19e&\x04e\xCE\rp\xE8=\x87h\xBE2\xE0\xAE\x90\xFF\xB22az\x17\xA4IO7}\xE3h2Q\xB8S\x18+&\xFE\x13\xC44\x14\xE3q\xEE\x13\x1A\xB2\x81\e9\x8Bd\xB5>^{\xC0\xD0", }, "hmac-ripemd160@openssh.com" => { false => "vO\xD4Mst\xD2 } _\xE3e\xC4\x8A\xAA\xCD\x9E*\xE2\xA5\xC0\xED\xBB\xD5\x99\x12 ^2\xC3\x9DF\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\x1Du9\xC7\x12\xA4\x9B\r\b\x19e&\x04e\xCE\rp\xE8=\x87h\xBE2\xE0\xAE\x90\xFF\xB22az\x17\xA4IO7}\xE3h2Q\xB8S\x18+&\xFE\x13\xC44\x14\xE3q\xEE\x13\x1A\xB2\x81\e9\x8Bd\xB5>^{\xC0\xD0", }, "none" => { false => "vO\xD4Mst\xD2 } _\xE3e\xC4\x8A\xAA\xCD\x9E*\xE2\xA5\xC0\xED\xBB\xD5\x99\x12 ^2\xC3\x9D", :standard => "\x1Du9\xC7\x12\xA4\x9B\r\b\x19e&\x04e\xCE\rp\xE8=\x87h\xBE2\xE0\xAE\x90\xFF\xB22az\x17\xA4IO7}\xE3h2Q\xB8S\x18+&\xFE\x13", }, }, "camellia192-cbc" => { "hmac-md5" => { false => "Nnl\x00\xD2\xBA\x89j-(\xDD\xF4\\\x19\xF4\xB7\x16,\x90\xEA,\xE26\x00I\xF9\xB5Z\x060\x83E\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94\xFB\xF3\v\xB1", :standard => "\x8Cm\x02.\x18\xFA\x87\x7F\x18a\xA8\xAC \x82u\xC7]\xE6rs/\xB3\xF5.>Aw\x96\xEF\xADLO\xDE[\x02\x14k\xCEn\x06\xF6\xBD^\"4';\x12-\xE5\b\x15\xA2#\xDEP8\xE3\xF1\xB3\\\xA1\xD6\xC9", }, "hmac-md5-96" => { false => "Nnl\x00\xD2\xBA\x89j-(\xDD\xF4\\\x19\xF4\xB7\x16,\x90\xEA,\xE26\x00I\xF9\xB5Z\x060\x83E\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94", :standard => "\x8Cm\x02.\x18\xFA\x87\x7F\x18a\xA8\xAC \x82u\xC7]\xE6rs/\xB3\xF5.>Aw\x96\xEF\xADLO\xDE[\x02\x14k\xCEn\x06\xF6\xBD^\"4';\x12-\xE5\b\x15\xA2#\xDEP8\xE3\xF1\xB3", }, "hmac-sha1" => { false => "Nnl\x00\xD2\xBA\x89j-(\xDD\xF4\\\x19\xF4\xB7\x16,\x90\xEA,\xE26\x00I\xF9\xB5Z\x060\x83E\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m\xBD\x05\f\x82g\xB0g\xFE", :standard => "\x8Cm\x02.\x18\xFA\x87\x7F\x18a\xA8\xAC \x82u\xC7]\xE6rs/\xB3\xF5.>Aw\x96\xEF\xADLO\xDE[\x02\x14k\xCEn\x06\xF6\xBD^\"4';\x12yC\xBA\xCC@\xC1\n\xE6$\x93\xF7\r\x16\xF6\xFD(i'\x8A\xE9", }, "hmac-sha1-96" => { false => "Nnl\x00\xD2\xBA\x89j-(\xDD\xF4\\\x19\xF4\xB7\x16,\x90\xEA,\xE26\x00I\xF9\xB5Z\x060\x83E\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m", :standard => "\x8Cm\x02.\x18\xFA\x87\x7F\x18a\xA8\xAC \x82u\xC7]\xE6rs/\xB3\xF5.>Aw\x96\xEF\xADLO\xDE[\x02\x14k\xCEn\x06\xF6\xBD^\"4';\x12yC\xBA\xCC@\xC1\n\xE6$\x93\xF7\r", }, "hmac-ripemd160" => { false => "Nnl\x00\xD2\xBA\x89j-(\xDD\xF4\\\x19\xF4\xB7\x16,\x90\xEA,\xE26\x00I\xF9\xB5Z\x060\x83EF\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\x8Cm\x02.\x18\xFA\x87\x7F\x18a\xA8\xAC \x82u\xC7]\xE6rs/\xB3\xF5.>Aw\x96\xEF\xADLO\xDE[\x02\x14k\xCEn\x06\xF6\xBD^\"4';\x12\xC44\x14\xE3q\xEE\x13\x1A\xB2\x81\e9\x8Bd\xB5>^{\xC0\xD0", }, "hmac-ripemd160@openssh.com" => { false => "Nnl\x00\xD2\xBA\x89j-(\xDD\xF4\\\x19\xF4\xB7\x16,\x90\xEA,\xE26\x00I\xF9\xB5Z\x060\x83EF\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\x8Cm\x02.\x18\xFA\x87\x7F\x18a\xA8\xAC \x82u\xC7]\xE6rs/\xB3\xF5.>Aw\x96\xEF\xADLO\xDE[\x02\x14k\xCEn\x06\xF6\xBD^\"4';\x12\xC44\x14\xE3q\xEE\x13\x1A\xB2\x81\e9\x8Bd\xB5>^{\xC0\xD0", }, "none" => { false => "Nnl\x00\xD2\xBA\x89j-(\xDD\xF4\\\x19\xF4\xB7\x16,\x90\xEA,\xE26\x00I\xF9\xB5Z\x060\x83E", :standard => "\x8Cm\x02.\x18\xFA\x87\x7F\x18a\xA8\xAC \x82u\xC7]\xE6rs/\xB3\xF5.>Aw\x96\xEF\xADLO\xDE[\x02\x14k\xCEn\x06\xF6\xBD^\"4';\x12", }, }, "camellia256-cbc" => { "hmac-md5" => { false => "\xE9\xAB&\x85*\x8B\x9C\xFF\xC9\xD2\x91\xE7\e\xE7P]\xD7\t\xA0\x99\a\xCD\x83K\x161\xA4\xBD\xCE\x82y|\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94\xFB\xF3\v\xB1", :standard => "\x9D\x87\e\x99\x80mG\ex-\xA1\xEFA\xBB\xBD+!\xF9s\xC1\xBA_\xA8\xE0\x82\xBEX\xA6\xE8\x85\x1E\xBA\xAFY\x0E\xAC\xCB\xE1\xBF\xD1\xFD\xC3X\x8A\xF1qFi-\xE5\b\x15\xA2#\xDEP8\xE3\xF1\xB3\\\xA1\xD6\xC9", }, "hmac-md5-96" => { false => "\xE9\xAB&\x85*\x8B\x9C\xFF\xC9\xD2\x91\xE7\e\xE7P]\xD7\t\xA0\x99\a\xCD\x83K\x161\xA4\xBD\xCE\x82y|\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94", :standard => "\x9D\x87\e\x99\x80mG\ex-\xA1\xEFA\xBB\xBD+!\xF9s\xC1\xBA_\xA8\xE0\x82\xBEX\xA6\xE8\x85\x1E\xBA\xAFY\x0E\xAC\xCB\xE1\xBF\xD1\xFD\xC3X\x8A\xF1qFi-\xE5\b\x15\xA2#\xDEP8\xE3\xF1\xB3", }, "hmac-sha1" => { false => "\xE9\xAB&\x85*\x8B\x9C\xFF\xC9\xD2\x91\xE7\e\xE7P]\xD7\t\xA0\x99\a\xCD\x83K\x161\xA4\xBD\xCE\x82y|\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m\xBD\x05\f\x82g\xB0g\xFE", :standard => "\x9D\x87\e\x99\x80mG\ex-\xA1\xEFA\xBB\xBD+!\xF9s\xC1\xBA_\xA8\xE0\x82\xBEX\xA6\xE8\x85\x1E\xBA\xAFY\x0E\xAC\xCB\xE1\xBF\xD1\xFD\xC3X\x8A\xF1qFiyC\xBA\xCC@\xC1\n\xE6$\x93\xF7\r\x16\xF6\xFD(i'\x8A\xE9", }, "hmac-sha1-96" => { false => "\xE9\xAB&\x85*\x8B\x9C\xFF\xC9\xD2\x91\xE7\e\xE7P]\xD7\t\xA0\x99\a\xCD\x83K\x161\xA4\xBD\xCE\x82y|\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m", :standard => "\x9D\x87\e\x99\x80mG\ex-\xA1\xEFA\xBB\xBD+!\xF9s\xC1\xBA_\xA8\xE0\x82\xBEX\xA6\xE8\x85\x1E\xBA\xAFY\x0E\xAC\xCB\xE1\xBF\xD1\xFD\xC3X\x8A\xF1qFiyC\xBA\xCC@\xC1\n\xE6$\x93\xF7\r", }, "hmac-ripemd160" => { false => "\xE9\xAB&\x85*\x8B\x9C\xFF\xC9\xD2\x91\xE7\e\xE7P]\xD7\t\xA0\x99\a\xCD\x83K\x161\xA4\xBD\xCE\x82y|F\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\x9D\x87\e\x99\x80mG\ex-\xA1\xEFA\xBB\xBD+!\xF9s\xC1\xBA_\xA8\xE0\x82\xBEX\xA6\xE8\x85\x1E\xBA\xAFY\x0E\xAC\xCB\xE1\xBF\xD1\xFD\xC3X\x8A\xF1qFi\xC44\x14\xE3q\xEE\x13\x1A\xB2\x81\e9\x8Bd\xB5>^{\xC0\xD0", }, "hmac-ripemd160@openssh.com" => { false => "\xE9\xAB&\x85*\x8B\x9C\xFF\xC9\xD2\x91\xE7\e\xE7P]\xD7\t\xA0\x99\a\xCD\x83K\x161\xA4\xBD\xCE\x82y|F\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\x9D\x87\e\x99\x80mG\ex-\xA1\xEFA\xBB\xBD+!\xF9s\xC1\xBA_\xA8\xE0\x82\xBEX\xA6\xE8\x85\x1E\xBA\xAFY\x0E\xAC\xCB\xE1\xBF\xD1\xFD\xC3X\x8A\xF1qFi\xC44\x14\xE3q\xEE\x13\x1A\xB2\x81\e9\x8Bd\xB5>^{\xC0\xD0", }, "none" => { false => "\xE9\xAB&\x85*\x8B\x9C\xFF\xC9\xD2\x91\xE7\e\xE7P]\xD7\t\xA0\x99\a\xCD\x83K\x161\xA4\xBD\xCE\x82y|", :standard => "\x9D\x87\e\x99\x80mG\ex-\xA1\xEFA\xBB\xBD+!\xF9s\xC1\xBA_\xA8\xE0\x82\xBEX\xA6\xE8\x85\x1E\xBA\xAFY\x0E\xAC\xCB\xE1\xBF\xD1\xFD\xC3X\x8A\xF1qFi", }, }, "3des-ctr" => { "hmac-md5" => { false => "\xED#\x86\xD5\xE1mP\v\f\xB9\xC1\xE6\xFD\xA0~,\xD3\x13\x12\x8Cp\xD4F\x92\xCB\xB6R>\xFA]\x9B\xB1\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94\xFB\xF3\v\xB1", :standard => "\xED#\x86\xED\xE0\x11\xCDim\xDD\xA8\xE2x\x8EB\x06\x9E73$\xBC\x9FA\xE0\xDB\xAE\x11Y\xAD\xED\xD43\x86N\x89\xFE\x14V\x91B\xEC=g\xF1\xB9[E\xB5\x8F\xCE\xCC\b\x82\x9D\x96\xDC", }, "hmac-md5-96" => { false => "\xED#\x86\xD5\xE1mP\v\f\xB9\xC1\xE6\xFD\xA0~,\xD3\x13\x12\x8Cp\xD4F\x92\xCB\xB6R>\xFA]\x9B\xB1\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94", :standard => "\xED#\x86\xED\xE0\x11\xCDim\xDD\xA8\xE2x\x8EB\x06\x9E73$\xBC\x9FA\xE0\xDB\xAE\x11Y\xAD\xED\xD43\x86N\x89\xFE\x14V\x91B\xEC=g\xF1\xB9[E\xB5\x8F\xCE\xCC\b", }, "hmac-sha1" => { false => "\xED#\x86\xD5\xE1mP\v\f\xB9\xC1\xE6\xFD\xA0~,\xD3\x13\x12\x8Cp\xD4F\x92\xCB\xB6R>\xFA]\x9B\xB1\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m\xBD\x05\f\x82g\xB0g\xFE", :standard => "\xED#\x86\xED\xE0\x11\xCDim\xDD\xA8\xE2x\x8EB\x06\x9E73$\xBC\x9FA\xE0\xDB\xAE\x11Y\xAD\xED\xD43\x86N\x89\xFE\x14V\x91B\x897U\xB6\xE44(\x9D\x1C\x13\xFF\xFE\xDD\xC1\xABrI\x8DW\xC9", }, "hmac-sha1-96" => { false => "\xED#\x86\xD5\xE1mP\v\f\xB9\xC1\xE6\xFD\xA0~,\xD3\x13\x12\x8Cp\xD4F\x92\xCB\xB6R>\xFA]\x9B\xB1\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m", :standard => "\xED#\x86\xED\xE0\x11\xCDim\xDD\xA8\xE2x\x8EB\x06\x9E73$\xBC\x9FA\xE0\xDB\xAE\x11Y\xAD\xED\xD43\x86N\x89\xFE\x14V\x91B\x897U\xB6\xE44(\x9D\x1C\x13\xFF\xFE", }, "hmac-ripemd160" => { false => "\xED#\x86\xD5\xE1mP\v\f\xB9\xC1\xE6\xFD\xA0~,\xD3\x13\x12\x8Cp\xD4F\x92\xCB\xB6R>\xFA]\x9B\xB1F\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\xED#\x86\xED\xE0\x11\xCDim\xDD\xA8\xE2x\x8EB\x06\x9E73$\xBC\x9FA\xE0\xDB\xAE\x11Y\xAD\xED\xD43\x86N\x89\xFE\x14V\x91B)U\xBD\x03U\xDB\x95\x91Y)\xCF\xAE\xA0\xA6\x000\xE9\x1A\xF3Y", }, "hmac-ripemd160@openssh.com" => { false => "\xED#\x86\xD5\xE1mP\v\f\xB9\xC1\xE6\xFD\xA0~,\xD3\x13\x12\x8Cp\xD4F\x92\xCB\xB6R>\xFA]\x9B\xB1F\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\xED#\x86\xED\xE0\x11\xCDim\xDD\xA8\xE2x\x8EB\x06\x9E73$\xBC\x9FA\xE0\xDB\xAE\x11Y\xAD\xED\xD43\x86N\x89\xFE\x14V\x91B)U\xBD\x03U\xDB\x95\x91Y)\xCF\xAE\xA0\xA6\x000\xE9\x1A\xF3Y", }, "none" => { false => "\xED#\x86\xD5\xE1mP\v\f\xB9\xC1\xE6\xFD\xA0~,\xD3\x13\x12\x8Cp\xD4F\x92\xCB\xB6R>\xFA]\x9B\xB1", :standard => "\xED#\x86\xED\xE0\x11\xCDim\xDD\xA8\xE2x\x8EB\x06\x9E73$\xBC\x9FA\xE0\xDB\xAE\x11Y\xAD\xED\xD43\x86N\x89\xFE\x14V\x91B", }, }, "blowfish-ctr" => { "hmac-md5" => { false => "\xF7gk6\xB8\xACK\x1D\xC4Ls\xB0{\x0F\xC7\xC4M\xC5>\xF6G8\xD4\xBCu\x152FoJ\xB0\xC0\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94\xFB\xF3\v\xB1", :standard => "\xF7gk\x0E\xB9\xD0\xD6\x7F\xA5(\x1A\xB4\xFE!\xFB\xEE\x00\xE1\x1F^\x8Bs\xD3\xCEe\rq!8\xFA\xFFB\r\xE9\xFC\xF6\xCA\xBC\x03\xA9\xEC=g\xF1\xB9[E\xB5\x8F\xCE\xCC\b\x82\x9D\x96\xDC", }, "hmac-md5-96" => { false => "\xF7gk6\xB8\xACK\x1D\xC4Ls\xB0{\x0F\xC7\xC4M\xC5>\xF6G8\xD4\xBCu\x152FoJ\xB0\xC0\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94", :standard => "\xF7gk\x0E\xB9\xD0\xD6\x7F\xA5(\x1A\xB4\xFE!\xFB\xEE\x00\xE1\x1F^\x8Bs\xD3\xCEe\rq!8\xFA\xFFB\r\xE9\xFC\xF6\xCA\xBC\x03\xA9\xEC=g\xF1\xB9[E\xB5\x8F\xCE\xCC\b", }, "hmac-sha1" => { false => "\xF7gk6\xB8\xACK\x1D\xC4Ls\xB0{\x0F\xC7\xC4M\xC5>\xF6G8\xD4\xBCu\x152FoJ\xB0\xC0\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m\xBD\x05\f\x82g\xB0g\xFE", :standard => "\xF7gk\x0E\xB9\xD0\xD6\x7F\xA5(\x1A\xB4\xFE!\xFB\xEE\x00\xE1\x1F^\x8Bs\xD3\xCEe\rq!8\xFA\xFFB\r\xE9\xFC\xF6\xCA\xBC\x03\xA9\x897U\xB6\xE44(\x9D\x1C\x13\xFF\xFE\xDD\xC1\xABrI\x8DW\xC9", }, "hmac-sha1-96" => { false => "\xF7gk6\xB8\xACK\x1D\xC4Ls\xB0{\x0F\xC7\xC4M\xC5>\xF6G8\xD4\xBCu\x152FoJ\xB0\xC0\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m", :standard => "\xF7gk\x0E\xB9\xD0\xD6\x7F\xA5(\x1A\xB4\xFE!\xFB\xEE\x00\xE1\x1F^\x8Bs\xD3\xCEe\rq!8\xFA\xFFB\r\xE9\xFC\xF6\xCA\xBC\x03\xA9\x897U\xB6\xE44(\x9D\x1C\x13\xFF\xFE", }, "hmac-ripemd160" => { false => "\xF7gk6\xB8\xACK\x1D\xC4Ls\xB0{\x0F\xC7\xC4M\xC5>\xF6G8\xD4\xBCu\x152FoJ\xB0\xC0F\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\xF7gk\x0E\xB9\xD0\xD6\x7F\xA5(\x1A\xB4\xFE!\xFB\xEE\x00\xE1\x1F^\x8Bs\xD3\xCEe\rq!8\xFA\xFFB\r\xE9\xFC\xF6\xCA\xBC\x03\xA9)U\xBD\x03U\xDB\x95\x91Y)\xCF\xAE\xA0\xA6\x000\xE9\x1A\xF3Y", }, "hmac-ripemd160@openssh.com" => { false => "\xF7gk6\xB8\xACK\x1D\xC4Ls\xB0{\x0F\xC7\xC4M\xC5>\xF6G8\xD4\xBCu\x152FoJ\xB0\xC0F\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\xF7gk\x0E\xB9\xD0\xD6\x7F\xA5(\x1A\xB4\xFE!\xFB\xEE\x00\xE1\x1F^\x8Bs\xD3\xCEe\rq!8\xFA\xFFB\r\xE9\xFC\xF6\xCA\xBC\x03\xA9)U\xBD\x03U\xDB\x95\x91Y)\xCF\xAE\xA0\xA6\x000\xE9\x1A\xF3Y", }, "none" => { false => "\xF7gk6\xB8\xACK\x1D\xC4Ls\xB0{\x0F\xC7\xC4M\xC5>\xF6G8\xD4\xBCu\x152FoJ\xB0\xC0", :standard => "\xF7gk\x0E\xB9\xD0\xD6\x7F\xA5(\x1A\xB4\xFE!\xFB\xEE\x00\xE1\x1F^\x8Bs\xD3\xCEe\rq!8\xFA\xFFB\r\xE9\xFC\xF6\xCA\xBC\x03\xA9", }, }, "aes128-ctr" => { "hmac-md5" => { false => "\xD6\x98\xC1n+6\xCA`s2\x06\xAA\x80\xFA\xF3\xF6\xCA\xF9\xC8[BB\xDC\x9F\xDC$\x88*\xA7\x00\x8E\xFD\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94\xFB\xF3\v\xB1", :standard => "\xD6\x98\xC1^2JW\x02\x12Vo\xAE\x05\xD4\xCF\xDC\x87\xDD\xE9\xF3\x8E\t\xDB\xED\xCC<\xCBM\xF0\xB0\xC1\x7F\xD7\x17\x931\xBC~\r\xF2\x87\xB89\x9B\x8B\xB3\x8E\x15-\xE5\b\x15\xA2#\xDEP8\xE3\xF1\xB3\\\xA1\xD6\xC9", }, "hmac-md5-96" => { false => "\xD6\x98\xC1n+6\xCA`s2\x06\xAA\x80\xFA\xF3\xF6\xCA\xF9\xC8[BB\xDC\x9F\xDC$\x88*\xA7\x00\x8E\xFD\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94", :standard => "\xD6\x98\xC1^2JW\x02\x12Vo\xAE\x05\xD4\xCF\xDC\x87\xDD\xE9\xF3\x8E\t\xDB\xED\xCC<\xCBM\xF0\xB0\xC1\x7F\xD7\x17\x931\xBC~\r\xF2\x87\xB89\x9B\x8B\xB3\x8E\x15-\xE5\b\x15\xA2#\xDEP8\xE3\xF1\xB3", }, "hmac-sha1" => { false => "\xD6\x98\xC1n+6\xCA`s2\x06\xAA\x80\xFA\xF3\xF6\xCA\xF9\xC8[BB\xDC\x9F\xDC$\x88*\xA7\x00\x8E\xFD\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m\xBD\x05\f\x82g\xB0g\xFE", :standard => "\xD6\x98\xC1^2JW\x02\x12Vo\xAE\x05\xD4\xCF\xDC\x87\xDD\xE9\xF3\x8E\t\xDB\xED\xCC<\xCBM\xF0\xB0\xC1\x7F\xD7\x17\x931\xBC~\r\xF2\x87\xB89\x9B\x8B\xB3\x8E\x15yC\xBA\xCC@\xC1\n\xE6$\x93\xF7\r\x16\xF6\xFD(i'\x8A\xE9", }, "hmac-sha1-96" => { false => "\xD6\x98\xC1n+6\xCA`s2\x06\xAA\x80\xFA\xF3\xF6\xCA\xF9\xC8[BB\xDC\x9F\xDC$\x88*\xA7\x00\x8E\xFD\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m", :standard => "\xD6\x98\xC1^2JW\x02\x12Vo\xAE\x05\xD4\xCF\xDC\x87\xDD\xE9\xF3\x8E\t\xDB\xED\xCC<\xCBM\xF0\xB0\xC1\x7F\xD7\x17\x931\xBC~\r\xF2\x87\xB89\x9B\x8B\xB3\x8E\x15yC\xBA\xCC@\xC1\n\xE6$\x93\xF7\r", }, "hmac-ripemd160" => { false => "\xD6\x98\xC1n+6\xCA`s2\x06\xAA\x80\xFA\xF3\xF6\xCA\xF9\xC8[BB\xDC\x9F\xDC$\x88*\xA7\x00\x8E\xFDF\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\xD6\x98\xC1^2JW\x02\x12Vo\xAE\x05\xD4\xCF\xDC\x87\xDD\xE9\xF3\x8E\t\xDB\xED\xCC<\xCBM\xF0\xB0\xC1\x7F\xD7\x17\x931\xBC~\r\xF2\x87\xB89\x9B\x8B\xB3\x8E\x15\xC44\x14\xE3q\xEE\x13\x1A\xB2\x81\e9\x8Bd\xB5>^{\xC0\xD0", }, "hmac-ripemd160@openssh.com" => { false => "\xD6\x98\xC1n+6\xCA`s2\x06\xAA\x80\xFA\xF3\xF6\xCA\xF9\xC8[BB\xDC\x9F\xDC$\x88*\xA7\x00\x8E\xFDF\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\xD6\x98\xC1^2JW\x02\x12Vo\xAE\x05\xD4\xCF\xDC\x87\xDD\xE9\xF3\x8E\t\xDB\xED\xCC<\xCBM\xF0\xB0\xC1\x7F\xD7\x17\x931\xBC~\r\xF2\x87\xB89\x9B\x8B\xB3\x8E\x15\xC44\x14\xE3q\xEE\x13\x1A\xB2\x81\e9\x8Bd\xB5>^{\xC0\xD0", }, "none" => { false => "\xD6\x98\xC1n+6\xCA`s2\x06\xAA\x80\xFA\xF3\xF6\xCA\xF9\xC8[BB\xDC\x9F\xDC$\x88*\xA7\x00\x8E\xFD", :standard => "\xD6\x98\xC1^2JW\x02\x12Vo\xAE\x05\xD4\xCF\xDC\x87\xDD\xE9\xF3\x8E\t\xDB\xED\xCC<\xCBM\xF0\xB0\xC1\x7F\xD7\x17\x931\xBC~\r\xF2\x87\xB89\x9B\x8B\xB3\x8E\x15", }, }, "aes192-ctr" => { "hmac-md5" => { false => "\xA8\x02\xB4-\xFBYo4F\"\xCF\xB8\x92\xF08\xAC\xE8\xECk\xECO\xE7\xF8\x01\xF8\xB0\x9E\x05\xFB\xA7\xA7\x91\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94\xFB\xF3\v\xB1", :standard => "\xA8\x02\xB4\x1D\xE2%\xF2V'F\xA6\xBC\x17\xDE\x04\x86\xA5\xC8JD\x83\xAC\xFFs\xE8\xA8\xDDb\xAC\x17\xE8\x13\x92V\x9E\x00!\x1F\xD4\x00\x92T\x15\xDE\xA4\xCA\xE9\xC1-\xE5\b\x15\xA2#\xDEP8\xE3\xF1\xB3\\\xA1\xD6\xC9", }, "hmac-md5-96" => { false => "\xA8\x02\xB4-\xFBYo4F\"\xCF\xB8\x92\xF08\xAC\xE8\xECk\xECO\xE7\xF8\x01\xF8\xB0\x9E\x05\xFB\xA7\xA7\x91\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94", :standard => "\xA8\x02\xB4\x1D\xE2%\xF2V'F\xA6\xBC\x17\xDE\x04\x86\xA5\xC8JD\x83\xAC\xFFs\xE8\xA8\xDDb\xAC\x17\xE8\x13\x92V\x9E\x00!\x1F\xD4\x00\x92T\x15\xDE\xA4\xCA\xE9\xC1-\xE5\b\x15\xA2#\xDEP8\xE3\xF1\xB3", }, "hmac-sha1" => { false => "\xA8\x02\xB4-\xFBYo4F\"\xCF\xB8\x92\xF08\xAC\xE8\xECk\xECO\xE7\xF8\x01\xF8\xB0\x9E\x05\xFB\xA7\xA7\x91\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m\xBD\x05\f\x82g\xB0g\xFE", :standard => "\xA8\x02\xB4\x1D\xE2%\xF2V'F\xA6\xBC\x17\xDE\x04\x86\xA5\xC8JD\x83\xAC\xFFs\xE8\xA8\xDDb\xAC\x17\xE8\x13\x92V\x9E\x00!\x1F\xD4\x00\x92T\x15\xDE\xA4\xCA\xE9\xC1yC\xBA\xCC@\xC1\n\xE6$\x93\xF7\r\x16\xF6\xFD(i'\x8A\xE9", }, "hmac-sha1-96" => { false => "\xA8\x02\xB4-\xFBYo4F\"\xCF\xB8\x92\xF08\xAC\xE8\xECk\xECO\xE7\xF8\x01\xF8\xB0\x9E\x05\xFB\xA7\xA7\x91\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m", :standard => "\xA8\x02\xB4\x1D\xE2%\xF2V'F\xA6\xBC\x17\xDE\x04\x86\xA5\xC8JD\x83\xAC\xFFs\xE8\xA8\xDDb\xAC\x17\xE8\x13\x92V\x9E\x00!\x1F\xD4\x00\x92T\x15\xDE\xA4\xCA\xE9\xC1yC\xBA\xCC@\xC1\n\xE6$\x93\xF7\r", }, "hmac-ripemd160" => { false => "\xA8\x02\xB4-\xFBYo4F\"\xCF\xB8\x92\xF08\xAC\xE8\xECk\xECO\xE7\xF8\x01\xF8\xB0\x9E\x05\xFB\xA7\xA7\x91F\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\xA8\x02\xB4\x1D\xE2%\xF2V'F\xA6\xBC\x17\xDE\x04\x86\xA5\xC8JD\x83\xAC\xFFs\xE8\xA8\xDDb\xAC\x17\xE8\x13\x92V\x9E\x00!\x1F\xD4\x00\x92T\x15\xDE\xA4\xCA\xE9\xC1\xC44\x14\xE3q\xEE\x13\x1A\xB2\x81\e9\x8Bd\xB5>^{\xC0\xD0", }, "hmac-ripemd160@openssh.com" => { false => "\xA8\x02\xB4-\xFBYo4F\"\xCF\xB8\x92\xF08\xAC\xE8\xECk\xECO\xE7\xF8\x01\xF8\xB0\x9E\x05\xFB\xA7\xA7\x91F\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\xA8\x02\xB4\x1D\xE2%\xF2V'F\xA6\xBC\x17\xDE\x04\x86\xA5\xC8JD\x83\xAC\xFFs\xE8\xA8\xDDb\xAC\x17\xE8\x13\x92V\x9E\x00!\x1F\xD4\x00\x92T\x15\xDE\xA4\xCA\xE9\xC1\xC44\x14\xE3q\xEE\x13\x1A\xB2\x81\e9\x8Bd\xB5>^{\xC0\xD0", }, "none" => { false => "\xA8\x02\xB4-\xFBYo4F\"\xCF\xB8\x92\xF08\xAC\xE8\xECk\xECO\xE7\xF8\x01\xF8\xB0\x9E\x05\xFB\xA7\xA7\x91", :standard => "\xA8\x02\xB4\x1D\xE2%\xF2V'F\xA6\xBC\x17\xDE\x04\x86\xA5\xC8JD\x83\xAC\xFFs\xE8\xA8\xDDb\xAC\x17\xE8\x13\x92V\x9E\x00!\x1F\xD4\x00\x92T\x15\xDE\xA4\xCA\xE9\xC1", }, }, "aes256-ctr" => { "hmac-md5" => { false => "M\x1DcA\r]\\\x95?&\xE3D[\xCC1\x9B\xE0\xAF\x96\xA8\x86Y\xBD\x16\xE5xR%u\xC9(\r\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94\xFB\xF3\v\xB1", :standard => "M\x1Dcq\x14!\xC1\xF7^B\x8A@\xDE\xE2\r\xB1\xAD\x8B\xB7\x00J\x12\xBAd\xF5`\x11B\"yg\x8F\x9F\xAB\xC8 d\xB4\xE7^w\xC4\x89\a\x17\x15\x82\n-\xE5\b\x15\xA2#\xDEP8\xE3\xF1\xB3\\\xA1\xD6\xC9", }, "hmac-md5-96" => { false => "M\x1DcA\r]\\\x95?&\xE3D[\xCC1\x9B\xE0\xAF\x96\xA8\x86Y\xBD\x16\xE5xR%u\xC9(\r\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94", :standard => "M\x1Dcq\x14!\xC1\xF7^B\x8A@\xDE\xE2\r\xB1\xAD\x8B\xB7\x00J\x12\xBAd\xF5`\x11B\"yg\x8F\x9F\xAB\xC8 d\xB4\xE7^w\xC4\x89\a\x17\x15\x82\n-\xE5\b\x15\xA2#\xDEP8\xE3\xF1\xB3", }, "hmac-sha1" => { false => "M\x1DcA\r]\\\x95?&\xE3D[\xCC1\x9B\xE0\xAF\x96\xA8\x86Y\xBD\x16\xE5xR%u\xC9(\r\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m\xBD\x05\f\x82g\xB0g\xFE", :standard => "M\x1Dcq\x14!\xC1\xF7^B\x8A@\xDE\xE2\r\xB1\xAD\x8B\xB7\x00J\x12\xBAd\xF5`\x11B\"yg\x8F\x9F\xAB\xC8 d\xB4\xE7^w\xC4\x89\a\x17\x15\x82\nyC\xBA\xCC@\xC1\n\xE6$\x93\xF7\r\x16\xF6\xFD(i'\x8A\xE9", }, "hmac-sha1-96" => { false => "M\x1DcA\r]\\\x95?&\xE3D[\xCC1\x9B\xE0\xAF\x96\xA8\x86Y\xBD\x16\xE5xR%u\xC9(\r\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m", :standard => "M\x1Dcq\x14!\xC1\xF7^B\x8A@\xDE\xE2\r\xB1\xAD\x8B\xB7\x00J\x12\xBAd\xF5`\x11B\"yg\x8F\x9F\xAB\xC8 d\xB4\xE7^w\xC4\x89\a\x17\x15\x82\nyC\xBA\xCC@\xC1\n\xE6$\x93\xF7\r", }, "hmac-ripemd160" => { false => "M\x1DcA\r]\\\x95?&\xE3D[\xCC1\x9B\xE0\xAF\x96\xA8\x86Y\xBD\x16\xE5xR%u\xC9(\rF\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "M\x1Dcq\x14!\xC1\xF7^B\x8A@\xDE\xE2\r\xB1\xAD\x8B\xB7\x00J\x12\xBAd\xF5`\x11B\"yg\x8F\x9F\xAB\xC8 d\xB4\xE7^w\xC4\x89\a\x17\x15\x82\n\xC44\x14\xE3q\xEE\x13\x1A\xB2\x81\e9\x8Bd\xB5>^{\xC0\xD0", }, "hmac-ripemd160@openssh.com" => { false => "M\x1DcA\r]\\\x95?&\xE3D[\xCC1\x9B\xE0\xAF\x96\xA8\x86Y\xBD\x16\xE5xR%u\xC9(\rF\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "M\x1Dcq\x14!\xC1\xF7^B\x8A@\xDE\xE2\r\xB1\xAD\x8B\xB7\x00J\x12\xBAd\xF5`\x11B\"yg\x8F\x9F\xAB\xC8 d\xB4\xE7^w\xC4\x89\a\x17\x15\x82\n\xC44\x14\xE3q\xEE\x13\x1A\xB2\x81\e9\x8Bd\xB5>^{\xC0\xD0", }, "none" => { false => "M\x1DcA\r]\\\x95?&\xE3D[\xCC1\x9B\xE0\xAF\x96\xA8\x86Y\xBD\x16\xE5xR%u\xC9(\r", :standard => "M\x1Dcq\x14!\xC1\xF7^B\x8A@\xDE\xE2\r\xB1\xAD\x8B\xB7\x00J\x12\xBAd\xF5`\x11B\"yg\x8F\x9F\xAB\xC8 d\xB4\xE7^w\xC4\x89\a\x17\x15\x82\n", }, }, "cast128-ctr" => { "hmac-md5" => { false => "\x10\xA0cJ6W\xC9\xC7\x02\xF8\xCD\xE31\xF9\xE7n\x0Fj\x7F\x99\x8A\f\x84\x80\x80\xE8p\x9C\x14\x83\x1C\xC7\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94\xFB\xF3\v\xB1", :standard => "\x10\xA0cr7+T\xA5c\x9C\xA4\xE7\xB4\xD7\xDBDBN^1FG\x83\xF2\x90\xF03\xFBC3SE\xF7x;q\x89\xA80\xEA\xEC=g\xF1\xB9[E\xB5\x8F\xCE\xCC\b\x82\x9D\x96\xDC", }, "hmac-md5-96" => { false => "\x10\xA0cJ6W\xC9\xC7\x02\xF8\xCD\xE31\xF9\xE7n\x0Fj\x7F\x99\x8A\f\x84\x80\x80\xE8p\x9C\x14\x83\x1C\xC7\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94", :standard => "\x10\xA0cr7+T\xA5c\x9C\xA4\xE7\xB4\xD7\xDBDBN^1FG\x83\xF2\x90\xF03\xFBC3SE\xF7x;q\x89\xA80\xEA\xEC=g\xF1\xB9[E\xB5\x8F\xCE\xCC\b", }, "hmac-sha1" => { false => "\x10\xA0cJ6W\xC9\xC7\x02\xF8\xCD\xE31\xF9\xE7n\x0Fj\x7F\x99\x8A\f\x84\x80\x80\xE8p\x9C\x14\x83\x1C\xC7\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m\xBD\x05\f\x82g\xB0g\xFE", :standard => "\x10\xA0cr7+T\xA5c\x9C\xA4\xE7\xB4\xD7\xDBDBN^1FG\x83\xF2\x90\xF03\xFBC3SE\xF7x;q\x89\xA80\xEA\x897U\xB6\xE44(\x9D\x1C\x13\xFF\xFE\xDD\xC1\xABrI\x8DW\xC9", }, "hmac-sha1-96" => { false => "\x10\xA0cJ6W\xC9\xC7\x02\xF8\xCD\xE31\xF9\xE7n\x0Fj\x7F\x99\x8A\f\x84\x80\x80\xE8p\x9C\x14\x83\x1C\xC7\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m", :standard => "\x10\xA0cr7+T\xA5c\x9C\xA4\xE7\xB4\xD7\xDBDBN^1FG\x83\xF2\x90\xF03\xFBC3SE\xF7x;q\x89\xA80\xEA\x897U\xB6\xE44(\x9D\x1C\x13\xFF\xFE", }, "hmac-ripemd160" => { false => "\x10\xA0cJ6W\xC9\xC7\x02\xF8\xCD\xE31\xF9\xE7n\x0Fj\x7F\x99\x8A\f\x84\x80\x80\xE8p\x9C\x14\x83\x1C\xC7F\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\x10\xA0cr7+T\xA5c\x9C\xA4\xE7\xB4\xD7\xDBDBN^1FG\x83\xF2\x90\xF03\xFBC3SE\xF7x;q\x89\xA80\xEA)U\xBD\x03U\xDB\x95\x91Y)\xCF\xAE\xA0\xA6\x000\xE9\x1A\xF3Y", }, "hmac-ripemd160@openssh.com" => { false => "\x10\xA0cJ6W\xC9\xC7\x02\xF8\xCD\xE31\xF9\xE7n\x0Fj\x7F\x99\x8A\f\x84\x80\x80\xE8p\x9C\x14\x83\x1C\xC7F\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\x10\xA0cr7+T\xA5c\x9C\xA4\xE7\xB4\xD7\xDBDBN^1FG\x83\xF2\x90\xF03\xFBC3SE\xF7x;q\x89\xA80\xEA)U\xBD\x03U\xDB\x95\x91Y)\xCF\xAE\xA0\xA6\x000\xE9\x1A\xF3Y", }, "none" => { false => "\x10\xA0cJ6W\xC9\xC7\x02\xF8\xCD\xE31\xF9\xE7n\x0Fj\x7F\x99\x8A\f\x84\x80\x80\xE8p\x9C\x14\x83\x1C\xC7", :standard => "\x10\xA0cr7+T\xA5c\x9C\xA4\xE7\xB4\xD7\xDBDBN^1FG\x83\xF2\x90\xF03\xFBC3SE\xF7x;q\x89\xA80\xEA", }, }, "camellia128-ctr@openssh.org" => { "hmac-md5" => { false => "\xE4>\xD9'`\xA5W\x9A\xB7\x19\xA9\x98\xB0\x87f2}\x0F\xBE\xBDS\xA8\xA5\x17\x10\x80\x10 "\xE4>\xD9\x17y\xD9\xCA\xF8\xD6}\xC0\x9C5\xA9Z\x180+\x9F\x15\x9F\xE3\xA2e\x00\x98S[\x00\xC71\x9D\xAEx\x19\x17m\x9E\xD6\xC5\x90\xE2d\xFA#\xEB\x94\xA9-\xE5\b\x15\xA2#\xDEP8\xE3\xF1\xB3\\\xA1\xD6\xC9", }, "hmac-md5-96" => { false => "\xE4>\xD9'`\xA5W\x9A\xB7\x19\xA9\x98\xB0\x87f2}\x0F\xBE\xBDS\xA8\xA5\x17\x10\x80\x10 "\xE4>\xD9\x17y\xD9\xCA\xF8\xD6}\xC0\x9C5\xA9Z\x180+\x9F\x15\x9F\xE3\xA2e\x00\x98S[\x00\xC71\x9D\xAEx\x19\x17m\x9E\xD6\xC5\x90\xE2d\xFA#\xEB\x94\xA9-\xE5\b\x15\xA2#\xDEP8\xE3\xF1\xB3", }, "hmac-sha1" => { false => "\xE4>\xD9'`\xA5W\x9A\xB7\x19\xA9\x98\xB0\x87f2}\x0F\xBE\xBDS\xA8\xA5\x17\x10\x80\x10 "\xE4>\xD9\x17y\xD9\xCA\xF8\xD6}\xC0\x9C5\xA9Z\x180+\x9F\x15\x9F\xE3\xA2e\x00\x98S[\x00\xC71\x9D\xAEx\x19\x17m\x9E\xD6\xC5\x90\xE2d\xFA#\xEB\x94\xA9yC\xBA\xCC@\xC1\n\xE6$\x93\xF7\r\x16\xF6\xFD(i'\x8A\xE9", }, "hmac-sha1-96" => { false => "\xE4>\xD9'`\xA5W\x9A\xB7\x19\xA9\x98\xB0\x87f2}\x0F\xBE\xBDS\xA8\xA5\x17\x10\x80\x10 "\xE4>\xD9\x17y\xD9\xCA\xF8\xD6}\xC0\x9C5\xA9Z\x180+\x9F\x15\x9F\xE3\xA2e\x00\x98S[\x00\xC71\x9D\xAEx\x19\x17m\x9E\xD6\xC5\x90\xE2d\xFA#\xEB\x94\xA9yC\xBA\xCC@\xC1\n\xE6$\x93\xF7\r", }, "hmac-ripemd160" => { false => "\xE4>\xD9'`\xA5W\x9A\xB7\x19\xA9\x98\xB0\x87f2}\x0F\xBE\xBDS\xA8\xA5\x17\x10\x80\x10 "\xE4>\xD9\x17y\xD9\xCA\xF8\xD6}\xC0\x9C5\xA9Z\x180+\x9F\x15\x9F\xE3\xA2e\x00\x98S[\x00\xC71\x9D\xAEx\x19\x17m\x9E\xD6\xC5\x90\xE2d\xFA#\xEB\x94\xA9\xC44\x14\xE3q\xEE\x13\x1A\xB2\x81\e9\x8Bd\xB5>^{\xC0\xD0", }, "hmac-ripemd160@openssh.com" => { false => "\xE4>\xD9'`\xA5W\x9A\xB7\x19\xA9\x98\xB0\x87f2}\x0F\xBE\xBDS\xA8\xA5\x17\x10\x80\x10 "\xE4>\xD9\x17y\xD9\xCA\xF8\xD6}\xC0\x9C5\xA9Z\x180+\x9F\x15\x9F\xE3\xA2e\x00\x98S[\x00\xC71\x9D\xAEx\x19\x17m\x9E\xD6\xC5\x90\xE2d\xFA#\xEB\x94\xA9\xC44\x14\xE3q\xEE\x13\x1A\xB2\x81\e9\x8Bd\xB5>^{\xC0\xD0", }, "none" => { false => "\xE4>\xD9'`\xA5W\x9A\xB7\x19\xA9\x98\xB0\x87f2}\x0F\xBE\xBDS\xA8\xA5\x17\x10\x80\x10 "\xE4>\xD9\x17y\xD9\xCA\xF8\xD6}\xC0\x9C5\xA9Z\x180+\x9F\x15\x9F\xE3\xA2e\x00\x98S[\x00\xC71\x9D\xAEx\x19\x17m\x9E\xD6\xC5\x90\xE2d\xFA#\xEB\x94\xA9", }, }, "camellia192-ctr@openssh.org" => { "hmac-md5" => { false => "\xEE8:\xB5\x0E\xED\xF4?yh\x8A\xB2{\xF5\x8DH\x95\xA4\xFA\xDF\x01\xAC\xC4\xD5Xb\xBB\xC1\x8B\xD7\xBC\xBE\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94\xFB\xF3\v\xB1", :standard => "\xEE8:\x85\x17\x91i]\x18\f\xE3\xB6\xFE\xDB\xB1b\xD8\x80\xDBw\xCD\xE7\xC3\xA7Hz\xF8\xA6\xDCg\xF3 { false => "\xEE8:\xB5\x0E\xED\xF4?yh\x8A\xB2{\xF5\x8DH\x95\xA4\xFA\xDF\x01\xAC\xC4\xD5Xb\xBB\xC1\x8B\xD7\xBC\xBE\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94", :standard => "\xEE8:\x85\x17\x91i]\x18\f\xE3\xB6\xFE\xDB\xB1b\xD8\x80\xDBw\xCD\xE7\xC3\xA7Hz\xF8\xA6\xDCg\xF3 { false => "\xEE8:\xB5\x0E\xED\xF4?yh\x8A\xB2{\xF5\x8DH\x95\xA4\xFA\xDF\x01\xAC\xC4\xD5Xb\xBB\xC1\x8B\xD7\xBC\xBE\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m\xBD\x05\f\x82g\xB0g\xFE", :standard => "\xEE8:\x85\x17\x91i]\x18\f\xE3\xB6\xFE\xDB\xB1b\xD8\x80\xDBw\xCD\xE7\xC3\xA7Hz\xF8\xA6\xDCg\xF3 { false => "\xEE8:\xB5\x0E\xED\xF4?yh\x8A\xB2{\xF5\x8DH\x95\xA4\xFA\xDF\x01\xAC\xC4\xD5Xb\xBB\xC1\x8B\xD7\xBC\xBE\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m", :standard => "\xEE8:\x85\x17\x91i]\x18\f\xE3\xB6\xFE\xDB\xB1b\xD8\x80\xDBw\xCD\xE7\xC3\xA7Hz\xF8\xA6\xDCg\xF3 { false => "\xEE8:\xB5\x0E\xED\xF4?yh\x8A\xB2{\xF5\x8DH\x95\xA4\xFA\xDF\x01\xAC\xC4\xD5Xb\xBB\xC1\x8B\xD7\xBC\xBEF\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\xEE8:\x85\x17\x91i]\x18\f\xE3\xB6\xFE\xDB\xB1b\xD8\x80\xDBw\xCD\xE7\xC3\xA7Hz\xF8\xA6\xDCg\xF3^{\xC0\xD0", }, "hmac-ripemd160@openssh.com" => { false => "\xEE8:\xB5\x0E\xED\xF4?yh\x8A\xB2{\xF5\x8DH\x95\xA4\xFA\xDF\x01\xAC\xC4\xD5Xb\xBB\xC1\x8B\xD7\xBC\xBEF\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\xEE8:\x85\x17\x91i]\x18\f\xE3\xB6\xFE\xDB\xB1b\xD8\x80\xDBw\xCD\xE7\xC3\xA7Hz\xF8\xA6\xDCg\xF3^{\xC0\xD0", }, "none" => { false => "\xEE8:\xB5\x0E\xED\xF4?yh\x8A\xB2{\xF5\x8DH\x95\xA4\xFA\xDF\x01\xAC\xC4\xD5Xb\xBB\xC1\x8B\xD7\xBC\xBE", :standard => "\xEE8:\x85\x17\x91i]\x18\f\xE3\xB6\xFE\xDB\xB1b\xD8\x80\xDBw\xCD\xE7\xC3\xA7Hz\xF8\xA6\xDCg\xF3 { "hmac-md5" => { false => "\xE3-1\x8E\xA1\xB7\x95\x9E`\x1E\xFB:[\xFD\x15\x8Ee\xD6|\xB6q\xF98\xFF\t\xB3\xD4F\x03\xB3\xFA\xEC\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94\xFB\xF3\v\xB1", :standard => "\xE3-1\xBE\xB8\xCB\b\xFC\x01z\x92>\xDE\xD3)\xA4(\xF2]\x1E\xBD\xB2?\x8D\x19\xAB\x97!T\x03\xB5n\xC0)\xBE.]\x92\xF5\x05~\t\x04\x99\xFB\xDC\xD6\x93-\xE5\b\x15\xA2#\xDEP8\xE3\xF1\xB3\\\xA1\xD6\xC9", }, "hmac-md5-96" => { false => "\xE3-1\x8E\xA1\xB7\x95\x9E`\x1E\xFB:[\xFD\x15\x8Ee\xD6|\xB6q\xF98\xFF\t\xB3\xD4F\x03\xB3\xFA\xEC\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94", :standard => "\xE3-1\xBE\xB8\xCB\b\xFC\x01z\x92>\xDE\xD3)\xA4(\xF2]\x1E\xBD\xB2?\x8D\x19\xAB\x97!T\x03\xB5n\xC0)\xBE.]\x92\xF5\x05~\t\x04\x99\xFB\xDC\xD6\x93-\xE5\b\x15\xA2#\xDEP8\xE3\xF1\xB3", }, "hmac-sha1" => { false => "\xE3-1\x8E\xA1\xB7\x95\x9E`\x1E\xFB:[\xFD\x15\x8Ee\xD6|\xB6q\xF98\xFF\t\xB3\xD4F\x03\xB3\xFA\xEC\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m\xBD\x05\f\x82g\xB0g\xFE", :standard => "\xE3-1\xBE\xB8\xCB\b\xFC\x01z\x92>\xDE\xD3)\xA4(\xF2]\x1E\xBD\xB2?\x8D\x19\xAB\x97!T\x03\xB5n\xC0)\xBE.]\x92\xF5\x05~\t\x04\x99\xFB\xDC\xD6\x93yC\xBA\xCC@\xC1\n\xE6$\x93\xF7\r\x16\xF6\xFD(i'\x8A\xE9", }, "hmac-sha1-96" => { false => "\xE3-1\x8E\xA1\xB7\x95\x9E`\x1E\xFB:[\xFD\x15\x8Ee\xD6|\xB6q\xF98\xFF\t\xB3\xD4F\x03\xB3\xFA\xEC\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m", :standard => "\xE3-1\xBE\xB8\xCB\b\xFC\x01z\x92>\xDE\xD3)\xA4(\xF2]\x1E\xBD\xB2?\x8D\x19\xAB\x97!T\x03\xB5n\xC0)\xBE.]\x92\xF5\x05~\t\x04\x99\xFB\xDC\xD6\x93yC\xBA\xCC@\xC1\n\xE6$\x93\xF7\r", }, "hmac-ripemd160" => { false => "\xE3-1\x8E\xA1\xB7\x95\x9E`\x1E\xFB:[\xFD\x15\x8Ee\xD6|\xB6q\xF98\xFF\t\xB3\xD4F\x03\xB3\xFA\xECF\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\xE3-1\xBE\xB8\xCB\b\xFC\x01z\x92>\xDE\xD3)\xA4(\xF2]\x1E\xBD\xB2?\x8D\x19\xAB\x97!T\x03\xB5n\xC0)\xBE.]\x92\xF5\x05~\t\x04\x99\xFB\xDC\xD6\x93\xC44\x14\xE3q\xEE\x13\x1A\xB2\x81\e9\x8Bd\xB5>^{\xC0\xD0", }, "hmac-ripemd160@openssh.com" => { false => "\xE3-1\x8E\xA1\xB7\x95\x9E`\x1E\xFB:[\xFD\x15\x8Ee\xD6|\xB6q\xF98\xFF\t\xB3\xD4F\x03\xB3\xFA\xECF\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\xE3-1\xBE\xB8\xCB\b\xFC\x01z\x92>\xDE\xD3)\xA4(\xF2]\x1E\xBD\xB2?\x8D\x19\xAB\x97!T\x03\xB5n\xC0)\xBE.]\x92\xF5\x05~\t\x04\x99\xFB\xDC\xD6\x93\xC44\x14\xE3q\xEE\x13\x1A\xB2\x81\e9\x8Bd\xB5>^{\xC0\xD0", }, "none" => { false => "\xE3-1\x8E\xA1\xB7\x95\x9E`\x1E\xFB:[\xFD\x15\x8Ee\xD6|\xB6q\xF98\xFF\t\xB3\xD4F\x03\xB3\xFA\xEC", :standard => "\xE3-1\xBE\xB8\xCB\b\xFC\x01z\x92>\xDE\xD3)\xA4(\xF2]\x1E\xBD\xB2?\x8D\x19\xAB\x97!T\x03\xB5n\xC0)\xBE.]\x92\xF5\x05~\t\x04\x99\xFB\xDC\xD6\x93", }, }, "camellia128-ctr" => { "hmac-md5" => { false => "\xE4>\xD9'`\xA5W\x9A\xB7\x19\xA9\x98\xB0\x87f2}\x0F\xBE\xBDS\xA8\xA5\x17\x10\x80\x10 "\xE4>\xD9\x17y\xD9\xCA\xF8\xD6}\xC0\x9C5\xA9Z\x180+\x9F\x15\x9F\xE3\xA2e\x00\x98S[\x00\xC71\x9D\xAEx\x19\x17m\x9E\xD6\xC5\x90\xE2d\xFA#\xEB\x94\xA9-\xE5\b\x15\xA2#\xDEP8\xE3\xF1\xB3\\\xA1\xD6\xC9", }, "hmac-md5-96" => { false => "\xE4>\xD9'`\xA5W\x9A\xB7\x19\xA9\x98\xB0\x87f2}\x0F\xBE\xBDS\xA8\xA5\x17\x10\x80\x10 "\xE4>\xD9\x17y\xD9\xCA\xF8\xD6}\xC0\x9C5\xA9Z\x180+\x9F\x15\x9F\xE3\xA2e\x00\x98S[\x00\xC71\x9D\xAEx\x19\x17m\x9E\xD6\xC5\x90\xE2d\xFA#\xEB\x94\xA9-\xE5\b\x15\xA2#\xDEP8\xE3\xF1\xB3", }, "hmac-sha1" => { false => "\xE4>\xD9'`\xA5W\x9A\xB7\x19\xA9\x98\xB0\x87f2}\x0F\xBE\xBDS\xA8\xA5\x17\x10\x80\x10 "\xE4>\xD9\x17y\xD9\xCA\xF8\xD6}\xC0\x9C5\xA9Z\x180+\x9F\x15\x9F\xE3\xA2e\x00\x98S[\x00\xC71\x9D\xAEx\x19\x17m\x9E\xD6\xC5\x90\xE2d\xFA#\xEB\x94\xA9yC\xBA\xCC@\xC1\n\xE6$\x93\xF7\r\x16\xF6\xFD(i'\x8A\xE9", }, "hmac-sha1-96" => { false => "\xE4>\xD9'`\xA5W\x9A\xB7\x19\xA9\x98\xB0\x87f2}\x0F\xBE\xBDS\xA8\xA5\x17\x10\x80\x10 "\xE4>\xD9\x17y\xD9\xCA\xF8\xD6}\xC0\x9C5\xA9Z\x180+\x9F\x15\x9F\xE3\xA2e\x00\x98S[\x00\xC71\x9D\xAEx\x19\x17m\x9E\xD6\xC5\x90\xE2d\xFA#\xEB\x94\xA9yC\xBA\xCC@\xC1\n\xE6$\x93\xF7\r", }, "hmac-ripemd160" => { false => "\xE4>\xD9'`\xA5W\x9A\xB7\x19\xA9\x98\xB0\x87f2}\x0F\xBE\xBDS\xA8\xA5\x17\x10\x80\x10 "\xE4>\xD9\x17y\xD9\xCA\xF8\xD6}\xC0\x9C5\xA9Z\x180+\x9F\x15\x9F\xE3\xA2e\x00\x98S[\x00\xC71\x9D\xAEx\x19\x17m\x9E\xD6\xC5\x90\xE2d\xFA#\xEB\x94\xA9\xC44\x14\xE3q\xEE\x13\x1A\xB2\x81\e9\x8Bd\xB5>^{\xC0\xD0", }, "hmac-ripemd160@openssh.com" => { false => "\xE4>\xD9'`\xA5W\x9A\xB7\x19\xA9\x98\xB0\x87f2}\x0F\xBE\xBDS\xA8\xA5\x17\x10\x80\x10 "\xE4>\xD9\x17y\xD9\xCA\xF8\xD6}\xC0\x9C5\xA9Z\x180+\x9F\x15\x9F\xE3\xA2e\x00\x98S[\x00\xC71\x9D\xAEx\x19\x17m\x9E\xD6\xC5\x90\xE2d\xFA#\xEB\x94\xA9\xC44\x14\xE3q\xEE\x13\x1A\xB2\x81\e9\x8Bd\xB5>^{\xC0\xD0", }, "none" => { false => "\xE4>\xD9'`\xA5W\x9A\xB7\x19\xA9\x98\xB0\x87f2}\x0F\xBE\xBDS\xA8\xA5\x17\x10\x80\x10 "\xE4>\xD9\x17y\xD9\xCA\xF8\xD6}\xC0\x9C5\xA9Z\x180+\x9F\x15\x9F\xE3\xA2e\x00\x98S[\x00\xC71\x9D\xAEx\x19\x17m\x9E\xD6\xC5\x90\xE2d\xFA#\xEB\x94\xA9", }, }, "camellia192-ctr" => { "hmac-md5" => { false => "\xEE8:\xB5\x0E\xED\xF4?yh\x8A\xB2{\xF5\x8DH\x95\xA4\xFA\xDF\x01\xAC\xC4\xD5Xb\xBB\xC1\x8B\xD7\xBC\xBE\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94\xFB\xF3\v\xB1", :standard => "\xEE8:\x85\x17\x91i]\x18\f\xE3\xB6\xFE\xDB\xB1b\xD8\x80\xDBw\xCD\xE7\xC3\xA7Hz\xF8\xA6\xDCg\xF3 { false => "\xEE8:\xB5\x0E\xED\xF4?yh\x8A\xB2{\xF5\x8DH\x95\xA4\xFA\xDF\x01\xAC\xC4\xD5Xb\xBB\xC1\x8B\xD7\xBC\xBE\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94", :standard => "\xEE8:\x85\x17\x91i]\x18\f\xE3\xB6\xFE\xDB\xB1b\xD8\x80\xDBw\xCD\xE7\xC3\xA7Hz\xF8\xA6\xDCg\xF3 { false => "\xEE8:\xB5\x0E\xED\xF4?yh\x8A\xB2{\xF5\x8DH\x95\xA4\xFA\xDF\x01\xAC\xC4\xD5Xb\xBB\xC1\x8B\xD7\xBC\xBE\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m\xBD\x05\f\x82g\xB0g\xFE", :standard => "\xEE8:\x85\x17\x91i]\x18\f\xE3\xB6\xFE\xDB\xB1b\xD8\x80\xDBw\xCD\xE7\xC3\xA7Hz\xF8\xA6\xDCg\xF3 { false => "\xEE8:\xB5\x0E\xED\xF4?yh\x8A\xB2{\xF5\x8DH\x95\xA4\xFA\xDF\x01\xAC\xC4\xD5Xb\xBB\xC1\x8B\xD7\xBC\xBE\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m", :standard => "\xEE8:\x85\x17\x91i]\x18\f\xE3\xB6\xFE\xDB\xB1b\xD8\x80\xDBw\xCD\xE7\xC3\xA7Hz\xF8\xA6\xDCg\xF3 { false => "\xEE8:\xB5\x0E\xED\xF4?yh\x8A\xB2{\xF5\x8DH\x95\xA4\xFA\xDF\x01\xAC\xC4\xD5Xb\xBB\xC1\x8B\xD7\xBC\xBEF\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\xEE8:\x85\x17\x91i]\x18\f\xE3\xB6\xFE\xDB\xB1b\xD8\x80\xDBw\xCD\xE7\xC3\xA7Hz\xF8\xA6\xDCg\xF3^{\xC0\xD0", }, "hmac-ripemd160@openssh.com" => { false => "\xEE8:\xB5\x0E\xED\xF4?yh\x8A\xB2{\xF5\x8DH\x95\xA4\xFA\xDF\x01\xAC\xC4\xD5Xb\xBB\xC1\x8B\xD7\xBC\xBEF\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\xEE8:\x85\x17\x91i]\x18\f\xE3\xB6\xFE\xDB\xB1b\xD8\x80\xDBw\xCD\xE7\xC3\xA7Hz\xF8\xA6\xDCg\xF3^{\xC0\xD0", }, "none" => { false => "\xEE8:\xB5\x0E\xED\xF4?yh\x8A\xB2{\xF5\x8DH\x95\xA4\xFA\xDF\x01\xAC\xC4\xD5Xb\xBB\xC1\x8B\xD7\xBC\xBE", :standard => "\xEE8:\x85\x17\x91i]\x18\f\xE3\xB6\xFE\xDB\xB1b\xD8\x80\xDBw\xCD\xE7\xC3\xA7Hz\xF8\xA6\xDCg\xF3 { "hmac-md5" => { false => "\xE3-1\x8E\xA1\xB7\x95\x9E`\x1E\xFB:[\xFD\x15\x8Ee\xD6|\xB6q\xF98\xFF\t\xB3\xD4F\x03\xB3\xFA\xEC\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94\xFB\xF3\v\xB1", :standard => "\xE3-1\xBE\xB8\xCB\b\xFC\x01z\x92>\xDE\xD3)\xA4(\xF2]\x1E\xBD\xB2?\x8D\x19\xAB\x97!T\x03\xB5n\xC0)\xBE.]\x92\xF5\x05~\t\x04\x99\xFB\xDC\xD6\x93-\xE5\b\x15\xA2#\xDEP8\xE3\xF1\xB3\\\xA1\xD6\xC9", }, "hmac-md5-96" => { false => "\xE3-1\x8E\xA1\xB7\x95\x9E`\x1E\xFB:[\xFD\x15\x8Ee\xD6|\xB6q\xF98\xFF\t\xB3\xD4F\x03\xB3\xFA\xEC\x00\x1Aw\xCA\t\xC6\xFC\xB9\xE5p\x8D\x94", :standard => "\xE3-1\xBE\xB8\xCB\b\xFC\x01z\x92>\xDE\xD3)\xA4(\xF2]\x1E\xBD\xB2?\x8D\x19\xAB\x97!T\x03\xB5n\xC0)\xBE.]\x92\xF5\x05~\t\x04\x99\xFB\xDC\xD6\x93-\xE5\b\x15\xA2#\xDEP8\xE3\xF1\xB3", }, "hmac-sha1" => { false => "\xE3-1\x8E\xA1\xB7\x95\x9E`\x1E\xFB:[\xFD\x15\x8Ee\xD6|\xB6q\xF98\xFF\t\xB3\xD4F\x03\xB3\xFA\xEC\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m\xBD\x05\f\x82g\xB0g\xFE", :standard => "\xE3-1\xBE\xB8\xCB\b\xFC\x01z\x92>\xDE\xD3)\xA4(\xF2]\x1E\xBD\xB2?\x8D\x19\xAB\x97!T\x03\xB5n\xC0)\xBE.]\x92\xF5\x05~\t\x04\x99\xFB\xDC\xD6\x93yC\xBA\xCC@\xC1\n\xE6$\x93\xF7\r\x16\xF6\xFD(i'\x8A\xE9", }, "hmac-sha1-96" => { false => "\xE3-1\x8E\xA1\xB7\x95\x9E`\x1E\xFB:[\xFD\x15\x8Ee\xD6|\xB6q\xF98\xFF\t\xB3\xD4F\x03\xB3\xFA\xEC\x04\a\x80\n\x04\x82z\xB8\x9E\xB1\xD8m", :standard => "\xE3-1\xBE\xB8\xCB\b\xFC\x01z\x92>\xDE\xD3)\xA4(\xF2]\x1E\xBD\xB2?\x8D\x19\xAB\x97!T\x03\xB5n\xC0)\xBE.]\x92\xF5\x05~\t\x04\x99\xFB\xDC\xD6\x93yC\xBA\xCC@\xC1\n\xE6$\x93\xF7\r", }, "hmac-ripemd160" => { false => "\xE3-1\x8E\xA1\xB7\x95\x9E`\x1E\xFB:[\xFD\x15\x8Ee\xD6|\xB6q\xF98\xFF\t\xB3\xD4F\x03\xB3\xFA\xECF\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\xE3-1\xBE\xB8\xCB\b\xFC\x01z\x92>\xDE\xD3)\xA4(\xF2]\x1E\xBD\xB2?\x8D\x19\xAB\x97!T\x03\xB5n\xC0)\xBE.]\x92\xF5\x05~\t\x04\x99\xFB\xDC\xD6\x93\xC44\x14\xE3q\xEE\x13\x1A\xB2\x81\e9\x8Bd\xB5>^{\xC0\xD0", }, "hmac-ripemd160@openssh.com" => { false => "\xE3-1\x8E\xA1\xB7\x95\x9E`\x1E\xFB:[\xFD\x15\x8Ee\xD6|\xB6q\xF98\xFF\t\xB3\xD4F\x03\xB3\xFA\xECF\xC3\xC7\x87\xA5\x86\xD5~\xCD(\xF8\xD9\xCB\xC5\vHI\xCAL\x8E", :standard => "\xE3-1\xBE\xB8\xCB\b\xFC\x01z\x92>\xDE\xD3)\xA4(\xF2]\x1E\xBD\xB2?\x8D\x19\xAB\x97!T\x03\xB5n\xC0)\xBE.]\x92\xF5\x05~\t\x04\x99\xFB\xDC\xD6\x93\xC44\x14\xE3q\xEE\x13\x1A\xB2\x81\e9\x8Bd\xB5>^{\xC0\xD0", }, "none" => { false => "\xE3-1\x8E\xA1\xB7\x95\x9E`\x1E\xFB:[\xFD\x15\x8Ee\xD6|\xB6q\xF98\xFF\t\xB3\xD4F\x03\xB3\xFA\xEC", :standard => "\xE3-1\xBE\xB8\xCB\b\xFC\x01z\x92>\xDE\xD3)\xA4(\xF2]\x1E\xBD\xB2?\x8D\x19\xAB\x97!T\x03\xB5n\xC0)\xBE.]\x92\xF5\x05~\t\x04\x99\xFB\xDC\xD6\x93", }, }, "none" => { "hmac-md5" => { false => "\000\000\000\034\b\004\001\000\000\000\tdebugging\000\000\000\000\b\030CgWO\260\212\000\032w\312\t\306\374\271\345p\215\224\373\363\v\261", :standard => "\000\000\000$\tx\234bad``\340LIM*MO\317\314K\ar\030\000\000\000\000\377\377\b\030CgWO\260\212^\354=g\361\271[E\265\217\316\314\b\202\235\226\334", }, "hmac-md5-96" => { false => "\000\000\000\034\b\004\001\000\000\000\tdebugging\000\000\000\000\b\030CgWO\260\212\000\032w\312\t\306\374\271\345p\215\224", :standard => "\000\000\000$\tx\234bad``\340LIM*MO\317\314K\ar\030\000\000\000\000\377\377\b\030CgWO\260\212^\354=g\361\271[E\265\217\316\314\b", }, "hmac-sha1-96" => { false => "\000\000\000\034\b\004\001\000\000\000\tdebugging\000\000\000\000\b\030CgWO\260\212\004\a\200\n\004\202z\270\236\261\330m", :standard => "\000\000\000$\tx\234bad``\340LIM*MO\317\314K\ar\030\000\000\000\000\377\377\b\030CgWO\260\212^\2117U\266\3444(\235\034\023\377\376", }, "hmac-sha1" => { false => "\000\000\000\034\b\004\001\000\000\000\tdebugging\000\000\000\000\b\030CgWO\260\212\004\a\200\n\004\202z\270\236\261\330m\275\005\f\202g\260g\376", :standard => "\000\000\000$\tx\234bad``\340LIM*MO\317\314K\ar\030\000\000\000\000\377\377\b\030CgWO\260\212^\2117U\266\3444(\235\034\023\377\376\335\301\253rI\215W\311", }, "hmac-ripemd160" => { false => "\000\000\000\034\b\004\001\000\000\000\tdebugging\000\000\000\000\b\030CgWO\260\212F\303\307\207\245\206\325~\315(\370\331\313\305\vHI\312L\216", :standard => "\000\000\000$\tx\234bad``\340LIM*MO\317\314K\ar\030\000\000\000\000\377\377\b\030CgWO\260\212^)U\275\003U\333\225\221Y)\317\256\240\246\0000\351\032\363Y", }, "hmac-ripemd160@openssh.com" => { false => "\000\000\000\034\b\004\001\000\000\000\tdebugging\000\000\000\000\b\030CgWO\260\212F\303\307\207\245\206\325~\315(\370\331\313\305\vHI\312L\216", :standard => "\000\000\000$\tx\234bad``\340LIM*MO\317\314K\ar\030\000\000\000\000\377\377\b\030CgWO\260\212^)U\275\003U\333\225\221Y)\317\256\240\246\0000\351\032\363Y", }, "none" => { false => "\000\000\000\034\b\004\001\000\000\000\tdebugging\000\000\000\000\b\030CgWO\260\212", :standard => "\000\000\000$\tx\234bad``\340LIM*MO\317\314K\ar\030\000\000\000\000\377\377\b\030CgWO\260\212^", }, }, "rijndael-cbc@lysator.liu.se" => { "hmac-md5" => { false => "\266\001oG(\201s\255[\202j\031-\354\353]\022\374\367j2\257\b#\273r\275\341\232\264\255\340\000\032w\312\t\306\374\271\345p\215\224\373\363\v\261", :standard => "\251!O/_\253\321\217e\225\202\202W\261p\r\357\357\375\231\264Y,nZ/\366\225G\256\3000\036\223\237\353\265vG\231\215cvY\236%\315\365-\345\b\025\242#\336P8\343\361\263\\\241\326\311", }, "hmac-md5-96" => { false => "\266\001oG(\201s\255[\202j\031-\354\353]\022\374\367j2\257\b#\273r\275\341\232\264\255\340\000\032w\312\t\306\374\271\345p\215\224", :standard => "\251!O/_\253\321\217e\225\202\202W\261p\r\357\357\375\231\264Y,nZ/\366\225G\256\3000\036\223\237\353\265vG\231\215cvY\236%\315\365-\345\b\025\242#\336P8\343\361\263", }, "hmac-sha1" => { false => "\266\001oG(\201s\255[\202j\031-\354\353]\022\374\367j2\257\b#\273r\275\341\232\264\255\340\004\a\200\n\004\202z\270\236\261\330m\275\005\f\202g\260g\376", :standard => "\251!O/_\253\321\217e\225\202\202W\261p\r\357\357\375\231\264Y,nZ/\366\225G\256\3000\036\223\237\353\265vG\231\215cvY\236%\315\365yC\272\314@\301\n\346$\223\367\r\026\366\375(i'\212\351", }, "hmac-sha1-96" => { false => "\266\001oG(\201s\255[\202j\031-\354\353]\022\374\367j2\257\b#\273r\275\341\232\264\255\340\004\a\200\n\004\202z\270\236\261\330m", :standard => "\251!O/_\253\321\217e\225\202\202W\261p\r\357\357\375\231\264Y,nZ/\366\225G\256\3000\036\223\237\353\265vG\231\215cvY\236%\315\365yC\272\314@\301\n\346$\223\367\r", }, "hmac-ripemd160" => { false => "\266\001oG(\201s\255[\202j\031-\354\353]\022\374\367j2\257\b#\273r\275\341\232\264\255\340F\303\307\207\245\206\325~\315(\370\331\313\305\vHI\312L\216", :standard => "\251!O/_\253\321\217e\225\202\202W\261p\r\357\357\375\231\264Y,nZ/\366\225G\256\3000\036\223\237\353\265vG\231\215cvY\236%\315\365\3044\024\343q\356\023\032\262\201\e9\213d\265>^{\300\320", }, "hmac-ripemd160@openssh.com" => { false => "\266\001oG(\201s\255[\202j\031-\354\353]\022\374\367j2\257\b#\273r\275\341\232\264\255\340F\303\307\207\245\206\325~\315(\370\331\313\305\vHI\312L\216", :standard => "\251!O/_\253\321\217e\225\202\202W\261p\r\357\357\375\231\264Y,nZ/\366\225G\256\3000\036\223\237\353\265vG\231\215cvY\236%\315\365\3044\024\343q\356\023\032\262\201\e9\213d\265>^{\300\320", }, "none" => { false => "\266\001oG(\201s\255[\202j\031-\354\353]\022\374\367j2\257\b#\273r\275\341\232\264\255\340", :standard => "\251!O/_\253\321\217e\225\202\202W\261p\r\357\357\375\231\264Y,nZ/\366\225G\256\3000\036\223\237\353\265vG\231\215cvY\236%\315\365", }, }, "arcfour" => { "hmac-md5" => { false => "O\"\200JH\004\200\020Y\323\334\334\273B^\226DL\370\205V\350[>\257\361\223\270\262%\331`\000\032w\312\t\306\374\271\345p\215\224\373\363\v\261", :standard => "O\"\200rIx\035r8\267\265\330>lb\274\th\331-\232\243\\L\277\351\320\337\345\225\226\342>b\350\215\253\n\002\017\354=g\361\271[E\265\217\316\314\b\202\235\226\334", }, "hmac-md5-96" => { false => "O\"\200JH\004\200\020Y\323\334\334\273B^\226DL\370\205V\350[>\257\361\223\270\262%\331`\000\032w\312\t\306\374\271\345p\215\224", :standard => "O\"\200rIx\035r8\267\265\330>lb\274\th\331-\232\243\\L\277\351\320\337\345\225\226\342>b\350\215\253\n\002\017\354=g\361\271[E\265\217\316\314\b", }, "hmac-sha1" => { false => "O\"\200JH\004\200\020Y\323\334\334\273B^\226DL\370\205V\350[>\257\361\223\270\262%\331`\004\a\200\n\004\202z\270\236\261\330m\275\005\f\202g\260g\376", :standard => "O\"\200rIx\035r8\267\265\330>lb\274\th\331-\232\243\\L\277\351\320\337\345\225\226\342>b\350\215\253\n\002\017\2117U\266\3444(\235\034\023\377\376\335\301\253rI\215W\311", }, "hmac-sha1-96" => { false => "O\"\200JH\004\200\020Y\323\334\334\273B^\226DL\370\205V\350[>\257\361\223\270\262%\331`\004\a\200\n\004\202z\270\236\261\330m", :standard => "O\"\200rIx\035r8\267\265\330>lb\274\th\331-\232\243\\L\277\351\320\337\345\225\226\342>b\350\215\253\n\002\017\2117U\266\3444(\235\034\023\377\376", }, "hmac-ripemd160" => { false => "O\"\200JH\004\200\020Y\323\334\334\273B^\226DL\370\205V\350[>\257\361\223\270\262%\331`F\303\307\207\245\206\325~\315(\370\331\313\305\vHI\312L\216", :standard => "O\"\200rIx\035r8\267\265\330>lb\274\th\331-\232\243\\L\277\351\320\337\345\225\226\342>b\350\215\253\n\002\017)U\275\003U\333\225\221Y)\317\256\240\246\0000\351\032\363Y", }, "hmac-ripemd160@openssh.com" => { false => "O\"\200JH\004\200\020Y\323\334\334\273B^\226DL\370\205V\350[>\257\361\223\270\262%\331`F\303\307\207\245\206\325~\315(\370\331\313\305\vHI\312L\216", :standard => "O\"\200rIx\035r8\267\265\330>lb\274\th\331-\232\243\\L\277\351\320\337\345\225\226\342>b\350\215\253\n\002\017)U\275\003U\333\225\221Y)\317\256\240\246\0000\351\032\363Y", }, "none" => { false => "O\"\200JH\004\200\020Y\323\334\334\273B^\226DL\370\205V\350[>\257\361\223\270\262%\331`", :standard => "O\"\200rIx\035r8\267\265\330>lb\274\th\331-\232\243\\L\277\351\320\337\345\225\226\342>b\350\215\253\n\002\017", }, }, } if defined?(OpenSSL::Digest::SHA256) sha2_packets = { "3des-cbc" => { "hmac-sha2-256" => { false => "\003\352\031\261k\243\200\204\301\203]!\a\306\217\201\a[^\304\317\322\264\265~\361\017\n\205\272, 7{\320\316\365Wy\"c\036y\260-\275\312~\217\020U\355\001\377\225F\345\206\255\307\023N\350J", :standard => "\317\222v\316\234<\310\377\310\034\346\351\020:\025{\372PDS\246\344\312J\364\301\n\262\r<\037\231Mu\031\240\255\026\362\200\367F\231v\265o\f9$\224\201\e\364+\226H\374\377=\ts\202`\026\e,\347\t\217\206t\307", }, "hmac-sha2-256-96" => { false => "\003\352\031\261k\243\200\204\301\203]!\a\306\217\201\a[^\304\317\322\264\265~\361\017\n\205\272, 7{\320\316\365Wy\"c\036y\260", :standard => "\317\222v\316\234<\310\377\310\034\346\351\020:\025{\372PDS\246\344\312J\364\301\n\262\r<\037\231Mu\031\240\255\026\362\200\367F\231v\265o\f9$\224\201\e", }, "hmac-sha2-512" => { false => "\003\352\031\261k\243\200\204\301\203]!\a\306\217\201\a[^\304\317\322\264\265~\361\017\n\205\272, #/\317\000\340I\274\363_\225U*\327z\201\316c\303\275A\362\330^J\277\3005oI\272\362\352\206\370h\213\262\3109\310v\037\004\022\200]&\365\310\300\220D[\350\036\225\211\353\361\366\237\267\204\325", :standard => "\317\222v\316\234<\310\377\310\034\346\351\020:\025{\372PDS\246\344\312J\364\301\n\262\r<\037\231Mu\031\240\255\026\362\200Q\3112O\223\361\216\235\022\216\0162\256\343\214\320\v\321\366/$\017]2\302\3435\217\324\245\037\301\225p\270\221c\307\302u\213b 4#\202PFI\371\267l\374\311\001\262z(\335|\334\2446\226", }, "hmac-sha2-512-96" => { false => "\003\352\031\261k\243\200\204\301\203]!\a\306\217\201\a[^\304\317\322\264\265~\361\017\n\205\272, #/\317\000\340I\274\363_\225U*", :standard => "\317\222v\316\234<\310\377\310\034\346\351\020:\025{\372PDS\246\344\312J\364\301\n\262\r<\037\231Mu\031\240\255\026\362\200Q\3112O\223\361\216\235\022\216\0162", }, }, "aes128-cbc" => { "hmac-sha2-256" => { false => "\240\016\243k]0\330\253\030\320\334\261(\034E\211\230#\326\374\267\311O\211E(\234\325n\306NY7{\320\316\365Wy\"c\036y\260-\275\312~\217\020U\355\001\377\225F\345\206\255\307\023N\350J", :standard => "\273\367\324\032\3762\334\026\r\246\342\022\016\325\024\270.\273\005\314\036\312\211\261\037A\361\362:W\316\352K\204\216b\2124>A\265g\331\177\233dK\251\373\035\334\340M\032B\307\324\232\211m'\347k\253\371\341\326\254\356\263[\2412\302R\320\274\365\255\003", }, "hmac-sha2-256-96" => { false => "\240\016\243k]0\330\253\030\320\334\261(\034E\211\230#\326\374\267\311O\211E(\234\325n\306NY7{\320\316\365Wy\"c\036y\260", :standard => "\273\367\324\032\3762\334\026\r\246\342\022\016\325\024\270.\273\005\314\036\312\211\261\037A\361\362:W\316\352K\204\216b\2124>A\265g\331\177\233dK\251\373\035\334\340M\032B\307\324\232\211m", }, "hmac-sha2-512" => { false => "\240\016\243k]0\330\253\030\320\334\261(\034E\211\230#\326\374\267\311O\211E(\234\325n\306NY#/\317\000\340I\274\363_\225U*\327z\201\316c\303\275A\362\330^J\277\3005oI\272\362\352\206\370h\213\262\3109\310v\037\004\022\200]&\365\310\300\220D[\350\036\225\211\353\361\366\237\267\204\325", :standard => "\273\367\324\032\3762\334\026\r\246\342\022\016\325\024\270.\273\005\314\036\312\211\261\037A\361\362:W\316\352K\204\216b\2124>A\265g\331\177\233dK\251N\005f\275u\230\344xF\354+RSTS\360\235\004\311$cW\357o\"fy\031\321yX\tYK\347\363kd\a\022\307r\177[ \274\0164\222\300 \037\330<\264\001^\246\337\004\365\233\202\310", }, "hmac-sha2-512-96" => { false => "\240\016\243k]0\330\253\030\320\334\261(\034E\211\230#\326\374\267\311O\211E(\234\325n\306NY#/\317\000\340I\274\363_\225U*", :standard => "\273\367\324\032\3762\334\026\r\246\342\022\016\325\024\270.\273\005\314\036\312\211\261\037A\361\362:W\316\352K\204\216b\2124>A\265g\331\177\233dK\251N\005f\275u\230\344xF\354+R", }, }, "aes192-cbc" => { "hmac-sha2-256" => { false => "P$\377\302\326\262\276\215\206\343&\257#\315>Mp\232P\345o\215\330\213\t\027\300\360\300\037\267\0037{\320\316\365Wy\"c\036y\260-\275\312~\217\020U\355\001\377\225F\345\206\255\307\023N\350J", :standard => "se\347\230\026\311\212\250yH\241\302n\364:\276\270M=H1\317\222^\362\237D\225N\354:\343\205M\006[\313$U/yZ\330\235\032\307\320D\373\035\334\340M\032B\307\324\232\211m'\347k\253\371\341\326\254\356\263[\2412\302R\320\274\365\255\003", }, "hmac-sha2-512" => { false => "P$\377\302\326\262\276\215\206\343&\257#\315>Mp\232P\345o\215\330\213\t\027\300\360\300\037\267\003#/\317\000\340I\274\363_\225U*\327z\201\316c\303\275A\362\330^J\277\3005oI\272\362\352\206\370h\213\262\3109\310v\037\004\022\200]&\365\310\300\220D[\350\036\225\211\353\361\366\237\267\204\325", :standard => "se\347\230\026\311\212\250yH\241\302n\364:\276\270M=H1\317\222^\362\237D\225N\354:\343\205M\006[\313$U/yZ\330\235\032\307\320DN\005f\275u\230\344xF\354+RSTS\360\235\004\311$cW\357o\"fy\031\321yX\tYK\347\363kd\a\022\307r\177[ \274\0164\222\300 \037\330<\264\001^\246\337\004\365\233\202\310", }, "hmac-sha2-256-96" => { false => "P$\377\302\326\262\276\215\206\343&\257#\315>Mp\232P\345o\215\330\213\t\027\300\360\300\037\267\0037{\320\316\365Wy\"c\036y\260", :standard => "se\347\230\026\311\212\250yH\241\302n\364:\276\270M=H1\317\222^\362\237D\225N\354:\343\205M\006[\313$U/yZ\330\235\032\307\320D\373\035\334\340M\032B\307\324\232\211m", }, "hmac-sha2-512-96" => { false => "P$\377\302\326\262\276\215\206\343&\257#\315>Mp\232P\345o\215\330\213\t\027\300\360\300\037\267\003#/\317\000\340I\274\363_\225U*", :standard => "se\347\230\026\311\212\250yH\241\302n\364:\276\270M=H1\317\222^\362\237D\225N\354:\343\205M\006[\313$U/yZ\330\235\032\307\320DN\005f\275u\230\344xF\354+R", }, }, "aes256-cbc" => { "hmac-sha2-256" => { false => "\266\001oG(\201s\255[\202j\031-\354\353]\022\374\367j2\257\b#\273r\275\341\232\264\255\3407{\320\316\365Wy\"c\036y\260-\275\312~\217\020U\355\001\377\225F\345\206\255\307\023N\350J", :standard => "\251!O/_\253\321\217e\225\202\202W\261p\r\357\357\375\231\264Y,nZ/\366\225G\256\3000\036\223\237\353\265vG\231\215cvY\236%\315\365\373\035\334\340M\032B\307\324\232\211m'\347k\253\371\341\326\254\356\263[\2412\302R\320\274\365\255\003", }, "hmac-sha2-256-96" => { false => "\266\001oG(\201s\255[\202j\031-\354\353]\022\374\367j2\257\b#\273r\275\341\232\264\255\3407{\320\316\365Wy\"c\036y\260", :standard => "\251!O/_\253\321\217e\225\202\202W\261p\r\357\357\375\231\264Y,nZ/\366\225G\256\3000\036\223\237\353\265vG\231\215cvY\236%\315\365\373\035\334\340M\032B\307\324\232\211m", }, "hmac-sha2-512" => { false => "\266\001oG(\201s\255[\202j\031-\354\353]\022\374\367j2\257\b#\273r\275\341\232\264\255\340#/\317\000\340I\274\363_\225U*\327z\201\316c\303\275A\362\330^J\277\3005oI\272\362\352\206\370h\213\262\3109\310v\037\004\022\200]&\365\310\300\220D[\350\036\225\211\353\361\366\237\267\204\325", :standard => "\251!O/_\253\321\217e\225\202\202W\261p\r\357\357\375\231\264Y,nZ/\366\225G\256\3000\036\223\237\353\265vG\231\215cvY\236%\315\365N\005f\275u\230\344xF\354+RSTS\360\235\004\311$cW\357o\"fy\031\321yX\tYK\347\363kd\a\022\307r\177[ \274\0164\222\300 \037\330<\264\001^\246\337\004\365\233\202\310", }, "hmac-sha2-512-96" => { false => "\266\001oG(\201s\255[\202j\031-\354\353]\022\374\367j2\257\b#\273r\275\341\232\264\255\340#/\317\000\340I\274\363_\225U*", :standard => "\251!O/_\253\321\217e\225\202\202W\261p\r\357\357\375\231\264Y,nZ/\366\225G\256\3000\036\223\237\353\265vG\231\215cvY\236%\315\365N\005f\275u\230\344xF\354+R", }, }, "blowfish-cbc" => { "hmac-sha2-256" => { false => "vT\353\203\247\206L\255e\371\001 6B/\234g\332\371\224l\227\257\346\373E\237C2\212u)7{\320\316\365Wy\"c\036y\260-\275\312~\217\020U\355\001\377\225F\345\206\255\307\023N\350J", :standard => "U\257\231e\347\274\bh\016X\232h\334\v\005\316e1G$-\367##\256$rW\000\210\335_\360\f\000\205#\370\201\006\367F\231v\265o\f9$\224\201\e\364+\226H\374\377=\ts\202`\026\e,\347\t\217\206t\307", }, "hmac-sha2-256-96" => { false => "vT\353\203\247\206L\255e\371\001 6B/\234g\332\371\224l\227\257\346\373E\237C2\212u)7{\320\316\365Wy\"c\036y\260", :standard => "U\257\231e\347\274\bh\016X\232h\334\v\005\316e1G$-\367##\256$rW\000\210\335_\360\f\000\205#\370\201\006\367F\231v\265o\f9$\224\201\e", }, "hmac-sha2-512" => { false => "vT\353\203\247\206L\255e\371\001 6B/\234g\332\371\224l\227\257\346\373E\237C2\212u)#/\317\000\340I\274\363_\225U*\327z\201\316c\303\275A\362\330^J\277\3005oI\272\362\352\206\370h\213\262\3109\310v\037\004\022\200]&\365\310\300\220D[\350\036\225\211\353\361\366\237\267\204\325", :standard => "U\257\231e\347\274\bh\016X\232h\334\v\005\316e1G$-\367##\256$rW\000\210\335_\360\f\000\205#\370\201\006Q\3112O\223\361\216\235\022\216\0162\256\343\214\320\v\321\366/$\017]2\302\3435\217\324\245\037\301\225p\270\221c\307\302u\213b 4#\202PFI\371\267l\374\311\001\262z(\335|\334\2446\226", }, "hmac-sha2-512-96" => { false => "vT\353\203\247\206L\255e\371\001 6B/\234g\332\371\224l\227\257\346\373E\237C2\212u)#/\317\000\340I\274\363_\225U*", :standard => "U\257\231e\347\274\bh\016X\232h\334\v\005\316e1G$-\367##\256$rW\000\210\335_\360\f\000\205#\370\201\006Q\3112O\223\361\216\235\022\216\0162", }, }, "cast128-cbc" => { "hmac-sha2-256" => { false => "\361\026\313!\31235|w~\n\261\257\277\e\277b\246b\342\333\eE\021N\345\343m\314\272\315\3767{\320\316\365Wy\"c\036y\260-\275\312~\217\020U\355\001\377\225F\345\206\255\307\023N\350J", :standard => "\375i\253\004\311E\2011)\220$\251A\245\f(\371\263\314\242\353\260\272\367\276\"\031\224$\244\311W\307Oe\224\0017\336\325\367F\231v\265o\f9$\224\201\e\364+\226H\374\377=\ts\202`\026\e,\347\t\217\206t\307", }, "hmac-sha2-256-96" => { false => "\361\026\313!\31235|w~\n\261\257\277\e\277b\246b\342\333\eE\021N\345\343m\314\272\315\3767{\320\316\365Wy\"c\036y\260", :standard => "\375i\253\004\311E\2011)\220$\251A\245\f(\371\263\314\242\353\260\272\367\276\"\031\224$\244\311W\307Oe\224\0017\336\325\367F\231v\265o\f9$\224\201\e", }, "hmac-sha2-512" => { false => "\361\026\313!\31235|w~\n\261\257\277\e\277b\246b\342\333\eE\021N\345\343m\314\272\315\376#/\317\000\340I\274\363_\225U*\327z\201\316c\303\275A\362\330^J\277\3005oI\272\362\352\206\370h\213\262\3109\310v\037\004\022\200]&\365\310\300\220D[\350\036\225\211\353\361\366\237\267\204\325", :standard => "\375i\253\004\311E\2011)\220$\251A\245\f(\371\263\314\242\353\260\272\367\276\"\031\224$\244\311W\307Oe\224\0017\336\325Q\3112O\223\361\216\235\022\216\0162\256\343\214\320\v\321\366/$\017]2\302\3435\217\324\245\037\301\225p\270\221c\307\302u\213b 4#\202PFI\371\267l\374\311\001\262z(\335|\334\2446\226", }, "hmac-sha2-512-96" => { false => "\361\026\313!\31235|w~\n\261\257\277\e\277b\246b\342\333\eE\021N\345\343m\314\272\315\376#/\317\000\340I\274\363_\225U*", :standard => "\375i\253\004\311E\2011)\220$\251A\245\f(\371\263\314\242\353\260\272\367\276\"\031\224$\244\311W\307Oe\224\0017\336\325Q\3112O\223\361\216\235\022\216\0162", }, }, "idea-cbc" => { "hmac-sha2-256" => { false => "\342\255\202$\273\201\025#\245\2341F\263\005@{\000<\266&s\016\251NH=J\322/\220 H7{\320\316\365Wy\"c\036y\260-\275\312~\217\020U\355\001\377\225F\345\206\255\307\023N\350J", :standard => "F\3048\360\357\265\215I\021)\a\254/\315%\354M\004\330\006\356\vFr\250K\225\223x\277+Q)\022\327\311K\025\322\317\367F\231v\265o\f9$\224\201\e\364+\226H\374\377=\ts\202`\026\e,\347\t\217\206t\307", }, "hmac-sha2-512" => { false => "\342\255\202$\273\201\025#\245\2341F\263\005@{\000<\266&s\016\251NH=J\322/\220 H#/\317\000\340I\274\363_\225U*\327z\201\316c\303\275A\362\330^J\277\3005oI\272\362\352\206\370h\213\262\3109\310v\037\004\022\200]&\365\310\300\220D[\350\036\225\211\353\361\366\237\267\204\325", :standard => "F\3048\360\357\265\215I\021)\a\254/\315%\354M\004\330\006\356\vFr\250K\225\223x\277+Q)\022\327\311K\025\322\317Q\3112O\223\361\216\235\022\216\0162\256\343\214\320\v\321\366/$\017]2\302\3435\217\324\245\037\301\225p\270\221c\307\302u\213b 4#\202PFI\371\267l\374\311\001\262z(\335|\334\2446\226", }, "hmac-sha2-256-96" => { false => "\342\255\202$\273\201\025#\245\2341F\263\005@{\000<\266&s\016\251NH=J\322/\220 H7{\320\316\365Wy\"c\036y\260", :standard => "F\3048\360\357\265\215I\021)\a\254/\315%\354M\004\330\006\356\vFr\250K\225\223x\277+Q)\022\327\311K\025\322\317\367F\231v\265o\f9$\224\201\e", }, "hmac-sha2-512-96" => { false => "\342\255\202$\273\201\025#\245\2341F\263\005@{\000<\266&s\016\251NH=J\322/\220 H#/\317\000\340I\274\363_\225U*", :standard => "F\3048\360\357\265\215I\021)\a\254/\315%\354M\004\330\006\356\vFr\250K\225\223x\277+Q)\022\327\311K\025\322\317Q\3112O\223\361\216\235\022\216\0162", }, }, "arcfour128" => { "hmac-sha2-256" => { false => "e_\204\037\366\363>\024\263q\025\334\354AO.\026t\231nvD\030\226\234\263\257\335:\001\300\2557{\320\316\365Wy\"c\036y\260-\275\312~\217\020U\355\001\377\225F\345\206\255\307\023N\350J", :standard => "e_\204'\367\217\243v\322\025|\330ios\004[P\270\306\272\017\037\344\214\253\354\272m\261\217/jW'V\277\341U\224\367F\231v\265o\f9$\224\201\e\364+\226H\374\377=\ts\202`\026\e,\347\t\217\206t\307", }, "hmac-sha2-512" => { false => "e_\204\037\366\363>\024\263q\025\334\354AO.\026t\231nvD\030\226\234\263\257\335:\001\300\255#/\317\000\340I\274\363_\225U*\327z\201\316c\303\275A\362\330^J\277\3005oI\272\362\352\206\370h\213\262\3109\310v\037\004\022\200]&\365\310\300\220D[\350\036\225\211\353\361\366\237\267\204\325", :standard => "e_\204'\367\217\243v\322\025|\330ios\004[P\270\306\272\017\037\344\214\253\354\272m\261\217/jW'V\277\341U\224Q\3112O\223\361\216\235\022\216\0162\256\343\214\320\v\321\366/$\017]2\302\3435\217\324\245\037\301\225p\270\221c\307\302u\213b 4#\202PFI\371\267l\374\311\001\262z(\335|\334\2446\226", }, "hmac-sha2-256-96" => { false => "e_\204\037\366\363>\024\263q\025\334\354AO.\026t\231nvD\030\226\234\263\257\335:\001\300\2557{\320\316\365Wy\"c\036y\260", :standard => "e_\204'\367\217\243v\322\025|\330ios\004[P\270\306\272\017\037\344\214\253\354\272m\261\217/jW'V\277\341U\224\367F\231v\265o\f9$\224\201\e", }, "hmac-sha2-512-96" => { false => "e_\204\037\366\363>\024\263q\025\334\354AO.\026t\231nvD\030\226\234\263\257\335:\001\300\255#/\317\000\340I\274\363_\225U*", :standard => "e_\204'\367\217\243v\322\025|\330ios\004[P\270\306\272\017\037\344\214\253\354\272m\261\217/jW'V\277\341U\224Q\3112O\223\361\216\235\022\216\0162", }, }, "arcfour256" => { "hmac-sha2-256" => { false => "B\374\256V\035b\337\215\305h\031bE\271\312\361\017T+\302\024x\3016\315g%\032\331\004fr7{\320\316\365Wy\"c\036y\260-\275\312~\217\020U\355\001\377\225F\345\206\255\307\023N\350J", :standard => "B\374\256n\034\036B\357\244\fpf\300\227\366\333Bp\nj\3303\306D\335\177f}\216\264)\360\325jU^M\357$\221\367F\231v\265o\f9$\224\201\e\364+\226H\374\377=\ts\202`\026\e,\347\t\217\206t\307", }, "hmac-sha2-512" => { false => "B\374\256V\035b\337\215\305h\031bE\271\312\361\017T+\302\024x\3016\315g%\032\331\004fr#/\317\000\340I\274\363_\225U*\327z\201\316c\303\275A\362\330^J\277\3005oI\272\362\352\206\370h\213\262\3109\310v\037\004\022\200]&\365\310\300\220D[\350\036\225\211\353\361\366\237\267\204\325", :standard => "B\374\256n\034\036B\357\244\fpf\300\227\366\333Bp\nj\3303\306D\335\177f}\216\264)\360\325jU^M\357$\221Q\3112O\223\361\216\235\022\216\0162\256\343\214\320\v\321\366/$\017]2\302\3435\217\324\245\037\301\225p\270\221c\307\302u\213b 4#\202PFI\371\267l\374\311\001\262z(\335|\334\2446\226", }, "hmac-sha2-256-96" => { false => "B\374\256V\035b\337\215\305h\031bE\271\312\361\017T+\302\024x\3016\315g%\032\331\004fr7{\320\316\365Wy\"c\036y\260", :standard => "B\374\256n\034\036B\357\244\fpf\300\227\366\333Bp\nj\3303\306D\335\177f}\216\264)\360\325jU^M\357$\221\367F\231v\265o\f9$\224\201\e", }, "hmac-sha2-512-96" => { false => "B\374\256V\035b\337\215\305h\031bE\271\312\361\017T+\302\024x\3016\315g%\032\331\004fr#/\317\000\340I\274\363_\225U*", :standard => "B\374\256n\034\036B\357\244\fpf\300\227\366\333Bp\nj\3303\306D\335\177f}\216\264)\360\325jU^M\357$\221Q\3112O\223\361\216\235\022\216\0162", }, }, "arcfour512" => { "hmac-sha2-256" => { false => "\n{\275\177Yw\307\f\277\221\247'\0318\237\223cR\340\361\356\017\357\235\342\374\005wL\267\330D7{\320\316\365Wy\"c\036y\260-\275\312~\217\020U\355\001\377\225F\345\206\255\307\023N\350J", :standard => "\n{\275GX\vZn\336\365\316#\234\026\243\271.v\301Y\"D\350\357\362\344F\020\e\a\227\306\366\025:\246\2349\233\313\367F\231v\265o\f9$\224\201\e\364+\226H\374\377=\ts\202`\026\e,\347\t\217\206t\307", }, "hmac-sha2-512" => { false => "\n{\275\177Yw\307\f\277\221\247'\0318\237\223cR\340\361\356\017\357\235\342\374\005wL\267\330D#/\317\000\340I\274\363_\225U*\327z\201\316c\303\275A\362\330^J\277\3005oI\272\362\352\206\370h\213\262\3109\310v\037\004\022\200]&\365\310\300\220D[\350\036\225\211\353\361\366\237\267\204\325", :standard => "\n{\275GX\vZn\336\365\316#\234\026\243\271.v\301Y\"D\350\357\362\344F\020\e\a\227\306\366\025:\246\2349\233\313Q\3112O\223\361\216\235\022\216\0162\256\343\214\320\v\321\366/$\017]2\302\3435\217\324\245\037\301\225p\270\221c\307\302u\213b 4#\202PFI\371\267l\374\311\001\262z(\335|\334\2446\226", }, "hmac-sha2-256-96" => { false => "\n{\275\177Yw\307\f\277\221\247'\0318\237\223cR\340\361\356\017\357\235\342\374\005wL\267\330D7{\320\316\365Wy\"c\036y\260", :standard => "\n{\275GX\vZn\336\365\316#\234\026\243\271.v\301Y\"D\350\357\362\344F\020\e\a\227\306\366\025:\246\2349\233\313\367F\231v\265o\f9$\224\201\e", }, "hmac-sha2-512-96" => { false => "\n{\275\177Yw\307\f\277\221\247'\0318\237\223cR\340\361\356\017\357\235\342\374\005wL\267\330D#/\317\000\340I\274\363_\225U*", :standard => "\n{\275GX\vZn\336\365\316#\234\026\243\271.v\301Y\"D\350\357\362\344F\020\e\a\227\306\366\025:\246\2349\233\313Q\3112O\223\361\216\235\022\216\0162", }, }, "arcfour" => { "hmac-sha2-256" => { false => "O\"\200JH\004\200\020Y\323\334\334\273B^\226DL\370\205V\350[>\257\361\223\270\262%\331`7{\320\316\365Wy\"c\036y\260-\275\312~\217\020U\355\001\377\225F\345\206\255\307\023N\350J", :standard => "O\"\200rIx\035r8\267\265\330>lb\274\th\331-\232\243\\L\277\351\320\337\345\225\226\342>b\350\215\253\n\002\017\367F\231v\265o\f9$\224\201\e\364+\226H\374\377=\ts\202`\026\e,\347\t\217\206t\307", }, "hmac-sha2-512" => { false => "O\"\200JH\004\200\020Y\323\334\334\273B^\226DL\370\205V\350[>\257\361\223\270\262%\331`#/\317\000\340I\274\363_\225U*\327z\201\316c\303\275A\362\330^J\277\3005oI\272\362\352\206\370h\213\262\3109\310v\037\004\022\200]&\365\310\300\220D[\350\036\225\211\353\361\366\237\267\204\325", :standard => "O\"\200rIx\035r8\267\265\330>lb\274\th\331-\232\243\\L\277\351\320\337\345\225\226\342>b\350\215\253\n\002\017Q\3112O\223\361\216\235\022\216\0162\256\343\214\320\v\321\366/$\017]2\302\3435\217\324\245\037\301\225p\270\221c\307\302u\213b 4#\202PFI\371\267l\374\311\001\262z(\335|\334\2446\226", }, "hmac-sha2-256-96" => { false => "O\"\200JH\004\200\020Y\323\334\334\273B^\226DL\370\205V\350[>\257\361\223\270\262%\331`7{\320\316\365Wy\"c\036y\260", :standard => "O\"\200rIx\035r8\267\265\330>lb\274\th\331-\232\243\\L\277\351\320\337\345\225\226\342>b\350\215\253\n\002\017\367F\231v\265o\f9$\224\201\e", }, "hmac-sha2-512-96" => { false => "O\"\200JH\004\200\020Y\323\334\334\273B^\226DL\370\205V\350[>\257\361\223\270\262%\331`#/\317\000\340I\274\363_\225U*", :standard => "O\"\200rIx\035r8\267\265\330>lb\274\th\331-\232\243\\L\277\351\320\337\345\225\226\342>b\350\215\253\n\002\017Q\3112O\223\361\216\235\022\216\0162", }, }, "camellia128-cbc@openssh.org" => { "hmac-sha2-256" => { false => "vO\xD4Mst\xD2 } _\xE3e\xC4\x8A\xAA\xCD\x9E*\xE2\xA5\xC0\xED\xBB\xD5\x99\x12 ^2\xC3\x9D7{\xD0\xCE\xF5Wy\"c\x1Ey\xB0-\xBD\xCA~\x8F\x10U\xED\x01\xFF\x95F\xE5\x86\xAD\xC7\x13N\xE8J", :standard => "\x1Du9\xC7\x12\xA4\x9B\r\b\x19e&\x04e\xCE\rp\xE8=\x87h\xBE2\xE0\xAE\x90\xFF\xB22az\x17\xA4IO7}\xE3h2Q\xB8S\x18+&\xFE\x13\xFB\x1D\xDC\xE0M\x1AB\xC7\xD4\x9A\x89m'\xE7k\xAB\xF9\xE1\xD6\xAC\xEE\xB3[\xA12\xC2R\xD0\xBC\xF5\xAD\x03", }, "hmac-sha2-256-96" => { false => "vO\xD4Mst\xD2 } _\xE3e\xC4\x8A\xAA\xCD\x9E*\xE2\xA5\xC0\xED\xBB\xD5\x99\x12 ^2\xC3\x9D7{\xD0\xCE\xF5Wy\"c\x1Ey\xB0", :standard => "\x1Du9\xC7\x12\xA4\x9B\r\b\x19e&\x04e\xCE\rp\xE8=\x87h\xBE2\xE0\xAE\x90\xFF\xB22az\x17\xA4IO7}\xE3h2Q\xB8S\x18+&\xFE\x13\xFB\x1D\xDC\xE0M\x1AB\xC7\xD4\x9A\x89m", }, "hmac-sha2-512" => { false => "vO\xD4Mst\xD2 } _\xE3e\xC4\x8A\xAA\xCD\x9E*\xE2\xA5\xC0\xED\xBB\xD5\x99\x12 ^2\xC3\x9D#/\xCF\x00\xE0I\xBC\xF3_\x95U*\xD7z\x81\xCEc\xC3\xBDA\xF2\xD8^J\xBF\xC05oI\xBA\xF2\xEA\x86\xF8h\x8B\xB2\xC89\xC8v\x1F\x04\x12\x80]&\xF5\xC8\xC0\x90D[\xE8\x1E\x95\x89\xEB\xF1\xF6\x9F\xB7\x84\xD5", :standard => "\x1Du9\xC7\x12\xA4\x9B\r\b\x19e&\x04e\xCE\rp\xE8=\x87h\xBE2\xE0\xAE\x90\xFF\xB22az\x17\xA4IO7}\xE3h2Q\xB8S\x18+&\xFE\x13N\x05f\xBDu\x98\xE4xF\xEC+RSTS\xF0\x9D\x04\xC9$cW\xEFo\"fy\x19\xD1yX\tYK\xE7\xF3kd\a\x12\xC7r\x7F[ \xBC\x0E4\x92\xC0 \x1F\xD8<\xB4\x01^\xA6\xDF\x04\xF5\x9B\x82\xC8", }, "hmac-sha2-512-96" => { false => "vO\xD4Mst\xD2 } _\xE3e\xC4\x8A\xAA\xCD\x9E*\xE2\xA5\xC0\xED\xBB\xD5\x99\x12 ^2\xC3\x9D#/\xCF\x00\xE0I\xBC\xF3_\x95U*", :standard => "\x1Du9\xC7\x12\xA4\x9B\r\b\x19e&\x04e\xCE\rp\xE8=\x87h\xBE2\xE0\xAE\x90\xFF\xB22az\x17\xA4IO7}\xE3h2Q\xB8S\x18+&\xFE\x13N\x05f\xBDu\x98\xE4xF\xEC+R", }, }, "camellia192-cbc@openssh.org" => { "hmac-sha2-256" => { false => "Nnl\x00\xD2\xBA\x89j-(\xDD\xF4\\\x19\xF4\xB7\x16,\x90\xEA,\xE26\x00I\xF9\xB5Z\x060\x83E7{\xD0\xCE\xF5Wy\"c\x1Ey\xB0-\xBD\xCA~\x8F\x10U\xED\x01\xFF\x95F\xE5\x86\xAD\xC7\x13N\xE8J", :standard => "\x8Cm\x02.\x18\xFA\x87\x7F\x18a\xA8\xAC \x82u\xC7]\xE6rs/\xB3\xF5.>Aw\x96\xEF\xADLO\xDE[\x02\x14k\xCEn\x06\xF6\xBD^\"4';\x12\xFB\x1D\xDC\xE0M\x1AB\xC7\xD4\x9A\x89m'\xE7k\xAB\xF9\xE1\xD6\xAC\xEE\xB3[\xA12\xC2R\xD0\xBC\xF5\xAD\x03", }, "hmac-sha2-256-96" => { false => "Nnl\x00\xD2\xBA\x89j-(\xDD\xF4\\\x19\xF4\xB7\x16,\x90\xEA,\xE26\x00I\xF9\xB5Z\x060\x83E7{\xD0\xCE\xF5Wy\"c\x1Ey\xB0", :standard => "\x8Cm\x02.\x18\xFA\x87\x7F\x18a\xA8\xAC \x82u\xC7]\xE6rs/\xB3\xF5.>Aw\x96\xEF\xADLO\xDE[\x02\x14k\xCEn\x06\xF6\xBD^\"4';\x12\xFB\x1D\xDC\xE0M\x1AB\xC7\xD4\x9A\x89m", }, "hmac-sha2-512" => { false => "Nnl\x00\xD2\xBA\x89j-(\xDD\xF4\\\x19\xF4\xB7\x16,\x90\xEA,\xE26\x00I\xF9\xB5Z\x060\x83E#/\xCF\x00\xE0I\xBC\xF3_\x95U*\xD7z\x81\xCEc\xC3\xBDA\xF2\xD8^J\xBF\xC05oI\xBA\xF2\xEA\x86\xF8h\x8B\xB2\xC89\xC8v\x1F\x04\x12\x80]&\xF5\xC8\xC0\x90D[\xE8\x1E\x95\x89\xEB\xF1\xF6\x9F\xB7\x84\xD5", :standard => "\x8Cm\x02.\x18\xFA\x87\x7F\x18a\xA8\xAC \x82u\xC7]\xE6rs/\xB3\xF5.>Aw\x96\xEF\xADLO\xDE[\x02\x14k\xCEn\x06\xF6\xBD^\"4';\x12N\x05f\xBDu\x98\xE4xF\xEC+RSTS\xF0\x9D\x04\xC9$cW\xEFo\"fy\x19\xD1yX\tYK\xE7\xF3kd\a\x12\xC7r\x7F[ \xBC\x0E4\x92\xC0 \x1F\xD8<\xB4\x01^\xA6\xDF\x04\xF5\x9B\x82\xC8", }, "hmac-sha2-512-96" => { false => "Nnl\x00\xD2\xBA\x89j-(\xDD\xF4\\\x19\xF4\xB7\x16,\x90\xEA,\xE26\x00I\xF9\xB5Z\x060\x83E#/\xCF\x00\xE0I\xBC\xF3_\x95U*", :standard => "\x8Cm\x02.\x18\xFA\x87\x7F\x18a\xA8\xAC \x82u\xC7]\xE6rs/\xB3\xF5.>Aw\x96\xEF\xADLO\xDE[\x02\x14k\xCEn\x06\xF6\xBD^\"4';\x12N\x05f\xBDu\x98\xE4xF\xEC+R", }, }, "camellia256-cbc@openssh.org" => { "hmac-sha2-256" => { false => "\xE9\xAB&\x85*\x8B\x9C\xFF\xC9\xD2\x91\xE7\e\xE7P]\xD7\t\xA0\x99\a\xCD\x83K\x161\xA4\xBD\xCE\x82y|7{\xD0\xCE\xF5Wy\"c\x1Ey\xB0-\xBD\xCA~\x8F\x10U\xED\x01\xFF\x95F\xE5\x86\xAD\xC7\x13N\xE8J", :standard => "\x9D\x87\e\x99\x80mG\ex-\xA1\xEFA\xBB\xBD+!\xF9s\xC1\xBA_\xA8\xE0\x82\xBEX\xA6\xE8\x85\x1E\xBA\xAFY\x0E\xAC\xCB\xE1\xBF\xD1\xFD\xC3X\x8A\xF1qFi\xFB\x1D\xDC\xE0M\x1AB\xC7\xD4\x9A\x89m'\xE7k\xAB\xF9\xE1\xD6\xAC\xEE\xB3[\xA12\xC2R\xD0\xBC\xF5\xAD\x03", }, "hmac-sha2-256-96" => { false => "\xE9\xAB&\x85*\x8B\x9C\xFF\xC9\xD2\x91\xE7\e\xE7P]\xD7\t\xA0\x99\a\xCD\x83K\x161\xA4\xBD\xCE\x82y|7{\xD0\xCE\xF5Wy\"c\x1Ey\xB0", :standard => "\x9D\x87\e\x99\x80mG\ex-\xA1\xEFA\xBB\xBD+!\xF9s\xC1\xBA_\xA8\xE0\x82\xBEX\xA6\xE8\x85\x1E\xBA\xAFY\x0E\xAC\xCB\xE1\xBF\xD1\xFD\xC3X\x8A\xF1qFi\xFB\x1D\xDC\xE0M\x1AB\xC7\xD4\x9A\x89m", }, "hmac-sha2-512" => { false => "\xE9\xAB&\x85*\x8B\x9C\xFF\xC9\xD2\x91\xE7\e\xE7P]\xD7\t\xA0\x99\a\xCD\x83K\x161\xA4\xBD\xCE\x82y|#/\xCF\x00\xE0I\xBC\xF3_\x95U*\xD7z\x81\xCEc\xC3\xBDA\xF2\xD8^J\xBF\xC05oI\xBA\xF2\xEA\x86\xF8h\x8B\xB2\xC89\xC8v\x1F\x04\x12\x80]&\xF5\xC8\xC0\x90D[\xE8\x1E\x95\x89\xEB\xF1\xF6\x9F\xB7\x84\xD5", :standard => "\x9D\x87\e\x99\x80mG\ex-\xA1\xEFA\xBB\xBD+!\xF9s\xC1\xBA_\xA8\xE0\x82\xBEX\xA6\xE8\x85\x1E\xBA\xAFY\x0E\xAC\xCB\xE1\xBF\xD1\xFD\xC3X\x8A\xF1qFiN\x05f\xBDu\x98\xE4xF\xEC+RSTS\xF0\x9D\x04\xC9$cW\xEFo\"fy\x19\xD1yX\tYK\xE7\xF3kd\a\x12\xC7r\x7F[ \xBC\x0E4\x92\xC0 \x1F\xD8<\xB4\x01^\xA6\xDF\x04\xF5\x9B\x82\xC8", }, "hmac-sha2-512-96" => { false => "\xE9\xAB&\x85*\x8B\x9C\xFF\xC9\xD2\x91\xE7\e\xE7P]\xD7\t\xA0\x99\a\xCD\x83K\x161\xA4\xBD\xCE\x82y|#/\xCF\x00\xE0I\xBC\xF3_\x95U*", :standard => "\x9D\x87\e\x99\x80mG\ex-\xA1\xEFA\xBB\xBD+!\xF9s\xC1\xBA_\xA8\xE0\x82\xBEX\xA6\xE8\x85\x1E\xBA\xAFY\x0E\xAC\xCB\xE1\xBF\xD1\xFD\xC3X\x8A\xF1qFiN\x05f\xBDu\x98\xE4xF\xEC+R", }, }, "camellia128-cbc" => { "hmac-sha2-256" => { false => "vO\xD4Mst\xD2 } _\xE3e\xC4\x8A\xAA\xCD\x9E*\xE2\xA5\xC0\xED\xBB\xD5\x99\x12 ^2\xC3\x9D7{\xD0\xCE\xF5Wy\"c\x1Ey\xB0-\xBD\xCA~\x8F\x10U\xED\x01\xFF\x95F\xE5\x86\xAD\xC7\x13N\xE8J", :standard => "\x1Du9\xC7\x12\xA4\x9B\r\b\x19e&\x04e\xCE\rp\xE8=\x87h\xBE2\xE0\xAE\x90\xFF\xB22az\x17\xA4IO7}\xE3h2Q\xB8S\x18+&\xFE\x13\xFB\x1D\xDC\xE0M\x1AB\xC7\xD4\x9A\x89m'\xE7k\xAB\xF9\xE1\xD6\xAC\xEE\xB3[\xA12\xC2R\xD0\xBC\xF5\xAD\x03", }, "hmac-sha2-256-96" => { false => "vO\xD4Mst\xD2 } _\xE3e\xC4\x8A\xAA\xCD\x9E*\xE2\xA5\xC0\xED\xBB\xD5\x99\x12 ^2\xC3\x9D7{\xD0\xCE\xF5Wy\"c\x1Ey\xB0", :standard => "\x1Du9\xC7\x12\xA4\x9B\r\b\x19e&\x04e\xCE\rp\xE8=\x87h\xBE2\xE0\xAE\x90\xFF\xB22az\x17\xA4IO7}\xE3h2Q\xB8S\x18+&\xFE\x13\xFB\x1D\xDC\xE0M\x1AB\xC7\xD4\x9A\x89m", }, "hmac-sha2-512" => { false => "vO\xD4Mst\xD2 } _\xE3e\xC4\x8A\xAA\xCD\x9E*\xE2\xA5\xC0\xED\xBB\xD5\x99\x12 ^2\xC3\x9D#/\xCF\x00\xE0I\xBC\xF3_\x95U*\xD7z\x81\xCEc\xC3\xBDA\xF2\xD8^J\xBF\xC05oI\xBA\xF2\xEA\x86\xF8h\x8B\xB2\xC89\xC8v\x1F\x04\x12\x80]&\xF5\xC8\xC0\x90D[\xE8\x1E\x95\x89\xEB\xF1\xF6\x9F\xB7\x84\xD5", :standard => "\x1Du9\xC7\x12\xA4\x9B\r\b\x19e&\x04e\xCE\rp\xE8=\x87h\xBE2\xE0\xAE\x90\xFF\xB22az\x17\xA4IO7}\xE3h2Q\xB8S\x18+&\xFE\x13N\x05f\xBDu\x98\xE4xF\xEC+RSTS\xF0\x9D\x04\xC9$cW\xEFo\"fy\x19\xD1yX\tYK\xE7\xF3kd\a\x12\xC7r\x7F[ \xBC\x0E4\x92\xC0 \x1F\xD8<\xB4\x01^\xA6\xDF\x04\xF5\x9B\x82\xC8", }, "hmac-sha2-512-96" => { false => "vO\xD4Mst\xD2 } _\xE3e\xC4\x8A\xAA\xCD\x9E*\xE2\xA5\xC0\xED\xBB\xD5\x99\x12 ^2\xC3\x9D#/\xCF\x00\xE0I\xBC\xF3_\x95U*", :standard => "\x1Du9\xC7\x12\xA4\x9B\r\b\x19e&\x04e\xCE\rp\xE8=\x87h\xBE2\xE0\xAE\x90\xFF\xB22az\x17\xA4IO7}\xE3h2Q\xB8S\x18+&\xFE\x13N\x05f\xBDu\x98\xE4xF\xEC+R", }, }, "camellia192-cbc" => { "hmac-sha2-256" => { false => "Nnl\x00\xD2\xBA\x89j-(\xDD\xF4\\\x19\xF4\xB7\x16,\x90\xEA,\xE26\x00I\xF9\xB5Z\x060\x83E7{\xD0\xCE\xF5Wy\"c\x1Ey\xB0-\xBD\xCA~\x8F\x10U\xED\x01\xFF\x95F\xE5\x86\xAD\xC7\x13N\xE8J", :standard => "\x8Cm\x02.\x18\xFA\x87\x7F\x18a\xA8\xAC \x82u\xC7]\xE6rs/\xB3\xF5.>Aw\x96\xEF\xADLO\xDE[\x02\x14k\xCEn\x06\xF6\xBD^\"4';\x12\xFB\x1D\xDC\xE0M\x1AB\xC7\xD4\x9A\x89m'\xE7k\xAB\xF9\xE1\xD6\xAC\xEE\xB3[\xA12\xC2R\xD0\xBC\xF5\xAD\x03", }, "hmac-sha2-256-96" => { false => "Nnl\x00\xD2\xBA\x89j-(\xDD\xF4\\\x19\xF4\xB7\x16,\x90\xEA,\xE26\x00I\xF9\xB5Z\x060\x83E7{\xD0\xCE\xF5Wy\"c\x1Ey\xB0", :standard => "\x8Cm\x02.\x18\xFA\x87\x7F\x18a\xA8\xAC \x82u\xC7]\xE6rs/\xB3\xF5.>Aw\x96\xEF\xADLO\xDE[\x02\x14k\xCEn\x06\xF6\xBD^\"4';\x12\xFB\x1D\xDC\xE0M\x1AB\xC7\xD4\x9A\x89m", }, "hmac-sha2-512" => { false => "Nnl\x00\xD2\xBA\x89j-(\xDD\xF4\\\x19\xF4\xB7\x16,\x90\xEA,\xE26\x00I\xF9\xB5Z\x060\x83E#/\xCF\x00\xE0I\xBC\xF3_\x95U*\xD7z\x81\xCEc\xC3\xBDA\xF2\xD8^J\xBF\xC05oI\xBA\xF2\xEA\x86\xF8h\x8B\xB2\xC89\xC8v\x1F\x04\x12\x80]&\xF5\xC8\xC0\x90D[\xE8\x1E\x95\x89\xEB\xF1\xF6\x9F\xB7\x84\xD5", :standard => "\x8Cm\x02.\x18\xFA\x87\x7F\x18a\xA8\xAC \x82u\xC7]\xE6rs/\xB3\xF5.>Aw\x96\xEF\xADLO\xDE[\x02\x14k\xCEn\x06\xF6\xBD^\"4';\x12N\x05f\xBDu\x98\xE4xF\xEC+RSTS\xF0\x9D\x04\xC9$cW\xEFo\"fy\x19\xD1yX\tYK\xE7\xF3kd\a\x12\xC7r\x7F[ \xBC\x0E4\x92\xC0 \x1F\xD8<\xB4\x01^\xA6\xDF\x04\xF5\x9B\x82\xC8", }, "hmac-sha2-512-96" => { false => "Nnl\x00\xD2\xBA\x89j-(\xDD\xF4\\\x19\xF4\xB7\x16,\x90\xEA,\xE26\x00I\xF9\xB5Z\x060\x83E#/\xCF\x00\xE0I\xBC\xF3_\x95U*", :standard => "\x8Cm\x02.\x18\xFA\x87\x7F\x18a\xA8\xAC \x82u\xC7]\xE6rs/\xB3\xF5.>Aw\x96\xEF\xADLO\xDE[\x02\x14k\xCEn\x06\xF6\xBD^\"4';\x12N\x05f\xBDu\x98\xE4xF\xEC+R", }, }, "camellia256-cbc" => { "hmac-sha2-256" => { false => "\xE9\xAB&\x85*\x8B\x9C\xFF\xC9\xD2\x91\xE7\e\xE7P]\xD7\t\xA0\x99\a\xCD\x83K\x161\xA4\xBD\xCE\x82y|7{\xD0\xCE\xF5Wy\"c\x1Ey\xB0-\xBD\xCA~\x8F\x10U\xED\x01\xFF\x95F\xE5\x86\xAD\xC7\x13N\xE8J", :standard => "\x9D\x87\e\x99\x80mG\ex-\xA1\xEFA\xBB\xBD+!\xF9s\xC1\xBA_\xA8\xE0\x82\xBEX\xA6\xE8\x85\x1E\xBA\xAFY\x0E\xAC\xCB\xE1\xBF\xD1\xFD\xC3X\x8A\xF1qFi\xFB\x1D\xDC\xE0M\x1AB\xC7\xD4\x9A\x89m'\xE7k\xAB\xF9\xE1\xD6\xAC\xEE\xB3[\xA12\xC2R\xD0\xBC\xF5\xAD\x03", }, "hmac-sha2-256-96" => { false => "\xE9\xAB&\x85*\x8B\x9C\xFF\xC9\xD2\x91\xE7\e\xE7P]\xD7\t\xA0\x99\a\xCD\x83K\x161\xA4\xBD\xCE\x82y|7{\xD0\xCE\xF5Wy\"c\x1Ey\xB0", :standard => "\x9D\x87\e\x99\x80mG\ex-\xA1\xEFA\xBB\xBD+!\xF9s\xC1\xBA_\xA8\xE0\x82\xBEX\xA6\xE8\x85\x1E\xBA\xAFY\x0E\xAC\xCB\xE1\xBF\xD1\xFD\xC3X\x8A\xF1qFi\xFB\x1D\xDC\xE0M\x1AB\xC7\xD4\x9A\x89m", }, "hmac-sha2-512" => { false => "\xE9\xAB&\x85*\x8B\x9C\xFF\xC9\xD2\x91\xE7\e\xE7P]\xD7\t\xA0\x99\a\xCD\x83K\x161\xA4\xBD\xCE\x82y|#/\xCF\x00\xE0I\xBC\xF3_\x95U*\xD7z\x81\xCEc\xC3\xBDA\xF2\xD8^J\xBF\xC05oI\xBA\xF2\xEA\x86\xF8h\x8B\xB2\xC89\xC8v\x1F\x04\x12\x80]&\xF5\xC8\xC0\x90D[\xE8\x1E\x95\x89\xEB\xF1\xF6\x9F\xB7\x84\xD5", :standard => "\x9D\x87\e\x99\x80mG\ex-\xA1\xEFA\xBB\xBD+!\xF9s\xC1\xBA_\xA8\xE0\x82\xBEX\xA6\xE8\x85\x1E\xBA\xAFY\x0E\xAC\xCB\xE1\xBF\xD1\xFD\xC3X\x8A\xF1qFiN\x05f\xBDu\x98\xE4xF\xEC+RSTS\xF0\x9D\x04\xC9$cW\xEFo\"fy\x19\xD1yX\tYK\xE7\xF3kd\a\x12\xC7r\x7F[ \xBC\x0E4\x92\xC0 \x1F\xD8<\xB4\x01^\xA6\xDF\x04\xF5\x9B\x82\xC8", }, "hmac-sha2-512-96" => { false => "\xE9\xAB&\x85*\x8B\x9C\xFF\xC9\xD2\x91\xE7\e\xE7P]\xD7\t\xA0\x99\a\xCD\x83K\x161\xA4\xBD\xCE\x82y|#/\xCF\x00\xE0I\xBC\xF3_\x95U*", :standard => "\x9D\x87\e\x99\x80mG\ex-\xA1\xEFA\xBB\xBD+!\xF9s\xC1\xBA_\xA8\xE0\x82\xBEX\xA6\xE8\x85\x1E\xBA\xAFY\x0E\xAC\xCB\xE1\xBF\xD1\xFD\xC3X\x8A\xF1qFiN\x05f\xBDu\x98\xE4xF\xEC+R", }, }, "3des-ctr" => { "hmac-sha2-256" => { false => "\xED#\x86\xD5\xE1mP\v\f\xB9\xC1\xE6\xFD\xA0~,\xD3\x13\x12\x8Cp\xD4F\x92\xCB\xB6R>\xFA]\x9B\xB17{\xD0\xCE\xF5Wy\"c\x1Ey\xB0-\xBD\xCA~\x8F\x10U\xED\x01\xFF\x95F\xE5\x86\xAD\xC7\x13N\xE8J", :standard => "\xED#\x86\xED\xE0\x11\xCDim\xDD\xA8\xE2x\x8EB\x06\x9E73$\xBC\x9FA\xE0\xDB\xAE\x11Y\xAD\xED\xD43\x86N\x89\xFE\x14V\x91B\xF7F\x99v\xB5o\f9$\x94\x81\e\xF4+\x96H\xFC\xFF=\ts\x82`\x16\e,\xE7\t\x8F\x86t\xC7", }, "hmac-sha2-256-96" => { false => "\xED#\x86\xD5\xE1mP\v\f\xB9\xC1\xE6\xFD\xA0~,\xD3\x13\x12\x8Cp\xD4F\x92\xCB\xB6R>\xFA]\x9B\xB17{\xD0\xCE\xF5Wy\"c\x1Ey\xB0", :standard => "\xED#\x86\xED\xE0\x11\xCDim\xDD\xA8\xE2x\x8EB\x06\x9E73$\xBC\x9FA\xE0\xDB\xAE\x11Y\xAD\xED\xD43\x86N\x89\xFE\x14V\x91B\xF7F\x99v\xB5o\f9$\x94\x81\e", }, "hmac-sha2-512" => { false => "\xED#\x86\xD5\xE1mP\v\f\xB9\xC1\xE6\xFD\xA0~,\xD3\x13\x12\x8Cp\xD4F\x92\xCB\xB6R>\xFA]\x9B\xB1#/\xCF\x00\xE0I\xBC\xF3_\x95U*\xD7z\x81\xCEc\xC3\xBDA\xF2\xD8^J\xBF\xC05oI\xBA\xF2\xEA\x86\xF8h\x8B\xB2\xC89\xC8v\x1F\x04\x12\x80]&\xF5\xC8\xC0\x90D[\xE8\x1E\x95\x89\xEB\xF1\xF6\x9F\xB7\x84\xD5", :standard => "\xED#\x86\xED\xE0\x11\xCDim\xDD\xA8\xE2x\x8EB\x06\x9E73$\xBC\x9FA\xE0\xDB\xAE\x11Y\xAD\xED\xD43\x86N\x89\xFE\x14V\x91BQ\xC92O\x93\xF1\x8E\x9D\x12\x8E\x0E2\xAE\xE3\x8C\xD0\v\xD1\xF6/$\x0F]2\xC2\xE35\x8F\xD4\xA5\x1F\xC1\x95p\xB8\x91c\xC7\xC2u\x8Bb 4#\x82PFI\xF9\xB7l\xFC\xC9\x01\xB2z(\xDD|\xDC\xA46\x96", }, "hmac-sha2-512-96" => { false => "\xED#\x86\xD5\xE1mP\v\f\xB9\xC1\xE6\xFD\xA0~,\xD3\x13\x12\x8Cp\xD4F\x92\xCB\xB6R>\xFA]\x9B\xB1#/\xCF\x00\xE0I\xBC\xF3_\x95U*", :standard => "\xED#\x86\xED\xE0\x11\xCDim\xDD\xA8\xE2x\x8EB\x06\x9E73$\xBC\x9FA\xE0\xDB\xAE\x11Y\xAD\xED\xD43\x86N\x89\xFE\x14V\x91BQ\xC92O\x93\xF1\x8E\x9D\x12\x8E\x0E2", }, }, "blowfish-ctr" => { "hmac-sha2-256" => { false => "\xF7gk6\xB8\xACK\x1D\xC4Ls\xB0{\x0F\xC7\xC4M\xC5>\xF6G8\xD4\xBCu\x152FoJ\xB0\xC07{\xD0\xCE\xF5Wy\"c\x1Ey\xB0-\xBD\xCA~\x8F\x10U\xED\x01\xFF\x95F\xE5\x86\xAD\xC7\x13N\xE8J", :standard => "\xF7gk\x0E\xB9\xD0\xD6\x7F\xA5(\x1A\xB4\xFE!\xFB\xEE\x00\xE1\x1F^\x8Bs\xD3\xCEe\rq!8\xFA\xFFB\r\xE9\xFC\xF6\xCA\xBC\x03\xA9\xF7F\x99v\xB5o\f9$\x94\x81\e\xF4+\x96H\xFC\xFF=\ts\x82`\x16\e,\xE7\t\x8F\x86t\xC7", }, "hmac-sha2-256-96" => { false => "\xF7gk6\xB8\xACK\x1D\xC4Ls\xB0{\x0F\xC7\xC4M\xC5>\xF6G8\xD4\xBCu\x152FoJ\xB0\xC07{\xD0\xCE\xF5Wy\"c\x1Ey\xB0", :standard => "\xF7gk\x0E\xB9\xD0\xD6\x7F\xA5(\x1A\xB4\xFE!\xFB\xEE\x00\xE1\x1F^\x8Bs\xD3\xCEe\rq!8\xFA\xFFB\r\xE9\xFC\xF6\xCA\xBC\x03\xA9\xF7F\x99v\xB5o\f9$\x94\x81\e", }, "hmac-sha2-512" => { false => "\xF7gk6\xB8\xACK\x1D\xC4Ls\xB0{\x0F\xC7\xC4M\xC5>\xF6G8\xD4\xBCu\x152FoJ\xB0\xC0#/\xCF\x00\xE0I\xBC\xF3_\x95U*\xD7z\x81\xCEc\xC3\xBDA\xF2\xD8^J\xBF\xC05oI\xBA\xF2\xEA\x86\xF8h\x8B\xB2\xC89\xC8v\x1F\x04\x12\x80]&\xF5\xC8\xC0\x90D[\xE8\x1E\x95\x89\xEB\xF1\xF6\x9F\xB7\x84\xD5", :standard => "\xF7gk\x0E\xB9\xD0\xD6\x7F\xA5(\x1A\xB4\xFE!\xFB\xEE\x00\xE1\x1F^\x8Bs\xD3\xCEe\rq!8\xFA\xFFB\r\xE9\xFC\xF6\xCA\xBC\x03\xA9Q\xC92O\x93\xF1\x8E\x9D\x12\x8E\x0E2\xAE\xE3\x8C\xD0\v\xD1\xF6/$\x0F]2\xC2\xE35\x8F\xD4\xA5\x1F\xC1\x95p\xB8\x91c\xC7\xC2u\x8Bb 4#\x82PFI\xF9\xB7l\xFC\xC9\x01\xB2z(\xDD|\xDC\xA46\x96", }, "hmac-sha2-512-96" => { false => "\xF7gk6\xB8\xACK\x1D\xC4Ls\xB0{\x0F\xC7\xC4M\xC5>\xF6G8\xD4\xBCu\x152FoJ\xB0\xC0#/\xCF\x00\xE0I\xBC\xF3_\x95U*", :standard => "\xF7gk\x0E\xB9\xD0\xD6\x7F\xA5(\x1A\xB4\xFE!\xFB\xEE\x00\xE1\x1F^\x8Bs\xD3\xCEe\rq!8\xFA\xFFB\r\xE9\xFC\xF6\xCA\xBC\x03\xA9Q\xC92O\x93\xF1\x8E\x9D\x12\x8E\x0E2", }, }, "aes128-ctr" => { "hmac-sha2-256" => { false => "\xD6\x98\xC1n+6\xCA`s2\x06\xAA\x80\xFA\xF3\xF6\xCA\xF9\xC8[BB\xDC\x9F\xDC$\x88*\xA7\x00\x8E\xFD7{\xD0\xCE\xF5Wy\"c\x1Ey\xB0-\xBD\xCA~\x8F\x10U\xED\x01\xFF\x95F\xE5\x86\xAD\xC7\x13N\xE8J", :standard => "\xD6\x98\xC1^2JW\x02\x12Vo\xAE\x05\xD4\xCF\xDC\x87\xDD\xE9\xF3\x8E\t\xDB\xED\xCC<\xCBM\xF0\xB0\xC1\x7F\xD7\x17\x931\xBC~\r\xF2\x87\xB89\x9B\x8B\xB3\x8E\x15\xFB\x1D\xDC\xE0M\x1AB\xC7\xD4\x9A\x89m'\xE7k\xAB\xF9\xE1\xD6\xAC\xEE\xB3[\xA12\xC2R\xD0\xBC\xF5\xAD\x03", }, "hmac-sha2-256-96" => { false => "\xD6\x98\xC1n+6\xCA`s2\x06\xAA\x80\xFA\xF3\xF6\xCA\xF9\xC8[BB\xDC\x9F\xDC$\x88*\xA7\x00\x8E\xFD7{\xD0\xCE\xF5Wy\"c\x1Ey\xB0", :standard => "\xD6\x98\xC1^2JW\x02\x12Vo\xAE\x05\xD4\xCF\xDC\x87\xDD\xE9\xF3\x8E\t\xDB\xED\xCC<\xCBM\xF0\xB0\xC1\x7F\xD7\x17\x931\xBC~\r\xF2\x87\xB89\x9B\x8B\xB3\x8E\x15\xFB\x1D\xDC\xE0M\x1AB\xC7\xD4\x9A\x89m", }, "hmac-sha2-512" => { false => "\xD6\x98\xC1n+6\xCA`s2\x06\xAA\x80\xFA\xF3\xF6\xCA\xF9\xC8[BB\xDC\x9F\xDC$\x88*\xA7\x00\x8E\xFD#/\xCF\x00\xE0I\xBC\xF3_\x95U*\xD7z\x81\xCEc\xC3\xBDA\xF2\xD8^J\xBF\xC05oI\xBA\xF2\xEA\x86\xF8h\x8B\xB2\xC89\xC8v\x1F\x04\x12\x80]&\xF5\xC8\xC0\x90D[\xE8\x1E\x95\x89\xEB\xF1\xF6\x9F\xB7\x84\xD5", :standard => "\xD6\x98\xC1^2JW\x02\x12Vo\xAE\x05\xD4\xCF\xDC\x87\xDD\xE9\xF3\x8E\t\xDB\xED\xCC<\xCBM\xF0\xB0\xC1\x7F\xD7\x17\x931\xBC~\r\xF2\x87\xB89\x9B\x8B\xB3\x8E\x15N\x05f\xBDu\x98\xE4xF\xEC+RSTS\xF0\x9D\x04\xC9$cW\xEFo\"fy\x19\xD1yX\tYK\xE7\xF3kd\a\x12\xC7r\x7F[ \xBC\x0E4\x92\xC0 \x1F\xD8<\xB4\x01^\xA6\xDF\x04\xF5\x9B\x82\xC8", }, "hmac-sha2-512-96" => { false => "\xD6\x98\xC1n+6\xCA`s2\x06\xAA\x80\xFA\xF3\xF6\xCA\xF9\xC8[BB\xDC\x9F\xDC$\x88*\xA7\x00\x8E\xFD#/\xCF\x00\xE0I\xBC\xF3_\x95U*", :standard => "\xD6\x98\xC1^2JW\x02\x12Vo\xAE\x05\xD4\xCF\xDC\x87\xDD\xE9\xF3\x8E\t\xDB\xED\xCC<\xCBM\xF0\xB0\xC1\x7F\xD7\x17\x931\xBC~\r\xF2\x87\xB89\x9B\x8B\xB3\x8E\x15N\x05f\xBDu\x98\xE4xF\xEC+R", }, }, "aes192-ctr" => { "hmac-sha2-256" => { false => "\xA8\x02\xB4-\xFBYo4F\"\xCF\xB8\x92\xF08\xAC\xE8\xECk\xECO\xE7\xF8\x01\xF8\xB0\x9E\x05\xFB\xA7\xA7\x917{\xD0\xCE\xF5Wy\"c\x1Ey\xB0-\xBD\xCA~\x8F\x10U\xED\x01\xFF\x95F\xE5\x86\xAD\xC7\x13N\xE8J", :standard => "\xA8\x02\xB4\x1D\xE2%\xF2V'F\xA6\xBC\x17\xDE\x04\x86\xA5\xC8JD\x83\xAC\xFFs\xE8\xA8\xDDb\xAC\x17\xE8\x13\x92V\x9E\x00!\x1F\xD4\x00\x92T\x15\xDE\xA4\xCA\xE9\xC1\xFB\x1D\xDC\xE0M\x1AB\xC7\xD4\x9A\x89m'\xE7k\xAB\xF9\xE1\xD6\xAC\xEE\xB3[\xA12\xC2R\xD0\xBC\xF5\xAD\x03", }, "hmac-sha2-256-96" => { false => "\xA8\x02\xB4-\xFBYo4F\"\xCF\xB8\x92\xF08\xAC\xE8\xECk\xECO\xE7\xF8\x01\xF8\xB0\x9E\x05\xFB\xA7\xA7\x917{\xD0\xCE\xF5Wy\"c\x1Ey\xB0", :standard => "\xA8\x02\xB4\x1D\xE2%\xF2V'F\xA6\xBC\x17\xDE\x04\x86\xA5\xC8JD\x83\xAC\xFFs\xE8\xA8\xDDb\xAC\x17\xE8\x13\x92V\x9E\x00!\x1F\xD4\x00\x92T\x15\xDE\xA4\xCA\xE9\xC1\xFB\x1D\xDC\xE0M\x1AB\xC7\xD4\x9A\x89m", }, "hmac-sha2-512" => { false => "\xA8\x02\xB4-\xFBYo4F\"\xCF\xB8\x92\xF08\xAC\xE8\xECk\xECO\xE7\xF8\x01\xF8\xB0\x9E\x05\xFB\xA7\xA7\x91#/\xCF\x00\xE0I\xBC\xF3_\x95U*\xD7z\x81\xCEc\xC3\xBDA\xF2\xD8^J\xBF\xC05oI\xBA\xF2\xEA\x86\xF8h\x8B\xB2\xC89\xC8v\x1F\x04\x12\x80]&\xF5\xC8\xC0\x90D[\xE8\x1E\x95\x89\xEB\xF1\xF6\x9F\xB7\x84\xD5", :standard => "\xA8\x02\xB4\x1D\xE2%\xF2V'F\xA6\xBC\x17\xDE\x04\x86\xA5\xC8JD\x83\xAC\xFFs\xE8\xA8\xDDb\xAC\x17\xE8\x13\x92V\x9E\x00!\x1F\xD4\x00\x92T\x15\xDE\xA4\xCA\xE9\xC1N\x05f\xBDu\x98\xE4xF\xEC+RSTS\xF0\x9D\x04\xC9$cW\xEFo\"fy\x19\xD1yX\tYK\xE7\xF3kd\a\x12\xC7r\x7F[ \xBC\x0E4\x92\xC0 \x1F\xD8<\xB4\x01^\xA6\xDF\x04\xF5\x9B\x82\xC8", }, "hmac-sha2-512-96" => { false => "\xA8\x02\xB4-\xFBYo4F\"\xCF\xB8\x92\xF08\xAC\xE8\xECk\xECO\xE7\xF8\x01\xF8\xB0\x9E\x05\xFB\xA7\xA7\x91#/\xCF\x00\xE0I\xBC\xF3_\x95U*", :standard => "\xA8\x02\xB4\x1D\xE2%\xF2V'F\xA6\xBC\x17\xDE\x04\x86\xA5\xC8JD\x83\xAC\xFFs\xE8\xA8\xDDb\xAC\x17\xE8\x13\x92V\x9E\x00!\x1F\xD4\x00\x92T\x15\xDE\xA4\xCA\xE9\xC1N\x05f\xBDu\x98\xE4xF\xEC+R", }, }, "aes256-ctr" => { "hmac-sha2-256" => { false => "M\x1DcA\r]\\\x95?&\xE3D[\xCC1\x9B\xE0\xAF\x96\xA8\x86Y\xBD\x16\xE5xR%u\xC9(\r7{\xD0\xCE\xF5Wy\"c\x1Ey\xB0-\xBD\xCA~\x8F\x10U\xED\x01\xFF\x95F\xE5\x86\xAD\xC7\x13N\xE8J", :standard => "M\x1Dcq\x14!\xC1\xF7^B\x8A@\xDE\xE2\r\xB1\xAD\x8B\xB7\x00J\x12\xBAd\xF5`\x11B\"yg\x8F\x9F\xAB\xC8 d\xB4\xE7^w\xC4\x89\a\x17\x15\x82\n\xFB\x1D\xDC\xE0M\x1AB\xC7\xD4\x9A\x89m'\xE7k\xAB\xF9\xE1\xD6\xAC\xEE\xB3[\xA12\xC2R\xD0\xBC\xF5\xAD\x03", }, "hmac-sha2-256-96" => { false => "M\x1DcA\r]\\\x95?&\xE3D[\xCC1\x9B\xE0\xAF\x96\xA8\x86Y\xBD\x16\xE5xR%u\xC9(\r7{\xD0\xCE\xF5Wy\"c\x1Ey\xB0", :standard => "M\x1Dcq\x14!\xC1\xF7^B\x8A@\xDE\xE2\r\xB1\xAD\x8B\xB7\x00J\x12\xBAd\xF5`\x11B\"yg\x8F\x9F\xAB\xC8 d\xB4\xE7^w\xC4\x89\a\x17\x15\x82\n\xFB\x1D\xDC\xE0M\x1AB\xC7\xD4\x9A\x89m", }, "hmac-sha2-512" => { false => "M\x1DcA\r]\\\x95?&\xE3D[\xCC1\x9B\xE0\xAF\x96\xA8\x86Y\xBD\x16\xE5xR%u\xC9(\r#/\xCF\x00\xE0I\xBC\xF3_\x95U*\xD7z\x81\xCEc\xC3\xBDA\xF2\xD8^J\xBF\xC05oI\xBA\xF2\xEA\x86\xF8h\x8B\xB2\xC89\xC8v\x1F\x04\x12\x80]&\xF5\xC8\xC0\x90D[\xE8\x1E\x95\x89\xEB\xF1\xF6\x9F\xB7\x84\xD5", :standard => "M\x1Dcq\x14!\xC1\xF7^B\x8A@\xDE\xE2\r\xB1\xAD\x8B\xB7\x00J\x12\xBAd\xF5`\x11B\"yg\x8F\x9F\xAB\xC8 d\xB4\xE7^w\xC4\x89\a\x17\x15\x82\nN\x05f\xBDu\x98\xE4xF\xEC+RSTS\xF0\x9D\x04\xC9$cW\xEFo\"fy\x19\xD1yX\tYK\xE7\xF3kd\a\x12\xC7r\x7F[ \xBC\x0E4\x92\xC0 \x1F\xD8<\xB4\x01^\xA6\xDF\x04\xF5\x9B\x82\xC8", }, "hmac-sha2-512-96" => { false => "M\x1DcA\r]\\\x95?&\xE3D[\xCC1\x9B\xE0\xAF\x96\xA8\x86Y\xBD\x16\xE5xR%u\xC9(\r#/\xCF\x00\xE0I\xBC\xF3_\x95U*", :standard => "M\x1Dcq\x14!\xC1\xF7^B\x8A@\xDE\xE2\r\xB1\xAD\x8B\xB7\x00J\x12\xBAd\xF5`\x11B\"yg\x8F\x9F\xAB\xC8 d\xB4\xE7^w\xC4\x89\a\x17\x15\x82\nN\x05f\xBDu\x98\xE4xF\xEC+R", }, }, "cast128-ctr" => { "hmac-sha2-256" => { false => "\x10\xA0cJ6W\xC9\xC7\x02\xF8\xCD\xE31\xF9\xE7n\x0Fj\x7F\x99\x8A\f\x84\x80\x80\xE8p\x9C\x14\x83\x1C\xC77{\xD0\xCE\xF5Wy\"c\x1Ey\xB0-\xBD\xCA~\x8F\x10U\xED\x01\xFF\x95F\xE5\x86\xAD\xC7\x13N\xE8J", :standard => "\x10\xA0cr7+T\xA5c\x9C\xA4\xE7\xB4\xD7\xDBDBN^1FG\x83\xF2\x90\xF03\xFBC3SE\xF7x;q\x89\xA80\xEA\xF7F\x99v\xB5o\f9$\x94\x81\e\xF4+\x96H\xFC\xFF=\ts\x82`\x16\e,\xE7\t\x8F\x86t\xC7", }, "hmac-sha2-256-96" => { false => "\x10\xA0cJ6W\xC9\xC7\x02\xF8\xCD\xE31\xF9\xE7n\x0Fj\x7F\x99\x8A\f\x84\x80\x80\xE8p\x9C\x14\x83\x1C\xC77{\xD0\xCE\xF5Wy\"c\x1Ey\xB0", :standard => "\x10\xA0cr7+T\xA5c\x9C\xA4\xE7\xB4\xD7\xDBDBN^1FG\x83\xF2\x90\xF03\xFBC3SE\xF7x;q\x89\xA80\xEA\xF7F\x99v\xB5o\f9$\x94\x81\e", }, "hmac-sha2-512" => { false => "\x10\xA0cJ6W\xC9\xC7\x02\xF8\xCD\xE31\xF9\xE7n\x0Fj\x7F\x99\x8A\f\x84\x80\x80\xE8p\x9C\x14\x83\x1C\xC7#/\xCF\x00\xE0I\xBC\xF3_\x95U*\xD7z\x81\xCEc\xC3\xBDA\xF2\xD8^J\xBF\xC05oI\xBA\xF2\xEA\x86\xF8h\x8B\xB2\xC89\xC8v\x1F\x04\x12\x80]&\xF5\xC8\xC0\x90D[\xE8\x1E\x95\x89\xEB\xF1\xF6\x9F\xB7\x84\xD5", :standard => "\x10\xA0cr7+T\xA5c\x9C\xA4\xE7\xB4\xD7\xDBDBN^1FG\x83\xF2\x90\xF03\xFBC3SE\xF7x;q\x89\xA80\xEAQ\xC92O\x93\xF1\x8E\x9D\x12\x8E\x0E2\xAE\xE3\x8C\xD0\v\xD1\xF6/$\x0F]2\xC2\xE35\x8F\xD4\xA5\x1F\xC1\x95p\xB8\x91c\xC7\xC2u\x8Bb 4#\x82PFI\xF9\xB7l\xFC\xC9\x01\xB2z(\xDD|\xDC\xA46\x96", }, "hmac-sha2-512-96" => { false => "\x10\xA0cJ6W\xC9\xC7\x02\xF8\xCD\xE31\xF9\xE7n\x0Fj\x7F\x99\x8A\f\x84\x80\x80\xE8p\x9C\x14\x83\x1C\xC7#/\xCF\x00\xE0I\xBC\xF3_\x95U*", :standard => "\x10\xA0cr7+T\xA5c\x9C\xA4\xE7\xB4\xD7\xDBDBN^1FG\x83\xF2\x90\xF03\xFBC3SE\xF7x;q\x89\xA80\xEAQ\xC92O\x93\xF1\x8E\x9D\x12\x8E\x0E2", }, }, "camellia128-ctr@openssh.org" => { "hmac-sha2-256" => { false => "\xE4>\xD9'`\xA5W\x9A\xB7\x19\xA9\x98\xB0\x87f2}\x0F\xBE\xBDS\xA8\xA5\x17\x10\x80\x10 "\xE4>\xD9\x17y\xD9\xCA\xF8\xD6}\xC0\x9C5\xA9Z\x180+\x9F\x15\x9F\xE3\xA2e\x00\x98S[\x00\xC71\x9D\xAEx\x19\x17m\x9E\xD6\xC5\x90\xE2d\xFA#\xEB\x94\xA9\xFB\x1D\xDC\xE0M\x1AB\xC7\xD4\x9A\x89m'\xE7k\xAB\xF9\xE1\xD6\xAC\xEE\xB3[\xA12\xC2R\xD0\xBC\xF5\xAD\x03", }, "hmac-sha2-256-96" => { false => "\xE4>\xD9'`\xA5W\x9A\xB7\x19\xA9\x98\xB0\x87f2}\x0F\xBE\xBDS\xA8\xA5\x17\x10\x80\x10 "\xE4>\xD9\x17y\xD9\xCA\xF8\xD6}\xC0\x9C5\xA9Z\x180+\x9F\x15\x9F\xE3\xA2e\x00\x98S[\x00\xC71\x9D\xAEx\x19\x17m\x9E\xD6\xC5\x90\xE2d\xFA#\xEB\x94\xA9\xFB\x1D\xDC\xE0M\x1AB\xC7\xD4\x9A\x89m", }, "hmac-sha2-512" => { false => "\xE4>\xD9'`\xA5W\x9A\xB7\x19\xA9\x98\xB0\x87f2}\x0F\xBE\xBDS\xA8\xA5\x17\x10\x80\x10 "\xE4>\xD9\x17y\xD9\xCA\xF8\xD6}\xC0\x9C5\xA9Z\x180+\x9F\x15\x9F\xE3\xA2e\x00\x98S[\x00\xC71\x9D\xAEx\x19\x17m\x9E\xD6\xC5\x90\xE2d\xFA#\xEB\x94\xA9N\x05f\xBDu\x98\xE4xF\xEC+RSTS\xF0\x9D\x04\xC9$cW\xEFo\"fy\x19\xD1yX\tYK\xE7\xF3kd\a\x12\xC7r\x7F[ \xBC\x0E4\x92\xC0 \x1F\xD8<\xB4\x01^\xA6\xDF\x04\xF5\x9B\x82\xC8", }, "hmac-sha2-512-96" => { false => "\xE4>\xD9'`\xA5W\x9A\xB7\x19\xA9\x98\xB0\x87f2}\x0F\xBE\xBDS\xA8\xA5\x17\x10\x80\x10 "\xE4>\xD9\x17y\xD9\xCA\xF8\xD6}\xC0\x9C5\xA9Z\x180+\x9F\x15\x9F\xE3\xA2e\x00\x98S[\x00\xC71\x9D\xAEx\x19\x17m\x9E\xD6\xC5\x90\xE2d\xFA#\xEB\x94\xA9N\x05f\xBDu\x98\xE4xF\xEC+R", }, }, "camellia192-ctr@openssh.org" => { "hmac-sha2-256" => { false => "\xEE8:\xB5\x0E\xED\xF4?yh\x8A\xB2{\xF5\x8DH\x95\xA4\xFA\xDF\x01\xAC\xC4\xD5Xb\xBB\xC1\x8B\xD7\xBC\xBE7{\xD0\xCE\xF5Wy\"c\x1Ey\xB0-\xBD\xCA~\x8F\x10U\xED\x01\xFF\x95F\xE5\x86\xAD\xC7\x13N\xE8J", :standard => "\xEE8:\x85\x17\x91i]\x18\f\xE3\xB6\xFE\xDB\xB1b\xD8\x80\xDBw\xCD\xE7\xC3\xA7Hz\xF8\xA6\xDCg\xF3 { false => "\xEE8:\xB5\x0E\xED\xF4?yh\x8A\xB2{\xF5\x8DH\x95\xA4\xFA\xDF\x01\xAC\xC4\xD5Xb\xBB\xC1\x8B\xD7\xBC\xBE7{\xD0\xCE\xF5Wy\"c\x1Ey\xB0", :standard => "\xEE8:\x85\x17\x91i]\x18\f\xE3\xB6\xFE\xDB\xB1b\xD8\x80\xDBw\xCD\xE7\xC3\xA7Hz\xF8\xA6\xDCg\xF3 { false => "\xEE8:\xB5\x0E\xED\xF4?yh\x8A\xB2{\xF5\x8DH\x95\xA4\xFA\xDF\x01\xAC\xC4\xD5Xb\xBB\xC1\x8B\xD7\xBC\xBE#/\xCF\x00\xE0I\xBC\xF3_\x95U*\xD7z\x81\xCEc\xC3\xBDA\xF2\xD8^J\xBF\xC05oI\xBA\xF2\xEA\x86\xF8h\x8B\xB2\xC89\xC8v\x1F\x04\x12\x80]&\xF5\xC8\xC0\x90D[\xE8\x1E\x95\x89\xEB\xF1\xF6\x9F\xB7\x84\xD5", :standard => "\xEE8:\x85\x17\x91i]\x18\f\xE3\xB6\xFE\xDB\xB1b\xD8\x80\xDBw\xCD\xE7\xC3\xA7Hz\xF8\xA6\xDCg\xF3 { false => "\xEE8:\xB5\x0E\xED\xF4?yh\x8A\xB2{\xF5\x8DH\x95\xA4\xFA\xDF\x01\xAC\xC4\xD5Xb\xBB\xC1\x8B\xD7\xBC\xBE#/\xCF\x00\xE0I\xBC\xF3_\x95U*", :standard => "\xEE8:\x85\x17\x91i]\x18\f\xE3\xB6\xFE\xDB\xB1b\xD8\x80\xDBw\xCD\xE7\xC3\xA7Hz\xF8\xA6\xDCg\xF3 { "hmac-sha2-256" => { false => "\xE3-1\x8E\xA1\xB7\x95\x9E`\x1E\xFB:[\xFD\x15\x8Ee\xD6|\xB6q\xF98\xFF\t\xB3\xD4F\x03\xB3\xFA\xEC7{\xD0\xCE\xF5Wy\"c\x1Ey\xB0-\xBD\xCA~\x8F\x10U\xED\x01\xFF\x95F\xE5\x86\xAD\xC7\x13N\xE8J", :standard => "\xE3-1\xBE\xB8\xCB\b\xFC\x01z\x92>\xDE\xD3)\xA4(\xF2]\x1E\xBD\xB2?\x8D\x19\xAB\x97!T\x03\xB5n\xC0)\xBE.]\x92\xF5\x05~\t\x04\x99\xFB\xDC\xD6\x93\xFB\x1D\xDC\xE0M\x1AB\xC7\xD4\x9A\x89m'\xE7k\xAB\xF9\xE1\xD6\xAC\xEE\xB3[\xA12\xC2R\xD0\xBC\xF5\xAD\x03", }, "hmac-sha2-256-96" => { false => "\xE3-1\x8E\xA1\xB7\x95\x9E`\x1E\xFB:[\xFD\x15\x8Ee\xD6|\xB6q\xF98\xFF\t\xB3\xD4F\x03\xB3\xFA\xEC7{\xD0\xCE\xF5Wy\"c\x1Ey\xB0", :standard => "\xE3-1\xBE\xB8\xCB\b\xFC\x01z\x92>\xDE\xD3)\xA4(\xF2]\x1E\xBD\xB2?\x8D\x19\xAB\x97!T\x03\xB5n\xC0)\xBE.]\x92\xF5\x05~\t\x04\x99\xFB\xDC\xD6\x93\xFB\x1D\xDC\xE0M\x1AB\xC7\xD4\x9A\x89m", }, "hmac-sha2-512" => { false => "\xE3-1\x8E\xA1\xB7\x95\x9E`\x1E\xFB:[\xFD\x15\x8Ee\xD6|\xB6q\xF98\xFF\t\xB3\xD4F\x03\xB3\xFA\xEC#/\xCF\x00\xE0I\xBC\xF3_\x95U*\xD7z\x81\xCEc\xC3\xBDA\xF2\xD8^J\xBF\xC05oI\xBA\xF2\xEA\x86\xF8h\x8B\xB2\xC89\xC8v\x1F\x04\x12\x80]&\xF5\xC8\xC0\x90D[\xE8\x1E\x95\x89\xEB\xF1\xF6\x9F\xB7\x84\xD5", :standard => "\xE3-1\xBE\xB8\xCB\b\xFC\x01z\x92>\xDE\xD3)\xA4(\xF2]\x1E\xBD\xB2?\x8D\x19\xAB\x97!T\x03\xB5n\xC0)\xBE.]\x92\xF5\x05~\t\x04\x99\xFB\xDC\xD6\x93N\x05f\xBDu\x98\xE4xF\xEC+RSTS\xF0\x9D\x04\xC9$cW\xEFo\"fy\x19\xD1yX\tYK\xE7\xF3kd\a\x12\xC7r\x7F[ \xBC\x0E4\x92\xC0 \x1F\xD8<\xB4\x01^\xA6\xDF\x04\xF5\x9B\x82\xC8", }, "hmac-sha2-512-96" => { false => "\xE3-1\x8E\xA1\xB7\x95\x9E`\x1E\xFB:[\xFD\x15\x8Ee\xD6|\xB6q\xF98\xFF\t\xB3\xD4F\x03\xB3\xFA\xEC#/\xCF\x00\xE0I\xBC\xF3_\x95U*", :standard => "\xE3-1\xBE\xB8\xCB\b\xFC\x01z\x92>\xDE\xD3)\xA4(\xF2]\x1E\xBD\xB2?\x8D\x19\xAB\x97!T\x03\xB5n\xC0)\xBE.]\x92\xF5\x05~\t\x04\x99\xFB\xDC\xD6\x93N\x05f\xBDu\x98\xE4xF\xEC+R", }, }, "camellia128-ctr" => { "hmac-sha2-256" => { false => "\xE4>\xD9'`\xA5W\x9A\xB7\x19\xA9\x98\xB0\x87f2}\x0F\xBE\xBDS\xA8\xA5\x17\x10\x80\x10 "\xE4>\xD9\x17y\xD9\xCA\xF8\xD6}\xC0\x9C5\xA9Z\x180+\x9F\x15\x9F\xE3\xA2e\x00\x98S[\x00\xC71\x9D\xAEx\x19\x17m\x9E\xD6\xC5\x90\xE2d\xFA#\xEB\x94\xA9\xFB\x1D\xDC\xE0M\x1AB\xC7\xD4\x9A\x89m'\xE7k\xAB\xF9\xE1\xD6\xAC\xEE\xB3[\xA12\xC2R\xD0\xBC\xF5\xAD\x03", }, "hmac-sha2-256-96" => { false => "\xE4>\xD9'`\xA5W\x9A\xB7\x19\xA9\x98\xB0\x87f2}\x0F\xBE\xBDS\xA8\xA5\x17\x10\x80\x10 "\xE4>\xD9\x17y\xD9\xCA\xF8\xD6}\xC0\x9C5\xA9Z\x180+\x9F\x15\x9F\xE3\xA2e\x00\x98S[\x00\xC71\x9D\xAEx\x19\x17m\x9E\xD6\xC5\x90\xE2d\xFA#\xEB\x94\xA9\xFB\x1D\xDC\xE0M\x1AB\xC7\xD4\x9A\x89m", }, "hmac-sha2-512" => { false => "\xE4>\xD9'`\xA5W\x9A\xB7\x19\xA9\x98\xB0\x87f2}\x0F\xBE\xBDS\xA8\xA5\x17\x10\x80\x10 "\xE4>\xD9\x17y\xD9\xCA\xF8\xD6}\xC0\x9C5\xA9Z\x180+\x9F\x15\x9F\xE3\xA2e\x00\x98S[\x00\xC71\x9D\xAEx\x19\x17m\x9E\xD6\xC5\x90\xE2d\xFA#\xEB\x94\xA9N\x05f\xBDu\x98\xE4xF\xEC+RSTS\xF0\x9D\x04\xC9$cW\xEFo\"fy\x19\xD1yX\tYK\xE7\xF3kd\a\x12\xC7r\x7F[ \xBC\x0E4\x92\xC0 \x1F\xD8<\xB4\x01^\xA6\xDF\x04\xF5\x9B\x82\xC8", }, "hmac-sha2-512-96" => { false => "\xE4>\xD9'`\xA5W\x9A\xB7\x19\xA9\x98\xB0\x87f2}\x0F\xBE\xBDS\xA8\xA5\x17\x10\x80\x10 "\xE4>\xD9\x17y\xD9\xCA\xF8\xD6}\xC0\x9C5\xA9Z\x180+\x9F\x15\x9F\xE3\xA2e\x00\x98S[\x00\xC71\x9D\xAEx\x19\x17m\x9E\xD6\xC5\x90\xE2d\xFA#\xEB\x94\xA9N\x05f\xBDu\x98\xE4xF\xEC+R", }, }, "camellia192-ctr" => { "hmac-sha2-256" => { false => "\xEE8:\xB5\x0E\xED\xF4?yh\x8A\xB2{\xF5\x8DH\x95\xA4\xFA\xDF\x01\xAC\xC4\xD5Xb\xBB\xC1\x8B\xD7\xBC\xBE7{\xD0\xCE\xF5Wy\"c\x1Ey\xB0-\xBD\xCA~\x8F\x10U\xED\x01\xFF\x95F\xE5\x86\xAD\xC7\x13N\xE8J", :standard => "\xEE8:\x85\x17\x91i]\x18\f\xE3\xB6\xFE\xDB\xB1b\xD8\x80\xDBw\xCD\xE7\xC3\xA7Hz\xF8\xA6\xDCg\xF3 { false => "\xEE8:\xB5\x0E\xED\xF4?yh\x8A\xB2{\xF5\x8DH\x95\xA4\xFA\xDF\x01\xAC\xC4\xD5Xb\xBB\xC1\x8B\xD7\xBC\xBE7{\xD0\xCE\xF5Wy\"c\x1Ey\xB0", :standard => "\xEE8:\x85\x17\x91i]\x18\f\xE3\xB6\xFE\xDB\xB1b\xD8\x80\xDBw\xCD\xE7\xC3\xA7Hz\xF8\xA6\xDCg\xF3 { false => "\xEE8:\xB5\x0E\xED\xF4?yh\x8A\xB2{\xF5\x8DH\x95\xA4\xFA\xDF\x01\xAC\xC4\xD5Xb\xBB\xC1\x8B\xD7\xBC\xBE#/\xCF\x00\xE0I\xBC\xF3_\x95U*\xD7z\x81\xCEc\xC3\xBDA\xF2\xD8^J\xBF\xC05oI\xBA\xF2\xEA\x86\xF8h\x8B\xB2\xC89\xC8v\x1F\x04\x12\x80]&\xF5\xC8\xC0\x90D[\xE8\x1E\x95\x89\xEB\xF1\xF6\x9F\xB7\x84\xD5", :standard => "\xEE8:\x85\x17\x91i]\x18\f\xE3\xB6\xFE\xDB\xB1b\xD8\x80\xDBw\xCD\xE7\xC3\xA7Hz\xF8\xA6\xDCg\xF3 { false => "\xEE8:\xB5\x0E\xED\xF4?yh\x8A\xB2{\xF5\x8DH\x95\xA4\xFA\xDF\x01\xAC\xC4\xD5Xb\xBB\xC1\x8B\xD7\xBC\xBE#/\xCF\x00\xE0I\xBC\xF3_\x95U*", :standard => "\xEE8:\x85\x17\x91i]\x18\f\xE3\xB6\xFE\xDB\xB1b\xD8\x80\xDBw\xCD\xE7\xC3\xA7Hz\xF8\xA6\xDCg\xF3 { "hmac-sha2-256" => { false => "\xE3-1\x8E\xA1\xB7\x95\x9E`\x1E\xFB:[\xFD\x15\x8Ee\xD6|\xB6q\xF98\xFF\t\xB3\xD4F\x03\xB3\xFA\xEC7{\xD0\xCE\xF5Wy\"c\x1Ey\xB0-\xBD\xCA~\x8F\x10U\xED\x01\xFF\x95F\xE5\x86\xAD\xC7\x13N\xE8J", :standard => "\xE3-1\xBE\xB8\xCB\b\xFC\x01z\x92>\xDE\xD3)\xA4(\xF2]\x1E\xBD\xB2?\x8D\x19\xAB\x97!T\x03\xB5n\xC0)\xBE.]\x92\xF5\x05~\t\x04\x99\xFB\xDC\xD6\x93\xFB\x1D\xDC\xE0M\x1AB\xC7\xD4\x9A\x89m'\xE7k\xAB\xF9\xE1\xD6\xAC\xEE\xB3[\xA12\xC2R\xD0\xBC\xF5\xAD\x03", }, "hmac-sha2-256-96" => { false => "\xE3-1\x8E\xA1\xB7\x95\x9E`\x1E\xFB:[\xFD\x15\x8Ee\xD6|\xB6q\xF98\xFF\t\xB3\xD4F\x03\xB3\xFA\xEC7{\xD0\xCE\xF5Wy\"c\x1Ey\xB0", :standard => "\xE3-1\xBE\xB8\xCB\b\xFC\x01z\x92>\xDE\xD3)\xA4(\xF2]\x1E\xBD\xB2?\x8D\x19\xAB\x97!T\x03\xB5n\xC0)\xBE.]\x92\xF5\x05~\t\x04\x99\xFB\xDC\xD6\x93\xFB\x1D\xDC\xE0M\x1AB\xC7\xD4\x9A\x89m", }, "hmac-sha2-512" => { false => "\xE3-1\x8E\xA1\xB7\x95\x9E`\x1E\xFB:[\xFD\x15\x8Ee\xD6|\xB6q\xF98\xFF\t\xB3\xD4F\x03\xB3\xFA\xEC#/\xCF\x00\xE0I\xBC\xF3_\x95U*\xD7z\x81\xCEc\xC3\xBDA\xF2\xD8^J\xBF\xC05oI\xBA\xF2\xEA\x86\xF8h\x8B\xB2\xC89\xC8v\x1F\x04\x12\x80]&\xF5\xC8\xC0\x90D[\xE8\x1E\x95\x89\xEB\xF1\xF6\x9F\xB7\x84\xD5", :standard => "\xE3-1\xBE\xB8\xCB\b\xFC\x01z\x92>\xDE\xD3)\xA4(\xF2]\x1E\xBD\xB2?\x8D\x19\xAB\x97!T\x03\xB5n\xC0)\xBE.]\x92\xF5\x05~\t\x04\x99\xFB\xDC\xD6\x93N\x05f\xBDu\x98\xE4xF\xEC+RSTS\xF0\x9D\x04\xC9$cW\xEFo\"fy\x19\xD1yX\tYK\xE7\xF3kd\a\x12\xC7r\x7F[ \xBC\x0E4\x92\xC0 \x1F\xD8<\xB4\x01^\xA6\xDF\x04\xF5\x9B\x82\xC8", }, "hmac-sha2-512-96" => { false => "\xE3-1\x8E\xA1\xB7\x95\x9E`\x1E\xFB:[\xFD\x15\x8Ee\xD6|\xB6q\xF98\xFF\t\xB3\xD4F\x03\xB3\xFA\xEC#/\xCF\x00\xE0I\xBC\xF3_\x95U*", :standard => "\xE3-1\xBE\xB8\xCB\b\xFC\x01z\x92>\xDE\xD3)\xA4(\xF2]\x1E\xBD\xB2?\x8D\x19\xAB\x97!T\x03\xB5n\xC0)\xBE.]\x92\xF5\x05~\t\x04\x99\xFB\xDC\xD6\x93N\x05f\xBDu\x98\xE4xF\xEC+R", }, }, "none" => { "hmac-sha2-256" => { false => "\000\000\000\034\b\004\001\000\000\000\tdebugging\000\000\000\000\b\030CgWO\260\2127{\320\316\365Wy\"c\036y\260-\275\312~\217\020U\355\001\377\225F\345\206\255\307\023N\350J", :standard => "\000\000\000$\tx\234bad``\340LIM*MO\317\314K\ar\030\000\000\000\000\377\377\b\030CgWO\260\212^\367F\231v\265o\f9$\224\201\e\364+\226H\374\377=\ts\202`\026\e,\347\t\217\206t\307", }, "hmac-sha2-256-96" => { false => "\000\000\000\034\b\004\001\000\000\000\tdebugging\000\000\000\000\b\030CgWO\260\2127{\320\316\365Wy\"c\036y\260", :standard => "\000\000\000$\tx\234bad``\340LIM*MO\317\314K\ar\030\000\000\000\000\377\377\b\030CgWO\260\212^\367F\231v\265o\f9$\224\201\e", }, "hmac-sha2-512" => { false => "\000\000\000\034\b\004\001\000\000\000\tdebugging\000\000\000\000\b\030CgWO\260\212#/\317\000\340I\274\363_\225U*\327z\201\316c\303\275A\362\330^J\277\3005oI\272\362\352\206\370h\213\262\3109\310v\037\004\022\200]&\365\310\300\220D[\350\036\225\211\353\361\366\237\267\204\325", :standard => "\000\000\000$\tx\234bad``\340LIM*MO\317\314K\ar\030\000\000\000\000\377\377\b\030CgWO\260\212^Q\3112O\223\361\216\235\022\216\0162\256\343\214\320\v\321\366/$\017]2\302\3435\217\324\245\037\301\225p\270\221c\307\302u\213b 4#\202PFI\371\267l\374\311\001\262z(\335|\334\2446\226", }, "hmac-sha2-512-96" => { false => "\000\000\000\034\b\004\001\000\000\000\tdebugging\000\000\000\000\b\030CgWO\260\212#/\317\000\340I\274\363_\225U*", :standard => "\000\000\000$\tx\234bad``\340LIM*MO\317\314K\ar\030\000\000\000\000\377\377\b\030CgWO\260\212^Q\3112O\223\361\216\235\022\216\0162", }, }, "rijndael-cbc@lysator.liu.se" => { "hmac-sha2-256" => { false => "\266\001oG(\201s\255[\202j\031-\354\353]\022\374\367j2\257\b#\273r\275\341\232\264\255\3407{\320\316\365Wy\"c\036y\260-\275\312~\217\020U\355\001\377\225F\345\206\255\307\023N\350J", :standard => "\251!O/_\253\321\217e\225\202\202W\261p\r\357\357\375\231\264Y,nZ/\366\225G\256\3000\036\223\237\353\265vG\231\215cvY\236%\315\365\373\035\334\340M\032B\307\324\232\211m'\347k\253\371\341\326\254\356\263[\2412\302R\320\274\365\255\003", }, "hmac-sha2-256-96" => { false => "\266\001oG(\201s\255[\202j\031-\354\353]\022\374\367j2\257\b#\273r\275\341\232\264\255\3407{\320\316\365Wy\"c\036y\260", :standard => "\251!O/_\253\321\217e\225\202\202W\261p\r\357\357\375\231\264Y,nZ/\366\225G\256\3000\036\223\237\353\265vG\231\215cvY\236%\315\365\373\035\334\340M\032B\307\324\232\211m", }, "hmac-sha2-512" => { false => "\266\001oG(\201s\255[\202j\031-\354\353]\022\374\367j2\257\b#\273r\275\341\232\264\255\340#/\317\000\340I\274\363_\225U*\327z\201\316c\303\275A\362\330^J\277\3005oI\272\362\352\206\370h\213\262\3109\310v\037\004\022\200]&\365\310\300\220D[\350\036\225\211\353\361\366\237\267\204\325", :standard => "\251!O/_\253\321\217e\225\202\202W\261p\r\357\357\375\231\264Y,nZ/\366\225G\256\3000\036\223\237\353\265vG\231\215cvY\236%\315\365N\005f\275u\230\344xF\354+RSTS\360\235\004\311$cW\357o\"fy\031\321yX\tYK\347\363kd\a\022\307r\177[ \274\0164\222\300 \037\330<\264\001^\246\337\004\365\233\202\310", }, "hmac-sha2-512-96" => { false => "\266\001oG(\201s\255[\202j\031-\354\353]\022\374\367j2\257\b#\273r\275\341\232\264\255\340#/\317\000\340I\274\363_\225U*", :standard => "\251!O/_\253\321\217e\225\202\202W\261p\r\357\357\375\231\264Y,nZ/\366\225G\256\3000\036\223\237\353\265vG\231\215cvY\236%\315\365N\005f\275u\230\344xF\354+R", }, }, } sha2_packets.each do |key, val| PACKETS[key].merge!(val) end end ciphers = Net::SSH::Transport::CipherFactory::SSH_TO_OSSL.keys hmacs = Net::SSH::Transport::HMAC::MAP.keys ciphers.each do |cipher_name| unless Net::SSH::Transport::CipherFactory.supported?(cipher_name) puts "Skipping packet stream test for #{cipher_name}" next end # JRuby Zlib implementation (1.4 & 1.5) does not have byte-to-byte compatibility with MRI's. # skip these 80 or more tests under JRuby. if defined?(JRUBY_VERSION) puts "Skipping zlib tests for JRuby" next end hmacs.each do |hmac_name| [false, :standard].each do |compress| cipher_method_name = cipher_name.gsub(/\W/, "_") hmac_method_name = hmac_name.gsub(/\W/, "_") define_method("test_next_packet_with_#{cipher_method_name}_and_#{hmac_method_name}_and_#{compress}_compression") do opts = { :shared => "123", :hash => "^&*", :digester => OpenSSL::Digest::SHA1 } cipher = Net::SSH::Transport::CipherFactory.get(cipher_name, opts.merge(:key => "ABC", :decrypt => true, :iv => "abc")) hmac = Net::SSH::Transport::HMAC.get(hmac_name, "{}|", opts) stream.server.set :cipher => cipher, :hmac => hmac, :compression => compress stream.stubs(:recv).returns(PACKETS[cipher_name][hmac_name][compress]) IO.stubs(:select).returns([[stream]]) packet = stream.next_packet(:nonblock) assert_not_nil packet assert_equal DEBUG, packet.type assert packet[:always_display] assert_equal "debugging", packet[:message] assert_equal "", packet[:language] stream.cleanup end define_method("test_enqueue_packet_with_#{cipher_method_name}_and_#{hmac_method_name}_and_#{compress}_compression") do opts = { :shared => "123", :digester => OpenSSL::Digest::SHA1, :hash => "^&*" } cipher = Net::SSH::Transport::CipherFactory.get(cipher_name, opts.merge(:key => "ABC", :iv => "abc", :encrypt => true)) hmac = Net::SSH::Transport::HMAC.get(hmac_name, "{}|", opts) srand(100) stream.client.set :cipher => cipher, :hmac => hmac, :compression => compress stream.enqueue_packet(ssh_packet) assert_equal PACKETS[cipher_name][hmac_name][compress], stream.write_buffer stream.cleanup end end end end private def stream @stream ||= begin stream = mock("packet_stream") stream.extend(Net::SSH::Transport::PacketStream) stream end end def ssh_packet Net::SSH::Buffer.from(:byte, DEBUG, :bool, true, :string, "debugging", :string, "") end def packet @packet ||= begin data = ssh_packet length = data.length + 4 + 1 # length + padding length padding = stream.server.cipher.block_size - (length % stream.server.cipher.block_size) padding += stream.server.cipher.block_size if padding < 4 Net::SSH::Buffer.from(:long, length + padding - 4, :byte, padding, :raw, data, :raw, "\0" * padding).to_s end end end end net-ssh-2.6.8/test/transport/hmac/0000755000004100000410000000000012166626376017102 5ustar www-datawww-datanet-ssh-2.6.8/test/transport/hmac/test_none.rb0000644000004100000410000000135612166626376021432 0ustar www-datawww-datarequire 'common' require 'net/ssh/transport/hmac/none' module Transport; module HMAC class TestNone < Test::Unit::TestCase def test_expected_digest_class assert_equal nil, subject.digest_class assert_equal nil, subject.new.digest_class end def test_expected_key_length assert_equal 0, subject.key_length assert_equal 0, subject.new.key_length end def test_expected_mac_length assert_equal 0, subject.mac_length assert_equal 0, subject.new.mac_length end def test_expected_digest hmac = subject.new("1234567890123456") assert_equal "", hmac.digest("hello world") end private def subject Net::SSH::Transport::HMAC::None end end end; endnet-ssh-2.6.8/test/transport/hmac/test_md5.rb0000644000004100000410000000176612166626376021165 0ustar www-datawww-data# encoding: ASCII-8BIT require 'common' require 'net/ssh/transport/hmac/md5' module Transport; module HMAC class TestMD5 < Test::Unit::TestCase def test_expected_digest_class assert_equal OpenSSL::Digest::MD5, subject.digest_class assert_equal OpenSSL::Digest::MD5, subject.new.digest_class end def test_expected_key_length assert_equal 16, subject.key_length assert_equal 16, subject.new.key_length end def test_expected_mac_length assert_equal 16, subject.mac_length assert_equal 16, subject.new.mac_length end def test_expected_digest hmac = subject.new("1234567890123456") assert_equal "\275\345\006\307y~Oi\035<.\341\031\250<\257", hmac.digest("hello world") end def test_key_should_be_truncated_to_required_length hmac = subject.new("12345678901234567890") assert_equal "1234567890123456", hmac.key end private def subject Net::SSH::Transport::HMAC::MD5 end end end; endnet-ssh-2.6.8/test/transport/hmac/test_md5_96.rb0000644000004100000410000000106712166626376021475 0ustar www-datawww-data# encoding: ASCII-8BIT require 'common' require 'transport/hmac/test_md5' require 'net/ssh/transport/hmac/md5_96' module Transport; module HMAC class TestMD5_96 < TestMD5 def test_expected_mac_length assert_equal 12, subject.mac_length assert_equal 12, subject.new.mac_length end def test_expected_digest hmac = subject.new("1234567890123456") assert_equal "\275\345\006\307y~Oi\035<.\341", hmac.digest("hello world") end private def subject Net::SSH::Transport::HMAC::MD5_96 end end end; endnet-ssh-2.6.8/test/transport/hmac/test_sha2_512.rb0000644000004100000410000000175412166626376021721 0ustar www-datawww-data# encoding: ASCII-8BIT require 'common' require 'net/ssh/transport/hmac/sha2_512' module Transport; module HMAC class TestSHA2_512 < Test::Unit::TestCase def test_expected_digest_class assert_equal OpenSSL::Digest::SHA512, subject.digest_class assert_equal OpenSSL::Digest::SHA512, subject.new.digest_class end def test_expected_key_length assert_equal 64, subject.key_length assert_equal 64, subject.new.key_length end def test_expected_mac_length assert_equal 64, subject.mac_length assert_equal 64, subject.new.mac_length end def test_expected_digest hmac = subject.new("1234567890123456") assert_equal "^\xB6\"\xED\x8B\xC4\xDE\xD4\xCF\xD0\r\x18\xA0<\xF4\xB5\x01Efz\xA80i\xFC\x18\xC1\x9A+\xDD\xFE<\xA2\xFDE1Ac\xF4\xADU\r\xFB^0\x90= \x837z\xCC\xD5p4a4\x83\xC6\x04m\xAA\xC1\xC0m", hmac.digest("hello world") end private def subject Net::SSH::Transport::HMAC::SHA2_512 end end end; end net-ssh-2.6.8/test/transport/hmac/test_sha2_256_96.rb0000644000004100000410000000111312166626376022231 0ustar www-datawww-data# encoding: ASCII-8BIT require 'common' require 'transport/hmac/test_sha2_256' require 'net/ssh/transport/hmac/sha2_256_96' module Transport; module HMAC class TestSHA2_256_96 < TestSHA2_256 def test_expected_mac_length assert_equal 12, subject.mac_length assert_equal 12, subject.new.mac_length end def test_expected_digest hmac = subject.new("1234567890123456") assert_equal "\x16^>\x9FhO}\xB1>(\xBAF", hmac.digest("hello world") end private def subject Net::SSH::Transport::HMAC::SHA2_256_96 end end end; end net-ssh-2.6.8/test/transport/hmac/test_sha1_96.rb0000644000004100000410000000110212166626376021632 0ustar www-datawww-data# encoding: ASCII-8BIT require 'common' require 'transport/hmac/test_sha1' require 'net/ssh/transport/hmac/sha1_96' module Transport; module HMAC class TestSHA1_96 < TestSHA1 def test_expected_mac_length assert_equal 12, subject.mac_length assert_equal 12, subject.new.mac_length end def test_expected_digest hmac = subject.new("1234567890123456") assert_equal "\000\004W\202\204+&\335\311\251P\266", hmac.digest("hello world") end private def subject Net::SSH::Transport::HMAC::SHA1_96 end end end; endnet-ssh-2.6.8/test/transport/hmac/test_sha1.rb0000644000004100000410000000155412166626376021327 0ustar www-datawww-data# encoding: ASCII-8BIT require 'common' require 'net/ssh/transport/hmac/sha1' module Transport; module HMAC class TestSHA1 < Test::Unit::TestCase def test_expected_digest_class assert_equal OpenSSL::Digest::SHA1, subject.digest_class assert_equal OpenSSL::Digest::SHA1, subject.new.digest_class end def test_expected_key_length assert_equal 20, subject.key_length assert_equal 20, subject.new.key_length end def test_expected_mac_length assert_equal 20, subject.mac_length assert_equal 20, subject.new.mac_length end def test_expected_digest hmac = subject.new("1234567890123456") assert_equal "\000\004W\202\204+&\335\311\251P\266\250\214\276\206;\022U\365", hmac.digest("hello world") end private def subject Net::SSH::Transport::HMAC::SHA1 end end end; endnet-ssh-2.6.8/test/transport/hmac/test_sha2_256.rb0000644000004100000410000000162512166626376021723 0ustar www-datawww-data# encoding: ASCII-8BIT require 'common' require 'net/ssh/transport/hmac/sha2_256' module Transport; module HMAC class TestSHA2_256 < Test::Unit::TestCase def test_expected_digest_class assert_equal OpenSSL::Digest::SHA256, subject.digest_class assert_equal OpenSSL::Digest::SHA256, subject.new.digest_class end def test_expected_key_length assert_equal 32, subject.key_length assert_equal 32, subject.new.key_length end def test_expected_mac_length assert_equal 32, subject.mac_length assert_equal 32, subject.new.mac_length end def test_expected_digest hmac = subject.new("1234567890123456") assert_equal "\x16^>\x9FhO}\xB1>(\xBAF\xFBW\xB8\xF2\xFA\x824+\xC0\x94\x95\xC2\r\xE6\x88/\xEF\t\xF5%", hmac.digest("hello world") end private def subject Net::SSH::Transport::HMAC::SHA2_256 end end end; end net-ssh-2.6.8/test/transport/hmac/test_sha2_512_96.rb0000644000004100000410000000113412166626376022227 0ustar www-datawww-data# encoding: ASCII-8BIT require 'common' require 'transport/hmac/test_sha2_512' require 'net/ssh/transport/hmac/sha2_512_96' module Transport; module HMAC class TestSHA2_512_96 < TestSHA2_512 def test_expected_mac_length assert_equal 12, subject.mac_length assert_equal 12, subject.new.mac_length end def test_expected_digest hmac = subject.new("1234567890123456") assert_equal "^\xB6\"\xED\x8B\xC4\xDE\xD4\xCF\xD0\r\x18", hmac.digest("hello world") end private def subject Net::SSH::Transport::HMAC::SHA2_512_96 end end end; end net-ssh-2.6.8/test/transport/hmac/test_ripemd160.rb0000644000004100000410000000160412166626376022176 0ustar www-datawww-data# encoding: ASCII-8BIT require 'common' require 'net/ssh/transport/hmac/ripemd160' module Transport; module HMAC class TestRipemd160 < Test::Unit::TestCase def test_expected_digest_class assert_equal OpenSSL::Digest::RIPEMD160, subject.digest_class assert_equal OpenSSL::Digest::RIPEMD160, subject.new.digest_class end def test_expected_key_length assert_equal 20, subject.key_length assert_equal 20, subject.new.key_length end def test_expected_mac_length assert_equal 20, subject.mac_length assert_equal 20, subject.new.mac_length end def test_expected_digest hmac = subject.new("1234567890123456") assert_equal "\xE4\x10\t\xB3\xD8,\x14\xA0k\x10\xB5\x0F?\x0E\x96q\x02\x16;E", hmac.digest("hello world") end private def subject Net::SSH::Transport::HMAC::RIPEMD160 end end end; end net-ssh-2.6.8/test/transport/test_cipher_factory.rb0000644000004100000410000004445012166626376022566 0ustar www-datawww-data# encoding: ASCII-8BIT require 'common' require 'net/ssh/transport/cipher_factory' module Transport class TestCipherFactory < Test::Unit::TestCase def self.if_supported?(name) yield if Net::SSH::Transport::CipherFactory.supported?(name) end def test_lengths_for_none assert_equal [0,0], factory.get_lengths("none") assert_equal [0,0], factory.get_lengths("bogus") end def test_lengths_for_blowfish_cbc assert_equal [16,8], factory.get_lengths("blowfish-cbc") end if_supported?("idea-cbc") do def test_lengths_for_idea_cbc assert_equal [16,8], factory.get_lengths("idea-cbc") end end def test_lengths_for_rijndael_cbc assert_equal [32,16], factory.get_lengths("rijndael-cbc@lysator.liu.se") end def test_lengths_for_cast128_cbc assert_equal [16,8], factory.get_lengths("cast128-cbc") end def test_lengths_for_3des_cbc assert_equal [24,8], factory.get_lengths("3des-cbc") end def test_lengths_for_aes128_cbc assert_equal [16,16], factory.get_lengths("aes128-cbc") end def test_lengths_for_aes192_cbc assert_equal [24,16], factory.get_lengths("aes192-cbc") end def test_lengths_for_aes256_cbc assert_equal [32,16], factory.get_lengths("aes256-cbc") end def test_lengths_for_arcfour assert_equal [16,8], factory.get_lengths("arcfour") end def test_lengths_for_arcfour128 assert_equal [16,8], factory.get_lengths("arcfour128") end def test_lengths_for_arcfour256 assert_equal [32,8], factory.get_lengths("arcfour256") end def test_lengths_for_arcfour512 assert_equal [64,8], factory.get_lengths("arcfour512") end if_supported?("camellia128-cbc@openssh.org") do def test_lengths_for_camellia128_cbc_openssh_org assert_equal [16,16], factory.get_lengths("camellia128-cbc@openssh.org") end end if_supported?("camellia192-cbc@openssh.org") do def test_lengths_for_camellia192_cbc_openssh_org assert_equal [24,16], factory.get_lengths("camellia192-cbc@openssh.org") end end if_supported?("camellia256-cbc@openssh.org") do def test_lengths_for_camellia256_cbc_openssh_org assert_equal [32,16], factory.get_lengths("camellia256-cbc@openssh.org") end end def test_lengths_for_3des_ctr assert_equal [24,8], factory.get_lengths("3des-ctr") end def test_lengths_for_aes128_ctr assert_equal [16,16], factory.get_lengths("aes128-ctr") end def test_lengths_for_aes192_ctr assert_equal [24,16], factory.get_lengths("aes192-ctr") end def test_lengths_for_aes256_ctr assert_equal [32,16], factory.get_lengths("aes256-ctr") end def test_lengths_for_blowfish_ctr assert_equal [16,8], factory.get_lengths("blowfish-ctr") end def test_lengths_for_cast128_ctr assert_equal [16,8], factory.get_lengths("cast128-ctr") end if_supported?("camellia128-ctr@openssh.org") do def test_lengths_for_camellia128_ctr_openssh_org assert_equal [16,16], factory.get_lengths("camellia128-ctr@openssh.org") end end if_supported?("camellia192-ctr@openssh.org") do def test_lengths_for_camellia192_ctr_openssh_org assert_equal [24,16], factory.get_lengths("camellia192-ctr@openssh.org") end end if_supported?("camellia256-ctr@openssh.org") do def test_lengths_for_camellia256_ctr_openssh_org assert_equal [32,16], factory.get_lengths("camellia256-ctr@openssh.org") end end BLOWFISH_CBC = "\210\021\200\315\240_\026$\352\204g\233\244\242x\332e\370\001\327\224Nv@9_\323\037\252kb\037\036\237\375]\343/y\037\237\312Q\f7]\347Y\005\275%\377\0010$G\272\250B\265Nd\375\342\372\025r6}+Y\213y\n\237\267\\\374^\346BdJ$\353\220Ik\023<\236&H\277=\225" def test_blowfish_cbc_for_encryption assert_equal BLOWFISH_CBC, encrypt("blowfish-cbc") end def test_blowfish_cbc_for_decryption assert_equal TEXT, decrypt("blowfish-cbc", BLOWFISH_CBC) end if_supported?("idea-cbc") do IDEA_CBC = "W\234\017G\231\b\357\370H\b\256U]\343M\031k\233]~\023C\363\263\177\262-\261\341$\022\376mv\217\322\b\2763\270H\306\035\343z\313\312\3531\351\t\201\302U\022\360\300\354ul7$z\320O]\360g\024\305\005`V\005\335A\351\312\270c\320D\232\eQH1\340\265\2118\031g*\303v" def test_idea_cbc_for_encryption assert_equal IDEA_CBC, encrypt("idea-cbc") end def test_idea_cbc_for_decryption assert_equal TEXT, decrypt("idea-cbc", IDEA_CBC) end end RIJNDAEL = "$\253\271\255\005Z\354\336&\312\324\221\233\307Mj\315\360\310Fk\241EfN\037\231\213\361{'\310\204\347I\343\271\005\240`\325;\034\346uM>#\241\231C`\374\261\vo\226;Z\302:\b\250\366T\330\\#V\330\340\226\363\374!\bm\266\232\207!\232\347\340\t\307\370\356z\236\343=v\210\206y" def test_rijndael_cbc_for_encryption assert_equal RIJNDAEL, encrypt("rijndael-cbc@lysator.liu.se") end def test_rijndael_cbc_for_decryption assert_equal TEXT, decrypt("rijndael-cbc@lysator.liu.se", RIJNDAEL) end CAST128_CBC = "qW\302\331\333P\223t[9 ~(sg\322\271\227\272\022I\223\373p\255>k\326\314\260\2003\236C_W\211\227\373\205>\351\334\322\227\223\e\236\202Ii\032!P\214\035:\017\360h7D\371v\210\264\317\236a\262w1\2772\023\036\331\227\240:\f/X\351\324I\t[x\350\323E\2301\016m" def test_cast128_cbc_for_encryption assert_equal CAST128_CBC, encrypt("cast128-cbc") end def test_cast128_cbc_for_decryption assert_equal TEXT, decrypt("cast128-cbc", CAST128_CBC) end TRIPLE_DES_CBC = "\322\252\216D\303Q\375gg\367A{\177\313\3436\272\353%\223K?\257\206|\r&\353/%\340\336 \203E8rY\206\234\004\274\267\031\233T/{\"\227/B!i?[qGaw\306T\206\223\213n \212\032\244%]@\355\250\334\312\265E\251\017\361\270\357\230\274KP&^\031r+r%\370" def test_3des_cbc_for_encryption assert_equal TRIPLE_DES_CBC, encrypt("3des-cbc") end def test_3des_cbc_for_decryption assert_equal TEXT, decrypt("3des-cbc", TRIPLE_DES_CBC) end AES128_CBC = "k\026\350B\366-k\224\313\3277}B\035\004\200\035\r\233\024$\205\261\231Q\2214r\245\250\360\315\237\266hg\262C&+\321\346Pf\267v\376I\215P\327\345-\232&HK\375\326_\030<\a\276\212\303g\342C\242O\233\260\006\001a&V\345`\\T\e\236.\207\223l\233ri^\v\252\363\245" def test_aes128_cbc_for_encryption assert_equal AES128_CBC, encrypt("aes128-cbc") end def test_aes128_cbc_for_decryption assert_equal TEXT, decrypt("aes128-cbc", AES128_CBC) end AES192_CBC = "\256\017)x\270\213\336\303L\003f\235'jQ\3231k9\225\267\242\364C4\370\224\201\302~\217I\202\374\2167='\272\037\225\223\177Y\r\212\376(\275\n\3553\377\177\252C\254\236\016MA\274Z@H\331<\rL\317\205\323[\305X8\376\237=\374\352bH9\244\0231\353\204\352p\226\326~J\242" def test_aes192_cbc_for_encryption assert_equal AES192_CBC, encrypt("aes192-cbc") end def test_aes192_cbc_for_decryption assert_equal TEXT, decrypt("aes192-cbc", AES192_CBC) end AES256_CBC = "$\253\271\255\005Z\354\336&\312\324\221\233\307Mj\315\360\310Fk\241EfN\037\231\213\361{'\310\204\347I\343\271\005\240`\325;\034\346uM>#\241\231C`\374\261\vo\226;Z\302:\b\250\366T\330\\#V\330\340\226\363\374!\bm\266\232\207!\232\347\340\t\307\370\356z\236\343=v\210\206y" def test_aes256_cbc_for_encryption assert_equal AES256_CBC, encrypt("aes256-cbc") end def test_aes256_cbc_for_decryption assert_equal TEXT, decrypt("aes256-cbc", AES256_CBC) end ARCFOUR = "\xC1.\x1AdH\xD0+%\xF1CrG\x1C\xCC\xF6\xACho\xB0\x95\\\xBC\x02P\xF9\xAF\n\xBB<\x13\xF3\xCF\xEB\n\b(iO\xFB'\t^?\xA6\xE5a\xE2\x17\f\x97\xCAs\x9E\xFC\xF2\x88\xC93\v\x84\xCA\x82\x0E\x1D\x11\xEA\xE1\x82\x8E\xB3*\xC5\xFB\x8Cmgs\xB0\xFA\xF5\x9C\\\xE2\xB0\x95\x1F>LT" def test_arcfour_for_encryption assert_equal ARCFOUR, encrypt("arcfour") end def test_arcfour_for_decryption assert_equal TEXT, decrypt("arcfour", ARCFOUR) end ARCFOUR128 = "\n\x90\xED*\xD4\xBE\xCBg5\xA5\a\xEC]\x97\xB7L\x06)6\x12FL\x90@\xF4Sqxqh\r\x11\x1Aq \xC8\xE6v\xC6\x12\xD9 "ABC", :key => "abc", :digester => OpenSSL::Digest::MD5, :shared => "1234567890123456780", :hash => '!@#$%#$^%$&^&%#$@$' } def factory Net::SSH::Transport::CipherFactory end def encrypt(type) cipher = factory.get(type, OPTIONS.merge(:encrypt => true)) padding = TEXT.length % cipher.block_size result = cipher.update(TEXT.dup) result << cipher.update(" " * (cipher.block_size - padding)) if padding > 0 result << cipher.final end def decrypt(type, data) cipher = factory.get(type, OPTIONS.merge(:decrypt => true)) result = cipher.update(data.dup) result << cipher.final result.strip end end end net-ssh-2.6.8/test/transport/test_state.rb0000644000004100000410000001355012166626376020702 0ustar www-datawww-data# encoding: ASCII-8BIT require 'common' require 'net/ssh/transport/state' module Transport class TestState < Test::Unit::TestCase def setup @socket = @state = @deflater = @inflater = nil end def teardown if @deflater @deflater.finish if !@deflater.finished? @deflater.close end if @inflater @inflater.finish if !@inflater.finished? @inflater.close end state.cleanup end def test_constructor_should_initialize_all_values assert_equal 0, state.sequence_number assert_equal 0, state.packets assert_equal 0, state.blocks assert_nil state.compression assert_nil state.compression_level assert_nil state.max_packets assert_nil state.max_blocks assert_nil state.rekey_limit assert_equal "identity", state.cipher.name assert_instance_of Net::SSH::Transport::HMAC::None, state.hmac end def test_increment_should_increment_counters state.increment(24) assert_equal 1, state.sequence_number assert_equal 1, state.packets assert_equal 3, state.blocks end def test_reset_should_reset_counters_and_fix_defaults_for_maximums state.increment(24) state.reset! assert_equal 1, state.sequence_number assert_equal 0, state.packets assert_equal 0, state.blocks assert_equal 2147483648, state.max_packets assert_equal 134217728, state.max_blocks end def test_set_should_set_variables_and_reset_counters state.expects(:reset!) state.set :cipher => :a, :hmac => :b, :compression => :c, :compression_level => :d, :max_packets => 500, :max_blocks => 1000, :rekey_limit => 1500 assert_equal :a, state.cipher assert_equal :b, state.hmac assert_equal :c, state.compression assert_equal :d, state.compression_level assert_equal 500, state.max_packets assert_equal 1000, state.max_blocks assert_equal 1500, state.rekey_limit end def test_set_with_max_packets_should_respect_max_packets_setting state.set :max_packets => 500 assert_equal 500, state.max_packets end def test_set_with_max_blocks_should_respect_max_blocks_setting state.set :max_blocks => 1000 assert_equal 1000, state.max_blocks end def test_set_with_rekey_limit_should_include_rekey_limit_in_computation_of_max_blocks state.set :rekey_limit => 4000 assert_equal 500, state.max_blocks end def test_compressor_defaults_to_default_zlib_compression expect = deflater.deflate("hello world") assert_equal expect, state.compressor.deflate("hello world") end def test_compressor_uses_compression_level_when_given state.set :compression_level => 1 expect = deflater(1).deflate("hello world") assert_equal expect, state.compressor.deflate("hello world") end def test_compress_when_no_compression_is_active_returns_text assert_equal "hello everybody", state.compress("hello everybody") end def test_decompress_when_no_compression_is_active_returns_text assert_equal "hello everybody", state.decompress("hello everybody") end def test_compress_when_compression_is_delayed_and_no_auth_hint_is_set_should_return_text state.set :compression => :delayed assert_equal "hello everybody", state.compress("hello everybody") end def test_decompress_when_compression_is_delayed_and_no_auth_hint_is_set_should_return_text state.set :compression => :delayed assert_equal "hello everybody", state.decompress("hello everybody") end def test_compress_when_compression_is_enabled_should_return_compressed_text state.set :compression => :standard # JRuby Zlib implementation (1.4 & 1.5) does not have byte-to-byte compatibility with MRI's. # skip this test under JRuby. return if defined?(JRUBY_VERSION) assert_equal "x\234\312H\315\311\311WH-K-\252L\312O\251\004\000\000\000\377\377", state.compress("hello everybody") end def test_decompress_when_compression_is_enabled_should_return_decompressed_text state.set :compression => :standard # JRuby Zlib implementation (1.4 & 1.5) does not have byte-to-byte compatibility with MRI's. # skip this test under JRuby. return if defined?(JRUBY_VERSION) assert_equal "hello everybody", state.decompress("x\234\312H\315\311\311WH-K-\252L\312O\251\004\000\000\000\377\377") end def test_compress_when_compression_is_delayed_and_auth_hint_is_set_should_return_compressed_text socket.hints[:authenticated] = true state.set :compression => :delayed assert_equal "x\234\312H\315\311\311WH-K-\252L\312O\251\004\000\000\000\377\377", state.compress("hello everybody") end def test_decompress_when_compression_is_delayed_and_auth_hint_is_set_should_return_decompressed_text socket.hints[:authenticated] = true state.set :compression => :delayed assert_equal "hello everybody", state.decompress("x\234\312H\315\311\311WH-K-\252L\312O\251\004\000\000\000\377\377") end def test_needs_rekey_should_be_true_if_packets_exceeds_max_packets state.set :max_packets => 2 state.increment(8) state.increment(8) assert !state.needs_rekey? state.increment(8) assert state.needs_rekey? end def test_needs_rekey_should_be_true_if_blocks_exceeds_max_blocks state.set :max_blocks => 10 assert !state.needs_rekey? state.increment(88) assert state.needs_rekey? end private def deflater(level=Zlib::DEFAULT_COMPRESSION) @deflater ||= Zlib::Deflate.new(level) end def inflater @inflater ||= Zlib::Inflate.new(nil) end def socket @socket ||= stub("socket", :hints => {}) end def state @state ||= Net::SSH::Transport::State.new(socket, :test) end end endnet-ssh-2.6.8/test/transport/kex/0000755000004100000410000000000012166626376016761 5ustar www-datawww-datanet-ssh-2.6.8/test/transport/kex/test_ecdh_sha2_nistp521.rb0000644000004100000410000000163312166626376023635 0ustar www-datawww-datarequire 'openssl' unless defined?(OpenSSL::PKey::EC) puts "Skipping tests for ecdh-sha2-nistp521 key exchange" else module Transport; module Kex class TestEcdhSHA2NistP521 < TestEcdhSHA2NistP256 def setup @ecdh = @algorithms = @connection = @server_key = @packet_data = @shared_secret = nil end def test_exchange_keys_should_return_expected_results_when_successful result = exchange! assert_equal session_id, result[:session_id] assert_equal server_host_key.to_blob, result[:server_key].to_blob assert_equal shared_secret, result[:shared_secret] assert_equal digester, result[:hashing_algorithm] end private def digester OpenSSL::Digest::SHA512 end def subject Net::SSH::Transport::Kex::EcdhSHA2NistP521 end def ecparam "secp521r1" end end end; end end net-ssh-2.6.8/test/transport/kex/test_ecdh_sha2_nistp256.rb0000644000004100000410000001217212166626376023642 0ustar www-datawww-datarequire 'openssl' unless defined?(OpenSSL::PKey::EC) puts "Skipping tests for ecdh-sha2-nistp256 key exchange" else require 'common' require 'transport/kex/test_diffie_hellman_group1_sha1' require 'net/ssh/transport/kex/ecdh_sha2_nistp256' require 'ostruct' module Transport; module Kex class TestEcdhSHA2NistP256 < Test::Unit::TestCase include Net::SSH::Transport::Constants def setup @ecdh = @algorithms = @connection = @server_key = @packet_data = @shared_secret = nil end def test_exchange_keys_should_return_expected_results_when_successful result = exchange! assert_equal session_id, result[:session_id] assert_equal server_host_key.to_blob, result[:server_key].to_blob assert_equal shared_secret, result[:shared_secret] assert_equal digester, result[:hashing_algorithm] end def test_exchange_keys_with_unverifiable_host_should_raise_exception connection.verifier { false } assert_raises(Net::SSH::Exception) { exchange! } end def test_exchange_keys_with_signature_key_type_mismatch_should_raise_exception assert_raises(Net::SSH::Exception) { exchange! :key_type => "ssh-dss" } end def test_exchange_keys_with_host_key_type_mismatch_should_raise_exception algorithms :host_key => "ssh-dss" assert_raises(Net::SSH::Exception) { exchange! :key_type => "ssh-dss" } end def test_exchange_keys_when_server_signature_could_not_be_verified_should_raise_exception @signature = "1234567890" assert_raises(Net::SSH::Exception) { exchange! } end def test_exchange_keys_should_pass_expected_parameters_to_host_key_verifier verified = false connection.verifier do |data| verified = true assert_equal server_host_key.to_blob, data[:key].to_blob blob = b(:key, data[:key]).to_s fingerprint = OpenSSL::Digest::MD5.hexdigest(blob).scan(/../).join(":") assert_equal blob, data[:key_blob] assert_equal fingerprint, data[:fingerprint] assert_equal connection, data[:session] true end assert_nothing_raised { exchange! } assert verified end private def digester OpenSSL::Digest::SHA256 end def subject Net::SSH::Transport::Kex::EcdhSHA2NistP256 end def ecparam "prime256v1" end def key_type "ecdsa-sha2-nistp256" end def exchange!(options={}) connection.expect do |t, buffer| assert_equal KEXECDH_INIT, buffer.type assert_equal ecdh.ecdh.public_key.to_bn.to_s(2), buffer.read_string t.return(KEXECDH_REPLY, :string, b(:key, server_host_key), :string, server_ecdh_pubkey.to_bn.to_s(2), :string, b(:string, options[:key_type] || key_type, :string, signature)) connection.expect do |t2, buffer2| assert_equal NEWKEYS, buffer2.type t2.return(NEWKEYS) end end ecdh.exchange_keys end def ecdh @ecdh ||= subject.new(algorithms, connection, packet_data) end def algorithms(options={}) @algorithms ||= OpenStruct.new(:host_key => options[:server_host_key] || "ecdsa-sha2-nistp256") end def connection @connection ||= MockTransport.new end def server_key @server_key ||= OpenSSL::PKey::EC.new(ecparam).generate_key end def server_host_key @server_host_key ||= OpenSSL::PKey::EC.new("prime256v1").generate_key end def packet_data @packet_data ||= { :client_version_string => "client version string", :server_version_string => "server version string", :server_algorithm_packet => "server algorithm packet", :client_algorithm_packet => "client algorithm packet" } end def server_ecdh_pubkey @server_ecdh_pubkey ||= server_key.public_key end def shared_secret @shared_secret ||= OpenSSL::BN.new(ecdh.ecdh.dh_compute_key(server_ecdh_pubkey), 2) end def session_id @session_id ||= begin buffer = Net::SSH::Buffer.from(:string, packet_data[:client_version_string], :string, packet_data[:server_version_string], :string, packet_data[:client_algorithm_packet], :string, packet_data[:server_algorithm_packet], :string, Net::SSH::Buffer.from(:key, server_host_key), :string, ecdh.ecdh.public_key.to_bn.to_s(2), :string, server_ecdh_pubkey.to_bn.to_s(2), :bignum, shared_secret) digester.digest(buffer.to_s) end end def signature @signature ||= server_host_key.ssh_do_sign(session_id) end def b(*args) Net::SSH::Buffer.from(*args) end end end; end; end net-ssh-2.6.8/test/transport/kex/test_diffie_hellman_group1_sha1.rb0000644000004100000410000001100312166626376025477 0ustar www-datawww-datarequire 'common' require 'net/ssh/transport/kex/diffie_hellman_group1_sha1' require 'ostruct' module Transport; module Kex class TestDiffieHellmanGroup1SHA1 < Test::Unit::TestCase include Net::SSH::Transport::Constants def setup @dh_options = @dh = @algorithms = @connection = @server_key = @packet_data = @shared_secret = nil end def test_exchange_keys_should_return_expected_results_when_successful result = exchange! assert_equal session_id, result[:session_id] assert_equal server_key.to_blob, result[:server_key].to_blob assert_equal shared_secret, result[:shared_secret] assert_equal OpenSSL::Digest::SHA1, result[:hashing_algorithm] end def test_exchange_keys_with_unverifiable_host_should_raise_exception connection.verifier { false } assert_raises(Net::SSH::Exception) { exchange! } end def test_exchange_keys_with_signature_key_type_mismatch_should_raise_exception assert_raises(Net::SSH::Exception) { exchange! :key_type => "ssh-dss" } end def test_exchange_keys_with_host_key_type_mismatch_should_raise_exception algorithms :host_key => "ssh-dss" assert_raises(Net::SSH::Exception) { exchange! :key_type => "ssh-dss" } end def test_exchange_keys_when_server_signature_could_not_be_verified_should_raise_exception @signature = "1234567890" assert_raises(Net::SSH::Exception) { exchange! } end def test_exchange_keys_should_pass_expected_parameters_to_host_key_verifier verified = false connection.verifier do |data| verified = true assert_equal server_key.to_blob, data[:key].to_blob blob = b(:key, data[:key]).to_s fingerprint = OpenSSL::Digest::MD5.hexdigest(blob).scan(/../).join(":") assert_equal blob, data[:key_blob] assert_equal fingerprint, data[:fingerprint] assert_equal connection, data[:session] true end assert_nothing_raised { exchange! } assert verified end private def exchange!(options={}) connection.expect do |t, buffer| assert_equal KEXDH_INIT, buffer.type assert_equal dh.dh.pub_key, buffer.read_bignum t.return(KEXDH_REPLY, :string, b(:key, server_key), :bignum, server_dh_pubkey, :string, b(:string, options[:key_type] || "ssh-rsa", :string, signature)) connection.expect do |t2, buffer2| assert_equal NEWKEYS, buffer2.type t2.return(NEWKEYS) end end dh.exchange_keys end def dh_options(options={}) @dh_options = options end def dh @dh ||= subject.new(algorithms, connection, packet_data.merge(:need_bytes => 20).merge(@dh_options || {})) end def algorithms(options={}) @algorithms ||= OpenStruct.new(:host_key => options[:host_key] || "ssh-rsa") end def connection @connection ||= MockTransport.new end def subject Net::SSH::Transport::Kex::DiffieHellmanGroup1SHA1 end # 512 bits is the smallest possible key that will work with this, so # we use it for speed reasons def server_key(bits=512) @server_key ||= OpenSSL::PKey::RSA.new(bits) end def packet_data @packet_data ||= { :client_version_string => "client version string", :server_version_string => "server version string", :server_algorithm_packet => "server algorithm packet", :client_algorithm_packet => "client algorithm packet" } end def server_dh_pubkey @server_dh_pubkey ||= bn(1234567890) end def shared_secret @shared_secret ||= OpenSSL::BN.new(dh.dh.compute_key(server_dh_pubkey), 2) end def session_id @session_id ||= begin buffer = Net::SSH::Buffer.from(:string, packet_data[:client_version_string], :string, packet_data[:server_version_string], :string, packet_data[:client_algorithm_packet], :string, packet_data[:server_algorithm_packet], :string, Net::SSH::Buffer.from(:key, server_key), :bignum, dh.dh.pub_key, :bignum, server_dh_pubkey, :bignum, shared_secret) OpenSSL::Digest::SHA1.digest(buffer.to_s) end end def signature @signature ||= server_key.ssh_do_sign(session_id) end def bn(number, base=10) OpenSSL::BN.new(number.to_s, base) end def b(*args) Net::SSH::Buffer.from(*args) end end end; endnet-ssh-2.6.8/test/transport/kex/test_diffie_hellman_group14_sha1.rb0000644000004100000410000000053712166626376025575 0ustar www-datawww-datarequire 'common' require 'net/ssh/transport/kex/diffie_hellman_group14_sha1' require 'transport/kex/test_diffie_hellman_group1_sha1' require 'ostruct' module Transport; module Kex class TestDiffieHellmanGroup14SHA1 < TestDiffieHellmanGroup1SHA1 def subject Net::SSH::Transport::Kex::DiffieHellmanGroup14SHA1 end end end; end net-ssh-2.6.8/test/transport/kex/test_ecdh_sha2_nistp384.rb0000644000004100000410000000163512166626376023646 0ustar www-datawww-datarequire 'openssl' unless defined?(OpenSSL::PKey::EC) puts "Skipping tests for ecdh-sha2-nistp384 key exchange" else module Transport; module Kex class TestEcdhSHA2NistP384 < TestEcdhSHA2NistP256 def setup @ecdh = @algorithms = @connection = @server_key = @packet_data = @shared_secret = nil end def test_exchange_keys_should_return_expected_results_when_successful result = exchange! assert_equal session_id, result[:session_id] assert_equal server_host_key.to_blob, result[:server_key].to_blob assert_equal shared_secret, result[:shared_secret] assert_equal digester, result[:hashing_algorithm] end private def digester OpenSSL::Digest::SHA384 end def subject Net::SSH::Transport::Kex::EcdhSHA2NistP384 end def ecparam "secp384r1" end end end; end end net-ssh-2.6.8/test/transport/kex/test_diffie_hellman_group_exchange_sha256.rb0000644000004100000410000000200412166626376027435 0ustar www-datawww-datarequire 'common' require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha1' module Transport; module Kex class TestDiffieHellmanGroupExchangeSHA256 < TestDiffieHellmanGroupExchangeSHA1 private def subject Net::SSH::Transport::Kex::DiffieHellmanGroupExchangeSHA256 end def session_id @session_id ||= begin buffer = Net::SSH::Buffer.from(:string, packet_data[:client_version_string], :string, packet_data[:server_version_string], :string, packet_data[:client_algorithm_packet], :string, packet_data[:server_algorithm_packet], :string, Net::SSH::Buffer.from(:key, server_key), :long, 1024, :long, 1024, :long, 8192, :bignum, dh.dh.p, :bignum, dh.dh.g, :bignum, dh.dh.pub_key, :bignum, server_dh_pubkey, :bignum, shared_secret) OpenSSL::Digest::SHA256.digest(buffer.to_s) end end end end; end net-ssh-2.6.8/test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb0000644000004100000410000000631712166626376027274 0ustar www-datawww-datarequire 'common' require 'transport/kex/test_diffie_hellman_group1_sha1' require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha1' module Transport; module Kex class TestDiffieHellmanGroupExchangeSHA1 < TestDiffieHellmanGroup1SHA1 KEXDH_GEX_GROUP = 31 KEXDH_GEX_INIT = 32 KEXDH_GEX_REPLY = 33 KEXDH_GEX_REQUEST = 34 def test_exchange_with_fewer_than_minimum_bits_uses_minimum_bits dh_options :need_bytes => 20 assert_equal 1024, need_bits assert_nothing_raised { exchange! } end def test_exchange_with_fewer_than_maximum_bits_uses_need_bits dh_options :need_bytes => 500 need_bits(8001) assert_nothing_raised { exchange! } end def test_exchange_with_more_than_maximum_bits_uses_maximum_bits dh_options :need_bytes => 2000 need_bits(8192) assert_nothing_raised { exchange! } end def test_that_p_and_g_are_provided_by_the_server assert_nothing_raised { exchange! :p => default_p+2, :g => 3 } assert_equal default_p+2, dh.dh.p assert_equal 3, dh.dh.g end private def need_bits(bits=1024) @need_bits ||= bits end def default_p 142326151570335518660743995281621698377057354949884468943021767573608899048361360422513557553514790045512299468953431585300812548859419857171094366358158903433167915517332113861059747425408670144201099811846875730766487278261498262568348338476437200556998366087779709990807518291581860338635288400119315130179 end def exchange!(options={}) connection.expect do |t, buffer| assert_equal KEXDH_GEX_REQUEST, buffer.type assert_equal 1024, buffer.read_long assert_equal need_bits, buffer.read_long assert_equal 8192, buffer.read_long t.return(KEXDH_GEX_GROUP, :bignum, bn(options[:p] || default_p), :bignum, bn(options[:g] || 2)) t.expect do |t2, buffer2| assert_equal KEXDH_GEX_INIT, buffer2.type assert_equal dh.dh.pub_key, buffer2.read_bignum t2.return(KEXDH_GEX_REPLY, :string, b(:key, server_key), :bignum, server_dh_pubkey, :string, b(:string, options[:key_type] || "ssh-rsa", :string, signature)) t2.expect do |t3, buffer3| assert_equal NEWKEYS, buffer3.type t3.return(NEWKEYS) end end end dh.exchange_keys end def subject Net::SSH::Transport::Kex::DiffieHellmanGroupExchangeSHA1 end def session_id @session_id ||= begin buffer = Net::SSH::Buffer.from(:string, packet_data[:client_version_string], :string, packet_data[:server_version_string], :string, packet_data[:client_algorithm_packet], :string, packet_data[:server_algorithm_packet], :string, Net::SSH::Buffer.from(:key, server_key), :long, 1024, :long, need_bits, # need bits, figure this part out, :long, 8192, :bignum, dh.dh.p, :bignum, dh.dh.g, :bignum, dh.dh.pub_key, :bignum, server_dh_pubkey, :bignum, shared_secret) OpenSSL::Digest::SHA1.digest(buffer.to_s) end end end end; end net-ssh-2.6.8/test/manual/0000755000004100000410000000000012166626376015413 5ustar www-datawww-datanet-ssh-2.6.8/test/manual/test_forward.rb0000644000004100000410000001401212166626376020441 0ustar www-datawww-data# $ ruby -Ilib -Itest -rrubygems test/test_forward.rb # Tests for the following patch: # # http://github.com/net-ssh/net-ssh/tree/portfwfix # # It fixes 3 issues, regarding closing forwarded ports: # # 1.) if client closes a forwarded connection, but the server is reading, net-ssh terminates with IOError socket closed. # 2.) if client force closes (RST) a forwarded connection, but server is reading, net-ssh terminates with # 3.) if server closes the sending side, the on_eof is not handled. # # More info: # # http://net-ssh.lighthouseapp.com/projects/36253/tickets/7 require 'common' require 'net/ssh/buffer' require 'net/ssh' require 'timeout' require 'tempfile' class TestForward < Test::Unit::TestCase def localhost 'localhost' end def ssh_start_params [localhost ,ENV['USER'], {:keys => "~/.ssh/id_rsa", :verbose => :debug}] end def find_free_port server = TCPServer.open(0) server.setsockopt(Socket::SOL_SOCKET,Socket::SO_REUSEADDR,true) port = server.addr[1] server.close port end def start_server_sending_lot_of_data(exceptions) server = TCPServer.open(0) Thread.start do loop do Thread.start(server.accept) do |client| begin 10000.times do |i| client.puts "item#{i}" end client.close rescue exceptions << $! raise end end end end return server end def start_server_closing_soon(exceptions=nil) server = TCPServer.open(0) Thread.start do loop do Thread.start(server.accept) do |client| begin client.recv(1024) client.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, [1, 0].pack("ii")) client.close rescue exceptions << $! raise end end end end return server end def test_loop_should_not_abort_when_local_side_of_forward_is_closed session = Net::SSH.start(*ssh_start_params) server_exc = Queue.new server = start_server_sending_lot_of_data(server_exc) remote_port = server.addr[1] local_port = find_free_port session.forward.local(local_port, localhost, remote_port) client_done = Queue.new Thread.start do begin client = TCPSocket.new(localhost, local_port) client.recv(1024) client.close sleep(0.2) ensure client_done << true end end session.loop(0.1) { client_done.empty? } assert_equal "Broken pipe", "#{server_exc.pop}" unless server_exc.empty? end def test_loop_should_not_abort_when_local_side_of_forward_is_reset session = Net::SSH.start(*ssh_start_params) server_exc = Queue.new server = start_server_sending_lot_of_data(server_exc) remote_port = server.addr[1] local_port = find_free_port session.forward.local(local_port, localhost, remote_port) client_done = Queue.new Thread.start do begin client = TCPSocket.new(localhost, local_port) client.recv(1024) client.setsockopt(Socket::SOL_SOCKET, Socket::SO_LINGER, [1, 0].pack("ii")) client.close sleep(0.1) ensure client_done << true end end session.loop(0.1) { client_done.empty? } assert_equal "Broken pipe", "#{server_exc.pop}" unless server_exc.empty? end def create_local_socket(&blk) tempfile = Tempfile.new("net_ssh_forward_test") path = tempfile.path tempfile.delete yield UNIXServer.open(path) File.delete(path) end if defined?(UNIXServer) def test_forward_local_unix_socket_to_remote_port session = Net::SSH.start(*ssh_start_params) server_exc = Queue.new server = start_server_sending_lot_of_data(server_exc) remote_port = server.addr[1] client_data = nil create_local_socket do |local_socket| session.forward.local(local_socket, localhost, remote_port) client_done = Queue.new Thread.start do begin client = UNIXSocket.new(local_socket.path) client_data = client.recv(1024) client.close sleep(0.2) ensure client_done << true end end session.loop(0.1) { client_done.empty? } end assert_not_nil(client_data, "client should have received data") assert(client_data.match(/item\d/), 'client should have received the string item') end if defined?(UNIXSocket) def test_loop_should_not_abort_when_server_side_of_forward_is_closed session = Net::SSH.start(*ssh_start_params) server = start_server_closing_soon remote_port = server.addr[1] local_port = find_free_port session.forward.local(local_port, localhost, remote_port) client_done = Queue.new Thread.start do begin client = TCPSocket.new(localhost, local_port) 1.times do |i| client.puts "item#{i}" end client.close sleep(0.1) ensure client_done << true end end session.loop(0.1) { client_done.empty? } end def start_server server = TCPServer.open(0) Thread.start do loop do Thread.start(server.accept) do |client| yield(client) end end end return server end def test_server_eof_should_be_handled session = Net::SSH.start(*ssh_start_params) server = start_server do |client| client.write "This is a small message!" client.close end client_done = Queue.new client_exception = Queue.new client_data = Queue.new remote_port = server.addr[1] local_port = find_free_port session.forward.local(local_port, localhost, remote_port) Thread.start do begin client = TCPSocket.new(localhost, local_port) data = client.read(4096) client.close client_done << data rescue client_done << $! end end timeout(5) do session.loop(0.1) { client_done.empty? } assert_equal "This is a small message!", client_done.pop end end end net-ssh-2.6.8/test/test_key_factory.rb0000644000004100000410000002424712166626376020052 0ustar www-datawww-datarequire 'common' require 'net/ssh/key_factory' class TestKeyFactory < Test::Unit::TestCase def setup @key_file = File.expand_path("/key-file") end def test_load_unencrypted_private_RSA_key_should_return_key File.expects(:read).with(@key_file).returns(rsa_key.export) assert_equal rsa_key.to_der, Net::SSH::KeyFactory.load_private_key(@key_file).to_der end def test_load_unencrypted_private_DSA_key_should_return_key File.expects(:read).with(@key_file).returns(dsa_key.export) assert_equal dsa_key.to_der, Net::SSH::KeyFactory.load_private_key(@key_file).to_der end def test_load_encrypted_private_RSA_key_should_prompt_for_password_and_return_key File.expects(:read).with(@key_file).returns(encrypted(rsa_key, "password")) Net::SSH::KeyFactory.expects(:prompt).with("Enter passphrase for #{@key_file}:", false).returns("password") assert_equal rsa_key.to_der, Net::SSH::KeyFactory.load_private_key(@key_file).to_der end def test_load_encrypted_private_RSA_key_with_password_should_not_prompt_and_return_key File.expects(:read).with(@key_file).returns(encrypted(rsa_key, "password")) assert_equal rsa_key.to_der, Net::SSH::KeyFactory.load_private_key(@key_file, "password").to_der end def test_load_encrypted_private_DSA_key_should_prompt_for_password_and_return_key File.expects(:read).with(@key_file).returns(encrypted(dsa_key, "password")) Net::SSH::KeyFactory.expects(:prompt).with("Enter passphrase for #{@key_file}:", false).returns("password") assert_equal dsa_key.to_der, Net::SSH::KeyFactory.load_private_key(@key_file).to_der end def test_load_encrypted_private_DSA_key_with_password_should_not_prompt_and_return_key File.expects(:read).with(@key_file).returns(encrypted(dsa_key, "password")) assert_equal dsa_key.to_der, Net::SSH::KeyFactory.load_private_key(@key_file, "password").to_der end def test_load_encrypted_private_key_should_give_three_tries_for_the_password_and_then_raise_exception File.expects(:read).with(@key_file).returns(encrypted(rsa_key, "password")) Net::SSH::KeyFactory.expects(:prompt).times(3).with("Enter passphrase for #{@key_file}:", false).returns("passwod","passphrase","passwd") if OpenSSL::PKey.respond_to?(:read) error_class = ArgumentError else error_class = OpenSSL::PKey::RSAError end assert_raises(error_class) { Net::SSH::KeyFactory.load_private_key(@key_file) } end def test_load_encrypted_private_key_should_raise_exception_without_asking_passphrase File.expects(:read).with(@key_file).returns(encrypted(rsa_key, "password")) Net::SSH::KeyFactory.expects(:prompt).never if OpenSSL::PKey.respond_to?(:read) error_class = ArgumentError else error_class = OpenSSL::PKey::RSAError end assert_raises(error_class) { Net::SSH::KeyFactory.load_private_key(@key_file, nil, false) } end def test_load_public_rsa_key_should_return_key File.expects(:read).with(@key_file).returns(public(rsa_key)) assert_equal rsa_key.to_blob, Net::SSH::KeyFactory.load_public_key(@key_file).to_blob end if defined?(OpenSSL::PKey::EC) def test_load_unencrypted_private_ecdsa_sha2_nistp256_key_should_return_key File.expects(:read).with("/key-file").returns(ecdsa_sha2_nistp256_key.to_pem) assert_equal ecdsa_sha2_nistp256_key.to_der, Net::SSH::KeyFactory.load_private_key("/key-file").to_der end def test_load_unencrypted_private_ecdsa_sha2_nistp384_key_should_return_key File.expects(:read).with("/key-file").returns(ecdsa_sha2_nistp384_key.to_pem) assert_equal ecdsa_sha2_nistp384_key.to_der, Net::SSH::KeyFactory.load_private_key("/key-file").to_der end def test_load_unencrypted_private_ecdsa_sha2_nistp521_key_should_return_key File.expects(:read).with("/key-file").returns(ecdsa_sha2_nistp521_key.to_pem) assert_equal ecdsa_sha2_nistp521_key.to_der, Net::SSH::KeyFactory.load_private_key("/key-file").to_der end def test_load_public_ecdsa_sha2_nistp256_key_should_return_key File.expects(:read).with("/key-file").returns(public(ecdsa_sha2_nistp256_key)) assert_equal ecdsa_sha2_nistp256_key.to_blob, Net::SSH::KeyFactory.load_public_key("/key-file").to_blob end def test_load_public_ecdsa_sha2_nistp384_key_should_return_key File.expects(:read).with("/key-file").returns(public(ecdsa_sha2_nistp384_key)) assert_equal ecdsa_sha2_nistp384_key.to_blob, Net::SSH::KeyFactory.load_public_key("/key-file").to_blob end def test_load_public_ecdsa_sha2_nistp521_key_should_return_key File.expects(:read).with("/key-file").returns(public(ecdsa_sha2_nistp521_key)) assert_equal ecdsa_sha2_nistp521_key.to_blob, Net::SSH::KeyFactory.load_public_key("/key-file").to_blob end end def test_load_anonymous_private_key_should_return_key_or_raise_exception File.expects(:read).with(@key_file).returns(anonymous_private_key) if OpenSSL::PKey.respond_to?(:read) assert_equal OpenSSL::PKey::RSA.new(anonymous_private_key).to_der, Net::SSH::KeyFactory.load_private_key(@key_file).to_der else assert_raises(OpenSSL::PKey::PKeyError) { Net::SSH::KeyFactory.load_private_key(@key_file) } end end private def rsa_key # 512 bits @rsa_key ||= OpenSSL::PKey::RSA.new("0\202\001;\002\001\000\002A\000\235\236\374N\e@2E\321\3757\003\354c\276N\f\003\3479Ko\005\317\0027\a\255=\345!\306\220\340\211;\027u\331\260\362\2063x\332\301y4\353\v%\032\214v\312\304\212\271GJ\353\2701\031\002\003\001\000\001\002@\022Y\306*\031\306\031\224Cde\231QV3{\306\256U\2477\377\017\000\020\323\363R\332\027\351\034\224OU\020\227H|pUS\n\263+%\304\341\321\273/\271\e\004L\250\273\020&,\t\304By\002!\000\311c\246%a\002\305\277\262R\266\244\250\025V_\351]\264\016\265\341\355\305\223\347Z$8\205#\023\002!\000\310\\\367|\243I\363\350\020\307\246\302\365\ed\212L\273\2158M\223w\a\367 C\t\224A4\243\002!\000\262]+}\327\231\331\002\2331^\312\036\204'g\363\f&\271\020\245\365-\024}\306\374e\202\2459\002 }\231\341\276\3551\277\307{5\\\361\233\353G\024wS\237\fk}\004\302&\205\277\340rb\211\327\002!\000\223\307\025I:\215_\260\370\252\3757\256Y&X\364\354\342\215\350\203E8\227|\f\237M\375D|") end def dsa_key # 512 bits @dsa_key ||= OpenSSL::PKey::DSA.new("0\201\367\002\001\000\002A\000\203\316/\037u\272&J\265\003l3\315d\324h\372{\t8\252#\331_\026\006\035\270\266\255\343\353Z\302\276\335\336\306\220\375\202L\244\244J\206>\346\b\315\211\302L\246x\247u\a\376\366\345\302\016#\002\025\000\244\274\302\221Og\275/\302+\356\346\360\024\373wI\2573\361\002@\027\215\270r*\f\213\350C\245\021:\350 \006\\\376\345\022`\210b\262\3643\023XLKS\320\370\002\276\347A\nU\204\276\324\256`=\026\240\330\306J\316V\213\024\e\030\215\355\006\037q\337\356ln\002@\017\257\034\f\260\333'S\271#\237\230E\321\312\027\021\226\331\251Vj\220\305\316\036\v\266+\000\230\270\177B\003?t\a\305]e\344\261\334\023\253\323\251\223M\2175)a(\004\"lI8\312\303\307\a\002\024_\aznW\345\343\203V\326\246ua\203\376\201o\350\302\002") end if defined?(OpenSSL::PKey::EC) def ecdsa_sha2_nistp256_key @ecdsa_sha2_nistp256_key ||= OpenSSL::PKey::EC.new("-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEINv6pPVLlkqvT1v5MJlWgaSWGwqupISG4U79bUXQDNCaoAoGCCqGSM49\nAwEHoUQDQgAElqubvi/GkSme+bwtncU1NiE0dWQ0EO07VufUQg8lUJ5+Fi6f96qa\n95T1zwOMQhY1h8PP9rQIZr4S48vN/ZnQLw==\n-----END EC PRIVATE KEY-----\n") end def ecdsa_sha2_nistp384_key @ecdsa_sha2_nistp384_key ||= OpenSSL::PKey::EC.new("-----BEGIN EC PRIVATE KEY-----\nMIGkAgEBBDBxwkmydCn4mP4KMhlMpeBvIroQolWKVNoRPXpG7brFgK+Yiikqw8wd\nIZW5OlL4y3mgBwYFK4EEACKhZANiAARkoIR1oABi+aQJbKcmvzeYSKURQOyXM0HU\nR4T68v4hd/lJE4fFQRczj3wAaECe9u3CWI/oDlow4Vr0vab82ZGjIoblxblKQWYl\nyzENgzl226waGg1bLBo8Auilyf1B5yI=\n-----END EC PRIVATE KEY-----\n") end def ecdsa_sha2_nistp521_key @ecdsa_sha2_nistp521_key ||= OpenSSL::PKey::EC.new("-----BEGIN EC PRIVATE KEY-----\nMIHbAgEBBEHQ2i7kjEGQHQB4pUQW9a2eCLWR2S5Go8U3CDyfbRCrYEp/pTSgI8uu\nMXyR3bf3SjqFQgZ6MZk5lkyrissJuwmvZKAHBgUrgQQAI6GBiQOBhgAEAN14FACK\nbs/KTqw4rxijeozGTVJTh1hNzBl2XaIhM4Fv8o3fE/pvogymyFu53GCng6gC4dmx\n/hycF41iIM29xVKPAeBnRNl6MdFBjuthOmE8eCRezgk1Bak8aBDUrzNT8OQssscw\npvQK4nc6ga/wTDaQGy5kV8tCOHNs2wKH+p2LpWTJ\n-----END EC PRIVATE KEY-----\n") end end def anonymous_private_key @anonymous_key = <<-EOF -----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC3id5gZ6bglJth yli8JNaRxhsqKwwPlReEI/mplzz5IP6gWQ92LogXbdBXtHf9ZpA53BeLmtcNBEY0 Ygd7sPBhlHABS5D5///zltSSX2+L5GCEiC6dpfGsySjqymWF+SZ2PaqfZbkWLmCD 9u4ysueaHf7xbF6txGprNp69efttWxdy+vU5tno7HVxemMZQUalpShFrdAYKKXEo cV7MtbkQjzubS14gaWGpWCXIl9uNKQeHpLKtre1Qn5Ft/zVpCHmhLQcYDuB1LAj9 7eoev4rIiOE2sfdkvKDlmFxvzq3myYH4o27WwAg9OZ5SBusn2zesKkRCBBEZ55rl uVknOGHXAgMBAAECggEAZE0U2OxsNxkfXS6+lXswQ5PW7pF90towcsdSPgrniGIu pKRnHbfKKbuaewOl+zZcpTIRL/rbgUKPtzrHSiJlC36aQyrvvJ/ZWV5ZJvC+vd19 nY/qob65NyrrkHwxRSjmiwGiR9/IaUXI+vUsMUqx5Ph1hawqhZ3sZlEAKR4LeDO8 M+OguG77jLaqj5/SNfi+GwyUDe85de4VfEG4S9HrMQk2Cp66rx0BqDnCLacyFQaI R0VczMXTU52q0uETmgUr8G9A1SaRc5ZWKAfZwxJTvqdIImWC9E+CY7wm+mZD4FE6 iVzVC0ngcdEd596kTDdU2BPVMluWzLkfqIrTt/5CeQKBgQDzgRzCPNxFtai6RAIi ekBSHqrDnrbeTaw32GVq5ACk1Zfk2I0svctz1iQ9qJ2SRINpygQhcyJKQ4r/LXi1 7Av9H/d6QV4T2AZzS4WcqBkxxRXFUfARtnKChzuCzNt9tNz4EZiv75RyQmztGZjV i94+ZvCyqup5be4Svf4MBxin9QKBgQDA9P4nHzFWZakTMei78LGb/4Auc+r0rZp7 8xg8Z92tvrDeJjMdesdhiFrPP1qiSYHnQ81MSWpn6BycBsHZqitejQmYnYput/s4 qG+m7SrkN8WL6rijYsbB+U14VDjMlBlOgcEgjlSNU2oeS+68u+uVI/fgyXcXn4Jq 33TSWSgfGwKBgA2tRdE/G9wqfOShZ0FKfoxePpcoNfs8f5zPYbrkPYkEmjh3VU6b Bm9mKrjv3JHXmU3608qRLe7f5lG42xvUu0OnZP4P59nTe2FEb6fB5VBfUn63wHUu OzZLpDMPkJB59SNV0a6oFT1pr7aNhoEQDxaQL5rJcMwLOaEB3OAOEft1AoGASz7+ 4Zi7b7rDPVYIMUpCqNfxT6wqovIUPWPmPqAuhXPIm0kAQ+2+VN2MtCc7m+/Ydawu IiK7GPweNAY6kDxZH00WweolstmSYVzl9Y2lXUwWgGKvUB/T7I7g1Bzb7YOPftsA ykZW2Kn/xwLLfdQ2oXleT82g4Jh2jmDHuMPF7qMCgYEA6QF45PvOgnrJessgmwO/ dEmkLl07PQYJPGZLaZteuWrvfMrn+AiW5aAdHzhzNaOtNy5B3T7zGUHtgxXegqgd /QdCVCJgnZUO/zdAxkr22dDn+WEXkL4wgBVStQvvnQp9C2NJcoOExvex5PLzKWQg WEKt5v3QsUEgVrzkM4K9UbI= -----END PRIVATE KEY----- EOF end def encrypted(key, password) key.export(OpenSSL::Cipher::Cipher.new("des-ede3-cbc"), password) end def public(key) result = "#{key.ssh_type} " result << [Net::SSH::Buffer.from(:key, key).to_s].pack("m*").strip.tr("\n\r\t ", "") result << " joe@host.test" end end net-ssh-2.6.8/test/start/0000755000004100000410000000000012166626376015273 5ustar www-datawww-datanet-ssh-2.6.8/test/start/test_transport.rb0000644000004100000410000000152112166626376020712 0ustar www-datawww-datarequire 'common' require 'net/ssh' module NetSSH class TestStart < Test::Unit::TestCase attr_reader :transport_session attr_reader :authentication_session def setup @transport_session = mock('transport_session') @authentication_session = mock('authentication_session') Net::SSH::Transport::Session.expects(:new => transport_session) Net::SSH::Authentication::Session.expects(:new => authentication_session) end def test_close_transport_when_authentication_fails authentication_session.expects(:authenticate => false) transport_session.expects(:close).at_least_once begin Net::SSH.start('localhost', 'testuser') {} rescue Net::SSH::AuthenticationFailed # Authentication should fail, as it is part of the context end end end endnet-ssh-2.6.8/test/common.rb0000644000004100000410000000457512166626376015766 0ustar www-datawww-data$LOAD_PATH.unshift "#{File.dirname(__FILE__)}/../lib" gem "test-unit" # http://rubyforge.org/pipermail/test-unit-tracker/2009-July/000075.html gem 'mocha' require 'test/unit' require 'mocha/setup' require 'net/ssh/buffer' require 'net/ssh/config' require 'net/ssh/loggable' require 'net/ssh/packet' require 'net/ssh/transport/session' require 'ostruct' # clear the default files out so that tests don't get confused by existing # SSH config files. $original_config_default_files = Net::SSH::Config.default_files.dup Net::SSH::Config.default_files.clear def P(*args) Net::SSH::Packet.new(Net::SSH::Buffer.from(*args)) end class MockTransport < Net::SSH::Transport::Session class BlockVerifier def initialize(block) @block = block end def verify(data) @block.call(data) end end attr_reader :host_key_verifier attr_accessor :host_as_string attr_accessor :server_version attr_reader :client_options attr_reader :server_options attr_reader :hints, :queue attr_accessor :mock_enqueue def initialize(options={}) self.logger = options[:logger] self.host_as_string = "net.ssh.test,127.0.0.1" self.server_version = OpenStruct.new(:version => "SSH-2.0-Ruby/Net::SSH::Test") @expectation = nil @queue = [] @hints = {} @socket = options[:socket] @algorithms = OpenStruct.new(:session_id => "abcxyz123") verifier { |data| true } end def send_message(message) buffer = Net::SSH::Buffer.new(message.to_s) if @expectation.nil? raise "got #{message.to_s.inspect} but was not expecting anything" else block, @expectation = @expectation, nil block.call(self, Net::SSH::Packet.new(buffer)) end end def enqueue_message(message) if mock_enqueue send_message(message) else super end end def poll_message @queue.shift end def next_message @queue.shift or raise "expected a message from the server but nothing was ready to send" end def return(type, *args) @queue << P(:byte, type, *args) end def expect(&block) @expectation = block end def expect! expect {} end def verifier(&block) @host_key_verifier = BlockVerifier.new(block) end def configure_client(options) @client_options = options end def configure_server(options) @server_options = options end def hint(name, value=true) @hints[name] = value end end net-ssh-2.6.8/test/test_buffer.rb0000644000004100000410000003715112166626376017002 0ustar www-datawww-data# encoding: ASCII-8BIT require 'common' require 'net/ssh/buffer' class TestBuffer < Test::Unit::TestCase def test_constructor_should_initialize_buffer_to_empty_by_default buffer = new assert buffer.empty? assert_equal 0, buffer.position end def test_constructor_with_string_should_initialize_buffer_to_the_string buffer = new("hello") assert !buffer.empty? assert_equal "hello", buffer.to_s assert_equal 0, buffer.position end def test_from_should_require_an_even_number_of_arguments assert_raises(ArgumentError) { Net::SSH::Buffer.from("this") } end def test_from_should_build_new_buffer_from_definition buffer = Net::SSH::Buffer.from(:byte, 1, :long, 2, :int64, 3, :string, "4", :bool, true, :bool, false, :bignum, OpenSSL::BN.new("1234567890", 10), :raw, "something") assert_equal "\1\0\0\0\2\0\0\0\0\0\0\0\3\0\0\0\0014\1\0\000\000\000\004I\226\002\322something", buffer.to_s end def test_from_with_array_argument_should_write_multiple_of_the_given_type buffer = Net::SSH::Buffer.from(:byte, [1,2,3,4,5]) assert_equal "\1\2\3\4\5", buffer.to_s end def test_from_should_measure_bytesize_of_utf_8_string_correctly buffer = Net::SSH::Buffer.from(:string, "\u2603") # Snowman is 3 bytes assert_equal "\0\0\0\3\u2603", buffer.to_s end def test_read_without_argument_should_read_to_end buffer = new("hello world") assert_equal "hello world", buffer.read assert buffer.eof? assert_equal 11, buffer.position end def test_read_with_argument_that_is_less_than_length_should_read_that_many_bytes buffer = new "hello world" assert_equal "hello", buffer.read(5) assert_equal 5, buffer.position end def test_read_with_argument_that_is_more_than_length_should_read_no_more_than_length buffer = new "hello world" assert_equal "hello world", buffer.read(500) assert_equal 11, buffer.position end def test_read_at_eof_should_return_empty_string buffer = new "hello" buffer.position = 5 assert_equal "", buffer.read end def test_consume_without_argument_should_resize_buffer_to_start_at_position buffer = new "hello world" buffer.read(5) assert_equal 5, buffer.position assert_equal 11, buffer.length buffer.consume! assert_equal 0, buffer.position assert_equal 6, buffer.length assert_equal " world", buffer.to_s end def test_consume_with_argument_should_resize_buffer_starting_at_n buffer = new "hello world" assert_equal 0, buffer.position buffer.consume!(5) assert_equal 0, buffer.position assert_equal 6, buffer.length assert_equal " world", buffer.to_s end def test_read_bang_should_read_and_consume_and_return_read_portion buffer = new "hello world" assert_equal "hello", buffer.read!(5) assert_equal 0, buffer.position assert_equal 6, buffer.length assert_equal " world", buffer.to_s end def test_available_should_return_length_after_position_to_end_of_string buffer = new "hello world" buffer.read(5) assert_equal 6, buffer.available end def test_clear_bang_should_reset_buffer_contents_and_counters buffer = new "hello world" buffer.read(5) buffer.clear! assert_equal 0, buffer.length assert_equal 0, buffer.position assert_equal "", buffer.to_s end def test_append_should_append_argument_without_changing_position_and_should_return_self buffer = new "hello world" buffer.read(5) buffer.append(" again") assert_equal 5, buffer.position assert_equal 12, buffer.available assert_equal 17, buffer.length assert_equal "hello world again", buffer.to_s end def test_remainder_as_buffer_should_return_a_new_buffer_filled_with_the_text_after_the_current_position buffer = new "hello world" buffer.read(6) b2 = buffer.remainder_as_buffer assert_equal 6, buffer.position assert_equal 0, b2.position assert_equal "world", b2.to_s end def test_read_int64_should_return_8_byte_integer buffer = new "\xff\xee\xdd\xcc\xbb\xaa\x99\x88" assert_equal 0xffeeddccbbaa9988, buffer.read_int64 assert_equal 8, buffer.position end def test_read_int64_should_return_nil_on_partial_read buffer = new "\0\0\0\0\0\0\0" assert_nil buffer.read_int64 assert buffer.eof? end def test_read_long_should_return_4_byte_integer buffer = new "\xff\xee\xdd\xcc\xbb\xaa\x99\x88" assert_equal 0xffeeddcc, buffer.read_long assert_equal 4, buffer.position end def test_read_long_should_return_nil_on_partial_read buffer = new "\0\0\0" assert_nil buffer.read_long assert buffer.eof? end def test_read_byte_should_return_single_byte_integer buffer = new "\xfe\xdc" assert_equal 0xfe, buffer.read_byte assert_equal 1, buffer.position end def test_read_byte_should_return_nil_at_eof assert_nil new.read_byte end def test_read_string_should_read_length_and_data_from_buffer buffer = new "\0\0\0\x0bhello world" assert_equal "hello world", buffer.read_string end def test_read_string_should_return_nil_if_4_byte_length_cannot_be_read assert_nil new("\0\1").read_string end def test_read_bool_should_return_true_if_non_zero_byte_is_read buffer = new "\1\2\3\4\5\6" 6.times { assert_equal true, buffer.read_bool } end def test_read_bool_should_return_false_if_zero_byte_is_read buffer = new "\0" assert_equal false, buffer.read_bool end def test_read_bool_should_return_nil_at_eof assert_nil new.read_bool end def test_read_bignum_should_read_openssl_formatted_bignum buffer = new("\000\000\000\004I\226\002\322") assert_equal OpenSSL::BN.new("1234567890", 10), buffer.read_bignum end def test_read_bignum_should_return_nil_if_length_cannot_be_read assert_nil new("\0\1\2").read_bignum end def test_read_key_blob_should_read_dsa_keys random_dss { |buffer| buffer.read_keyblob("ssh-dss") } end def test_read_key_blob_should_read_rsa_keys random_rsa { |buffer| buffer.read_keyblob("ssh-rsa") } end def test_read_key_should_read_dsa_key_type_and_keyblob random_dss do |buffer| b2 = Net::SSH::Buffer.from(:string, "ssh-dss", :raw, buffer) b2.read_key end end def test_read_key_should_read_rsa_key_type_and_keyblob random_rsa do |buffer| b2 = Net::SSH::Buffer.from(:string, "ssh-rsa", :raw, buffer) b2.read_key end end def test_read_buffer_should_read_a_string_and_return_it_wrapped_in_a_buffer buffer = new("\0\0\0\x0bhello world") b2 = buffer.read_buffer assert_equal 0, b2.position assert_equal 11, b2.length assert_equal "hello world", b2.read end def test_read_to_should_return_nil_if_pattern_does_not_exist_in_buffer buffer = new("one two three") assert_nil buffer.read_to("\n") end def test_read_to_should_grok_string_patterns buffer = new("one two three") assert_equal "one tw", buffer.read_to("tw") assert_equal 6, buffer.position end def test_read_to_should_grok_regex_patterns buffer = new("one two three") assert_equal "one tw", buffer.read_to(/tw/) assert_equal 6, buffer.position end def test_read_to_should_grok_fixnum_patterns buffer = new("one two three") assert_equal "one tw", buffer.read_to(?w) assert_equal 6, buffer.position end def test_reset_bang_should_reset_position_to_0 buffer = new("hello world") buffer.read(5) assert_equal 5, buffer.position buffer.reset! assert_equal 0, buffer.position end def test_write_should_write_arguments_directly_to_end_buffer buffer = new("start") buffer.write "hello", " ", "world" assert_equal "starthello world", buffer.to_s assert_equal 0, buffer.position end def test_write_int64_should_write_arguments_as_8_byte_integers_to_end_of_buffer buffer = new("start") buffer.write_int64 0xffeeddccbbaa9988, 0x7766554433221100 assert_equal "start\xff\xee\xdd\xcc\xbb\xaa\x99\x88\x77\x66\x55\x44\x33\x22\x11\x00", buffer.to_s end def test_write_long_should_write_arguments_as_4_byte_integers_to_end_of_buffer buffer = new("start") buffer.write_long 0xffeeddcc, 0xbbaa9988 assert_equal "start\xff\xee\xdd\xcc\xbb\xaa\x99\x88", buffer.to_s end def test_write_byte_should_write_arguments_as_1_byte_integers_to_end_of_buffer buffer = new("start") buffer.write_byte 1, 2, 3, 4, 5 assert_equal "start\1\2\3\4\5", buffer.to_s end def test_write_bool_should_write_arguments_as_1_byte_boolean_values_to_end_of_buffer buffer = new("start") buffer.write_bool nil, false, true, 1, Object.new assert_equal "start\0\0\1\1\1", buffer.to_s end def test_write_bignum_should_write_arguments_as_ssh_formatted_bignum_values_to_end_of_buffer buffer = new("start") buffer.write_bignum OpenSSL::BN.new('1234567890', 10) assert_equal "start\000\000\000\004I\226\002\322", buffer.to_s end def test_write_dss_key_should_write_argument_to_end_of_buffer buffer = new("start") key = OpenSSL::PKey::DSA.new key.p = 0xffeeddccbbaa9988 key.q = 0x7766554433221100 key.g = 0xffddbb9977553311 key.pub_key = 0xeeccaa8866442200 buffer.write_key(key) assert_equal "start\0\0\0\7ssh-dss\0\0\0\011\0\xff\xee\xdd\xcc\xbb\xaa\x99\x88\0\0\0\010\x77\x66\x55\x44\x33\x22\x11\x00\0\0\0\011\0\xff\xdd\xbb\x99\x77\x55\x33\x11\0\0\0\011\0\xee\xcc\xaa\x88\x66\x44\x22\x00", buffer.to_s end def test_write_rsa_key_should_write_argument_to_end_of_buffer buffer = new("start") key = OpenSSL::PKey::RSA.new key.e = 0xffeeddccbbaa9988 key.n = 0x7766554433221100 buffer.write_key(key) assert_equal "start\0\0\0\7ssh-rsa\0\0\0\011\0\xff\xee\xdd\xcc\xbb\xaa\x99\x88\0\0\0\010\x77\x66\x55\x44\x33\x22\x11\x00", buffer.to_s end if defined?(OpenSSL::PKey::EC) def test_read_key_blob_should_read_ecdsa_sha2_nistp256_keys random_ecdsa_sha2_nistp256 { |buffer| buffer.read_keyblob("ecdsa-sha2-nistp256") } end def test_read_key_blob_should_read_ecdsa_sha2_nistp384_keys random_ecdsa_sha2_nistp384 { |buffer| buffer.read_keyblob("ecdsa-sha2-nistp384") } end def test_read_key_blob_should_read_ecdsa_sha2_nistp521_keys random_ecdsa_sha2_nistp521 { |buffer| buffer.read_keyblob("ecdsa-sha2-nistp521") } end def test_read_key_should_read_ecdsa_sha2_nistp256_key_type_and_keyblob random_ecdsa_sha2_nistp256 do |buffer| b2 = Net::SSH::Buffer.from(:string, "ecdsa-sha2-nistp256", :raw, buffer) b2.read_key end end def test_read_key_should_read_ecdsa_sha2_nistp384_key_type_and_keyblob random_ecdsa_sha2_nistp384 do |buffer| b2 = Net::SSH::Buffer.from(:string, "ecdsa-sha2-nistp384", :raw, buffer) b2.read_key end end def test_read_key_should_read_ecdsa_sha2_nistp521_key_type_and_keyblob random_ecdsa_sha2_nistp521 do |buffer| b2 = Net::SSH::Buffer.from(:string, "ecdsa-sha2-nistp521", :raw, buffer) b2.read_key end end def test_write_ecdsa_sha2_nistp256_key_should_write_argument_to_end_of_buffer buffer = new("start") key = OpenSSL::PKey::EC.new("-----BEGIN EC PRIVATE KEY-----\nMHcCAQEEIISGj5vAJCWt2KPI8NwaWVDSNLl2vbRxDIOkY+n6O0VVoAoGCCqGSM49\nAwEHoUQDQgAEnKbs0yEogTKT4QRu8T9nb2svl2mEWXb6g224oCpD2o6TYNXNw54H\nmWkdCv+kFCqSlfSi5fqFhrXdfEY6zSzQYQ==\n-----END EC PRIVATE KEY-----\n") buffer.write_key(key) assert_equal "start\000\000\000\023ecdsa-sha2-nistp256\000\000\000\bnistp256\000\000\000A\004\234\246\354\323!(\2012\223\341\004n\361?gok/\227i\204Yv\372\203m\270\240*C\332\216\223`\325\315\303\236\a\231i\035\n\377\244\024*\222\225\364\242\345\372\205\206\265\335|F:\315,\320a", buffer.to_s end def test_write_ecdsa_sha2_nistp384_key_should_write_argument_to_end_of_buffer buffer = new("start") key = OpenSSL::PKey::EC.new("-----BEGIN EC PRIVATE KEY-----\nMIGkAgEBBDBAfxJpzhsR7O+wMol6BcDgualR8rJBvYegUDYbBUrDnPzDx2/gD1lZ\nnwG1FuD2s9igBwYFK4EEACKhZANiAATsfiU4Kxyvvj1DdvFYsdDnZIT7loRlan9I\n8geCWPPl6x7NFRP+awrnTaarMgieGqxG8IQaIA0SsDOICfbDBkuatRi0S1Et/in4\nZwVEZvO81Ro5YSrjuUDAsytnI6OXS28=\n-----END EC PRIVATE KEY-----\n") buffer.write_key(key) assert_equal "start\000\000\000\023ecdsa-sha2-nistp384\000\000\000\bnistp384\000\000\000a\004\354~%8+\034\257\276=Cv\361X\261\320\347d\204\373\226\204ej\177H\362\a\202X\363\345\353\036\315\025\023\376k\n\347M\246\2532\b\236\032\254F\360\204\032 \r\022\2603\210\t\366\303\006K\232\265\030\264KQ-\376)\370g\005Df\363\274\325\0329a*\343\271@\300\263+g#\243\227Ko", buffer.to_s end def test_write_ecdsa_sha2_nistp521_key_should_write_argument_to_end_of_buffer buffer = new("start") key = OpenSSL::PKey::EC.new("-----BEGIN EC PRIVATE KEY-----\nMIHbAgEBBEGhnQF/SFo4Vym88HnCfc6BR8WwYqDh9wNTPeqzR8auxIpp0GKQlCG2\nuHzyteJX5/YalV8empYhEzNmNLNn8x7j0aAHBgUrgQQAI6GBiQOBhgAEAYygOgV9\nVI8UyLQ3BDlv+rb3es+ufrIcj++cqcc9QcmRn237NiWRr/1NKy2AKijsEdACtZXo\nxPC0x9Vs9ieC2oR+ANOBubcxPl2giDnBYm8ywAmmlXsP5ByAM17k97CzW5O+Z/uO\nbxGUzzhoXTNcjqpAckhRVKdnh6FL/rKelT0tBYi+\n-----END EC PRIVATE KEY-----\n") buffer.write_key(key) assert_equal "start\000\000\000\023ecdsa-sha2-nistp521\000\000\000\bnistp521\000\000\000\205\004\001\214\240:\005}T\217\024\310\2647\0049o\372\266\367z\317\256~\262\034\217\357\234\251\307=A\311\221\237m\3736%\221\257\375M+-\200*(\354\021\320\002\265\225\350\304\360\264\307\325l\366'\202\332\204~\000\323\201\271\2671>]\240\2109\301bo2\300\t\246\225{\017\344\034\2003^\344\367\260\263[\223\276g\373\216o\021\224\3178h]3\\\216\252@rHQT\247g\207\241K\376\262\236\225=-\005\210\276", buffer.to_s end end private def random_rsa n1 = OpenSSL::BN.new(rand(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF).to_s, 10) n2 = OpenSSL::BN.new(rand(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF).to_s, 10) buffer = Net::SSH::Buffer.from(:bignum, [n1, n2]) key = yield(buffer) assert_equal "ssh-rsa", key.ssh_type assert_equal n1, key.e assert_equal n2, key.n end def random_dss n1 = OpenSSL::BN.new(rand(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF).to_s, 10) n2 = OpenSSL::BN.new(rand(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF).to_s, 10) n3 = OpenSSL::BN.new(rand(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF).to_s, 10) n4 = OpenSSL::BN.new(rand(0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF).to_s, 10) buffer = Net::SSH::Buffer.from(:bignum, [n1, n2, n3, n4]) key = yield(buffer) assert_equal "ssh-dss", key.ssh_type assert_equal n1, key.p assert_equal n2, key.q assert_equal n3, key.g assert_equal n4, key.pub_key end if defined?(OpenSSL::PKey::EC) def random_ecdsa_sha2_nistp256 k = OpenSSL::PKey::EC.new("prime256v1").generate_key buffer = Net::SSH::Buffer.from(:string, "nistp256", :string, k.public_key.to_bn.to_s(2)) key = yield(buffer) assert_equal "ecdsa-sha2-nistp256", key.ssh_type assert_equal k.public_key, key.public_key end def random_ecdsa_sha2_nistp384 k = OpenSSL::PKey::EC.new("secp384r1").generate_key buffer = Net::SSH::Buffer.from(:string, "nistp384", :string, k.public_key.to_bn.to_s(2)) key = yield(buffer) assert_equal "ecdsa-sha2-nistp384", key.ssh_type assert_equal k.public_key, key.public_key end def random_ecdsa_sha2_nistp521 k = OpenSSL::PKey::EC.new("secp521r1").generate_key buffer = Net::SSH::Buffer.from(:string, "nistp521", :string, k.public_key.to_bn.to_s(2)) key = yield(buffer) assert_equal "ecdsa-sha2-nistp521", key.ssh_type assert_equal k.public_key, key.public_key end end def new(*args) Net::SSH::Buffer.new(*args) end end net-ssh-2.6.8/test/test_all.rb0000644000004100000410000000102312166626376016266 0ustar www-datawww-data$: << '.' # $ ruby -Ilib -Itest -rrubygems test/test_all.rb # $ ruby -Ilib -Itest -rrubygems test/transport/test_server_version.rb Dir.chdir(File.dirname(__FILE__)) do test_files = Dir['**/test_*.rb']-['test_all.rb'] # prevent circular require test_files = test_files.reject { |f| f =~ /^manual/ } test_files = test_files.select { |f| f =~ Regexp.new(ENV['ONLY']) } if ENV['ONLY'] test_files = test_files.reject { |f| f =~ Regexp.new(ENV['EXCEPT']) } if ENV['EXCEPT'] test_files.each { |file| require(file) } endnet-ssh-2.6.8/test/authentication/0000755000004100000410000000000012166626376017155 5ustar www-datawww-datanet-ssh-2.6.8/test/authentication/test_key_manager.rb0000644000004100000410000001777512166626376023044 0ustar www-datawww-datarequire 'common' require 'net/ssh/authentication/key_manager' module Authentication class TestKeyManager < Test::Unit::TestCase def test_key_files_and_known_identities_are_empty_by_default assert manager.key_files.empty? assert manager.known_identities.empty? end def test_assume_agent_is_available_by_default assert manager.use_agent? end def test_add_ensures_list_is_unique manager.add "/first" manager.add "/second" manager.add "/third" manager.add "/second" assert_true manager.key_files.length == 3 final_files = manager.key_files.map {|item| item.split('/').last} assert_equal %w(first second third), final_files end def test_use_agent_should_be_set_to_false_if_agent_could_not_be_found Net::SSH::Authentication::Agent.expects(:connect).raises(Net::SSH::Authentication::AgentNotAvailable) assert manager.use_agent? assert_nil manager.agent assert !manager.use_agent? end def test_each_identity_should_load_from_key_files manager.stubs(:agent).returns(nil) first = File.expand_path("/first") second = File.expand_path("/second") stub_file_private_key first, rsa stub_file_private_key second, dsa identities = [] manager.each_identity { |identity| identities << identity } assert_equal 2, identities.length assert_equal rsa.to_blob, identities.first.to_blob assert_equal dsa.to_blob, identities.last.to_blob assert_equal({:from => :file, :file => first, :key => rsa}, manager.known_identities[rsa]) assert_equal({:from => :file, :file => second, :key => dsa}, manager.known_identities[dsa]) end def test_identities_should_load_from_agent manager.stubs(:agent).returns(agent) identities = [] manager.each_identity { |identity| identities << identity } assert_equal 2, identities.length assert_equal rsa.to_blob, identities.first.to_blob assert_equal dsa.to_blob, identities.last.to_blob assert_equal({:from => :agent}, manager.known_identities[rsa]) assert_equal({:from => :agent}, manager.known_identities[dsa]) end if defined?(OpenSSL::PKey::EC) def test_identities_with_ecdsa_should_load_from_agent manager.stubs(:agent).returns(agent_with_ecdsa_keys) identities = [] manager.each_identity { |identity| identities << identity } assert_equal 5, identities.length assert_equal rsa.to_blob, identities[0].to_blob assert_equal dsa.to_blob, identities[1].to_blob assert_equal ecdsa_sha2_nistp256.to_blob, identities[2].to_blob assert_equal ecdsa_sha2_nistp384.to_blob, identities[3].to_blob assert_equal ecdsa_sha2_nistp521.to_blob, identities[4].to_blob assert_equal({:from => :agent}, manager.known_identities[rsa]) assert_equal({:from => :agent}, manager.known_identities[dsa]) assert_equal({:from => :agent}, manager.known_identities[ecdsa_sha2_nistp256]) assert_equal({:from => :agent}, manager.known_identities[ecdsa_sha2_nistp384]) assert_equal({:from => :agent}, manager.known_identities[ecdsa_sha2_nistp521]) end end def test_only_identities_with_key_files_should_load_from_agent_of_keys_only_set manager(:keys_only => true).stubs(:agent).returns(agent) first = File.expand_path("/first") stub_file_private_key first, rsa identities = [] manager.each_identity { |identity| identities << identity } assert_equal 1, identities.length assert_equal rsa.to_blob, identities.first.to_blob assert_equal({:from => :agent}, manager.known_identities[rsa]) end def test_identities_without_public_key_files_should_not_be_touched_if_identity_loaded_from_agent manager.stubs(:agent).returns(agent) first = File.expand_path("/first") stub_file_public_key first, rsa second = File.expand_path("/second") stub_file_private_key second, dsa, :passphrase => :should_not_be_asked identities = [] manager.each_identity do |identity| identities << identity break if manager.known_identities[identity][:from] == :agent end assert_equal 1, identities.length assert_equal rsa.to_blob, identities.first.to_blob end def test_sign_with_agent_originated_key_should_request_signature_from_agent manager.stubs(:agent).returns(agent) manager.each_identity { |identity| } # preload the known_identities agent.expects(:sign).with(rsa, "hello, world").returns("abcxyz123") assert_equal "abcxyz123", manager.sign(rsa, "hello, world") end def test_sign_with_file_originated_key_should_load_private_key_and_sign_with_it manager.stubs(:agent).returns(nil) first = File.expand_path("/first") stub_file_private_key first, rsa(512) rsa.expects(:ssh_do_sign).with("hello, world").returns("abcxyz123") manager.each_identity { |identity| } # preload the known_identities assert_equal "\0\0\0\assh-rsa\0\0\0\011abcxyz123", manager.sign(rsa, "hello, world") end def test_sign_with_file_originated_key_should_raise_key_manager_error_if_unloadable manager.known_identities[rsa] = { :from => :file, :file => "/first" } Net::SSH::KeyFactory.expects(:load_private_key).raises(OpenSSL::PKey::RSAError) assert_raises Net::SSH::Authentication::KeyManagerError do manager.sign(rsa, "hello, world") end end private def stub_file_private_key(name, key, options = {}) manager.add(name) File.stubs(:readable?).with(name).returns(true) File.stubs(:readable?).with(name + ".pub").returns(false) case options.fetch(:passphrase, :indifferently) when :should_be_asked Net::SSH::KeyFactory.expects(:load_private_key).with(name, nil, false).raises(OpenSSL::PKey::RSAError).at_least_once Net::SSH::KeyFactory.expects(:load_private_key).with(name, nil, true).returns(key).at_least_once when :should_not_be_asked Net::SSH::KeyFactory.expects(:load_private_key).with(name, nil, false).raises(OpenSSL::PKey::RSAError).at_least_once Net::SSH::KeyFactory.expects(:load_private_key).with(name, nil, true).never else # :indifferently Net::SSH::KeyFactory.expects(:load_private_key).with(name, nil, any_of(true, false)).returns(key).at_least_once end # do not override OpenSSL::PKey::EC#public_key # (it will be called in transport/openssl.rb.) unless defined?(OpenSSL::PKey::EC) && key.public_key.kind_of?(OpenSSL::PKey::EC::Point) key.stubs(:public_key).returns(key) end end def stub_file_public_key(name, key) manager.add(name) File.stubs(:readable?).with(name).returns(false) File.stubs(:readable?).with(name + ".pub").returns(true) Net::SSH::KeyFactory.expects(:load_public_key).with(name + ".pub").returns(key).at_least_once end def rsa(size=512) @rsa ||= OpenSSL::PKey::RSA.new(size) end def dsa @dsa ||= OpenSSL::PKey::DSA.new(512) end if defined?(OpenSSL::PKey::EC) def ecdsa_sha2_nistp256 @ecdsa_sha2_nistp256 ||= OpenSSL::PKey::EC.new("prime256v1").generate_key end def ecdsa_sha2_nistp384 @ecdsa_sha2_nistp384 ||= OpenSSL::PKey::EC.new("secp384r1").generate_key end def ecdsa_sha2_nistp521 @ecdsa_sha2_nistp521 ||= OpenSSL::PKey::EC.new("secp521r1").generate_key end end def agent @agent ||= stub("agent", :identities => [rsa, dsa]) end def agent_with_ecdsa_keys @agent ||= stub("agent", :identities => [rsa, dsa, ecdsa_sha2_nistp256, ecdsa_sha2_nistp384, ecdsa_sha2_nistp521]) end def manager(options = {}) @manager ||= Net::SSH::Authentication::KeyManager.new(nil, options) end end end net-ssh-2.6.8/test/authentication/test_session.rb0000644000004100000410000001073312166626376022230 0ustar www-datawww-datarequire 'common' require 'net/ssh/authentication/session' module Authentication class TestSession < Test::Unit::TestCase include Net::SSH::Transport::Constants include Net::SSH::Authentication::Constants def test_constructor_should_set_defaults assert_equal %w(none publickey hostbased password keyboard-interactive), session.auth_methods assert_equal session.auth_methods, session.allowed_auth_methods end def test_authenticate_should_continue_if_method_disallowed transport.expect do |t, packet| assert_equal SERVICE_REQUEST, packet.type assert_equal "ssh-userauth", packet.read_string t.return(SERVICE_ACCEPT) end Net::SSH::Authentication::Methods::Publickey.any_instance.expects(:authenticate).with("next service", "username", "password").raises(Net::SSH::Authentication::DisallowedMethod) Net::SSH::Authentication::Methods::Hostbased.any_instance.expects(:authenticate).with("next service", "username", "password").returns(true) Net::SSH::Authentication::Methods::None.any_instance.expects(:authenticate).with("next service", "username", "password").returns(false) assert session.authenticate("next service", "username", "password") end def test_authenticate_should_raise_error_if_service_request_fails transport.expect do |t, packet| assert_equal SERVICE_REQUEST, packet.type assert_equal "ssh-userauth", packet.read_string t.return(255) end assert_raises(Net::SSH::Exception) { session.authenticate("next service", "username", "password") } end def test_authenticate_should_return_false_if_all_auth_methods_fail transport.expect do |t, packet| assert_equal SERVICE_REQUEST, packet.type assert_equal "ssh-userauth", packet.read_string t.return(SERVICE_ACCEPT) end Net::SSH::Authentication::Methods::Publickey.any_instance.expects(:authenticate).with("next service", "username", "password").returns(false) Net::SSH::Authentication::Methods::Hostbased.any_instance.expects(:authenticate).with("next service", "username", "password").returns(false) Net::SSH::Authentication::Methods::Password.any_instance.expects(:authenticate).with("next service", "username", "password").returns(false) Net::SSH::Authentication::Methods::KeyboardInteractive.any_instance.expects(:authenticate).with("next service", "username", "password").returns(false) Net::SSH::Authentication::Methods::None.any_instance.expects(:authenticate).with("next service", "username", "password").returns(false) assert_equal false, session.authenticate("next service", "username", "password") end def test_next_message_should_silently_handle_USERAUTH_BANNER_packets transport.return(USERAUTH_BANNER, :string, "Howdy, folks!") transport.return(SERVICE_ACCEPT) assert_equal SERVICE_ACCEPT, session.next_message.type end def test_next_message_should_understand_USERAUTH_FAILURE transport.return(USERAUTH_FAILURE, :string, "a,b,c", :bool, false) packet = session.next_message assert_equal USERAUTH_FAILURE, packet.type assert_equal %w(a b c), session.allowed_auth_methods end (60..79).each do |type| define_method("test_next_message_should_return_packets_of_type_#{type}") do transport.return(type) assert_equal type, session.next_message.type end end def test_next_message_should_understand_USERAUTH_SUCCESS transport.return(USERAUTH_SUCCESS) assert !transport.hints[:authenticated] assert_equal USERAUTH_SUCCESS, session.next_message.type assert transport.hints[:authenticated] end def test_next_message_should_raise_error_on_unrecognized_packet_types transport.return(1) assert_raises(Net::SSH::Exception) { session.next_message } end def test_expect_message_should_raise_exception_if_next_packet_is_not_expected_type transport.return(SERVICE_ACCEPT) assert_raises(Net::SSH::Exception) { session.expect_message(USERAUTH_BANNER) } end def test_expect_message_should_return_packet_if_next_packet_is_expected_type transport.return(SERVICE_ACCEPT) assert_equal SERVICE_ACCEPT, session.expect_message(SERVICE_ACCEPT).type end private def session(options={}) @session ||= Net::SSH::Authentication::Session.new(transport(options), options) end def transport(options={}) @transport ||= MockTransport.new(options) end end end net-ssh-2.6.8/test/authentication/methods/0000755000004100000410000000000012166626376020620 5ustar www-datawww-datanet-ssh-2.6.8/test/authentication/methods/test_none.rb0000644000004100000410000000216312166626376023145 0ustar www-datawww-datarequire 'common' require 'net/ssh/authentication/methods/none' require 'authentication/methods/common' module Authentication; module Methods class TestNone < Test::Unit::TestCase include Common def test_authenticate_should_raise_if_none_disallowed transport.expect do |t,packet| assert_equal USERAUTH_REQUEST, packet.type assert_equal "jamis", packet.read_string assert_equal "ssh-connection", packet.read_string assert_equal "none", packet.read_string t.return(USERAUTH_FAILURE, :string, "publickey") end assert_raises Net::SSH::Authentication::DisallowedMethod do subject.authenticate("ssh-connection", "jamis", "pass") end end def test_authenticate_should_return_true transport.expect do |t,packet| assert_equal USERAUTH_REQUEST, packet.type t.return(USERAUTH_SUCCESS) end assert subject.authenticate("ssh-connection", "", "") end private def subject(options={}) @subject ||= Net::SSH::Authentication::Methods::None.new(session(options), options) end end end; end net-ssh-2.6.8/test/authentication/methods/test_publickey.rb0000644000004100000410000001335512166626376024202 0ustar www-datawww-datarequire 'common' require 'net/ssh/authentication/methods/publickey' require 'authentication/methods/common' module Authentication; module Methods class TestPublickey < Test::Unit::TestCase include Common def test_authenticate_should_return_false_when_no_key_manager_has_been_set assert_equal false, subject(:key_manager => nil).authenticate("ssh-connection", "jamis") end def test_authenticate_should_return_false_when_key_manager_has_no_keys assert_equal false, subject(:keys => []).authenticate("ssh-connection", "jamis") end def test_authenticate_should_return_false_if_no_keys_can_authenticate transport.expect do |t, packet| assert_equal USERAUTH_REQUEST, packet.type assert verify_userauth_request_packet(packet, keys.first, false) t.return(USERAUTH_FAILURE, :string, "hostbased,password") t.expect do |t2, packet2| assert_equal USERAUTH_REQUEST, packet2.type assert verify_userauth_request_packet(packet2, keys.last, false) t2.return(USERAUTH_FAILURE, :string, "hostbased,password") end end assert_equal false, subject.authenticate("ssh-connection", "jamis") end def test_authenticate_should_raise_if_publickey_disallowed key_manager.expects(:sign).with(&signature_parameters(keys.first)).returns("sig-one") transport.expect do |t, packet| assert_equal USERAUTH_REQUEST, packet.type assert verify_userauth_request_packet(packet, keys.first, false) t.return(USERAUTH_PK_OK, :string, keys.first.ssh_type, :string, Net::SSH::Buffer.from(:key, keys.first)) t.expect do |t2,packet2| assert_equal USERAUTH_REQUEST, packet2.type assert verify_userauth_request_packet(packet2, keys.first, true) assert_equal "sig-one", packet2.read_string t2.return(USERAUTH_FAILURE, :string, "hostbased,password") end end assert_raises Net::SSH::Authentication::DisallowedMethod do subject.authenticate("ssh-connection", "jamis") end end def test_authenticate_should_return_false_if_signature_exchange_fails key_manager.expects(:sign).with(&signature_parameters(keys.first)).returns("sig-one") key_manager.expects(:sign).with(&signature_parameters(keys.last)).returns("sig-two") transport.expect do |t, packet| assert_equal USERAUTH_REQUEST, packet.type assert verify_userauth_request_packet(packet, keys.first, false) t.return(USERAUTH_PK_OK, :string, keys.first.ssh_type, :string, Net::SSH::Buffer.from(:key, keys.first)) t.expect do |t2,packet2| assert_equal USERAUTH_REQUEST, packet2.type assert verify_userauth_request_packet(packet2, keys.first, true) assert_equal "sig-one", packet2.read_string t2.return(USERAUTH_FAILURE, :string, "publickey") t2.expect do |t3, packet3| assert_equal USERAUTH_REQUEST, packet3.type assert verify_userauth_request_packet(packet3, keys.last, false) t3.return(USERAUTH_PK_OK, :string, keys.last.ssh_type, :string, Net::SSH::Buffer.from(:key, keys.last)) t3.expect do |t4,packet4| assert_equal USERAUTH_REQUEST, packet4.type assert verify_userauth_request_packet(packet4, keys.last, true) assert_equal "sig-two", packet4.read_string t4.return(USERAUTH_FAILURE, :string, "publickey") end end end end assert !subject.authenticate("ssh-connection", "jamis") end def test_authenticate_should_return_true_if_any_key_can_authenticate key_manager.expects(:sign).with(&signature_parameters(keys.first)).returns("sig-one") transport.expect do |t, packet| assert_equal USERAUTH_REQUEST, packet.type assert verify_userauth_request_packet(packet, keys.first, false) t.return(USERAUTH_PK_OK, :string, keys.first.ssh_type, :string, Net::SSH::Buffer.from(:key, keys.first)) t.expect do |t2,packet2| assert_equal USERAUTH_REQUEST, packet2.type assert verify_userauth_request_packet(packet2, keys.first, true) assert_equal "sig-one", packet2.read_string t2.return(USERAUTH_SUCCESS) end end assert subject.authenticate("ssh-connection", "jamis") end private def signature_parameters(key) Proc.new do |given_key, data| next false unless given_key.to_blob == key.to_blob buffer = Net::SSH::Buffer.new(data) buffer.read_string == "abcxyz123" && # session-id buffer.read_byte == USERAUTH_REQUEST && # type verify_userauth_request_packet(buffer, key, true) end end def verify_userauth_request_packet(packet, key, has_sig) packet.read_string == "jamis" && # user-name packet.read_string == "ssh-connection" && # next service packet.read_string == "publickey" && # auth-method packet.read_bool == has_sig && # whether a signature is appended packet.read_string == key.ssh_type && # ssh key type packet.read_buffer.read_key.to_blob == key.to_blob # key end @@keys = nil def keys @@keys ||= [OpenSSL::PKey::RSA.new(512), OpenSSL::PKey::DSA.new(512)] end def key_manager(options={}) @key_manager ||= begin manager = stub("key_manager") manager.stubs(:each_identity).multiple_yields(*(options[:keys] || keys)) manager end end def subject(options={}) options[:key_manager] = key_manager(options) unless options.key?(:key_manager) @subject ||= Net::SSH::Authentication::Methods::Publickey.new(session(options), options) end end end; end net-ssh-2.6.8/test/authentication/methods/test_keyboard_interactive.rb0000644000004100000410000000750212166626376026405 0ustar www-datawww-datarequire 'common' require 'net/ssh/authentication/methods/keyboard_interactive' require 'authentication/methods/common' module Authentication; module Methods class TestKeyboardInteractive < Test::Unit::TestCase include Common USERAUTH_INFO_REQUEST = 60 USERAUTH_INFO_RESPONSE = 61 def test_authenticate_should_raise_if_keyboard_interactive_disallowed transport.expect do |t,packet| assert_equal USERAUTH_REQUEST, packet.type assert_equal "jamis", packet.read_string assert_equal "ssh-connection", packet.read_string assert_equal "keyboard-interactive", packet.read_string assert_equal "", packet.read_string # language tags assert_equal "", packet.read_string # submethods t.return(USERAUTH_FAILURE, :string, "password") end assert_raises Net::SSH::Authentication::DisallowedMethod do subject.authenticate("ssh-connection", "jamis") end end def test_authenticate_should_be_false_if_given_password_is_not_accepted transport.expect do |t,packet| assert_equal USERAUTH_REQUEST, packet.type t.return(USERAUTH_INFO_REQUEST, :string, "", :string, "", :string, "", :long, 1, :string, "Password:", :bool, false) t.expect do |t2,packet2| assert_equal USERAUTH_INFO_RESPONSE, packet2.type assert_equal 1, packet2.read_long assert_equal "the-password", packet2.read_string t2.return(USERAUTH_FAILURE, :string, "keyboard-interactive") end end assert_equal false, subject.authenticate("ssh-connection", "jamis", "the-password") end def test_authenticate_should_be_true_if_given_password_is_accepted transport.expect do |t,packet| assert_equal USERAUTH_REQUEST, packet.type t.return(USERAUTH_INFO_REQUEST, :string, "", :string, "", :string, "", :long, 1, :string, "Password:", :bool, false) t.expect do |t2,packet2| assert_equal USERAUTH_INFO_RESPONSE, packet2.type t2.return(USERAUTH_SUCCESS) end end assert subject.authenticate("ssh-connection", "jamis", "the-password") end def test_authenticate_should_duplicate_password_as_needed_to_fill_request transport.expect do |t,packet| assert_equal USERAUTH_REQUEST, packet.type t.return(USERAUTH_INFO_REQUEST, :string, "", :string, "", :string, "", :long, 2, :string, "Password:", :bool, false, :string, "Again:", :bool, false) t.expect do |t2,packet2| assert_equal USERAUTH_INFO_RESPONSE, packet2.type assert_equal 2, packet2.read_long assert_equal "the-password", packet2.read_string assert_equal "the-password", packet2.read_string t2.return(USERAUTH_SUCCESS) end end assert subject.authenticate("ssh-connection", "jamis", "the-password") end def test_authenticate_should_prompt_for_input_when_password_is_not_given subject.expects(:prompt).with("Name:", true).returns("name") subject.expects(:prompt).with("Password:", false).returns("password") transport.expect do |t,packet| assert_equal USERAUTH_REQUEST, packet.type t.return(USERAUTH_INFO_REQUEST, :string, "", :string, "", :string, "", :long, 2, :string, "Name:", :bool, true, :string, "Password:", :bool, false) t.expect do |t2,packet2| assert_equal USERAUTH_INFO_RESPONSE, packet2.type assert_equal 2, packet2.read_long assert_equal "name", packet2.read_string assert_equal "password", packet2.read_string t2.return(USERAUTH_SUCCESS) end end assert subject.authenticate("ssh-connection", "jamis", nil) end private def subject(options={}) @subject ||= Net::SSH::Authentication::Methods::KeyboardInteractive.new(session(options), options) end end end; end net-ssh-2.6.8/test/authentication/methods/test_abstract.rb0000644000004100000410000000340012166626376024004 0ustar www-datawww-datarequire 'common' require 'authentication/methods/common' require 'net/ssh/authentication/methods/abstract' module Authentication; module Methods class TestAbstract < Test::Unit::TestCase include Common def test_constructor_should_set_defaults assert_nil subject.key_manager end def test_constructor_should_honor_options assert_equal :manager, subject(:key_manager => :manager).key_manager end def test_session_id_should_query_session_id_from_key_exchange transport.stubs(:algorithms).returns(stub("algorithms", :session_id => "abcxyz123")) assert_equal "abcxyz123", subject.session_id end def test_send_message_should_delegate_to_transport transport.expects(:send_message).with("abcxyz123") subject.send_message("abcxyz123") end def test_userauth_request_should_build_well_formed_userauth_packet packet = subject.userauth_request("jamis", "ssh-connection", "password") assert_equal "\062\0\0\0\005jamis\0\0\0\016ssh-connection\0\0\0\010password", packet.to_s end def test_userauth_request_should_translate_extra_booleans_onto_end packet = subject.userauth_request("jamis", "ssh-connection", "password", true, false) assert_equal "\062\0\0\0\005jamis\0\0\0\016ssh-connection\0\0\0\010password\1\0", packet.to_s end def test_userauth_request_should_translate_extra_strings_onto_end packet = subject.userauth_request("jamis", "ssh-connection", "password", "foo", "bar") assert_equal "\062\0\0\0\005jamis\0\0\0\016ssh-connection\0\0\0\010password\0\0\0\3foo\0\0\0\3bar", packet.to_s end private def subject(options={}) @subject ||= Net::SSH::Authentication::Methods::Abstract.new(session(options), options) end end end; endnet-ssh-2.6.8/test/authentication/methods/test_password.rb0000644000004100000410000000320312166626376024044 0ustar www-datawww-datarequire 'common' require 'net/ssh/authentication/methods/password' require 'authentication/methods/common' module Authentication; module Methods class TestPassword < Test::Unit::TestCase include Common def test_authenticate_should_raise_if_password_disallowed transport.expect do |t,packet| assert_equal USERAUTH_REQUEST, packet.type assert_equal "jamis", packet.read_string assert_equal "ssh-connection", packet.read_string assert_equal "password", packet.read_string assert_equal false, packet.read_bool assert_equal "the-password", packet.read_string t.return(USERAUTH_FAILURE, :string, "publickey") end assert_raises Net::SSH::Authentication::DisallowedMethod do subject.authenticate("ssh-connection", "jamis", "the-password") end end def test_authenticate_when_password_is_acceptible_should_return_true transport.expect do |t,packet| assert_equal USERAUTH_REQUEST, packet.type t.return(USERAUTH_SUCCESS) end assert subject.authenticate("ssh-connection", "jamis", "the-password") end def test_authenticate_should_return_false_if_password_change_request_is_received transport.expect do |t,packet| assert_equal USERAUTH_REQUEST, packet.type t.return(USERAUTH_PASSWD_CHANGEREQ, :string, "Change your password:", :string, "") end assert !subject.authenticate("ssh-connection", "jamis", "the-password") end private def subject(options={}) @subject ||= Net::SSH::Authentication::Methods::Password.new(session(options), options) end end end; end net-ssh-2.6.8/test/authentication/methods/common.rb0000644000004100000410000000115412166626376022436 0ustar www-datawww-datamodule Authentication; module Methods module Common include Net::SSH::Authentication::Constants private def socket(options={}) @socket ||= stub("socket", :client_name => "me.ssh.test") end def transport(options={}) @transport ||= MockTransport.new(options.merge(:socket => socket)) end def session(options={}) @session ||= begin sess = stub("auth-session", :logger => nil, :transport => transport(options)) def sess.next_message transport.next_message end sess end end end end; endnet-ssh-2.6.8/test/authentication/methods/test_hostbased.rb0000644000004100000410000000773612166626376024175 0ustar www-datawww-datarequire 'common' require 'net/ssh/authentication/methods/hostbased' require 'authentication/methods/common' module Authentication; module Methods class TestHostbased < Test::Unit::TestCase include Common def test_authenticate_should_return_false_when_no_key_manager_has_been_set assert_equal false, subject(:key_manager => nil).authenticate("ssh-connection", "jamis") end def test_authenticate_should_return_false_when_key_manager_has_no_keys assert_equal false, subject(:keys => []).authenticate("ssh-connection", "jamis") end def test_authenticate_should_return_false_if_no_keys_can_authenticate ENV.stubs(:[]).with('USER').returns(nil) key_manager.expects(:sign).with(&signature_parameters(keys.first)).returns("sig-one") key_manager.expects(:sign).with(&signature_parameters(keys.last)).returns("sig-two") transport.expect do |t, packet| assert_equal USERAUTH_REQUEST, packet.type assert verify_userauth_request_packet(packet, keys.first) assert_equal "sig-one", packet.read_string t.return(USERAUTH_FAILURE, :string, "hostbased,password") t.expect do |t2, packet2| assert_equal USERAUTH_REQUEST, packet2.type assert verify_userauth_request_packet(packet2, keys.last) assert_equal "sig-two", packet2.read_string t2.return(USERAUTH_FAILURE, :string, "hostbased,password") end end assert_equal false, subject.authenticate("ssh-connection", "jamis") end def test_authenticate_should_return_true_if_any_key_can_authenticate ENV.stubs(:[]).with('USER').returns(nil) key_manager.expects(:sign).with(&signature_parameters(keys.first)).returns("sig-one") transport.expect do |t, packet| assert_equal USERAUTH_REQUEST, packet.type assert verify_userauth_request_packet(packet, keys.first) assert_equal "sig-one", packet.read_string t.return(USERAUTH_SUCCESS) end assert subject.authenticate("ssh-connection", "jamis") end private def signature_parameters(key) Proc.new do |given_key, data| next false unless given_key.to_blob == key.to_blob buffer = Net::SSH::Buffer.new(data) buffer.read_string == "abcxyz123" && # session-id buffer.read_byte == USERAUTH_REQUEST && # type verify_userauth_request_packet(buffer, key) end end def verify_userauth_request_packet(packet, key) packet.read_string == "jamis" && # user-name packet.read_string == "ssh-connection" && # next service packet.read_string == "hostbased" && # auth-method packet.read_string == key.ssh_type && # key type packet.read_buffer.read_key.to_blob == key.to_blob && # key packet.read_string == "me.ssh.test." && # client hostname packet.read_string == "jamis" # client username end @@keys = nil def keys @@keys ||= [OpenSSL::PKey::RSA.new(512), OpenSSL::PKey::DSA.new(512)] end def key_manager(options={}) @key_manager ||= begin manager = stub("key_manager") manager.stubs(:each_identity).multiple_yields(*(options[:keys] || keys)) manager end end def subject(options={}) options[:key_manager] = key_manager(options) unless options.key?(:key_manager) @subject ||= Net::SSH::Authentication::Methods::Hostbased.new(session(options), options) end def socket(options={}) @socket ||= stub("socket", :client_name => "me.ssh.test") end def transport(options={}) @transport ||= MockTransport.new(options.merge(:socket => socket)) end def session(options={}) @session ||= begin sess = stub("auth-session", :logger => nil, :transport => transport(options)) def sess.next_message transport.next_message end sess end end end end; end net-ssh-2.6.8/test/authentication/test_agent.rb0000644000004100000410000001520712166626376021644 0ustar www-datawww-datarequire 'common' require 'net/ssh/authentication/agent' module Authentication class TestAgent < Test::Unit::TestCase SSH2_AGENT_REQUEST_VERSION = 1 SSH2_AGENT_REQUEST_IDENTITIES = 11 SSH2_AGENT_IDENTITIES_ANSWER = 12 SSH2_AGENT_SIGN_REQUEST = 13 SSH2_AGENT_SIGN_RESPONSE = 14 SSH2_AGENT_FAILURE = 30 SSH2_AGENT_VERSION_RESPONSE = 103 SSH_COM_AGENT2_FAILURE = 102 SSH_AGENT_REQUEST_RSA_IDENTITIES = 1 SSH_AGENT_RSA_IDENTITIES_ANSWER = 2 SSH_AGENT_FAILURE = 5 def setup @original, ENV['SSH_AUTH_SOCK'] = ENV['SSH_AUTH_SOCK'], "/path/to/ssh.agent.sock" end def teardown ENV['SSH_AUTH_SOCK'] = @original end def test_connect_should_use_agent_factory_to_determine_connection_type factory.expects(:open).with("/path/to/ssh.agent.sock").returns(socket) agent(false).connect! end def test_connect_should_raise_error_if_connection_could_not_be_established factory.expects(:open).raises(SocketError) assert_raises(Net::SSH::Authentication::AgentNotAvailable) { agent(false).connect! } end def test_negotiate_should_raise_error_if_ssh2_agent_response_recieved socket.expect do |s, type, buffer| assert_equal SSH2_AGENT_REQUEST_VERSION, type assert_equal Net::SSH::Transport::ServerVersion::PROTO_VERSION, buffer.read_string s.return(SSH2_AGENT_VERSION_RESPONSE) end assert_raises(NotImplementedError) { agent.negotiate! } end def test_negotiate_should_raise_error_if_response_was_unexpected socket.expect do |s, type, buffer| assert_equal SSH2_AGENT_REQUEST_VERSION, type s.return(255) end assert_raises(Net::SSH::Authentication::AgentError) { agent.negotiate! } end def test_negotiate_should_be_successful_with_expected_response socket.expect do |s, type, buffer| assert_equal SSH2_AGENT_REQUEST_VERSION, type s.return(SSH_AGENT_RSA_IDENTITIES_ANSWER) end assert_nothing_raised { agent(:connect).negotiate! } end def test_identities_should_fail_if_SSH_AGENT_FAILURE_recieved socket.expect do |s, type, buffer| assert_equal SSH2_AGENT_REQUEST_IDENTITIES, type s.return(SSH_AGENT_FAILURE) end assert_raises(Net::SSH::Authentication::AgentError) { agent.identities } end def test_identities_should_fail_if_SSH2_AGENT_FAILURE_recieved socket.expect do |s, type, buffer| assert_equal SSH2_AGENT_REQUEST_IDENTITIES, type s.return(SSH2_AGENT_FAILURE) end assert_raises(Net::SSH::Authentication::AgentError) { agent.identities } end def test_identities_should_fail_if_SSH_COM_AGENT2_FAILURE_recieved socket.expect do |s, type, buffer| assert_equal SSH2_AGENT_REQUEST_IDENTITIES, type s.return(SSH_COM_AGENT2_FAILURE) end assert_raises(Net::SSH::Authentication::AgentError) { agent.identities } end def test_identities_should_fail_if_response_is_not_SSH2_AGENT_IDENTITIES_ANSWER socket.expect do |s, type, buffer| assert_equal SSH2_AGENT_REQUEST_IDENTITIES, type s.return(255) end assert_raises(Net::SSH::Authentication::AgentError) { agent.identities } end def test_identities_should_augment_identities_with_comment_field key1 = key key2 = OpenSSL::PKey::DSA.new(512) socket.expect do |s, type, buffer| assert_equal SSH2_AGENT_REQUEST_IDENTITIES, type s.return(SSH2_AGENT_IDENTITIES_ANSWER, :long, 2, :string, Net::SSH::Buffer.from(:key, key1), :string, "My favorite key", :string, Net::SSH::Buffer.from(:key, key2), :string, "Okay, but not the best") end result = agent.identities assert_equal key1.to_blob, result.first.to_blob assert_equal key2.to_blob, result.last.to_blob assert_equal "My favorite key", result.first.comment assert_equal "Okay, but not the best", result.last.comment end def test_close_should_close_socket socket.expects(:close) agent.close end def test_sign_should_fail_if_response_is_SSH_AGENT_FAILURE socket.expect { |s,| s.return(SSH_AGENT_FAILURE) } assert_raises(Net::SSH::Authentication::AgentError) { agent.sign(key, "hello world") } end def test_sign_should_fail_if_response_is_SSH2_AGENT_FAILURE socket.expect { |s,| s.return(SSH2_AGENT_FAILURE) } assert_raises(Net::SSH::Authentication::AgentError) { agent.sign(key, "hello world") } end def test_sign_should_fail_if_response_is_SSH_COM_AGENT2_FAILURE socket.expect { |s,| s.return(SSH_COM_AGENT2_FAILURE) } assert_raises(Net::SSH::Authentication::AgentError) { agent.sign(key, "hello world") } end def test_sign_should_fail_if_response_is_not_SSH2_AGENT_SIGN_RESPONSE socket.expect { |s,| s.return(255) } assert_raises(Net::SSH::Authentication::AgentError) { agent.sign(key, "hello world") } end def test_sign_should_return_signed_data_from_agent socket.expect do |s,type,buffer| assert_equal SSH2_AGENT_SIGN_REQUEST, type assert_equal key.to_blob, Net::SSH::Buffer.new(buffer.read_string).read_key.to_blob assert_equal "hello world", buffer.read_string assert_equal 0, buffer.read_long s.return(SSH2_AGENT_SIGN_RESPONSE, :string, "abcxyz123") end assert_equal "abcxyz123", agent.sign(key, "hello world") end private class MockSocket def initialize @expectation = nil @buffer = Net::SSH::Buffer.new end def expect(&block) @expectation = block end def return(type, *args) data = Net::SSH::Buffer.from(*args) @buffer.append([data.length+1, type, data.to_s].pack("NCA*")) end def send(data, flags) raise "got #{data.inspect} but no packet was expected" unless @expectation buffer = Net::SSH::Buffer.new(data) buffer.read_long # skip the length type = buffer.read_byte @expectation.call(self, type, buffer) @expectation = nil end def read(length) @buffer.read(length) end end def key @key ||= OpenSSL::PKey::RSA.new(512) end def socket @socket ||= MockSocket.new end def factory @factory ||= stub("socket factory", :open => socket) end def agent(auto=:connect) @agent ||= begin agent = Net::SSH::Authentication::Agent.new agent.stubs(:agent_socket_factory).returns(factory) agent.connect! if auto == :connect agent end end end endnet-ssh-2.6.8/test/test_known_hosts.rb0000644000004100000410000000053312166626376020077 0ustar www-datawww-datarequire 'common' class TestKnownHosts < Test::Unit::TestCase def test_key_for_when_all_hosts_are_recognized source = File.join(File.dirname(__FILE__),"known_hosts/github") kh = Net::SSH::KnownHosts.new(source) keys = kh.keys_for("github.com") assert_equal(1, keys.count) assert_equal("ssh-rsa", keys[0].ssh_type) end endnet-ssh-2.6.8/test/test_buffered_io.rb0000644000004100000410000000352412166626376017777 0ustar www-datawww-datarequire 'common' require 'net/ssh/buffered_io' class TestBufferedIo < Test::Unit::TestCase def test_fill_should_pull_from_underlying_io io.expects(:recv).with(8192).returns("here is some data") assert_equal 17, io.fill assert_equal 17, io.available assert_equal "here is some data", io.read_available(20) end def test_enqueue_should_not_write_to_underlying_io assert !io.pending_write? io.expects(:send).never io.enqueue("here is some data") assert io.pending_write? end def test_send_pending_should_not_fail_when_no_writes_are_pending assert !io.pending_write? io.expects(:send).never assert_nothing_raised { io.send_pending } end def test_send_pending_with_pending_writes_should_write_to_underlying_io io.enqueue("here is some data") io.expects(:send).with("here is some data", 0).returns(17) assert io.pending_write? assert_nothing_raised { io.send_pending } assert !io.pending_write? end def test_wait_for_pending_sends_should_write_only_once_if_all_can_be_written_at_once io.enqueue("here is some data") io.expects(:send).with("here is some data", 0).returns(17) assert io.pending_write? assert_nothing_raised { io.wait_for_pending_sends } assert !io.pending_write? end def test_wait_for_pending_sends_should_write_multiple_times_if_first_write_was_partial io.enqueue("here is some data") io.expects(:send).with("here is some data", 0).returns(10) io.expects(:send).with("me data", 0).returns(4) io.expects(:send).with("ata", 0).returns(3) IO.expects(:select).times(2).with(nil, [io]).returns([[], [io]]) assert_nothing_raised { io.wait_for_pending_sends } assert !io.pending_write? end private def io @io ||= begin io = mock("io") io.extend(Net::SSH::BufferedIo) io end end endnet-ssh-2.6.8/test/test_config.rb0000644000004100000410000001177712166626376017004 0ustar www-datawww-datarequire 'common' require 'net/ssh/config' require 'pathname' class TestConfig < Test::Unit::TestCase def test_home_should_be_absolute_path assert Pathname.new(ENV['HOME']).absolute? end def test_load_for_non_existant_file_should_return_empty_hash bogus_file = File.expand_path("/bogus/file") File.expects(:readable?).with(bogus_file).returns(false) assert_equal({}, Net::SSH::Config.load(bogus_file, "host.name")) end def test_load_should_expand_path expected = File.expand_path("~/.ssh/config") File.expects(:readable?).with(expected).returns(false) Net::SSH::Config.load("~/.ssh/config", "host.name") end def test_load_with_exact_host_match_should_load_that_section config = Net::SSH::Config.load(config(:exact_match), "test.host") assert config['compression'] assert config['forwardagent'] assert_equal 1234, config['port'] end def test_load_with_wild_card_matches_should_load_all_matches_with_first_match_taking_precedence config = Net::SSH::Config.load(config(:wild_cards), "test.host") assert_equal 1234, config['port'] assert !config['compression'] assert config['forwardagent'] assert_equal %w(~/.ssh/id_dsa), config['identityfile'] assert !config.key?('rekeylimit') end def test_for_should_load_all_files_and_translate_to_net_ssh_options config = Net::SSH::Config.for("test.host", [config(:exact_match), config(:wild_cards)]) assert_equal 1234, config[:port] assert config[:compression] assert config[:forward_agent] assert_equal %w(~/.ssh/id_dsa), config[:keys] assert !config.key?(:rekey_limit) end def test_load_with_no_host config = Net::SSH::Config.load(config(:nohost), "test.host") assert_equal %w(~/.ssh/id_dsa ~/.ssh/id_rsa), config['identityfile'] assert_equal 1985, config['port'] end def test_load_with_multiple_hosts config = Net::SSH::Config.load(config(:multihost), "test.host") assert config['compression'] assert_equal '2G', config['rekeylimit'] assert_equal 1980, config['port'] end def test_load_with_multiple_hosts_and_config_should_match_for_both aconfig = Net::SSH::Config.load(config(:multihost), "test.host") bconfig = Net::SSH::Config.load(config(:multihost), "other.host") assert_equal aconfig['port'], bconfig['port'] assert_equal aconfig['compression'], bconfig['compression'] assert_equal aconfig['rekeylimit'], bconfig['rekeylimit'] end def test_load_should_parse_equal_sign_delimiters config = Net::SSH::Config.load(config(:eqsign), "test.test") assert config['compression'] assert_equal 1234, config['port'] end def test_translate_should_correctly_translate_from_openssh_to_net_ssh_names open_ssh = { 'bindaddress' => "127.0.0.1", 'ciphers' => "a,b,c", 'compression' => true, 'compressionlevel' => 6, 'connecttimeout' => 100, 'forwardagent' => true, 'hostbasedauthentication' => true, 'hostkeyalgorithms' => "d,e,f", 'identityfile' => %w(g h i), 'macs' => "j,k,l", 'passwordauthentication' => true, 'port' => 1234, 'pubkeyauthentication' => true, 'rekeylimit' => 1024 } net_ssh = Net::SSH::Config.translate(open_ssh) assert_equal %w(a b c), net_ssh[:encryption] assert_equal true, net_ssh[:compression] assert_equal 6, net_ssh[:compression_level] assert_equal 100, net_ssh[:timeout] assert_equal true, net_ssh[:forward_agent] assert_equal %w(hostbased password publickey), net_ssh[:auth_methods].sort assert_equal %w(d e f), net_ssh[:host_key] assert_equal %w(g h i), net_ssh[:keys] assert_equal %w(j k l), net_ssh[:hmac] assert_equal 1234, net_ssh[:port] assert_equal 1024, net_ssh[:rekey_limit] assert_equal "127.0.0.1", net_ssh[:bind_address] end def test_load_with_plus_sign_hosts config = Net::SSH::Config.load(config(:host_plus), "test.host") assert config['compression'] end def test_load_with_numeric_host config = Net::SSH::Config.load(config(:numeric_host), "1234") assert config['compression'] assert_equal '2G', config['rekeylimit'] assert_equal 1980, config['port'] end def test_load_wildcar_with_substitutes config = Net::SSH::Config.load(config(:substitutes), "toto") net_ssh = Net::SSH::Config.translate(config) assert_equal 'toto', net_ssh[:host_name] end def test_load_sufix_with_substitutes config = Net::SSH::Config.load(config(:substitutes), "test") net_ssh = Net::SSH::Config.translate(config) assert_equal 'test.sufix', net_ssh[:host_name] end def test_load_prefix_and_sufix_with_substitutes config = Net::SSH::Config.load(config(:substitutes), "1234") net_ssh = Net::SSH::Config.translate(config) assert_equal 'prefix.1234.sufix', net_ssh[:host_name] end private def config(name) "test/configs/#{name}" end end net-ssh-2.6.8/test/known_hosts/0000755000004100000410000000000012166626376016512 5ustar www-datawww-datanet-ssh-2.6.8/test/known_hosts/github0000644000004100000410000000060712166626376017722 0ustar www-datawww-datagithub.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==net-ssh-2.6.8/test/README.txt0000644000004100000410000000213212166626376015632 0ustar www-datawww-data2011-01-19 RUNNING TESTS Run the test suite from the net-ssh directory with the following command: ruby -Ilib -Itest -rrubygems test/test_all.rb Run a single test file like this: ruby -Ilib -Itest -rrubygems test/transport/test_server_version.rb EXPECTED RESULTS * Ruby 1.9: all tests pass * Ruby 1.8: all tests pass (up until version 2.5) * JRuby 1.7: 98% test pass (510 tests, 1914 assertions, 2 failures, 9 errors) * JRuby 1.6: 98% test pass (510 tests, 1914 assertions, 4 failures, 5 errors) * JRuby 1.5: 98% tests pass (510 tests, 1914 assertions, 5 failures, 5 errors) PORT FORWARDING TESTS ruby -Ilib -Itest -rrubygems test/manual/test_forward.rb test_forward.rb must be run separately from the test suite because it requires authorizing your public SSH keys on you localhost. If you already have keys you can do this: cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys If you don't have keys see: http://kimmo.suominen.com/docs/ssh/#ssh-keygen You should now be able to login to your localhost with out bring prompted for a password: ssh localhost -Delano net-ssh-2.6.8/README.rdoc0000644000004100000410000002000512166626376014762 0ustar www-datawww-data= Net::SSH 2.x Please note: this project is in maintenance mode. It is not under active development but pull requests are very much welcome. Just be sure to include tests! -- delano * Docs: http://net-ssh.github.com/net-ssh * Issues: https://github.com/net-ssh/net-ssh/issues * Codes: https://github.com/net-ssh/net-ssh * Email: net-ssh@solutious.com As of v2.6.4, all gem releases are signed. See INSTALL. == DESCRIPTION: Net::SSH is a pure-Ruby implementation of the SSH2 client protocol. It allows you to write programs that invoke and interact with processes on remote servers, via SSH2. == FEATURES: * Execute processes on remote servers and capture their output * Run multiple processes in parallel over a single SSH connection * Support for SSH subsystems * Forward local and remote ports via an SSH connection == SYNOPSIS: In a nutshell: require 'net/ssh' Net::SSH.start('host', 'user', :password => "password") do |ssh| # capture all stderr and stdout output from a remote process output = ssh.exec!("hostname") # capture only stdout matching a particular pattern stdout = "" ssh.exec!("ls -l /home/jamis") do |channel, stream, data| stdout << data if stream == :stdout end puts stdout # run multiple processes in parallel to completion ssh.exec "sed ..." ssh.exec "awk ..." ssh.exec "rm -rf ..." ssh.loop # open a new channel and configure a minimal set of callbacks, then run # the event loop until the channel finishes (closes) channel = ssh.open_channel do |ch| ch.exec "/usr/local/bin/ruby /path/to/file.rb" do |ch, success| raise "could not execute command" unless success # "on_data" is called when the process writes something to stdout ch.on_data do |c, data| $stdout.print data end # "on_extended_data" is called when the process writes something to stderr ch.on_extended_data do |c, type, data| $stderr.print data end ch.on_close { puts "done!" } end end channel.wait # forward connections on local port 1234 to port 80 of www.capify.org ssh.forward.local(1234, "www.capify.org", 80) ssh.loop { true } end See Net::SSH for more documentation, and links to further information. == REQUIREMENTS: The only requirement you might be missing is the OpenSSL bindings for Ruby. These are built by default on most platforms, but you can verify that they're built and installed on your system by running the following command line: ruby -ropenssl -e 'puts OpenSSL::OPENSSL_VERSION' If that spits out something like "OpenSSL 0.9.8g 19 Oct 2007", then you're set. If you get an error, then you'll need to see about rebuilding ruby with OpenSSL support, or (if your platform supports it) installing the OpenSSL bindings separately. Additionally: if you are going to be having Net::SSH prompt you for things like passwords or certificate passphrases, you'll want to have either the Highline (recommended) or Termios (unix systems only) gem installed, so that the passwords don't echo in clear text. Lastly, if you want to run the tests or use any of the Rake tasks, you'll need: * Echoe (for the Rakefile) * Mocha (for the tests) == INSTALL: * gem install net-ssh (might need sudo privileges) NOTE: If you are running on jruby you need to install jruby-pageant manually (gemspec doesn't allow for platform specific dependencies). However, in order to be sure the code you're installing hasn't been tampered with, it's recommended that you verify the signature[http://docs.rubygems.org/read/chapter/21]. To do this, you need to add my public key as a trusted certificate (you only need to do this once): # Add the public key as a trusted certificate # (You only need to do this once) $ curl -O https://raw.github.com/net-ssh/net-ssh/master/gem-public_cert.pem $ gem cert --add gem-public_cert.pem Then, when install the gem, do so with high security: $ gem install net-ssh -P HighSecurity If you don't add the public key, you'll see an error like "Couldn't verify data signature". If you're still having trouble let me know and I'll give you a hand. == RUBY 1.8 SUPPORT net-ssh supports Ruby 1.8.x up until the 2.5.1 release. Later releases will work but the test suite is no longer guaranteed to pass all tests. == JRUBY 1.6 There is an issue with jruby-openssl that produces the following error in jruby 1.6: wrong number of arguments (2 for 1) /home/offers/tracking/shared/bundle/jruby/1.8/gems/net-ssh-2.6.0/lib/net/ssh/key_factory.rb:77:in `load_data_private_key' You can downgrade jruby-openssl to version 0.7.4 (before they added the PKey.read method) to resolve it or upgrade jruby to 1.7. See issue #61 for more info: https://github.com/net-ssh/net-ssh/issues/61. == ARCFOUR SUPPORT: from Karl Varga: Ruby's OpenSSL bindings always return a key length of 16 for RC4 ciphers, which means that when we try to use ARCFOUR256 or higher, Net::SSH generates keys which are consistently too short - 16 bytes as opposed to 32 bytes - resulting in the following error: OpenSSL::CipherError: key length too short My patch simply instructs Net::SSH to build keys of the the proper length, regardless of the required key length reported by OpenSSL. You should also be aware that your OpenSSL C libraries may also contain this bug. I've updated to 0.9.8k, but according to this thread[https://bugzilla.mindrot.org/show_bug.cgi?id=1291], the bug existed as recently as 0.9.8e! I've manually taken a look at my header files and they look ok, which is what makes me think it's a bug in the Ruby implementation. To see your OpenSSL version: $ openssl version OpenSSL 0.9.8k 25 Mar 2009 After installing this gem, verify that Net::SSH is generating keys of the correct length by running the script support/arcfour_check.rb: $ ruby arcfour_support.rb which should produce the following: arcfour128: [16, 8] OpenSSL::Cipher::Cipher arcfour256: [32, 8] OpenSSL::Cipher::Cipher arcfour512: [64, 8] OpenSSL::Cipher::Cipher == RUNNING TESTS Run the test suite from the net-ssh directory with the following command: bash -c 'unset HOME && ruby -Ilib -Itest -rrubygems test/test_all.rb' Run a single test file like this: ruby -Ilib -Itest -rrubygems test/transport/test_server_version.rb === EXPECTED RESULTS * Ruby 1.8: all tests pass * Ruby 1.9: all tests pass * JRuby 1.5: 99% tests pass (448 tests, 1846 assertions, 1 failures) === PORT FORWARDING TESTS ruby -Ilib -Itest -rrubygems test/manual/test_forward.rb test_forward.rb must be run separately from the test suite because it requires authorizing your public SSH keys on you localhost. If you already have keys you can do this: cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys If you don't have keys see: http://kimmo.suominen.com/docs/ssh/#ssh-keygen You should now be able to login to your localhost with out bring prompted for a password: ssh localhost == LICENSE: (The MIT License) Copyright (c) 2008 Jamis Buck Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. net-ssh-2.6.8/Rakefile0000644000004100000410000000351512166626376014630 0ustar www-datawww-datarequire "rubygems" require "rake" require "rake/clean" require "rdoc/task" task :default => ["build"] CLEAN.include [ 'pkg', 'rdoc' ] name = "net-ssh" $:.unshift File.join(File.dirname(__FILE__), 'lib') require "net/ssh" version = Net::SSH::Version::CURRENT begin require "jeweler" Jeweler::Tasks.new do |s| s.version = version s.name = name s.rubyforge_project = s.name s.summary = "Net::SSH: a pure-Ruby implementation of the SSH2 client protocol." s.description = s.summary + " It allows you to write programs that invoke and interact with processes on remote servers, via SSH2." s.email = "net-ssh@solutious.com" s.homepage = "https://github.com/net-ssh/net-ssh" s.authors = ["Jamis Buck", "Delano Mandelbaum"] # Note: this is run at package time not install time so if you are # running on jruby, you need to install jruby-pageant manually. if RUBY_PLATFORM == "java" s.add_dependency 'jruby-pageant', ">=1.1.1" end s.add_development_dependency 'test-unit' s.add_development_dependency 'mocha' s.license = "MIT" #s.signing_key = File.join('/mnt/gem/', 'gem-private_key.pem') #s.cert_chain = ['gem-public_cert.pem'] end Jeweler::GemcutterTasks.new rescue LoadError puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler" end require 'rake/testtask' Rake::TestTask.new do |t| t.libs = ["lib", "test"] end extra_files = %w[LICENSE.txt THANKS.txt CHANGES.txt ] RDoc::Task.new do |rdoc| rdoc.rdoc_dir = "rdoc" rdoc.title = "#{name} #{version}" rdoc.generator = 'hanna' # gem install hanna-nouveau rdoc.main = 'README.rdoc' rdoc.rdoc_files.include("README*") rdoc.rdoc_files.include("bin/*.rb") rdoc.rdoc_files.include("lib/**/*.rb") extra_files.each { |file| rdoc.rdoc_files.include(file) if File.exists?(file) } end net-ssh-2.6.8/Rudyfile0000644000004100000410000000401012166626376014660 0ustar www-datawww-data# Rudyfile # # This configuration is used to test installing # and running net-ssh on a clean machine. # # Usage: # # $ rudy -vv startup # $ rudy -vv testsuite # $ rudy -vv shutdown # # Requires: Rudy 0.9 (http://code.google.com/p/rudy/) # defaults do color true environment :test role :netssh end machines do region :'us-east-1' do ami 'ami-e348af8a' # Alestic Debian 5.0, 32-bit (US) end env :test do role :netssh do user :root end end end commands do allow :apt_get, "apt-get", :y, :q allow :gem_install, "/usr/bin/gem", "install", :n, '/usr/bin', :y, :V, "--no-rdoc", "--no-ri" allow :gem_sources, "/usr/bin/gem", "sources" allow :gem_uninstall, "/usr/bin/gem", "uninstall", :V allow :update_rubygems allow :rm end routines do testsuite do before :sysupdate, :installdeps, :install_gem remote :root do directory_upload 'test', '/tmp/' cd '/tmp' ruby :I, 'lib/', :I, 'test/', :r, 'rubygems', 'test/test_all.rb' end after :install_rubyforge, :install_github end install_gem do before :package_gem remote :root do disable_safe_mode file_upload "pkg/net-ssh-*.gem", "/tmp/" gem_install "/tmp/net-ssh-*.gem" end end package_gem do local do rm :r, :f, 'pkg' rake 'package' end end remove do remote :root do gem_uninstall 'net-ssh' end end installdeps do remote :root do gem_install "rye", "test-unit", "mocha" rye 'authorize-local' end end sysupdate do remote :root do apt_get "update" apt_get "install", "build-essential", "git-core" apt_get "install", "ruby1.8-dev", "rdoc", "libzlib-ruby", "rubygems" mkdir :p, "/var/lib/gems/1.8/bin" # Doesn't get created, but causes Rubygems to fail gem_install "builder", "session" gem_install 'rubygems-update', "-v=1.3.4" # circular issue with 1.3.5 and hoe update_rubygems end end end net-ssh-2.6.8/LICENSE.txt0000644000004100000410000000204512166626376015003 0ustar www-datawww-dataCopyright © 2008 Jamis Buck Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the ‘Software’), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED ‘AS IS’, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. net-ssh-2.6.8/gem-public_cert.pem0000644000004100000410000000223012166626376016720 0ustar www-datawww-data-----BEGIN CERTIFICATE----- MIIDNjCCAh6gAwIBAgIBADANBgkqhkiG9w0BAQUFADBBMQ8wDQYDVQQDDAZkZWxh bm8xGTAXBgoJkiaJk/IsZAEZFglzb2x1dGlvdXMxEzARBgoJkiaJk/IsZAEZFgNj b20wHhcNMTMwMjA2MTE1NzQ1WhcNMTQwMjA2MTE1NzQ1WjBBMQ8wDQYDVQQDDAZk ZWxhbm8xGTAXBgoJkiaJk/IsZAEZFglzb2x1dGlvdXMxEzARBgoJkiaJk/IsZAEZ FgNjb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDg1hMtl0XsMuUK AKTgYWv3gjj7vuEsE2EjT+vyBg8/LpqVVwZziiaebJT9IZiQ+sCFqbiakj0b53pI hg1yOaBEmH6/W0L7rwzqaRV9sW1eJs9JxFYQCnd67zUnzj8nnRlOjG+hhIG+Vsij npsGbt28pefuNZJjO5q2clAlfSniIIHfIsU7/StEYu6FUGOjnwryZ0r5yJlr9RrE Gs+q0DW8QnZ9UpAfuDFQZuIqeKQFFLE7nMmCGaA+0BN1nLl3fVHNbLHq7Avk8+Z+ ZuuvkdscbHlO/l+3xCNQ5nUnHwq0ADAbMLOlmiYYzqXoWLjmeI6me/clktJCfN2R oZG3UQvvAgMBAAGjOTA3MAkGA1UdEwQCMAAwHQYDVR0OBBYEFMSJOEtHzE4l0azv M0JK0kKNToK1MAsGA1UdDwQEAwIEsDANBgkqhkiG9w0BAQUFAAOCAQEAtOdE73qx OH2ydi9oT2hS5f9G0y1Z70Tlwh+VGExyfxzVE9XwC+iPpJxNraiHYgF/9/oky7ZZ R9q0/tJneuhAenZdiQkX7oi4O3v9wRS6YHoWBxMPFKVRLNTzvVJsbmfpCAlp5/5g ps4wQFy5mibElGVlOobf/ghqZ25HS9J6kd0/C/ry0AUtTogsL7TxGwT4kbCx63ub 3vywEEhsJUzfd97GCABmtQfRTldX/j7F1z/5wd8p+hfdox1iibds9ZtfaZA3KzKn kchWN9B6zg9r1XMQ8BM2Jz0XoPanPe354+lWwjpkRKbFow/ZbQHcCLCq24+N6b6g dgKfNDzwiDpqCA== -----END CERTIFICATE----- net-ssh-2.6.8/Manifest0000644000004100000410000001063112166626376014651 0ustar www-datawww-dataCHANGELOG.rdoc Manifest README.rdoc Rakefile Rudyfile THANKS.rdoc lib/net/ssh.rb lib/net/ssh/authentication/agent.rb lib/net/ssh/authentication/constants.rb lib/net/ssh/authentication/key_manager.rb lib/net/ssh/authentication/methods/abstract.rb lib/net/ssh/authentication/methods/hostbased.rb lib/net/ssh/authentication/methods/keyboard_interactive.rb lib/net/ssh/authentication/methods/password.rb lib/net/ssh/authentication/methods/publickey.rb lib/net/ssh/authentication/pageant.rb lib/net/ssh/authentication/session.rb lib/net/ssh/buffer.rb lib/net/ssh/buffered_io.rb lib/net/ssh/config.rb lib/net/ssh/connection/channel.rb lib/net/ssh/connection/constants.rb lib/net/ssh/connection/session.rb lib/net/ssh/connection/term.rb lib/net/ssh/errors.rb lib/net/ssh/key_factory.rb lib/net/ssh/known_hosts.rb lib/net/ssh/loggable.rb lib/net/ssh/packet.rb lib/net/ssh/prompt.rb lib/net/ssh/proxy/command.rb lib/net/ssh/proxy/errors.rb lib/net/ssh/proxy/http.rb lib/net/ssh/proxy/socks4.rb lib/net/ssh/proxy/socks5.rb lib/net/ssh/ruby_compat.rb lib/net/ssh/service/forward.rb lib/net/ssh/test.rb lib/net/ssh/test/channel.rb lib/net/ssh/test/extensions.rb lib/net/ssh/test/kex.rb lib/net/ssh/test/local_packet.rb lib/net/ssh/test/packet.rb lib/net/ssh/test/remote_packet.rb lib/net/ssh/test/script.rb lib/net/ssh/test/socket.rb lib/net/ssh/transport/algorithms.rb lib/net/ssh/transport/cipher_factory.rb lib/net/ssh/transport/constants.rb lib/net/ssh/transport/ctr.rb lib/net/ssh/transport/hmac.rb lib/net/ssh/transport/hmac/abstract.rb lib/net/ssh/transport/hmac/md5.rb lib/net/ssh/transport/hmac/md5_96.rb lib/net/ssh/transport/hmac/none.rb lib/net/ssh/transport/hmac/ripemd160.rb lib/net/ssh/transport/hmac/sha1.rb lib/net/ssh/transport/hmac/sha1_96.rb lib/net/ssh/transport/hmac/sha2_256.rb lib/net/ssh/transport/hmac/sha2_256_96.rb lib/net/ssh/transport/hmac/sha2_512.rb lib/net/ssh/transport/hmac/sha2_512_96.rb lib/net/ssh/transport/identity_cipher.rb lib/net/ssh/transport/key_expander.rb lib/net/ssh/transport/kex.rb lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb lib/net/ssh/transport/openssl.rb lib/net/ssh/transport/packet_stream.rb lib/net/ssh/transport/server_version.rb lib/net/ssh/transport/session.rb lib/net/ssh/transport/state.rb lib/net/ssh/verifiers/lenient.rb lib/net/ssh/verifiers/null.rb lib/net/ssh/verifiers/secure.rb lib/net/ssh/verifiers/strict.rb lib/net/ssh/version.rb net-ssh.gemspec setup.rb support/arcfour_check.rb support/ssh_tunnel_bug.rb test/authentication/methods/common.rb test/authentication/methods/test_abstract.rb test/authentication/methods/test_hostbased.rb test/authentication/methods/test_keyboard_interactive.rb test/authentication/methods/test_password.rb test/authentication/methods/test_publickey.rb test/authentication/test_agent.rb test/authentication/test_key_manager.rb test/authentication/test_session.rb test/common.rb test/configs/eqsign test/configs/exact_match test/configs/host_plus test/configs/multihost test/configs/wild_cards test/connection/test_channel.rb test/connection/test_session.rb test/test_all.rb test/test_buffer.rb test/test_buffered_io.rb test/test_config.rb test/test_key_factory.rb test/transport/hmac/test_md5.rb test/transport/hmac/test_md5_96.rb test/transport/hmac/test_none.rb test/transport/hmac/test_ripemd160.rb test/transport/hmac/test_sha1.rb test/transport/hmac/test_sha1_96.rb test/transport/hmac/test_sha2_256.rb test/transport/hmac/test_sha2_256_96.rb test/transport/hmac/test_sha2_512.rb test/transport/hmac/test_sha2_512_96.rb test/transport/kex/test_diffie_hellman_group1_sha1.rb test/transport/kex/test_diffie_hellman_group14_sha1.rb test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb test/transport/kex/test_diffie_hellman_group_exchange_sha256.rb test/transport/kex/test_ecdh_sha2_nistp256.rb test/transport/kex/test_ecdh_sha2_nistp384.rb test/transport/kex/test_ecdh_sha2_nistp521.rb test/transport/test_algorithms.rb test/transport/test_cipher_factory.rb test/transport/test_hmac.rb test/transport/test_identity_cipher.rb test/transport/test_packet_stream.rb test/transport/test_server_version.rb test/transport/test_session.rb test/transport/test_state.rb net-ssh-2.6.8/metadata.yml0000644000004100000410000001601012166626376015460 0ustar www-datawww-data--- !ruby/object:Gem::Specification name: net-ssh version: !ruby/object:Gem::Version version: 2.6.8 prerelease: platform: ruby authors: - Jamis Buck - Delano Mandelbaum autorequire: bindir: bin cert_chain: [] date: 2013-07-06 00:00:00.000000000 Z dependencies: - !ruby/object:Gem::Dependency name: test-unit requirement: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' - !ruby/object:Gem::Dependency name: mocha requirement: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' type: :development prerelease: false version_requirements: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' description: ! 'Net::SSH: a pure-Ruby implementation of the SSH2 client protocol. It allows you to write programs that invoke and interact with processes on remote servers, via SSH2.' email: net-ssh@solutious.com executables: [] extensions: [] extra_rdoc_files: - LICENSE.txt - README.rdoc files: - CHANGES.txt - LICENSE.txt - Manifest - README.rdoc - Rakefile - Rudyfile - THANKS.txt - gem-public_cert.pem - lib/net/ssh.rb - lib/net/ssh/authentication/agent.rb - lib/net/ssh/authentication/agent/java_pageant.rb - lib/net/ssh/authentication/agent/socket.rb - lib/net/ssh/authentication/constants.rb - lib/net/ssh/authentication/key_manager.rb - lib/net/ssh/authentication/methods/abstract.rb - lib/net/ssh/authentication/methods/hostbased.rb - lib/net/ssh/authentication/methods/keyboard_interactive.rb - lib/net/ssh/authentication/methods/none.rb - lib/net/ssh/authentication/methods/password.rb - lib/net/ssh/authentication/methods/publickey.rb - lib/net/ssh/authentication/pageant.rb - lib/net/ssh/authentication/session.rb - lib/net/ssh/buffer.rb - lib/net/ssh/buffered_io.rb - lib/net/ssh/config.rb - lib/net/ssh/connection/channel.rb - lib/net/ssh/connection/constants.rb - lib/net/ssh/connection/session.rb - lib/net/ssh/connection/term.rb - lib/net/ssh/errors.rb - lib/net/ssh/key_factory.rb - lib/net/ssh/known_hosts.rb - lib/net/ssh/loggable.rb - lib/net/ssh/packet.rb - lib/net/ssh/prompt.rb - lib/net/ssh/proxy/command.rb - lib/net/ssh/proxy/errors.rb - lib/net/ssh/proxy/http.rb - lib/net/ssh/proxy/socks4.rb - lib/net/ssh/proxy/socks5.rb - lib/net/ssh/ruby_compat.rb - lib/net/ssh/service/forward.rb - lib/net/ssh/test.rb - lib/net/ssh/test/channel.rb - lib/net/ssh/test/extensions.rb - lib/net/ssh/test/kex.rb - lib/net/ssh/test/local_packet.rb - lib/net/ssh/test/packet.rb - lib/net/ssh/test/remote_packet.rb - lib/net/ssh/test/script.rb - lib/net/ssh/test/socket.rb - lib/net/ssh/transport/algorithms.rb - lib/net/ssh/transport/cipher_factory.rb - lib/net/ssh/transport/constants.rb - lib/net/ssh/transport/ctr.rb - lib/net/ssh/transport/hmac.rb - lib/net/ssh/transport/hmac/abstract.rb - lib/net/ssh/transport/hmac/md5.rb - lib/net/ssh/transport/hmac/md5_96.rb - lib/net/ssh/transport/hmac/none.rb - lib/net/ssh/transport/hmac/ripemd160.rb - lib/net/ssh/transport/hmac/sha1.rb - lib/net/ssh/transport/hmac/sha1_96.rb - lib/net/ssh/transport/hmac/sha2_256.rb - lib/net/ssh/transport/hmac/sha2_256_96.rb - lib/net/ssh/transport/hmac/sha2_512.rb - lib/net/ssh/transport/hmac/sha2_512_96.rb - lib/net/ssh/transport/identity_cipher.rb - lib/net/ssh/transport/kex.rb - lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb - lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb - lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb - lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb - lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb - lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb - lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb - lib/net/ssh/transport/key_expander.rb - lib/net/ssh/transport/openssl.rb - lib/net/ssh/transport/packet_stream.rb - lib/net/ssh/transport/server_version.rb - lib/net/ssh/transport/session.rb - lib/net/ssh/transport/state.rb - lib/net/ssh/verifiers/lenient.rb - lib/net/ssh/verifiers/null.rb - lib/net/ssh/verifiers/secure.rb - lib/net/ssh/verifiers/strict.rb - lib/net/ssh/version.rb - net-ssh.gemspec - setup.rb - support/arcfour_check.rb - support/ssh_tunnel_bug.rb - test/README.txt - test/authentication/methods/common.rb - test/authentication/methods/test_abstract.rb - test/authentication/methods/test_hostbased.rb - test/authentication/methods/test_keyboard_interactive.rb - test/authentication/methods/test_none.rb - test/authentication/methods/test_password.rb - test/authentication/methods/test_publickey.rb - test/authentication/test_agent.rb - test/authentication/test_key_manager.rb - test/authentication/test_session.rb - test/common.rb - test/configs/eqsign - test/configs/exact_match - test/configs/host_plus - test/configs/multihost - test/configs/nohost - test/configs/numeric_host - test/configs/substitutes - test/configs/wild_cards - test/connection/test_channel.rb - test/connection/test_session.rb - test/known_hosts/github - test/manual/test_forward.rb - test/start/test_transport.rb - test/test_all.rb - test/test_buffer.rb - test/test_buffered_io.rb - test/test_config.rb - test/test_key_factory.rb - test/test_known_hosts.rb - test/transport/hmac/test_md5.rb - test/transport/hmac/test_md5_96.rb - test/transport/hmac/test_none.rb - test/transport/hmac/test_ripemd160.rb - test/transport/hmac/test_sha1.rb - test/transport/hmac/test_sha1_96.rb - test/transport/hmac/test_sha2_256.rb - test/transport/hmac/test_sha2_256_96.rb - test/transport/hmac/test_sha2_512.rb - test/transport/hmac/test_sha2_512_96.rb - test/transport/kex/test_diffie_hellman_group14_sha1.rb - test/transport/kex/test_diffie_hellman_group1_sha1.rb - test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb - test/transport/kex/test_diffie_hellman_group_exchange_sha256.rb - test/transport/kex/test_ecdh_sha2_nistp256.rb - test/transport/kex/test_ecdh_sha2_nistp384.rb - test/transport/kex/test_ecdh_sha2_nistp521.rb - test/transport/test_algorithms.rb - test/transport/test_cipher_factory.rb - test/transport/test_hmac.rb - test/transport/test_identity_cipher.rb - test/transport/test_packet_stream.rb - test/transport/test_server_version.rb - test/transport/test_session.rb - test/transport/test_state.rb homepage: https://github.com/net-ssh/net-ssh licenses: - MIT post_install_message: rdoc_options: [] require_paths: - lib required_ruby_version: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' required_rubygems_version: !ruby/object:Gem::Requirement none: false requirements: - - ! '>=' - !ruby/object:Gem::Version version: '0' requirements: [] rubyforge_project: net-ssh rubygems_version: 1.8.25 signing_key: specification_version: 3 summary: ! 'Net::SSH: a pure-Ruby implementation of the SSH2 client protocol.' test_files: [] net-ssh-2.6.8/THANKS.txt0000644000004100000410000000302612166626376014711 0ustar www-datawww-dataNet::SSH was originally written by Jamis Buck . It is currently maintained by Delano Mandelbaum . In addition, the following individuals are gratefully acknowledged for their contributions: GOTOU Yuuzou * help and code related to OpenSSL Guillaume Marçais * support for communicating with the the PuTTY "pageant" process Daniel Berger * help getting unit tests in earlier Net::SSH versions to pass in Windows * initial version of Net::SSH::Config provided inspiration and encouragement Chris Andrews and Lee Jensen * support for ssh agent forwarding Hiroshi Nakamura * fixed errors with JRuby tests Andreas Wolff mhuffnagle ohrite iltempo nagachika Nobuhiro IMAI arturaz dubspeed Andy Brody Marco Sandrini Ryosuke Yamazaki muffl0n pcn musybite Mark Imbriaco Joel Watson Woon Jung Edmund Haselwanter robbebob Daniel Pittman Markus Roberts Gavin Brock Rich Lane Lee Marlow xbaldauf Delano Mandelbaum Miklós Fazekas Andy Lo-A-Foe Jason Weathered Hans de Graaff Travis Reeder Akinori MUSHA Alex Peuchert Daniel Azuma Will Bryant Gerald Talton ckoehler Karl Varga Denis Bernard Steven Hazel Alex Holems Andrew Babkin Bob Cotton Yanko Ivanov Angel N. Sciortino arilerner@mac.com David Dollar Timo Gatsonides Matthew Todd Brian Candler Francis Sullivan James Rosen Mike Timm guns devrandom kachick Pablo Merino thedarkone czarneckid jbarnette watsonian Grant Hutchins Michael Schubert mtrudel net-ssh-2.6.8/setup.rb0000644000004100000410000010650212166626376014650 0ustar www-datawww-data# # setup.rb # # Copyright (c) 2000-2005 Minero Aoki # # This program is free software. # You can distribute/modify this program under the terms of # the GNU LGPL, Lesser General Public License version 2.1. # unless Enumerable.method_defined?(:map) # Ruby 1.4.6 module Enumerable alias map collect end end unless File.respond_to?(:read) # Ruby 1.6 def File.read(fname) open(fname) {|f| return f.read } end end unless Errno.const_defined?(:ENOTEMPTY) # Windows? module Errno class ENOTEMPTY # We do not raise this exception, implementation is not needed. end end end def File.binread(fname) open(fname, 'rb') {|f| return f.read } end # for corrupted Windows' stat(2) def File.dir?(path) File.directory?((path[-1,1] == '/') ? path : path + '/') end class ConfigTable include Enumerable def initialize(rbconfig) @rbconfig = rbconfig @items = [] @table = {} # options @install_prefix = nil @config_opt = nil @verbose = true @no_harm = false end attr_accessor :install_prefix attr_accessor :config_opt attr_writer :verbose def verbose? @verbose end attr_writer :no_harm def no_harm? @no_harm end def [](key) lookup(key).resolve(self) end def []=(key, val) lookup(key).set val end def names @items.map {|i| i.name } end def each(&block) @items.each(&block) end def key?(name) @table.key?(name) end def lookup(name) @table[name] or setup_rb_error "no such config item: #{name}" end def add(item) @items.push item @table[item.name] = item end def remove(name) item = lookup(name) @items.delete_if {|i| i.name == name } @table.delete_if {|name, i| i.name == name } item end def load_script(path, inst = nil) if File.file?(path) MetaConfigEnvironment.new(self, inst).instance_eval File.read(path), path end end def savefile '.config' end def load_savefile begin File.foreach(savefile()) do |line| k, v = *line.split(/=/, 2) self[k] = v.strip end rescue Errno::ENOENT setup_rb_error $!.message + "\n#{File.basename($0)} config first" end end def save @items.each {|i| i.value } File.open(savefile(), 'w') {|f| @items.each do |i| f.printf "%s=%s\n", i.name, i.value if i.value? and i.value end } end def load_standard_entries standard_entries(@rbconfig).each do |ent| add ent end end def standard_entries(rbconfig) c = rbconfig rubypath = File.join(c['bindir'], c['ruby_install_name'] + c['EXEEXT']) major = c['MAJOR'].to_i minor = c['MINOR'].to_i teeny = c['TEENY'].to_i version = "#{major}.#{minor}" # ruby ver. >= 1.4.4? newpath_p = ((major >= 2) or ((major == 1) and ((minor >= 5) or ((minor == 4) and (teeny >= 4))))) if c['rubylibdir'] # V > 1.6.3 libruby = "#{c['prefix']}/lib/ruby" librubyver = c['rubylibdir'] librubyverarch = c['archdir'] siteruby = c['sitedir'] siterubyver = c['sitelibdir'] siterubyverarch = c['sitearchdir'] elsif newpath_p # 1.4.4 <= V <= 1.6.3 libruby = "#{c['prefix']}/lib/ruby" librubyver = "#{c['prefix']}/lib/ruby/#{version}" librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}" siteruby = c['sitedir'] siterubyver = "$siteruby/#{version}" siterubyverarch = "$siterubyver/#{c['arch']}" else # V < 1.4.4 libruby = "#{c['prefix']}/lib/ruby" librubyver = "#{c['prefix']}/lib/ruby/#{version}" librubyverarch = "#{c['prefix']}/lib/ruby/#{version}/#{c['arch']}" siteruby = "#{c['prefix']}/lib/ruby/#{version}/site_ruby" siterubyver = siteruby siterubyverarch = "$siterubyver/#{c['arch']}" end parameterize = lambda {|path| path.sub(/\A#{Regexp.quote(c['prefix'])}/, '$prefix') } if arg = c['configure_args'].split.detect {|arg| /--with-make-prog=/ =~ arg } makeprog = arg.sub(/'/, '').split(/=/, 2)[1] else makeprog = 'make' end [ ExecItem.new('installdirs', 'std/site/home', 'std: install under libruby; site: install under site_ruby; home: install under $HOME')\ {|val, table| case val when 'std' table['rbdir'] = '$librubyver' table['sodir'] = '$librubyverarch' when 'site' table['rbdir'] = '$siterubyver' table['sodir'] = '$siterubyverarch' when 'home' setup_rb_error '$HOME was not set' unless ENV['HOME'] table['prefix'] = ENV['HOME'] table['rbdir'] = '$libdir/ruby' table['sodir'] = '$libdir/ruby' end }, PathItem.new('prefix', 'path', c['prefix'], 'path prefix of target environment'), PathItem.new('bindir', 'path', parameterize.call(c['bindir']), 'the directory for commands'), PathItem.new('libdir', 'path', parameterize.call(c['libdir']), 'the directory for libraries'), PathItem.new('datadir', 'path', parameterize.call(c['datadir']), 'the directory for shared data'), PathItem.new('mandir', 'path', parameterize.call(c['mandir']), 'the directory for man pages'), PathItem.new('sysconfdir', 'path', parameterize.call(c['sysconfdir']), 'the directory for system configuration files'), PathItem.new('localstatedir', 'path', parameterize.call(c['localstatedir']), 'the directory for local state data'), PathItem.new('libruby', 'path', libruby, 'the directory for ruby libraries'), PathItem.new('librubyver', 'path', librubyver, 'the directory for standard ruby libraries'), PathItem.new('librubyverarch', 'path', librubyverarch, 'the directory for standard ruby extensions'), PathItem.new('siteruby', 'path', siteruby, 'the directory for version-independent aux ruby libraries'), PathItem.new('siterubyver', 'path', siterubyver, 'the directory for aux ruby libraries'), PathItem.new('siterubyverarch', 'path', siterubyverarch, 'the directory for aux ruby binaries'), PathItem.new('rbdir', 'path', '$siterubyver', 'the directory for ruby scripts'), PathItem.new('sodir', 'path', '$siterubyverarch', 'the directory for ruby extentions'), PathItem.new('rubypath', 'path', rubypath, 'the path to set to #! line'), ProgramItem.new('rubyprog', 'name', rubypath, 'the ruby program using for installation'), ProgramItem.new('makeprog', 'name', makeprog, 'the make program to compile ruby extentions'), SelectItem.new('shebang', 'all/ruby/never', 'ruby', 'shebang line (#!) editing mode'), BoolItem.new('without-ext', 'yes/no', 'no', 'does not compile/install ruby extentions') ] end private :standard_entries def load_multipackage_entries multipackage_entries().each do |ent| add ent end end def multipackage_entries [ PackageSelectionItem.new('with', 'name,name...', '', 'ALL', 'package names that you want to install'), PackageSelectionItem.new('without', 'name,name...', '', 'NONE', 'package names that you do not want to install') ] end private :multipackage_entries ALIASES = { 'std-ruby' => 'librubyver', 'stdruby' => 'librubyver', 'rubylibdir' => 'librubyver', 'archdir' => 'librubyverarch', 'site-ruby-common' => 'siteruby', # For backward compatibility 'site-ruby' => 'siterubyver', # For backward compatibility 'bin-dir' => 'bindir', 'bin-dir' => 'bindir', 'rb-dir' => 'rbdir', 'so-dir' => 'sodir', 'data-dir' => 'datadir', 'ruby-path' => 'rubypath', 'ruby-prog' => 'rubyprog', 'ruby' => 'rubyprog', 'make-prog' => 'makeprog', 'make' => 'makeprog' } def fixup ALIASES.each do |ali, name| @table[ali] = @table[name] end @items.freeze @table.freeze @options_re = /\A--(#{@table.keys.join('|')})(?:=(.*))?\z/ end def parse_opt(opt) m = @options_re.match(opt) or setup_rb_error "config: unknown option #{opt}" m.to_a[1,2] end def dllext @rbconfig['DLEXT'] end def value_config?(name) lookup(name).value? end class Item def initialize(name, template, default, desc) @name = name.freeze @template = template @value = default @default = default @description = desc end attr_reader :name attr_reader :description attr_accessor :default alias help_default default def help_opt "--#{@name}=#{@template}" end def value? true end def value @value end def resolve(table) @value.gsub(%r<\$([^/]+)>) { table[$1] } end def set(val) @value = check(val) end private def check(val) setup_rb_error "config: --#{name} requires argument" unless val val end end class BoolItem < Item def config_type 'bool' end def help_opt "--#{@name}" end private def check(val) return 'yes' unless val case val when /\Ay(es)?\z/i, /\At(rue)?\z/i then 'yes' when /\An(o)?\z/i, /\Af(alse)\z/i then 'no' else setup_rb_error "config: --#{@name} accepts only yes/no for argument" end end end class PathItem < Item def config_type 'path' end private def check(path) setup_rb_error "config: --#{@name} requires argument" unless path path[0,1] == '$' ? path : File.expand_path(path) end end class ProgramItem < Item def config_type 'program' end end class SelectItem < Item def initialize(name, selection, default, desc) super @ok = selection.split('/') end def config_type 'select' end private def check(val) unless @ok.include?(val.strip) setup_rb_error "config: use --#{@name}=#{@template} (#{val})" end val.strip end end class ExecItem < Item def initialize(name, selection, desc, &block) super name, selection, nil, desc @ok = selection.split('/') @action = block end def config_type 'exec' end def value? false end def resolve(table) setup_rb_error "$#{name()} wrongly used as option value" end undef set def evaluate(val, table) v = val.strip.downcase unless @ok.include?(v) setup_rb_error "invalid option --#{@name}=#{val} (use #{@template})" end @action.call v, table end end class PackageSelectionItem < Item def initialize(name, template, default, help_default, desc) super name, template, default, desc @help_default = help_default end attr_reader :help_default def config_type 'package' end private def check(val) unless File.dir?("packages/#{val}") setup_rb_error "config: no such package: #{val}" end val end end class MetaConfigEnvironment def initialize(config, installer) @config = config @installer = installer end def config_names @config.names end def config?(name) @config.key?(name) end def bool_config?(name) @config.lookup(name).config_type == 'bool' end def path_config?(name) @config.lookup(name).config_type == 'path' end def value_config?(name) @config.lookup(name).config_type != 'exec' end def add_config(item) @config.add item end def add_bool_config(name, default, desc) @config.add BoolItem.new(name, 'yes/no', default ? 'yes' : 'no', desc) end def add_path_config(name, default, desc) @config.add PathItem.new(name, 'path', default, desc) end def set_config_default(name, default) @config.lookup(name).default = default end def remove_config(name) @config.remove(name) end # For only multipackage def packages raise '[setup.rb fatal] multi-package metaconfig API packages() called for single-package; contact application package vendor' unless @installer @installer.packages end # For only multipackage def declare_packages(list) raise '[setup.rb fatal] multi-package metaconfig API declare_packages() called for single-package; contact application package vendor' unless @installer @installer.packages = list end end end # class ConfigTable # This module requires: #verbose?, #no_harm? module FileOperations def mkdir_p(dirname, prefix = nil) dirname = prefix + File.expand_path(dirname) if prefix $stderr.puts "mkdir -p #{dirname}" if verbose? return if no_harm? # Does not check '/', it's too abnormal. dirs = File.expand_path(dirname).split(%r<(?=/)>) if /\A[a-z]:\z/i =~ dirs[0] disk = dirs.shift dirs[0] = disk + dirs[0] end dirs.each_index do |idx| path = dirs[0..idx].join('') Dir.mkdir path unless File.dir?(path) end end def rm_f(path) $stderr.puts "rm -f #{path}" if verbose? return if no_harm? force_remove_file path end def rm_rf(path) $stderr.puts "rm -rf #{path}" if verbose? return if no_harm? remove_tree path end def remove_tree(path) if File.symlink?(path) remove_file path elsif File.dir?(path) remove_tree0 path else force_remove_file path end end def remove_tree0(path) Dir.foreach(path) do |ent| next if ent == '.' next if ent == '..' entpath = "#{path}/#{ent}" if File.symlink?(entpath) remove_file entpath elsif File.dir?(entpath) remove_tree0 entpath else force_remove_file entpath end end begin Dir.rmdir path rescue Errno::ENOTEMPTY # directory may not be empty end end def move_file(src, dest) force_remove_file dest begin File.rename src, dest rescue File.open(dest, 'wb') {|f| f.write File.binread(src) } File.chmod File.stat(src).mode, dest File.unlink src end end def force_remove_file(path) begin remove_file path rescue end end def remove_file(path) File.chmod 0777, path File.unlink path end def install(from, dest, mode, prefix = nil) $stderr.puts "install #{from} #{dest}" if verbose? return if no_harm? realdest = prefix ? prefix + File.expand_path(dest) : dest realdest = File.join(realdest, File.basename(from)) if File.dir?(realdest) str = File.binread(from) if diff?(str, realdest) verbose_off { rm_f realdest if File.exist?(realdest) } File.open(realdest, 'wb') {|f| f.write str } File.chmod mode, realdest File.open("#{objdir_root()}/InstalledFiles", 'a') {|f| if prefix f.puts realdest.sub(prefix, '') else f.puts realdest end } end end def diff?(new_content, path) return true unless File.exist?(path) new_content != File.binread(path) end def command(*args) $stderr.puts args.join(' ') if verbose? system(*args) or raise RuntimeError, "system(#{args.map{|a| a.inspect }.join(' ')}) failed" end def ruby(*args) command config('rubyprog'), *args end def make(task = nil) command(*[config('makeprog'), task].compact) end def extdir?(dir) File.exist?("#{dir}/MANIFEST") or File.exist?("#{dir}/extconf.rb") end def files_of(dir) Dir.open(dir) {|d| return d.select {|ent| File.file?("#{dir}/#{ent}") } } end DIR_REJECT = %w( . .. CVS SCCS RCS CVS.adm .svn ) def directories_of(dir) Dir.open(dir) {|d| return d.select {|ent| File.dir?("#{dir}/#{ent}") } - DIR_REJECT } end end # This module requires: #srcdir_root, #objdir_root, #relpath module HookScriptAPI def get_config(key) @config[key] end alias config get_config # obsolete: use metaconfig to change configuration def set_config(key, val) @config[key] = val end # # srcdir/objdir (works only in the package directory) # def curr_srcdir "#{srcdir_root()}/#{relpath()}" end def curr_objdir "#{objdir_root()}/#{relpath()}" end def srcfile(path) "#{curr_srcdir()}/#{path}" end def srcexist?(path) File.exist?(srcfile(path)) end def srcdirectory?(path) File.dir?(srcfile(path)) end def srcfile?(path) File.file?(srcfile(path)) end def srcentries(path = '.') Dir.open("#{curr_srcdir()}/#{path}") {|d| return d.to_a - %w(. ..) } end def srcfiles(path = '.') srcentries(path).select {|fname| File.file?(File.join(curr_srcdir(), path, fname)) } end def srcdirectories(path = '.') srcentries(path).select {|fname| File.dir?(File.join(curr_srcdir(), path, fname)) } end end class ToplevelInstaller Version = '3.4.1' Copyright = 'Copyright (c) 2000-2005 Minero Aoki' TASKS = [ [ 'all', 'do config, setup, then install' ], [ 'config', 'saves your configurations' ], [ 'show', 'shows current configuration' ], [ 'setup', 'compiles ruby extentions and others' ], [ 'install', 'installs files' ], [ 'test', 'run all tests in test/' ], [ 'clean', "does `make clean' for each extention" ], [ 'distclean',"does `make distclean' for each extention" ] ] def ToplevelInstaller.invoke config = ConfigTable.new(load_rbconfig()) config.load_standard_entries config.load_multipackage_entries if multipackage? config.fixup klass = (multipackage?() ? ToplevelInstallerMulti : ToplevelInstaller) klass.new(File.dirname($0), config).invoke end def ToplevelInstaller.multipackage? File.dir?(File.dirname($0) + '/packages') end def ToplevelInstaller.load_rbconfig if arg = ARGV.detect {|arg| /\A--rbconfig=/ =~ arg } ARGV.delete(arg) load File.expand_path(arg.split(/=/, 2)[1]) $".push 'rbconfig.rb' else require 'rbconfig' end ::Config::CONFIG end def initialize(ardir_root, config) @ardir = File.expand_path(ardir_root) @config = config # cache @valid_task_re = nil end def config(key) @config[key] end def inspect "#<#{self.class} #{__id__()}>" end def invoke run_metaconfigs case task = parsearg_global() when nil, 'all' parsearg_config init_installers exec_config exec_setup exec_install else case task when 'config', 'test' ; when 'clean', 'distclean' @config.load_savefile if File.exist?(@config.savefile) else @config.load_savefile end __send__ "parsearg_#{task}" init_installers __send__ "exec_#{task}" end end def run_metaconfigs @config.load_script "#{@ardir}/metaconfig" end def init_installers @installer = Installer.new(@config, @ardir, File.expand_path('.')) end # # Hook Script API bases # def srcdir_root @ardir end def objdir_root '.' end def relpath '.' end # # Option Parsing # def parsearg_global while arg = ARGV.shift case arg when /\A\w+\z/ setup_rb_error "invalid task: #{arg}" unless valid_task?(arg) return arg when '-q', '--quiet' @config.verbose = false when '--verbose' @config.verbose = true when '--help' print_usage $stdout exit 0 when '--version' puts "#{File.basename($0)} version #{Version}" exit 0 when '--copyright' puts Copyright exit 0 else setup_rb_error "unknown global option '#{arg}'" end end nil end def valid_task?(t) valid_task_re() =~ t end def valid_task_re @valid_task_re ||= /\A(?:#{TASKS.map {|task,desc| task }.join('|')})\z/ end def parsearg_no_options unless ARGV.empty? task = caller(0).first.slice(%r<`parsearg_(\w+)'>, 1) setup_rb_error "#{task}: unknown options: #{ARGV.join(' ')}" end end alias parsearg_show parsearg_no_options alias parsearg_setup parsearg_no_options alias parsearg_test parsearg_no_options alias parsearg_clean parsearg_no_options alias parsearg_distclean parsearg_no_options def parsearg_config evalopt = [] set = [] @config.config_opt = [] while i = ARGV.shift if /\A--?\z/ =~ i @config.config_opt = ARGV.dup break end name, value = *@config.parse_opt(i) if @config.value_config?(name) @config[name] = value else evalopt.push [name, value] end set.push name end evalopt.each do |name, value| @config.lookup(name).evaluate value, @config end # Check if configuration is valid set.each do |n| @config[n] if @config.value_config?(n) end end def parsearg_install @config.no_harm = false @config.install_prefix = '' while a = ARGV.shift case a when '--no-harm' @config.no_harm = true when /\A--prefix=/ path = a.split(/=/, 2)[1] path = File.expand_path(path) unless path[0,1] == '/' @config.install_prefix = path else setup_rb_error "install: unknown option #{a}" end end end def print_usage(out) out.puts 'Typical Installation Procedure:' out.puts " $ ruby #{File.basename $0} config" out.puts " $ ruby #{File.basename $0} setup" out.puts " # ruby #{File.basename $0} install (may require root privilege)" out.puts out.puts 'Detailed Usage:' out.puts " ruby #{File.basename $0} " out.puts " ruby #{File.basename $0} [] []" fmt = " %-24s %s\n" out.puts out.puts 'Global options:' out.printf fmt, '-q,--quiet', 'suppress message outputs' out.printf fmt, ' --verbose', 'output messages verbosely' out.printf fmt, ' --help', 'print this message' out.printf fmt, ' --version', 'print version and quit' out.printf fmt, ' --copyright', 'print copyright and quit' out.puts out.puts 'Tasks:' TASKS.each do |name, desc| out.printf fmt, name, desc end fmt = " %-24s %s [%s]\n" out.puts out.puts 'Options for CONFIG or ALL:' @config.each do |item| out.printf fmt, item.help_opt, item.description, item.help_default end out.printf fmt, '--rbconfig=path', 'rbconfig.rb to load',"running ruby's" out.puts out.puts 'Options for INSTALL:' out.printf fmt, '--no-harm', 'only display what to do if given', 'off' out.printf fmt, '--prefix=path', 'install path prefix', '' out.puts end # # Task Handlers # def exec_config @installer.exec_config @config.save # must be final end def exec_setup @installer.exec_setup end def exec_install @installer.exec_install end def exec_test @installer.exec_test end def exec_show @config.each do |i| printf "%-20s %s\n", i.name, i.value if i.value? end end def exec_clean @installer.exec_clean end def exec_distclean @installer.exec_distclean end end # class ToplevelInstaller class ToplevelInstallerMulti < ToplevelInstaller include FileOperations def initialize(ardir_root, config) super @packages = directories_of("#{@ardir}/packages") raise 'no package exists' if @packages.empty? @root_installer = Installer.new(@config, @ardir, File.expand_path('.')) end def run_metaconfigs @config.load_script "#{@ardir}/metaconfig", self @packages.each do |name| @config.load_script "#{@ardir}/packages/#{name}/metaconfig" end end attr_reader :packages def packages=(list) raise 'package list is empty' if list.empty? list.each do |name| raise "directory packages/#{name} does not exist"\ unless File.dir?("#{@ardir}/packages/#{name}") end @packages = list end def init_installers @installers = {} @packages.each do |pack| @installers[pack] = Installer.new(@config, "#{@ardir}/packages/#{pack}", "packages/#{pack}") end with = extract_selection(config('with')) without = extract_selection(config('without')) @selected = @installers.keys.select {|name| (with.empty? or with.include?(name)) \ and not without.include?(name) } end def extract_selection(list) a = list.split(/,/) a.each do |name| setup_rb_error "no such package: #{name}" unless @installers.key?(name) end a end def print_usage(f) super f.puts 'Inluded packages:' f.puts ' ' + @packages.sort.join(' ') f.puts end # # Task Handlers # def exec_config run_hook 'pre-config' each_selected_installers {|inst| inst.exec_config } run_hook 'post-config' @config.save # must be final end def exec_setup run_hook 'pre-setup' each_selected_installers {|inst| inst.exec_setup } run_hook 'post-setup' end def exec_install run_hook 'pre-install' each_selected_installers {|inst| inst.exec_install } run_hook 'post-install' end def exec_test run_hook 'pre-test' each_selected_installers {|inst| inst.exec_test } run_hook 'post-test' end def exec_clean rm_f @config.savefile run_hook 'pre-clean' each_selected_installers {|inst| inst.exec_clean } run_hook 'post-clean' end def exec_distclean rm_f @config.savefile run_hook 'pre-distclean' each_selected_installers {|inst| inst.exec_distclean } run_hook 'post-distclean' end # # lib # def each_selected_installers Dir.mkdir 'packages' unless File.dir?('packages') @selected.each do |pack| $stderr.puts "Processing the package `#{pack}' ..." if verbose? Dir.mkdir "packages/#{pack}" unless File.dir?("packages/#{pack}") Dir.chdir "packages/#{pack}" yield @installers[pack] Dir.chdir '../..' end end def run_hook(id) @root_installer.run_hook id end # module FileOperations requires this def verbose? @config.verbose? end # module FileOperations requires this def no_harm? @config.no_harm? end end # class ToplevelInstallerMulti class Installer FILETYPES = %w( bin lib ext data conf man ) include FileOperations include HookScriptAPI def initialize(config, srcroot, objroot) @config = config @srcdir = File.expand_path(srcroot) @objdir = File.expand_path(objroot) @currdir = '.' end def inspect "#<#{self.class} #{File.basename(@srcdir)}>" end def noop(rel) end # # Hook Script API base methods # def srcdir_root @srcdir end def objdir_root @objdir end def relpath @currdir end # # Config Access # # module FileOperations requires this def verbose? @config.verbose? end # module FileOperations requires this def no_harm? @config.no_harm? end def verbose_off begin save, @config.verbose = @config.verbose?, false yield ensure @config.verbose = save end end # # TASK config # def exec_config exec_task_traverse 'config' end alias config_dir_bin noop alias config_dir_lib noop def config_dir_ext(rel) extconf if extdir?(curr_srcdir()) end alias config_dir_data noop alias config_dir_conf noop alias config_dir_man noop def extconf ruby "#{curr_srcdir()}/extconf.rb", *@config.config_opt end # # TASK setup # def exec_setup exec_task_traverse 'setup' end def setup_dir_bin(rel) files_of(curr_srcdir()).each do |fname| update_shebang_line "#{curr_srcdir()}/#{fname}" end end alias setup_dir_lib noop def setup_dir_ext(rel) make if extdir?(curr_srcdir()) end alias setup_dir_data noop alias setup_dir_conf noop alias setup_dir_man noop def update_shebang_line(path) return if no_harm? return if config('shebang') == 'never' old = Shebang.load(path) if old $stderr.puts "warning: #{path}: Shebang line includes too many args. It is not portable and your program may not work." if old.args.size > 1 new = new_shebang(old) return if new.to_s == old.to_s else return unless config('shebang') == 'all' new = Shebang.new(config('rubypath')) end $stderr.puts "updating shebang: #{File.basename(path)}" if verbose? open_atomic_writer(path) {|output| File.open(path, 'rb') {|f| f.gets if old # discard output.puts new.to_s output.print f.read } } end def new_shebang(old) if /\Aruby/ =~ File.basename(old.cmd) Shebang.new(config('rubypath'), old.args) elsif File.basename(old.cmd) == 'env' and old.args.first == 'ruby' Shebang.new(config('rubypath'), old.args[1..-1]) else return old unless config('shebang') == 'all' Shebang.new(config('rubypath')) end end def open_atomic_writer(path, &block) tmpfile = File.basename(path) + '.tmp' begin File.open(tmpfile, 'wb', &block) File.rename tmpfile, File.basename(path) ensure File.unlink tmpfile if File.exist?(tmpfile) end end class Shebang def Shebang.load(path) line = nil File.open(path) {|f| line = f.gets } return nil unless /\A#!/ =~ line parse(line) end def Shebang.parse(line) cmd, *args = *line.strip.sub(/\A\#!/, '').split(' ') new(cmd, args) end def initialize(cmd, args = []) @cmd = cmd @args = args end attr_reader :cmd attr_reader :args def to_s "#! #{@cmd}" + (@args.empty? ? '' : " #{@args.join(' ')}") end end # # TASK install # def exec_install rm_f 'InstalledFiles' exec_task_traverse 'install' end def install_dir_bin(rel) install_files targetfiles(), "#{config('bindir')}/#{rel}", 0755 end def install_dir_lib(rel) install_files libfiles(), "#{config('rbdir')}/#{rel}", 0644 end def install_dir_ext(rel) return unless extdir?(curr_srcdir()) install_files rubyextentions('.'), "#{config('sodir')}/#{File.dirname(rel)}", 0555 end def install_dir_data(rel) install_files targetfiles(), "#{config('datadir')}/#{rel}", 0644 end def install_dir_conf(rel) # FIXME: should not remove current config files # (rename previous file to .old/.org) install_files targetfiles(), "#{config('sysconfdir')}/#{rel}", 0644 end def install_dir_man(rel) install_files targetfiles(), "#{config('mandir')}/#{rel}", 0644 end def install_files(list, dest, mode) mkdir_p dest, @config.install_prefix list.each do |fname| install fname, dest, mode, @config.install_prefix end end def libfiles glob_reject(%w(*.y *.output), targetfiles()) end def rubyextentions(dir) ents = glob_select("*.#{@config.dllext}", targetfiles()) if ents.empty? setup_rb_error "no ruby extention exists: 'ruby #{$0} setup' first" end ents end def targetfiles mapdir(existfiles() - hookfiles()) end def mapdir(ents) ents.map {|ent| if File.exist?(ent) then ent # objdir else "#{curr_srcdir()}/#{ent}" # srcdir end } end # picked up many entries from cvs-1.11.1/src/ignore.c JUNK_FILES = %w( core RCSLOG tags TAGS .make.state .nse_depinfo #* .#* cvslog.* ,* .del-* *.olb *~ *.old *.bak *.BAK *.orig *.rej _$* *$ *.org *.in .* ) def existfiles glob_reject(JUNK_FILES, (files_of(curr_srcdir()) | files_of('.'))) end def hookfiles %w( pre-%s post-%s pre-%s.rb post-%s.rb ).map {|fmt| %w( config setup install clean ).map {|t| sprintf(fmt, t) } }.flatten end def glob_select(pat, ents) re = globs2re([pat]) ents.select {|ent| re =~ ent } end def glob_reject(pats, ents) re = globs2re(pats) ents.reject {|ent| re =~ ent } end GLOB2REGEX = { '.' => '\.', '$' => '\$', '#' => '\#', '*' => '.*' } def globs2re(pats) /\A(?:#{ pats.map {|pat| pat.gsub(/[\.\$\#\*]/) {|ch| GLOB2REGEX[ch] } }.join('|') })\z/ end # # TASK test # TESTDIR = 'test' def exec_test unless File.directory?('test') $stderr.puts 'no test in this package' if verbose? return end $stderr.puts 'Running tests...' if verbose? begin require 'test/unit' rescue LoadError setup_rb_error 'test/unit cannot loaded. You need Ruby 1.8 or later to invoke this task.' end runner = Test::Unit::AutoRunner.new(true) runner.to_run << TESTDIR runner.run end # # TASK clean # def exec_clean exec_task_traverse 'clean' rm_f @config.savefile rm_f 'InstalledFiles' end alias clean_dir_bin noop alias clean_dir_lib noop alias clean_dir_data noop alias clean_dir_conf noop alias clean_dir_man noop def clean_dir_ext(rel) return unless extdir?(curr_srcdir()) make 'clean' if File.file?('Makefile') end # # TASK distclean # def exec_distclean exec_task_traverse 'distclean' rm_f @config.savefile rm_f 'InstalledFiles' end alias distclean_dir_bin noop alias distclean_dir_lib noop def distclean_dir_ext(rel) return unless extdir?(curr_srcdir()) make 'distclean' if File.file?('Makefile') end alias distclean_dir_data noop alias distclean_dir_conf noop alias distclean_dir_man noop # # Traversing # def exec_task_traverse(task) run_hook "pre-#{task}" FILETYPES.each do |type| if type == 'ext' and config('without-ext') == 'yes' $stderr.puts 'skipping ext/* by user option' if verbose? next end traverse task, type, "#{task}_dir_#{type}" end run_hook "post-#{task}" end def traverse(task, rel, mid) dive_into(rel) { run_hook "pre-#{task}" __send__ mid, rel.sub(%r[\A.*?(?:/|\z)], '') directories_of(curr_srcdir()).each do |d| traverse task, "#{rel}/#{d}", mid end run_hook "post-#{task}" } end def dive_into(rel) return unless File.dir?("#{@srcdir}/#{rel}") dir = File.basename(rel) Dir.mkdir dir unless File.dir?(dir) prevdir = Dir.pwd Dir.chdir dir $stderr.puts '---> ' + rel if verbose? @currdir = rel yield Dir.chdir prevdir $stderr.puts '<--- ' + rel if verbose? @currdir = File.dirname(rel) end def run_hook(id) path = [ "#{curr_srcdir()}/#{id}", "#{curr_srcdir()}/#{id}.rb" ].detect {|cand| File.file?(cand) } return unless path begin instance_eval File.read(path), path, 1 rescue raise if $DEBUG setup_rb_error "hook #{path} failed:\n" + $!.message end end end # class Installer class SetupError < StandardError; end def setup_rb_error(msg) raise SetupError, msg end if $0 == __FILE__ begin ToplevelInstaller.invoke rescue SetupError raise if $DEBUG $stderr.puts $!.message $stderr.puts "Try 'ruby #{$0} --help' for detailed usage." exit 1 end end net-ssh-2.6.8/net-ssh.gemspec0000644000004100000410000001632012166626376016107 0ustar www-datawww-data# Generated by jeweler # DO NOT EDIT THIS FILE DIRECTLY # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec' # -*- encoding: utf-8 -*- Gem::Specification.new do |s| s.name = "net-ssh" s.version = "2.6.8" s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.authors = ["Jamis Buck", "Delano Mandelbaum"] s.date = "2013-07-06" s.description = "Net::SSH: a pure-Ruby implementation of the SSH2 client protocol. It allows you to write programs that invoke and interact with processes on remote servers, via SSH2." s.email = "net-ssh@solutious.com" s.extra_rdoc_files = [ "LICENSE.txt", "README.rdoc" ] s.files = [ "CHANGES.txt", "LICENSE.txt", "Manifest", "README.rdoc", "Rakefile", "Rudyfile", "THANKS.txt", "gem-public_cert.pem", "lib/net/ssh.rb", "lib/net/ssh/authentication/agent.rb", "lib/net/ssh/authentication/agent/java_pageant.rb", "lib/net/ssh/authentication/agent/socket.rb", "lib/net/ssh/authentication/constants.rb", "lib/net/ssh/authentication/key_manager.rb", "lib/net/ssh/authentication/methods/abstract.rb", "lib/net/ssh/authentication/methods/hostbased.rb", "lib/net/ssh/authentication/methods/keyboard_interactive.rb", "lib/net/ssh/authentication/methods/none.rb", "lib/net/ssh/authentication/methods/password.rb", "lib/net/ssh/authentication/methods/publickey.rb", "lib/net/ssh/authentication/pageant.rb", "lib/net/ssh/authentication/session.rb", "lib/net/ssh/buffer.rb", "lib/net/ssh/buffered_io.rb", "lib/net/ssh/config.rb", "lib/net/ssh/connection/channel.rb", "lib/net/ssh/connection/constants.rb", "lib/net/ssh/connection/session.rb", "lib/net/ssh/connection/term.rb", "lib/net/ssh/errors.rb", "lib/net/ssh/key_factory.rb", "lib/net/ssh/known_hosts.rb", "lib/net/ssh/loggable.rb", "lib/net/ssh/packet.rb", "lib/net/ssh/prompt.rb", "lib/net/ssh/proxy/command.rb", "lib/net/ssh/proxy/errors.rb", "lib/net/ssh/proxy/http.rb", "lib/net/ssh/proxy/socks4.rb", "lib/net/ssh/proxy/socks5.rb", "lib/net/ssh/ruby_compat.rb", "lib/net/ssh/service/forward.rb", "lib/net/ssh/test.rb", "lib/net/ssh/test/channel.rb", "lib/net/ssh/test/extensions.rb", "lib/net/ssh/test/kex.rb", "lib/net/ssh/test/local_packet.rb", "lib/net/ssh/test/packet.rb", "lib/net/ssh/test/remote_packet.rb", "lib/net/ssh/test/script.rb", "lib/net/ssh/test/socket.rb", "lib/net/ssh/transport/algorithms.rb", "lib/net/ssh/transport/cipher_factory.rb", "lib/net/ssh/transport/constants.rb", "lib/net/ssh/transport/ctr.rb", "lib/net/ssh/transport/hmac.rb", "lib/net/ssh/transport/hmac/abstract.rb", "lib/net/ssh/transport/hmac/md5.rb", "lib/net/ssh/transport/hmac/md5_96.rb", "lib/net/ssh/transport/hmac/none.rb", "lib/net/ssh/transport/hmac/ripemd160.rb", "lib/net/ssh/transport/hmac/sha1.rb", "lib/net/ssh/transport/hmac/sha1_96.rb", "lib/net/ssh/transport/hmac/sha2_256.rb", "lib/net/ssh/transport/hmac/sha2_256_96.rb", "lib/net/ssh/transport/hmac/sha2_512.rb", "lib/net/ssh/transport/hmac/sha2_512_96.rb", "lib/net/ssh/transport/identity_cipher.rb", "lib/net/ssh/transport/kex.rb", "lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb", "lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb", "lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb", "lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb", "lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb", "lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb", "lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb", "lib/net/ssh/transport/key_expander.rb", "lib/net/ssh/transport/openssl.rb", "lib/net/ssh/transport/packet_stream.rb", "lib/net/ssh/transport/server_version.rb", "lib/net/ssh/transport/session.rb", "lib/net/ssh/transport/state.rb", "lib/net/ssh/verifiers/lenient.rb", "lib/net/ssh/verifiers/null.rb", "lib/net/ssh/verifiers/secure.rb", "lib/net/ssh/verifiers/strict.rb", "lib/net/ssh/version.rb", "net-ssh.gemspec", "setup.rb", "support/arcfour_check.rb", "support/ssh_tunnel_bug.rb", "test/README.txt", "test/authentication/methods/common.rb", "test/authentication/methods/test_abstract.rb", "test/authentication/methods/test_hostbased.rb", "test/authentication/methods/test_keyboard_interactive.rb", "test/authentication/methods/test_none.rb", "test/authentication/methods/test_password.rb", "test/authentication/methods/test_publickey.rb", "test/authentication/test_agent.rb", "test/authentication/test_key_manager.rb", "test/authentication/test_session.rb", "test/common.rb", "test/configs/eqsign", "test/configs/exact_match", "test/configs/host_plus", "test/configs/multihost", "test/configs/nohost", "test/configs/numeric_host", "test/configs/substitutes", "test/configs/wild_cards", "test/connection/test_channel.rb", "test/connection/test_session.rb", "test/known_hosts/github", "test/manual/test_forward.rb", "test/start/test_transport.rb", "test/test_all.rb", "test/test_buffer.rb", "test/test_buffered_io.rb", "test/test_config.rb", "test/test_key_factory.rb", "test/test_known_hosts.rb", "test/transport/hmac/test_md5.rb", "test/transport/hmac/test_md5_96.rb", "test/transport/hmac/test_none.rb", "test/transport/hmac/test_ripemd160.rb", "test/transport/hmac/test_sha1.rb", "test/transport/hmac/test_sha1_96.rb", "test/transport/hmac/test_sha2_256.rb", "test/transport/hmac/test_sha2_256_96.rb", "test/transport/hmac/test_sha2_512.rb", "test/transport/hmac/test_sha2_512_96.rb", "test/transport/kex/test_diffie_hellman_group14_sha1.rb", "test/transport/kex/test_diffie_hellman_group1_sha1.rb", "test/transport/kex/test_diffie_hellman_group_exchange_sha1.rb", "test/transport/kex/test_diffie_hellman_group_exchange_sha256.rb", "test/transport/kex/test_ecdh_sha2_nistp256.rb", "test/transport/kex/test_ecdh_sha2_nistp384.rb", "test/transport/kex/test_ecdh_sha2_nistp521.rb", "test/transport/test_algorithms.rb", "test/transport/test_cipher_factory.rb", "test/transport/test_hmac.rb", "test/transport/test_identity_cipher.rb", "test/transport/test_packet_stream.rb", "test/transport/test_server_version.rb", "test/transport/test_session.rb", "test/transport/test_state.rb" ] s.homepage = "https://github.com/net-ssh/net-ssh" s.licenses = ["MIT"] s.require_paths = ["lib"] s.rubyforge_project = "net-ssh" s.rubygems_version = "1.8.25" s.summary = "Net::SSH: a pure-Ruby implementation of the SSH2 client protocol." if s.respond_to? :specification_version then s.specification_version = 3 if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then s.add_development_dependency(%q, [">= 0"]) s.add_development_dependency(%q, [">= 0"]) else s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) end else s.add_dependency(%q, [">= 0"]) s.add_dependency(%q, [">= 0"]) end end net-ssh-2.6.8/lib/0000755000004100000410000000000012166626376013725 5ustar www-datawww-datanet-ssh-2.6.8/lib/net/0000755000004100000410000000000012166626376014513 5ustar www-datawww-datanet-ssh-2.6.8/lib/net/ssh/0000755000004100000410000000000012166626376015310 5ustar www-datawww-datanet-ssh-2.6.8/lib/net/ssh/connection/0000755000004100000410000000000012166626376017447 5ustar www-datawww-datanet-ssh-2.6.8/lib/net/ssh/connection/session.rb0000644000004100000410000005477212166626376021476 0ustar www-datawww-datarequire 'net/ssh/loggable' require 'net/ssh/ruby_compat' require 'net/ssh/connection/channel' require 'net/ssh/connection/constants' require 'net/ssh/service/forward' module Net; module SSH; module Connection # A session class representing the connection service running on top of # the SSH transport layer. It manages the creation of channels (see # #open_channel), and the dispatching of messages to the various channels. # It also encapsulates the SSH event loop (via #loop and #process), # and serves as a central point-of-reference for all SSH-related services (e.g. # port forwarding, SFTP, SCP, etc.). # # You will rarely (if ever) need to instantiate this class directly; rather, # you'll almost always use Net::SSH.start to initialize a new network # connection, authenticate a user, and return a new connection session, # all in one call. # # Net::SSH.start("localhost", "user") do |ssh| # # 'ssh' is an instance of Net::SSH::Connection::Session # ssh.exec! "/etc/init.d/some_process start" # end class Session include Constants, Loggable # The underlying transport layer abstraction (see Net::SSH::Transport::Session). attr_reader :transport # The map of options that were used to initialize this instance. attr_reader :options # The collection of custom properties for this instance. (See #[] and #[]=). attr_reader :properties # The map of channels, each key being the local-id for the channel. attr_reader :channels #:nodoc: # The map of listeners that the event loop knows about. See #listen_to. attr_reader :listeners #:nodoc: # The map of specialized handlers for opening specific channel types. See # #on_open_channel. attr_reader :channel_open_handlers #:nodoc: # The list of callbacks for pending requests. See #send_global_request. attr_reader :pending_requests #:nodoc: class NilChannel def initialize(session) @session = session end def method_missing(sym, *args) @session.lwarn { "ignoring request #{sym.inspect} for non-existent (closed?) channel; probably ssh server bug" } end end # Create a new connection service instance atop the given transport # layer. Initializes the listeners to be only the underlying socket object. def initialize(transport, options={}) self.logger = transport.logger @transport = transport @options = options @channel_id_counter = -1 @channels = Hash.new(NilChannel.new(self)) @listeners = { transport.socket => nil } @pending_requests = [] @channel_open_handlers = {} @on_global_request = {} @properties = (options[:properties] || {}).dup @max_pkt_size = (options.has_key?(:max_pkt_size) ? options[:max_pkt_size] : 0x8000) @max_win_size = (options.has_key?(:max_win_size) ? options[:max_win_size] : 0x20000) end # Retrieves a custom property from this instance. This can be used to # store additional state in applications that must manage multiple # SSH connections. def [](key) @properties[key] end # Sets a custom property for this instance. def []=(key, value) @properties[key] = value end # Returns the name of the host that was given to the transport layer to # connect to. def host transport.host end # Returns true if the underlying transport has been closed. Note that # this can be a little misleading, since if the remote server has # closed the connection, the local end will still think it is open # until the next operation on the socket. Nevertheless, this method can # be useful if you just want to know if _you_ have closed the connection. def closed? transport.closed? end # Closes the session gracefully, blocking until all channels have # successfully closed, and then closes the underlying transport layer # connection. def close info { "closing remaining channels (#{channels.length} open)" } channels.each { |id, channel| channel.close } loop(0.1) { channels.any? } transport.close end # Performs a "hard" shutdown of the connection. In general, this should # never be done, but it might be necessary (in a rescue clause, for instance, # when the connection needs to close but you don't know the status of the # underlying protocol's state). def shutdown! transport.shutdown! end # preserve a reference to Kernel#loop alias :loop_forever :loop # Returns +true+ if there are any channels currently active on this # session. By default, this will not include "invisible" channels # (such as those created by forwarding ports and such), but if you pass # a +true+ value for +include_invisible+, then those will be counted. # # This can be useful for determining whether the event loop should continue # to be run. # # ssh.loop { ssh.busy? } def busy?(include_invisible=false) if include_invisible channels.any? else channels.any? { |id, ch| !ch[:invisible] } end end # The main event loop. Calls #process until #process returns false. If a # block is given, it is passed to #process, otherwise a default proc is # used that just returns true if there are any channels active (see #busy?). # The # +wait+ parameter is also passed through to #process (where it is # interpreted as the maximum number of seconds to wait for IO.select to return). # # # loop for as long as there are any channels active # ssh.loop # # # loop for as long as there are any channels active, but make sure # # the event loop runs at least once per 0.1 second # ssh.loop(0.1) # # # loop until ctrl-C is pressed # int_pressed = false # trap("INT") { int_pressed = true } # ssh.loop(0.1) { not int_pressed } def loop(wait=nil, &block) running = block || Proc.new { busy? } loop_forever { break unless process(wait, &running) } end # The core of the event loop. It processes a single iteration of the event # loop. If a block is given, it should return false when the processing # should abort, which causes #process to return false. Otherwise, # #process returns true. The session itself is yielded to the block as its # only argument. # # If +wait+ is nil (the default), this method will block until any of the # monitored IO objects are ready to be read from or written to. If you want # it to not block, you can pass 0, or you can pass any other numeric value # to indicate that it should block for no more than that many seconds. # Passing 0 is a good way to poll the connection, but if you do it too # frequently it can make your CPU quite busy! # # This will also cause all active channels to be processed once each (see # Net::SSH::Connection::Channel#on_process). # # # process multiple Net::SSH connections in parallel # connections = [ # Net::SSH.start("host1", ...), # Net::SSH.start("host2", ...) # ] # # connections.each do |ssh| # ssh.exec "grep something /in/some/files" # end # # condition = Proc.new { |s| s.busy? } # # loop do # connections.delete_if { |ssh| !ssh.process(0.1, &condition) } # break if connections.empty? # end def process(wait=nil, &block) return false unless preprocess(&block) r = listeners.keys w = r.select { |w2| w2.respond_to?(:pending_write?) && w2.pending_write? } readers, writers, = Net::SSH::Compat.io_select(r, w, nil, wait) postprocess(readers, writers) end # This is called internally as part of #process. It dispatches any # available incoming packets, and then runs Net::SSH::Connection::Channel#process # for any active channels. If a block is given, it is invoked at the # start of the method and again at the end, and if the block ever returns # false, this method returns false. Otherwise, it returns true. def preprocess return false if block_given? && !yield(self) dispatch_incoming_packets channels.each { |id, channel| channel.process unless channel.closing? } return false if block_given? && !yield(self) return true end # This is called internally as part of #process. It loops over the given # arrays of reader IO's and writer IO's, processing them as needed, and # then calls Net::SSH::Transport::Session#rekey_as_needed to allow the # transport layer to rekey. Then returns true. def postprocess(readers, writers) Array(readers).each do |reader| if listeners[reader] listeners[reader].call(reader) else if reader.fill.zero? reader.close stop_listening_to(reader) end end end Array(writers).each do |writer| writer.send_pending end transport.rekey_as_needed return true end # Send a global request of the given type. The +extra+ parameters must # be even in number, and conform to the same format as described for # Net::SSH::Buffer.from. If a callback is not specified, the request will # not require a response from the server, otherwise the server is required # to respond and indicate whether the request was successful or not. This # success or failure is indicated by the callback being invoked, with the # first parameter being true or false (success, or failure), and the second # being the packet itself. # # Generally, Net::SSH will manage global requests that need to be sent # (e.g. port forward requests and such are handled in the Net::SSH::Service::Forward # class, for instance). However, there may be times when you need to # send a global request that isn't explicitly handled by Net::SSH, and so # this method is available to you. # # ssh.send_global_request("keep-alive@openssh.com") def send_global_request(type, *extra, &callback) info { "sending global request #{type}" } msg = Buffer.from(:byte, GLOBAL_REQUEST, :string, type.to_s, :bool, !callback.nil?, *extra) send_message(msg) pending_requests << callback if callback self end # Requests that a new channel be opened. By default, the channel will be # of type "session", but if you know what you're doing you can select any # of the channel types supported by the SSH protocol. The +extra+ parameters # must be even in number and conform to the same format as described for # Net::SSH::Buffer.from. If a callback is given, it will be invoked when # the server confirms that the channel opened successfully. The sole parameter # for the callback is the channel object itself. # # In general, you'll use #open_channel without any arguments; the only # time you'd want to set the channel type or pass additional initialization # data is if you were implementing an SSH extension. # # channel = ssh.open_channel do |ch| # ch.exec "grep something /some/files" do |ch, success| # ... # end # end # # channel.wait def open_channel(type="session", *extra, &on_confirm) local_id = get_next_channel_id channel = Channel.new(self, type, local_id, @max_pkt_size, @max_win_size, &on_confirm) msg = Buffer.from(:byte, CHANNEL_OPEN, :string, type, :long, local_id, :long, channel.local_maximum_window_size, :long, channel.local_maximum_packet_size, *extra) send_message(msg) channels[local_id] = channel end # A convenience method for executing a command and interacting with it. If # no block is given, all output is printed via $stdout and $stderr. Otherwise, # the block is called for each data and extended data packet, with three # arguments: the channel object, a symbol indicating the data type # (:stdout or :stderr), and the data (as a string). # # Note that this method returns immediately, and requires an event loop # (see Session#loop) in order for the command to actually execute. # # This is effectively identical to calling #open_channel, and then # Net::SSH::Connection::Channel#exec, and then setting up the channel # callbacks. However, for most uses, this will be sufficient. # # ssh.exec "grep something /some/files" do |ch, stream, data| # if stream == :stderr # puts "ERROR: #{data}" # else # puts data # end # end def exec(command, &block) open_channel do |channel| channel.exec(command) do |ch, success| raise "could not execute command: #{command.inspect}" unless success channel.on_data do |ch2, data| if block block.call(ch2, :stdout, data) else $stdout.print(data) end end channel.on_extended_data do |ch2, type, data| if block block.call(ch2, :stderr, data) else $stderr.print(data) end end end end end # Same as #exec, except this will block until the command finishes. Also, # if a block is not given, this will return all output (stdout and stderr) # as a single string. # # matches = ssh.exec!("grep something /some/files") def exec!(command, &block) block ||= Proc.new do |ch, type, data| ch[:result] ||= "" ch[:result] << data end channel = exec(command, &block) channel.wait return channel[:result] end # Enqueues a message to be sent to the server as soon as the socket is # available for writing. Most programs will never need to call this, but # if you are implementing an extension to the SSH protocol, or if you # need to send a packet that Net::SSH does not directly support, you can # use this to send it. # # ssh.send_message(Buffer.from(:byte, REQUEST_SUCCESS).to_s) def send_message(message) transport.enqueue_message(message) end # Adds an IO object for the event loop to listen to. If a callback # is given, it will be invoked when the io is ready to be read, otherwise, # the io will merely have its #fill method invoked. # # Any +io+ value passed to this method _must_ have mixed into it the # Net::SSH::BufferedIo functionality, typically by calling #extend on the # object. # # The following example executes a process on the remote server, opens # a socket to somewhere, and then pipes data from that socket to the # remote process' stdin stream: # # channel = ssh.open_channel do |ch| # ch.exec "/some/process/that/wants/input" do |ch, success| # abort "can't execute!" unless success # # io = TCPSocket.new(somewhere, port) # io.extend(Net::SSH::BufferedIo) # ssh.listen_to(io) # # ch.on_process do # if io.available > 0 # ch.send_data(io.read_available) # end # end # # ch.on_close do # ssh.stop_listening_to(io) # io.close # end # end # end # # channel.wait def listen_to(io, &callback) listeners[io] = callback end # Removes the given io object from the listeners collection, so that the # event loop will no longer monitor it. def stop_listening_to(io) listeners.delete(io) end # Returns a reference to the Net::SSH::Service::Forward service, which can # be used for forwarding ports over SSH. def forward @forward ||= Service::Forward.new(self) end # Registers a handler to be invoked when the server wants to open a # channel on the client. The callback receives the connection object, # the new channel object, and the packet itself as arguments, and should # raise ChannelOpenFailed if it is unable to open the channel for some # reason. Otherwise, the channel will be opened and a confirmation message # sent to the server. # # This is used by the Net::SSH::Service::Forward service to open a channel # when a remote forwarded port receives a connection. However, you are # welcome to register handlers for other channel types, as needed. def on_open_channel(type, &block) channel_open_handlers[type] = block end # Registers a handler to be invoked when the server sends a global request # of the given type. The callback receives the request data as the first # parameter, and true/false as the second (indicating whether a response # is required). If the callback sends the response, it should return # :sent. Otherwise, if it returns true, REQUEST_SUCCESS will be sent, and # if it returns false, REQUEST_FAILURE will be sent. def on_global_request(type, &block) old, @on_global_request[type] = @on_global_request[type], block old end private # Read all pending packets from the connection and dispatch them as # appropriate. Returns as soon as there are no more pending packets. def dispatch_incoming_packets while packet = transport.poll_message unless MAP.key?(packet.type) raise Net::SSH::Exception, "unexpected response #{packet.type} (#{packet.inspect})" end send(MAP[packet.type], packet) end end # Returns the next available channel id to be assigned, and increments # the counter. def get_next_channel_id @channel_id_counter += 1 end # Invoked when a global request is received. The registered global # request callback will be invoked, if one exists, and the necessary # reply returned. def global_request(packet) info { "global request received: #{packet[:request_type]} #{packet[:want_reply]}" } callback = @on_global_request[packet[:request_type]] result = callback ? callback.call(packet[:request_data], packet[:want_reply]) : false if result != :sent && result != true && result != false raise "expected global request handler for `#{packet[:request_type]}' to return true, false, or :sent, but got #{result.inspect}" end if packet[:want_reply] && result != :sent msg = Buffer.from(:byte, result ? REQUEST_SUCCESS : REQUEST_FAILURE) send_message(msg) end end # Invokes the next pending request callback with +true+. def request_success(packet) info { "global request success" } callback = pending_requests.shift callback.call(true, packet) if callback end # Invokes the next pending request callback with +false+. def request_failure(packet) info { "global request failure" } callback = pending_requests.shift callback.call(false, packet) if callback end # Called when the server wants to open a channel. If no registered # channel handler exists for the given channel type, CHANNEL_OPEN_FAILURE # is returned, otherwise the callback is invoked and everything proceeds # accordingly. def channel_open(packet) info { "channel open #{packet[:channel_type]}" } local_id = get_next_channel_id channel = Channel.new(self, packet[:channel_type], local_id, @max_pkt_size, @max_win_size) channel.do_open_confirmation(packet[:remote_id], packet[:window_size], packet[:packet_size]) callback = channel_open_handlers[packet[:channel_type]] if callback begin callback[self, channel, packet] rescue ChannelOpenFailed => err failure = [err.code, err.reason] else channels[local_id] = channel msg = Buffer.from(:byte, CHANNEL_OPEN_CONFIRMATION, :long, channel.remote_id, :long, channel.local_id, :long, channel.local_maximum_window_size, :long, channel.local_maximum_packet_size) end else failure = [3, "unknown channel type #{channel.type}"] end if failure error { failure.inspect } msg = Buffer.from(:byte, CHANNEL_OPEN_FAILURE, :long, channel.remote_id, :long, failure[0], :string, failure[1], :string, "") end send_message(msg) end def channel_open_confirmation(packet) info { "channel_open_confirmation: #{packet[:local_id]} #{packet[:remote_id]} #{packet[:window_size]} #{packet[:packet_size]}" } channel = channels[packet[:local_id]] channel.do_open_confirmation(packet[:remote_id], packet[:window_size], packet[:packet_size]) end def channel_open_failure(packet) error { "channel_open_failed: #{packet[:local_id]} #{packet[:reason_code]} #{packet[:description]}" } channel = channels.delete(packet[:local_id]) channel.do_open_failed(packet[:reason_code], packet[:description]) end def channel_window_adjust(packet) info { "channel_window_adjust: #{packet[:local_id]} +#{packet[:extra_bytes]}" } channels[packet[:local_id]].do_window_adjust(packet[:extra_bytes]) end def channel_request(packet) info { "channel_request: #{packet[:local_id]} #{packet[:request]} #{packet[:want_reply]}" } channels[packet[:local_id]].do_request(packet[:request], packet[:want_reply], packet[:request_data]) end def channel_data(packet) info { "channel_data: #{packet[:local_id]} #{packet[:data].length}b" } channels[packet[:local_id]].do_data(packet[:data]) end def channel_extended_data(packet) info { "channel_extended_data: #{packet[:local_id]} #{packet[:data_type]} #{packet[:data].length}b" } channels[packet[:local_id]].do_extended_data(packet[:data_type], packet[:data]) end def channel_eof(packet) info { "channel_eof: #{packet[:local_id]}" } channels[packet[:local_id]].do_eof end def channel_close(packet) info { "channel_close: #{packet[:local_id]}" } channel = channels[packet[:local_id]] channel.close channels.delete(packet[:local_id]) channel.do_close end def channel_success(packet) info { "channel_success: #{packet[:local_id]}" } channels[packet[:local_id]].do_success end def channel_failure(packet) info { "channel_failure: #{packet[:local_id]}" } channels[packet[:local_id]].do_failure end MAP = Constants.constants.inject({}) do |memo, name| value = const_get(name) next unless Integer === value memo[value] = name.downcase.to_sym memo end end end; end; end net-ssh-2.6.8/lib/net/ssh/connection/channel.rb0000644000004100000410000006200212166626376021404 0ustar www-datawww-datarequire 'net/ssh/loggable' require 'net/ssh/connection/constants' require 'net/ssh/connection/term' module Net; module SSH; module Connection # The channel abstraction. Multiple "channels" can be multiplexed onto a # single SSH channel, each operating independently and seemingly in parallel. # This class represents a single such channel. Most operations performed # with the Net::SSH library will involve using one or more channels. # # Channels are intended to be used asynchronously. You request that one be # opened (via Connection::Session#open_channel), and when it is opened, your # callback is invoked. Then, you set various other callbacks on the newly # opened channel, which are called in response to the corresponding events. # Programming with Net::SSH works best if you think of your programs as # state machines. Complex programs are best implemented as objects that # wrap a channel. See Net::SCP and Net::SFTP for examples of how complex # state machines can be built on top of the SSH protocol. # # ssh.open_channel do |channel| # channel.exec("/invoke/some/command") do |ch, success| # abort "could not execute command" unless success # # channel.on_data do |ch, data| # puts "got stdout: #{data}" # channel.send_data "something for stdin\n" # end # # channel.on_extended_data do |ch, type, data| # puts "got stderr: #{data}" # end # # channel.on_close do |ch| # puts "channel is closing!" # end # end # end # # ssh.loop # # Channels also have a basic hash-like interface, that allows programs to # store arbitrary state information on a channel object. This helps simplify # the writing of state machines, especially when you may be juggling # multiple open channels at the same time. # # Note that data sent across SSH channels are governed by maximum packet # sizes and maximum window sizes. These details are managed internally # by Net::SSH::Connection::Channel, so you may remain blissfully ignorant # if you so desire, but you can always inspect the current maximums, as # well as the remaining window size, using the reader attributes for those # values. class Channel include Constants, Loggable # The local id for this channel, assigned by the Net::SSH::Connection::Session instance. attr_reader :local_id # The remote id for this channel, assigned by the remote host. attr_reader :remote_id # The type of this channel, usually "session". attr_reader :type # The underlying Net::SSH::Connection::Session instance that supports this channel. attr_reader :connection # The maximum packet size that the local host can receive. attr_reader :local_maximum_packet_size # The maximum amount of data that the local end of this channel can # receive. This is a total, not per-packet. attr_reader :local_maximum_window_size # The maximum packet size that the remote host can receive. attr_reader :remote_maximum_packet_size # The maximum amount of data that the remote end of this channel can # receive. This is a total, not per-packet. attr_reader :remote_maximum_window_size # This is the remaining window size on the local end of this channel. When # this reaches zero, no more data can be received. attr_reader :local_window_size # This is the remaining window size on the remote end of this channel. When # this reaches zero, no more data can be sent. attr_reader :remote_window_size # A hash of properties for this channel. These can be used to store state # information about this channel. See also #[] and #[]=. attr_reader :properties # The output buffer for this channel. Data written to the channel is # enqueued here, to be written as CHANNEL_DATA packets during each pass of # the event loop. See Connection::Session#process and #enqueue_pending_output. attr_reader :output #:nodoc: # The list of pending requests. Each time a request is sent which requires # a reply, the corresponding callback is pushed onto this queue. As responses # arrive, they are shifted off the front and handled. attr_reader :pending_requests #:nodoc: # Instantiates a new channel on the given connection, of the given type, # and with the given id. If a block is given, it will be remembered until # the channel is confirmed open by the server, and will be invoked at # that time (see #do_open_confirmation). # # This also sets the default maximum packet size and maximum window size. def initialize(connection, type, local_id, max_pkt_size = 0x8000, max_win_size = 0x20000, &on_confirm_open) self.logger = connection.logger @connection = connection @type = type @local_id = local_id @local_maximum_packet_size = max_pkt_size @local_window_size = @local_maximum_window_size = max_win_size @on_confirm_open = on_confirm_open @output = Buffer.new @properties = {} @pending_requests = [] @on_open_failed = @on_data = @on_extended_data = @on_process = @on_close = @on_eof = nil @on_request = {} @closing = @eof = @sent_eof = false end # A shortcut for accessing properties of the channel (see #properties). def [](name) @properties[name] end # A shortcut for setting properties of the channel (see #properties). def []=(name, value) @properties[name] = value end # Syntactic sugar for executing a command. Sends a channel request asking # that the given command be invoked. If the block is given, it will be # called when the server responds. The first parameter will be the # channel, and the second will be true or false, indicating whether the # request succeeded or not. In this case, success means that the command # is being executed, not that it has completed, and failure means that the # command altogether failed to be executed. # # channel.exec "ls -l /home" do |ch, success| # if success # puts "command has begun executing..." # # this is a good place to hang callbacks like #on_data... # else # puts "alas! the command could not be invoked!" # end # end def exec(command, &block) send_channel_request("exec", :string, command, &block) end # Syntactic sugar for requesting that a subsystem be started. Subsystems # are a way for other protocols (like SFTP) to be run, using SSH as # the transport. Generally, you'll never need to call this directly unless # you are the implementor of something that consumes an SSH subsystem, like # SFTP. # # channel.subsystem("sftp") do |ch, success| # if success # puts "subsystem successfully started" # else # puts "subsystem could not be started" # end # end def subsystem(subsystem, &block) send_channel_request("subsystem", :string, subsystem, &block) end # Syntactic sugar for setting an environment variable in the remote # process' environment. Note that for security reasons, the server may # refuse to set certain environment variables, or all, at the server's # discretion. If you are connecting to an OpenSSH server, you will # need to update the AcceptEnv setting in the sshd_config to include the # environment variables you want to send. # # channel.env "PATH", "/usr/local/bin" def env(variable_name, variable_value, &block) send_channel_request("env", :string, variable_name, :string, variable_value, &block) end # A hash of the valid PTY options (see #request_pty). VALID_PTY_OPTIONS = { :term => "xterm", :chars_wide => 80, :chars_high => 24, :pixels_wide => 640, :pixels_high => 480, :modes => {} } # Requests that a pseudo-tty (or "pty") be made available for this channel. # This is useful when you want to invoke and interact with some kind of # screen-based program (e.g., vim, or some menuing system). # # Note, that without a pty some programs (e.g. sudo, or subversion) on # some systems, will not be able to run interactively, and will error # instead of prompt if they ever need some user interaction. # # Note, too, that when a pty is requested, user's shell configuration # scripts (.bashrc and such) are not run by default, whereas they are # run when a pty is not present. # # channel.request_pty do |ch, success| # if success # puts "pty successfully obtained" # else # puts "could not obtain pty" # end # end def request_pty(opts={}, &block) extra = opts.keys - VALID_PTY_OPTIONS.keys raise ArgumentError, "invalid option(s) to request_pty: #{extra.inspect}" if extra.any? opts = VALID_PTY_OPTIONS.merge(opts) modes = opts[:modes].inject(Buffer.new) do |memo, (mode, data)| memo.write_byte(mode).write_long(data) end # mark the end of the mode opcode list with a 0 byte modes.write_byte(0) send_channel_request("pty-req", :string, opts[:term], :long, opts[:chars_wide], :long, opts[:chars_high], :long, opts[:pixels_wide], :long, opts[:pixels_high], :string, modes.to_s, &block) end # Sends data to the channel's remote endpoint. This usually has the # effect of sending the given string to the remote process' stdin stream. # Note that it does not immediately send the data across the channel, # but instead merely appends the given data to the channel's output buffer, # preparatory to being packaged up and sent out the next time the connection # is accepting data. (A connection might not be accepting data if, for # instance, it has filled its data window and has not yet been resized by # the remote end-point.) # # This will raise an exception if the channel has previously declared # that no more data will be sent (see #eof!). # # channel.send_data("the password\n") def send_data(data) raise EOFError, "cannot send data if channel has declared eof" if eof? output.append(data.to_s) end # Returns true if the channel exists in the channel list of the session, # and false otherwise. This can be used to determine whether a channel has # been closed or not. # # ssh.loop { channel.active? } def active? connection.channels.key?(local_id) end # Runs the SSH event loop until the channel is no longer active. This is # handy for blocking while you wait for some channel to finish. # # channel.exec("grep ...") { ... } # channel.wait def wait connection.loop { active? } end # Returns true if the channel is currently closing, but not actually # closed. A channel is closing when, for instance, #close has been # invoked, but the server has not yet responded with a CHANNEL_CLOSE # packet of its own. def closing? @closing end # Requests that the channel be closed. If the channel is already closing, # this does nothing, nor does it do anything if the channel has not yet # been confirmed open (see #do_open_confirmation). Otherwise, it sends a # CHANNEL_CLOSE message and marks the channel as closing. def close return if @closing if remote_id @closing = true connection.send_message(Buffer.from(:byte, CHANNEL_CLOSE, :long, remote_id)) end end # Returns true if the local end of the channel has declared that no more # data is forthcoming (see #eof!). Trying to send data via #send_data when # this is true will result in an exception being raised. def eof? @eof end # Tells the remote end of the channel that no more data is forthcoming # from this end of the channel. The remote end may still send data. # The CHANNEL_EOF packet will be sent once the output buffer is empty. def eof! return if eof? @eof = true end # If an #on_process handler has been set up, this will cause it to be # invoked (passing the channel itself as an argument). It also causes all # pending output to be enqueued as CHANNEL_DATA packets (see #enqueue_pending_output). def process @on_process.call(self) if @on_process enqueue_pending_output if @eof and not @sent_eof and output.empty? and remote_id connection.send_message(Buffer.from(:byte, CHANNEL_EOF, :long, remote_id)) @sent_eof = true end end # Registers a callback to be invoked when data packets are received by the # channel. The callback is called with the channel as the first argument, # and the data as the second. # # channel.on_data do |ch, data| # puts "got data: #{data.inspect}" # end # # Data received this way is typically the data written by the remote # process to its +stdout+ stream. def on_data(&block) old, @on_data = @on_data, block old end # Registers a callback to be invoked when extended data packets are received # by the channel. The callback is called with the channel as the first # argument, the data type (as an integer) as the second, and the data as # the third. Extended data is almost exclusively used to send +stderr+ data # (+type+ == 1). Other extended data types are not defined by the SSH # protocol. # # channel.on_extended_data do |ch, type, data| # puts "got stderr: #{data.inspect}" # end def on_extended_data(&block) old, @on_extended_data = @on_extended_data, block old end # Registers a callback to be invoked for each pass of the event loop for # this channel. There are no guarantees on timeliness in the event loop, # but it will be called roughly once for each packet received by the # connection (not the channel). This callback is invoked with the channel # as the sole argument. # # Here's an example that accumulates the channel data into a variable on # the channel itself, and displays individual lines in the input one # at a time when the channel is processed: # # channel[:data] = "" # # channel.on_data do |ch, data| # channel[:data] << data # end # # channel.on_process do |ch| # if channel[:data] =~ /^.*?\n/ # puts $& # channel[:data] = $' # end # end def on_process(&block) old, @on_process = @on_process, block old end # Registers a callback to be invoked when the server acknowledges that a # channel is closed. This is invoked with the channel as the sole argument. # # channel.on_close do |ch| # puts "remote end is closing!" # end def on_close(&block) old, @on_close = @on_close, block old end # Registers a callback to be invoked when the server indicates that no more # data will be sent to the channel (although the channel can still send # data to the server). The channel is the sole argument to the callback. # # channel.on_eof do |ch| # puts "remote end is done sending data" # end def on_eof(&block) old, @on_eof = @on_eof, block old end # Registers a callback to be invoked when the server was unable to open # the requested channel. The channel itself will be passed to the block, # along with the integer "reason code" for the failure, and a textual # description of the failure from the server. # # channel = session.open_channel do |ch| # # .. # end # # channel.on_open_failed { |ch, code, desc| ... } def on_open_failed(&block) old, @on_open_failed = @on_open_failed, block old end # Registers a callback to be invoked when a channel request of the given # type is received. The callback will receive the channel as the first # argument, and the associated (unparsed) data as the second. The data # will be a Net::SSH::Buffer that you will need to parse, yourself, # according to the kind of request you are watching. # # By default, if the request wants a reply, Net::SSH will send a # CHANNEL_SUCCESS response for any request that was handled by a registered # callback, and CHANNEL_FAILURE for any that wasn't, but if you want your # registered callback to result in a CHANNEL_FAILURE response, just raise # Net::SSH::ChannelRequestFailed. # # Some common channel requests that your programs might want to listen # for are: # # * "exit-status" : the exit status of the remote process will be reported # as a long integer in the data buffer, which you can grab via # data.read_long. # * "exit-signal" : if the remote process died as a result of a signal # being sent to it, the signal will be reported as a string in the # data, via data.read_string. (Not all SSH servers support this channel # request type.) # # channel.on_request "exit-status" do |ch, data| # puts "process terminated with exit status: #{data.read_long}" # end def on_request(type, &block) old, @on_request[type] = @on_request[type], block old end # Sends a new channel request with the given name. The extra +data+ # parameter must either be empty, or consist of an even number of # arguments. See Net::SSH::Buffer.from for a description of their format. # If a block is given, it is registered as a callback for a pending # request, and the packet will be flagged so that the server knows a # reply is required. If no block is given, the server will send no # response to this request. Responses, where required, will cause the # callback to be invoked with the channel as the first argument, and # either true or false as the second, depending on whether the request # succeeded or not. The meaning of "success" and "failure" in this context # is dependent on the specific request that was sent. # # channel.send_channel_request "shell" do |ch, success| # if success # puts "user shell started successfully" # else # puts "could not start user shell" # end # end # # Most channel requests you'll want to send are already wrapped in more # convenient helper methods (see #exec and #subsystem). def send_channel_request(request_name, *data, &callback) info { "sending channel request #{request_name.inspect}" } msg = Buffer.from(:byte, CHANNEL_REQUEST, :long, remote_id, :string, request_name, :bool, !callback.nil?, *data) connection.send_message(msg) pending_requests << callback if callback end public # these methods are public, but for Net::SSH internal use only # Enqueues pending output at the connection as CHANNEL_DATA packets. This # does nothing if the channel has not yet been confirmed open (see # #do_open_confirmation). This is called automatically by #process, which # is called from the event loop (Connection::Session#process). You will # generally not need to invoke it directly. def enqueue_pending_output #:nodoc: return unless remote_id while output.length > 0 length = output.length length = remote_window_size if length > remote_window_size length = remote_maximum_packet_size if length > remote_maximum_packet_size if length > 0 connection.send_message(Buffer.from(:byte, CHANNEL_DATA, :long, remote_id, :string, output.read(length))) output.consume! @remote_window_size -= length else break end end end # Invoked when the server confirms that a channel has been opened. # The remote_id is the id of the channel as assigned by the remote host, # and max_window and max_packet are the maximum window and maximum # packet sizes, respectively. If an open-confirmation callback was # given when the channel was created, it is invoked at this time with # the channel itself as the sole argument. def do_open_confirmation(remote_id, max_window, max_packet) #:nodoc: @remote_id = remote_id @remote_window_size = @remote_maximum_window_size = max_window @remote_maximum_packet_size = max_packet connection.forward.agent(self) if connection.options[:forward_agent] && type == "session" @on_confirm_open.call(self) if @on_confirm_open end # Invoked when the server failed to open the channel. If an #on_open_failed # callback was specified, it will be invoked with the channel, reason code, # and description as arguments. Otherwise, a ChannelOpenFailed exception # will be raised. def do_open_failed(reason_code, description) if @on_open_failed @on_open_failed.call(self, reason_code, description) else raise ChannelOpenFailed.new(reason_code, description) end end # Invoked when the server sends a CHANNEL_WINDOW_ADJUST packet, and # causes the remote window size to be adjusted upwards by the given # number of bytes. This has the effect of allowing more data to be sent # from the local end to the remote end of the channel. def do_window_adjust(bytes) #:nodoc: @remote_maximum_window_size += bytes @remote_window_size += bytes end # Invoked when the server sends a channel request. If any #on_request # callback has been registered for the specific type of this request, # it is invoked. If +want_reply+ is true, a packet will be sent of # either CHANNEL_SUCCESS or CHANNEL_FAILURE type. If there was no callback # to handle the request, CHANNEL_FAILURE will be sent. Otherwise, # CHANNEL_SUCCESS, unless the callback raised ChannelRequestFailed. The # callback should accept the channel as the first argument, and the # request-specific data as the second. def do_request(request, want_reply, data) #:nodoc: result = true begin callback = @on_request[request] or raise ChannelRequestFailed callback.call(self, data) rescue ChannelRequestFailed result = false end if want_reply msg = Buffer.from(:byte, result ? CHANNEL_SUCCESS : CHANNEL_FAILURE, :long, remote_id) connection.send_message(msg) end end # Invokes the #on_data callback when the server sends data to the # channel. This will reduce the available window size on the local end, # but does not actually throttle requests that come in illegally when # the window size is too small. The callback is invoked with the channel # as the first argument, and the data as the second. def do_data(data) #:nodoc: update_local_window_size(data.length) @on_data.call(self, data) if @on_data end # Invokes the #on_extended_data callback when the server sends # extended data to the channel. This will reduce the available window # size on the local end. The callback is invoked with the channel, # type, and data. def do_extended_data(type, data) update_local_window_size(data.length) @on_extended_data.call(self, type, data) if @on_extended_data end # Invokes the #on_eof callback when the server indicates that no # further data is forthcoming. The callback is invoked with the channel # as the argument. def do_eof @on_eof.call(self) if @on_eof end # Invokes the #on_close callback when the server closes a channel. # The channel is the only argument. def do_close @on_close.call(self) if @on_close end # Invokes the next pending request callback with +false+ as the second # argument. def do_failure if callback = pending_requests.shift callback.call(self, false) else error { "channel failure recieved with no pending request to handle it (bug?)" } end end # Invokes the next pending request callback with +true+ as the second # argument. def do_success if callback = pending_requests.shift callback.call(self, true) else error { "channel success recieved with no pending request to handle it (bug?)" } end end private # Updates the local window size by the given amount. If the window # size drops to less than half of the local maximum (an arbitrary # threshold), a CHANNEL_WINDOW_ADJUST message will be sent to the # server telling it that the window size has grown. def update_local_window_size(size) @local_window_size -= size if local_window_size < local_maximum_window_size/2 connection.send_message(Buffer.from(:byte, CHANNEL_WINDOW_ADJUST, :long, remote_id, :long, 0x20000)) @local_window_size += 0x20000 @local_maximum_window_size += 0x20000 end end end end; end; end net-ssh-2.6.8/lib/net/ssh/connection/constants.rb0000644000004100000410000000141312166626376022007 0ustar www-datawww-datamodule Net; module SSH; module Connection # Definitions of constants that are specific to the connection layer of the # SSH protocol. module Constants #-- # Connection protocol generic messages #++ GLOBAL_REQUEST = 80 REQUEST_SUCCESS = 81 REQUEST_FAILURE = 82 #-- # Channel related messages #++ CHANNEL_OPEN = 90 CHANNEL_OPEN_CONFIRMATION = 91 CHANNEL_OPEN_FAILURE = 92 CHANNEL_WINDOW_ADJUST = 93 CHANNEL_DATA = 94 CHANNEL_EXTENDED_DATA = 95 CHANNEL_EOF = 96 CHANNEL_CLOSE = 97 CHANNEL_REQUEST = 98 CHANNEL_SUCCESS = 99 CHANNEL_FAILURE = 100 end end; end endnet-ssh-2.6.8/lib/net/ssh/connection/term.rb0000644000004100000410000000717712166626376020757 0ustar www-datawww-datamodule Net; module SSH; module Connection # These constants are used when requesting a pseudo-terminal (via # Net::SSH::Connection::Channel#request_pty). The descriptions for each are # taken directly from RFC 4254 ("The Secure Shell (SSH) Connection Protocol"), # http://tools.ietf.org/html/rfc4254. module Term # Interrupt character; 255 if none. Similarly for the other characters. # Not all of these characters are supported on all systems. VINTR = 1 # The quit character (sends SIGQUIT signal on POSIX systems). VQUIT = 2 # Erase the character to left of the cursor. VERASE = 3 # Kill the current input line. VKILL = 4 # End-of-file character (sends EOF from the terminal). VEOF = 5 # End-of-line character in addition to carriage return and/or linefeed. VEOL = 6 # Additional end-of-line character. VEOL2 = 7 # Continues paused output (normally control-Q). VSTART = 8 # Pauses output (normally control-S). VSTOP = 9 # Suspends the current program. VSUSP = 10 # Another suspend character. VDSUSP = 11 # Reprints the current input line. VREPRINT = 12 # Erases a word left of cursor. VWERASE = 13 # Enter the next character typed literally, even if it is a special # character. VLNEXT = 14 # Character to flush output. VFLUSH = 15 # Switch to a different shell layer. VSWITCH = 16 # Prints system status line (load, command, pid, etc). VSTATUS = 17 # Toggles the flushing of terminal output. VDISCARD = 18 # The ignore parity flag. The parameter SHOULD be 0 if this flag is FALSE, # and 1 if it is TRUE. IGNPAR = 30 # Mark parity and framing errors. PARMRK = 31 # Enable checking of parity errors. INPCK = 32 # Strip 8th bit off characters. ISTRIP = 33 # Map NL into CR on input. INCLR = 34 # Ignore CR on input. IGNCR = 35 # Map CR to NL on input. ICRNL = 36 # Translate uppercase characters to lowercase. IUCLC = 37 # Enable output flow control. IXON = 38 # Any char will restart after stop. IXANY = 39 # Enable input flow control. IXOFF = 40 # Ring bell on input queue full. IMAXBEL = 41 # Enable signals INTR, QUIT, [D]SUSP. ISIG = 50 # Canonicalize input lines. ICANON = 51 # Enable input and output of uppercase characters by preceding their # lowercase equivalents with "\". XCASE = 52 # Enable echoing. ECHO = 53 # Visually erase chars. ECHOE = 54 # Kill character discards current line. ECHOK = 55 # Echo NL even if ECHO is off. ECHONL = 56 # Don't flush after interrupt. NOFLSH = 57 # Stop background jobs from output. TOSTOP= 58 # Enable extensions. IEXTEN = 59 # Echo control characters as ^(Char). ECHOCTL = 60 # Visual erase for line kill. ECHOKE = 61 # Retype pending input. PENDIN = 62 # Enable output processing. OPOST = 70 # Convert lowercase to uppercase. OLCUC = 71 # Map NL to CR-NL. ONLCR = 72 # Translate carriage return to newline (output). OCRNL = 73 # Translate newline to carriage return-newline (output). ONOCR = 74 # Newline performs a carriage return (output). ONLRET = 75 # 7 bit mode. CS7 = 90 # 8 bit mode. CS8 = 91 # Parity enable. PARENB = 92 # Odd parity, else even. PARODD = 93 # Specifies the input baud rate in bits per second. TTY_OP_ISPEED = 128 # Specifies the output baud rate in bits per second. TTY_OP_OSPEED = 129 end end; end; end net-ssh-2.6.8/lib/net/ssh/transport/0000755000004100000410000000000012166626376017344 5ustar www-datawww-datanet-ssh-2.6.8/lib/net/ssh/transport/session.rb0000644000004100000410000002304012166626376021353 0ustar www-datawww-datarequire 'socket' require 'timeout' require 'net/ssh/errors' require 'net/ssh/loggable' require 'net/ssh/version' require 'net/ssh/transport/algorithms' require 'net/ssh/transport/constants' require 'net/ssh/transport/packet_stream' require 'net/ssh/transport/server_version' require 'net/ssh/verifiers/null' require 'net/ssh/verifiers/secure' require 'net/ssh/verifiers/strict' require 'net/ssh/verifiers/lenient' module Net; module SSH; module Transport # The transport layer represents the lowest level of the SSH protocol, and # implements basic message exchanging and protocol initialization. It will # never be instantiated directly (unless you really know what you're about), # but will instead be created for you automatically when you create a new # SSH session via Net::SSH.start. class Session include Constants, Loggable # The standard port for the SSH protocol. DEFAULT_PORT = 22 # The host to connect to, as given to the constructor. attr_reader :host # The port number to connect to, as given in the options to the constructor. # If no port number was given, this will default to DEFAULT_PORT. attr_reader :port # The underlying socket object being used to communicate with the remote # host. attr_reader :socket # The ServerVersion instance that encapsulates the negotiated protocol # version. attr_reader :server_version # The Algorithms instance used to perform key exchanges. attr_reader :algorithms # The host-key verifier object used to verify host keys, to ensure that # the connection is not being spoofed. attr_reader :host_key_verifier # The hash of options that were given to the object at initialization. attr_reader :options # Instantiates a new transport layer abstraction. This will block until # the initial key exchange completes, leaving you with a ready-to-use # transport session. def initialize(host, options={}) self.logger = options[:logger] @host = host @port = options[:port] || DEFAULT_PORT @bind_address = options[:bind_address] || nil @options = options debug { "establishing connection to #{@host}:#{@port}" } factory = options[:proxy] || TCPSocket @socket = timeout(options[:timeout] || 0) { @bind_address.nil? || options[:proxy] ? factory.open(@host, @port) : factory.open(@host,@port,@bind_address) } @socket.extend(PacketStream) @socket.logger = @logger debug { "connection established" } @queue = [] @host_key_verifier = select_host_key_verifier(options[:paranoid]) @server_version = timeout(options[:timeout] || 0) { ServerVersion.new(socket, logger) } @algorithms = Algorithms.new(self, options) wait { algorithms.initialized? } end # Returns the host (and possibly IP address) in a format compatible with # SSH known-host files. def host_as_string @host_as_string ||= begin string = "#{host}" string = "[#{string}]:#{port}" if port != DEFAULT_PORT if socket.peer_ip != host string2 = socket.peer_ip string2 = "[#{string2}]:#{port}" if port != DEFAULT_PORT string << "," << string2 end string end end # Returns true if the underlying socket has been closed. def closed? socket.closed? end # Cleans up (see PacketStream#cleanup) and closes the underlying socket. def close socket.cleanup socket.close end # Performs a "hard" shutdown of the connection. In general, this should # never be done, but it might be necessary (in a rescue clause, for instance, # when the connection needs to close but you don't know the status of the # underlying protocol's state). def shutdown! error { "forcing connection closed" } socket.close end # Returns a new service_request packet for the given service name, ready # for sending to the server. def service_request(service) Net::SSH::Buffer.from(:byte, SERVICE_REQUEST, :string, service) end # Requests a rekey operation, and blocks until the operation completes. # If a rekey is already pending, this returns immediately, having no # effect. def rekey! if !algorithms.pending? algorithms.rekey! wait { algorithms.initialized? } end end # Returns immediately if a rekey is already in process. Otherwise, if a # rekey is needed (as indicated by the socket, see PacketStream#if_needs_rekey?) # one is performed, causing this method to block until it completes. def rekey_as_needed return if algorithms.pending? socket.if_needs_rekey? { rekey! } end # Returns a hash of information about the peer (remote) side of the socket, # including :ip, :port, :host, and :canonized (see #host_as_string). def peer @peer ||= { :ip => socket.peer_ip, :port => @port.to_i, :host => @host, :canonized => host_as_string } end # Blocks until a new packet is available to be read, and returns that # packet. See #poll_message. def next_message poll_message(:block) end # Tries to read the next packet from the socket. If mode is :nonblock (the # default), this will not block and will return nil if there are no packets # waiting to be read. Otherwise, this will block until a packet is # available. Note that some packet types (DISCONNECT, IGNORE, UNIMPLEMENTED, # DEBUG, and KEXINIT) are handled silently by this method, and will never # be returned. # # If a key-exchange is in process and a disallowed packet type is # received, it will be enqueued and otherwise ignored. When a key-exchange # is not in process, and consume_queue is true, packets will be first # read from the queue before the socket is queried. def poll_message(mode=:nonblock, consume_queue=true) loop do if consume_queue && @queue.any? && algorithms.allow?(@queue.first) return @queue.shift end packet = socket.next_packet(mode) return nil if packet.nil? case packet.type when DISCONNECT raise Net::SSH::Disconnect, "disconnected: #{packet[:description]} (#{packet[:reason_code]})" when IGNORE debug { "IGNORE packet recieved: #{packet[:data].inspect}" } when UNIMPLEMENTED lwarn { "UNIMPLEMENTED: #{packet[:number]}" } when DEBUG send(packet[:always_display] ? :fatal : :debug) { packet[:message] } when KEXINIT algorithms.accept_kexinit(packet) else return packet if algorithms.allow?(packet) push(packet) end end end # Waits (blocks) until the given block returns true. If no block is given, # this just waits long enough to see if there are any pending packets. Any # packets read are enqueued (see #push). def wait loop do break if block_given? && yield message = poll_message(:nonblock, false) push(message) if message break if !block_given? end end # Adds the given packet to the packet queue. If the queue is non-empty, # #poll_message will return packets from the queue in the order they # were received. def push(packet) @queue.push(packet) end # Sends the given message via the packet stream, blocking until the # entire message has been sent. def send_message(message) socket.send_packet(message) end # Enqueues the given message, such that it will be sent at the earliest # opportunity. This does not block, but returns immediately. def enqueue_message(message) socket.enqueue_packet(message) end # Configure's the packet stream's client state with the given set of # options. This is typically used to define the cipher, compression, and # hmac algorithms to use when sending packets to the server. def configure_client(options={}) socket.client.set(options) end # Configure's the packet stream's server state with the given set of # options. This is typically used to define the cipher, compression, and # hmac algorithms to use when reading packets from the server. def configure_server(options={}) socket.server.set(options) end # Sets a new hint for the packet stream, which the packet stream may use # to change its behavior. (See PacketStream#hints). def hint(which, value=true) socket.hints[which] = value end public # this method is primarily for use in tests attr_reader :queue #:nodoc: private # Instantiates a new host-key verification class, based on the value of # the parameter. When true or nil, the default Lenient verifier is # returned. If it is false, the Null verifier is returned, and if it is # :very, the Strict verifier is returned. If it is :secure, the even more # strict Secure verifier is returned. If the argument happens to respond # to :verify, it is returned directly. Otherwise, an exception # is raised. def select_host_key_verifier(paranoid) case paranoid when true, nil then Net::SSH::Verifiers::Lenient.new when false then Net::SSH::Verifiers::Null.new when :very then Net::SSH::Verifiers::Strict.new when :secure then Net::SSH::Verifiers::Secure.new else if paranoid.respond_to?(:verify) paranoid else raise ArgumentError, "argument to :paranoid is not valid: #{paranoid.inspect}" end end end end end; end; end net-ssh-2.6.8/lib/net/ssh/transport/openssl.rb0000644000004100000410000001645012166626376021362 0ustar www-datawww-data# -*- coding: utf-8 -*- require 'openssl' module OpenSSL # This class is originally defined in the OpenSSL module. As needed, methods # have been added to it by the Net::SSH module for convenience in dealing with # SSH functionality. class BN # Converts a BN object to a string. The format used is that which is # required by the SSH2 protocol. def to_ssh if zero? return [0].pack("N") else buf = to_s(2) if buf.getbyte(0)[7] == 1 return [buf.length+1, 0, buf].pack("NCA*") else return [buf.length, buf].pack("NA*") end end end end module PKey class PKey def fingerprint @fingerprint ||= OpenSSL::Digest::MD5.hexdigest(to_blob).scan(/../).join(":") end end # This class is originally defined in the OpenSSL module. As needed, methods # have been added to it by the Net::SSH module for convenience in dealing # with SSH functionality. class DH # Determines whether the pub_key for this key is valid. (This algorithm # lifted more-or-less directly from OpenSSH, dh.c, dh_pub_is_valid.) def valid? return false if pub_key.nil? || pub_key < 0 bits_set = 0 pub_key.num_bits.times { |i| bits_set += 1 if pub_key.bit_set?(i) } return ( bits_set > 1 && pub_key < p ) end end # This class is originally defined in the OpenSSL module. As needed, methods # have been added to it by the Net::SSH module for convenience in dealing # with SSH functionality. class RSA # Returns "ssh-rsa", which is the description of this key type used by the # SSH2 protocol. def ssh_type "ssh-rsa" end # Converts the key to a blob, according to the SSH2 protocol. def to_blob @blob ||= Net::SSH::Buffer.from(:string, ssh_type, :bignum, e, :bignum, n).to_s end # Verifies the given signature matches the given data. def ssh_do_verify(sig, data) verify(OpenSSL::Digest::SHA1.new, sig, data) end # Returns the signature for the given data. def ssh_do_sign(data) sign(OpenSSL::Digest::SHA1.new, data) end end # This class is originally defined in the OpenSSL module. As needed, methods # have been added to it by the Net::SSH module for convenience in dealing # with SSH functionality. class DSA # Returns "ssh-dss", which is the description of this key type used by the # SSH2 protocol. def ssh_type "ssh-dss" end # Converts the key to a blob, according to the SSH2 protocol. def to_blob @blob ||= Net::SSH::Buffer.from(:string, ssh_type, :bignum, p, :bignum, q, :bignum, g, :bignum, pub_key).to_s end # Verifies the given signature matches the given data. def ssh_do_verify(sig, data) sig_r = sig[0,20].unpack("H*")[0].to_i(16) sig_s = sig[20,20].unpack("H*")[0].to_i(16) a1sig = OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::Integer(sig_r), OpenSSL::ASN1::Integer(sig_s) ]) return verify(OpenSSL::Digest::DSS1.new, a1sig.to_der, data) end # Signs the given data. def ssh_do_sign(data) sig = sign( OpenSSL::Digest::DSS1.new, data) a1sig = OpenSSL::ASN1.decode( sig ) sig_r = a1sig.value[0].value.to_s(2) sig_s = a1sig.value[1].value.to_s(2) if sig_r.length > 20 || sig_s.length > 20 raise OpenSSL::PKey::DSAError, "bad sig size" end sig_r = "\0" * ( 20 - sig_r.length ) + sig_r if sig_r.length < 20 sig_s = "\0" * ( 20 - sig_s.length ) + sig_s if sig_s.length < 20 return sig_r + sig_s end end if defined?(OpenSSL::PKey::EC) # This class is originally defined in the OpenSSL module. As needed, methods # have been added to it by the Net::SSH module for convenience in dealing # with SSH functionality. class EC CurveNameAlias = { "nistp256" => "prime256v1", "nistp384" => "secp384r1", "nistp521" => "secp521r1", } CurveNameAliasInv = { "prime256v1" => "nistp256", "secp384r1" => "nistp384", "secp521r1" => "nistp521", } def self.read_keyblob(curve_name_in_type, buffer) curve_name_in_key = buffer.read_string unless curve_name_in_type == curve_name_in_key raise Net::SSH::Exception, "curve name mismatched (`#{curve_name_in_key}' with `#{curve_name_in_type}')" end public_key_oct = buffer.read_string begin key = OpenSSL::PKey::EC.new(OpenSSL::PKey::EC::CurveNameAlias[curve_name_in_key]) group = key.group point = OpenSSL::PKey::EC::Point.new(group, OpenSSL::BN.new(public_key_oct, 2)) key.public_key = point return key rescue OpenSSL::PKey::ECError raise NotImplementedError, "unsupported key type `#{type}'" end end # Returns the description of this key type used by the # SSH2 protocol, like "ecdsa-sha2-nistp256" def ssh_type "ecdsa-sha2-#{CurveNameAliasInv[self.group.curve_name]}" end def digester if self.group.curve_name =~ /^[a-z]+(\d+)\w*\z/ curve_size = $1.to_i if curve_size <= 256 OpenSSL::Digest::SHA256.new elsif curve_size <= 384 OpenSSL::Digest::SHA384.new else OpenSSL::Digest::SHA512.new end else OpenSSL::Digest::SHA256.new end end private :digester # Converts the key to a blob, according to the SSH2 protocol. def to_blob @blob ||= Net::SSH::Buffer.from(:string, ssh_type, :string, CurveNameAliasInv[self.group.curve_name], :string, self.public_key.to_bn.to_s(2)).to_s @blob end # Verifies the given signature matches the given data. def ssh_do_verify(sig, data) digest = digester.digest(data) a1sig = nil begin sig_r_len = sig[0,4].unpack("H*")[0].to_i(16) sig_l_len = sig[4+sig_r_len,4].unpack("H*")[0].to_i(16) sig_r = sig[4,sig_r_len].unpack("H*")[0] sig_s = sig[4+sig_r_len+4,sig_l_len].unpack("H*")[0] a1sig = OpenSSL::ASN1::Sequence([ OpenSSL::ASN1::Integer(sig_r.to_i(16)), OpenSSL::ASN1::Integer(sig_s.to_i(16)), ]) rescue end if a1sig == nil return false else dsa_verify_asn1(digest, a1sig.to_der) end end # Returns the signature for the given data. def ssh_do_sign(data) digest = digester.digest(data) sig = dsa_sign_asn1(digest) a1sig = OpenSSL::ASN1.decode( sig ) sig_r = a1sig.value[0].value sig_s = a1sig.value[1].value return Net::SSH::Buffer.from(:bignum, sig_r, :bignum, sig_s).to_s end end else class OpenSSL::PKey::ECError < RuntimeError # for compatibility with interpreters # without EC support (i.e. JRuby) end end end end net-ssh-2.6.8/lib/net/ssh/transport/identity_cipher.rb0000644000004100000410000000205412166626376023055 0ustar www-datawww-datamodule Net; module SSH; module Transport # A cipher that does nothing but pass the data through, unchanged. This # keeps things in the code nice and clean when a cipher has not yet been # determined (i.e., during key exchange). class IdentityCipher class < "des-ede3-cbc", "blowfish-cbc" => "bf-cbc", "aes256-cbc" => "aes-256-cbc", "aes192-cbc" => "aes-192-cbc", "aes128-cbc" => "aes-128-cbc", "idea-cbc" => "idea-cbc", "cast128-cbc" => "cast-cbc", "rijndael-cbc@lysator.liu.se" => "aes-256-cbc", "arcfour128" => "rc4", "arcfour256" => "rc4", "arcfour512" => "rc4", "arcfour" => "rc4", "camellia128-cbc" => "camellia-128-cbc", "camellia192-cbc" => "camellia-192-cbc", "camellia256-cbc" => "camellia-256-cbc", "camellia128-cbc@openssh.org" => "camellia-128-cbc", "camellia192-cbc@openssh.org" => "camellia-192-cbc", "camellia256-cbc@openssh.org" => "camellia-256-cbc", "3des-ctr" => "des-ede3", "blowfish-ctr" => "bf-ecb", "aes256-ctr" => "aes-256-ecb", "aes192-ctr" => "aes-192-ecb", "aes128-ctr" => "aes-128-ecb", "cast128-ctr" => "cast5-ecb", "camellia128-ctr" => "camellia-128-ecb", "camellia192-ctr" => "camellia-192-ecb", "camellia256-ctr" => "camellia-256-ecb", "camellia128-ctr@openssh.org" => "camellia-128-ecb", "camellia192-ctr@openssh.org" => "camellia-192-ecb", "camellia256-ctr@openssh.org" => "camellia-256-ecb", "none" => "none", } # Ruby's OpenSSL bindings always return a key length of 16 for RC4 ciphers # resulting in the error: OpenSSL::CipherError: key length too short. # The following ciphers will override this key length. KEY_LEN_OVERRIDE = { "arcfour256" => 32, "arcfour512" => 64 } # Returns true if the underlying OpenSSL library supports the given cipher, # and false otherwise. def self.supported?(name) ossl_name = SSH_TO_OSSL[name] or raise NotImplementedError, "unimplemented cipher `#{name}'" return true if ossl_name == "none" return OpenSSL::Cipher.ciphers.include?(ossl_name) end # Retrieves a new instance of the named algorithm. The new instance # will be initialized using an iv and key generated from the given # iv, key, shared, hash and digester values. Additionally, the # cipher will be put into encryption or decryption mode, based on the # value of the +encrypt+ parameter. def self.get(name, options={}) ossl_name = SSH_TO_OSSL[name] or raise NotImplementedError, "unimplemented cipher `#{name}'" return IdentityCipher if ossl_name == "none" cipher = OpenSSL::Cipher::Cipher.new(ossl_name) cipher.send(options[:encrypt] ? :encrypt : :decrypt) cipher.padding = 0 cipher.extend(Net::SSH::Transport::CTR) if (name =~ /-ctr(@openssh.org)?$/) cipher.iv = Net::SSH::Transport::KeyExpander.expand_key(cipher.iv_len, options[:iv], options) if ossl_name != "rc4" key_len = KEY_LEN_OVERRIDE[name] || cipher.key_len cipher.key_len = key_len cipher.key = Net::SSH::Transport::KeyExpander.expand_key(key_len, options[:key], options) cipher.update(" " * 1536) if (ossl_name == "rc4" && name != "arcfour") return cipher end # Returns a two-element array containing the [ key-length, # block-size ] for the named cipher algorithm. If the cipher # algorithm is unknown, or is "none", 0 is returned for both elements # of the tuple. def self.get_lengths(name) ossl_name = SSH_TO_OSSL[name] return [0, 0] if ossl_name.nil? || ossl_name == "none" cipher = OpenSSL::Cipher::Cipher.new(ossl_name) key_len = KEY_LEN_OVERRIDE[name] || cipher.key_len cipher.key_len = key_len return [key_len, ossl_name=="rc4" ? 8 : cipher.block_size] end end end; end; end net-ssh-2.6.8/lib/net/ssh/transport/server_version.rb0000644000004100000410000000432212166626376022745 0ustar www-datawww-datarequire 'net/ssh/errors' require 'net/ssh/loggable' require 'net/ssh/version' module Net; module SSH; module Transport # Negotiates the SSH protocol version and trades information about server # and client. This is never used directly--it is always called by the # transport layer as part of the initialization process of the transport # layer. # # Note that this class also encapsulates the negotiated version, and acts as # the authoritative reference for any queries regarding the version in effect. class ServerVersion include Loggable # The SSH version string as reported by Net::SSH PROTO_VERSION = "SSH-2.0-Ruby/Net::SSH_#{Net::SSH::Version::CURRENT} #{RUBY_PLATFORM}" # Any header text sent by the server prior to sending the version. attr_reader :header # The version string reported by the server. attr_reader :version # Instantiates a new ServerVersion and immediately (and synchronously) # negotiates the SSH protocol in effect, using the given socket. def initialize(socket, logger) @header = "" @version = nil @logger = logger negotiate!(socket) end private # Negotiates the SSH protocol to use, via the given socket. If the server # reports an incompatible SSH version (e.g., SSH1), this will raise an # exception. def negotiate!(socket) info { "negotiating protocol version" } loop do @version = "" loop do begin b = socket.readpartial(1) raise Net::SSH::Disconnect, "connection closed by remote host" if b.nil? rescue EOFError raise Net::SSH::Disconnect, "connection closed by remote host" end @version << b break if b == "\n" end break if @version.match(/^SSH-/) @header << @version end @version.chomp! debug { "remote is `#{@version}'" } unless @version.match(/^SSH-(1\.99|2\.0)-/) raise Net::SSH::Exception, "incompatible SSH version `#{@version}'" end debug { "local is `#{PROTO_VERSION}'" } socket.write "#{PROTO_VERSION}\r\n" socket.flush end end end; end; end net-ssh-2.6.8/lib/net/ssh/transport/state.rb0000644000004100000410000001441312166626376021014 0ustar www-datawww-datarequire 'zlib' require 'net/ssh/transport/cipher_factory' require 'net/ssh/transport/hmac' module Net; module SSH; module Transport # 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. class State # The socket object that owns this state object. attr_reader :socket # The next packet sequence number for this socket endpoint. attr_reader :sequence_number # The hmac algorithm in use for this endpoint. attr_reader :hmac # The compression algorithm in use for this endpoint. attr_reader :compression # The compression level to use when compressing data (or nil, for the default). attr_reader :compression_level # The number of packets processed since the last call to #reset! attr_reader :packets # The number of data blocks processed since the last call to #reset! attr_reader :blocks # The cipher algorithm in use for this socket endpoint. attr_reader :cipher # The block size for the cipher attr_reader :block_size # The role that this state plays (either :client or :server) attr_reader :role # The maximum number of packets that this endpoint wants to process before # needing a rekey. attr_accessor :max_packets # The maximum number of blocks that this endpoint wants to process before # needing a rekey. attr_accessor :max_blocks # The user-specified maximum number of bytes that this endpoint ought to # process before needing a rekey. attr_accessor :rekey_limit # Creates a new state object, belonging to the given socket. Initializes # the algorithms to "none". 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 # A convenience method for quickly setting multiple values in a single # command. def set(values) values.each do |key, value| instance_variable_set("@#{key}", value) end reset! end def update_cipher(data) result = cipher.update(data) update_next_iv(role == :client ? result : data) return result end def final_cipher result = cipher.final update_next_iv(role == :client ? result : "", true) return result 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. def increment(packet_length) @sequence_number = (@sequence_number + 1) & 0xFFFFFFFF @packets += 1 @blocks += (packet_length + 4) / @block_size end # The compressor object to use when compressing data. This takes into account # the desired compression level. def compressor @compressor ||= Zlib::Deflate.new(compression_level || Zlib::DEFAULT_COMPRESSION) end # The decompressor object to use when decompressing data. def decompressor @decompressor ||= Zlib::Inflate.new(nil) 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. def compression? compression == :standard || (compression == :delayed && socket.hints[:authenticated]) 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. def compress(data) data = data.to_s return data unless compression? compressor.deflate(data, Zlib::SYNC_FLUSH) 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. def decompress(data) data = data.to_s return data unless compression? decompressor.inflate(data) 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. 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 # Closes any the compressor and/or decompressor objects that have been # instantiated. 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 # 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. def needs_rekey? max_packets && packets > max_packets || max_blocks && blocks > max_blocks end private def update_next_iv(data, reset=false) @next_iv << data @next_iv = @next_iv[-cipher.iv_len..-1] if reset cipher.reset cipher.iv = @next_iv end return data end end end; end; end net-ssh-2.6.8/lib/net/ssh/transport/kex.rb0000644000004100000410000000223112166626376020456 0ustar www-datawww-datarequire 'net/ssh/transport/kex/diffie_hellman_group1_sha1' require 'net/ssh/transport/kex/diffie_hellman_group14_sha1' require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha1' require 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha256' module Net::SSH::Transport module Kex # Maps the supported key-exchange algorithms as named by the SSH protocol # to their corresponding implementors. MAP = { 'diffie-hellman-group-exchange-sha1' => DiffieHellmanGroupExchangeSHA1, 'diffie-hellman-group1-sha1' => DiffieHellmanGroup1SHA1, 'diffie-hellman-group14-sha1' => DiffieHellmanGroup14SHA1, } if defined?(DiffieHellmanGroupExchangeSHA256) MAP['diffie-hellman-group-exchange-sha256'] = DiffieHellmanGroupExchangeSHA256 end if defined?(OpenSSL::PKey::EC) require 'net/ssh/transport/kex/ecdh_sha2_nistp256' require 'net/ssh/transport/kex/ecdh_sha2_nistp384' require 'net/ssh/transport/kex/ecdh_sha2_nistp521' MAP['ecdh-sha2-nistp256'] = EcdhSHA2NistP256 MAP['ecdh-sha2-nistp384'] = EcdhSHA2NistP384 MAP['ecdh-sha2-nistp521'] = EcdhSHA2NistP521 end end end net-ssh-2.6.8/lib/net/ssh/transport/constants.rb0000644000004100000410000000123512166626376021706 0ustar www-datawww-datamodule Net; module SSH; module Transport module Constants #-- # Transport layer generic messages #++ DISCONNECT = 1 IGNORE = 2 UNIMPLEMENTED = 3 DEBUG = 4 SERVICE_REQUEST = 5 SERVICE_ACCEPT = 6 #-- # Algorithm negotiation messages #++ KEXINIT = 20 NEWKEYS = 21 #-- # Key exchange method specific messages #++ KEXDH_INIT = 30 KEXDH_REPLY = 31 KEXECDH_INIT = 30 KEXECDH_REPLY = 31 end end; end; end net-ssh-2.6.8/lib/net/ssh/transport/packet_stream.rb0000644000004100000410000001763612166626376022530 0ustar www-datawww-datarequire 'net/ssh/buffered_io' require 'net/ssh/errors' require 'net/ssh/packet' require 'net/ssh/ruby_compat' require 'net/ssh/transport/cipher_factory' require 'net/ssh/transport/hmac' require 'net/ssh/transport/state' module Net; module SSH; module Transport # A module that builds additional functionality onto the Net::SSH::BufferedIo # module. It adds SSH encryption, compression, and packet validation, as # per the SSH2 protocol. It also adds an abstraction for polling packets, # to allow for both blocking and non-blocking reads. module PacketStream include BufferedIo def self.extended(object) object.__send__(:initialize_ssh) end # The map of "hints" that can be used to modify the behavior of the packet # stream. For instance, when authentication succeeds, an "authenticated" # hint is set, which is used to determine whether or not to compress the # data when using the "delayed" compression algorithm. attr_reader :hints # The server state object, which encapsulates the algorithms used to interpret # packets coming from the server. attr_reader :server # The client state object, which encapsulates the algorithms used to build # packets to send to the server. attr_reader :client # The name of the client (local) end of the socket, as reported by the # socket. def client_name @client_name ||= begin sockaddr = getsockname begin Socket.getnameinfo(sockaddr, Socket::NI_NAMEREQD).first rescue begin Socket.getnameinfo(sockaddr).first rescue begin Socket.gethostbyname(Socket.gethostname).first rescue lwarn { "the client ipaddr/name could not be determined" } "unknown" end end end end end # The IP address of the peer (remote) end of the socket, as reported by # the socket. def peer_ip @peer_ip ||= if respond_to?(:getpeername) addr = getpeername Socket.getnameinfo(addr, Socket::NI_NUMERICHOST | Socket::NI_NUMERICSERV).first else "" end end # Returns true if the IO is available for reading, and false otherwise. def available_for_read? result = Net::SSH::Compat.io_select([self], nil, nil, 0) result && result.first.any? end # Returns the next full packet. If the mode parameter is :nonblock (the # default), then this will return immediately, whether a packet is # available or not, and will return nil if there is no packet ready to be # returned. If the mode parameter is :block, then this method will block # until a packet is available. def next_packet(mode=:nonblock) case mode when :nonblock then if available_for_read? if fill <= 0 raise Net::SSH::Disconnect, "connection closed by remote host" end end poll_next_packet when :block then loop do packet = poll_next_packet return packet if packet loop do result = Net::SSH::Compat.io_select([self]) or next break if result.first.any? end if fill <= 0 raise Net::SSH::Disconnect, "connection closed by remote host" end end else raise ArgumentError, "expected :block or :nonblock, got #{mode.inspect}" end end # Enqueues a packet to be sent, and blocks until the entire packet is # sent. def send_packet(payload) enqueue_packet(payload) wait_for_pending_sends end # Enqueues a packet to be sent, but does not immediately send the packet. # The given payload is pre-processed according to the algorithms specified # in the client state (compression, cipher, and hmac). def enqueue_packet(payload) # try to compress the packet payload = client.compress(payload) # the length of the packet, minus the padding actual_length = 4 + payload.bytesize + 1 # compute the padding length padding_length = client.block_size - (actual_length % client.block_size) padding_length += client.block_size if padding_length < 4 # compute the packet length (sans the length field itself) packet_length = payload.bytesize + padding_length + 1 if packet_length < 16 padding_length += client.block_size packet_length = payload.bytesize + padding_length + 1 end padding = Array.new(padding_length) { rand(256) }.pack("C*") unencrypted_data = [packet_length, padding_length, payload, padding].pack("NCA*A*") mac = client.hmac.digest([client.sequence_number, unencrypted_data].pack("NA*")) encrypted_data = client.update_cipher(unencrypted_data) << client.final_cipher message = encrypted_data + mac debug { "queueing packet nr #{client.sequence_number} type #{payload.getbyte(0)} len #{packet_length}" } enqueue(message) client.increment(packet_length) self end # Performs any pending cleanup necessary on the IO and its associated # state objects. (See State#cleanup). def cleanup client.cleanup server.cleanup end # If the IO object requires a rekey operation (as indicated by either its # client or server state objects, see State#needs_rekey?), this will # yield. Otherwise, this does nothing. def if_needs_rekey? if client.needs_rekey? || server.needs_rekey? yield client.reset! if client.needs_rekey? server.reset! if server.needs_rekey? end end protected # Called when this module is used to extend an object. It initializes # the states and generally prepares the object for use as a packet stream. def initialize_ssh @hints = {} @server = State.new(self, :server) @client = State.new(self, :client) @packet = nil initialize_buffered_io end # Tries to read the next packet. If there is insufficient data to read # an entire packet, this returns immediately, otherwise the packet is # read, post-processed according to the cipher, hmac, and compression # algorithms specified in the server state object, and returned as a # new Packet object. def poll_next_packet if @packet.nil? minimum = server.block_size < 4 ? 4 : server.block_size return nil if available < minimum data = read_available(minimum) # decipher it @packet = Net::SSH::Buffer.new(server.update_cipher(data)) @packet_length = @packet.read_long end need = @packet_length + 4 - server.block_size raise Net::SSH::Exception, "padding error, need #{need} block #{server.block_size}" if need % server.block_size != 0 return nil if available < need + server.hmac.mac_length if need > 0 # read the remainder of the packet and decrypt it. data = read_available(need) @packet.append(server.update_cipher(data)) end # get the hmac from the tail of the packet (if one exists), and # then validate it. real_hmac = read_available(server.hmac.mac_length) || "" @packet.append(server.final_cipher) padding_length = @packet.read_byte payload = @packet.read(@packet_length - padding_length - 1) my_computed_hmac = server.hmac.digest([server.sequence_number, @packet.content].pack("NA*")) raise Net::SSH::Exception, "corrupted mac detected" if real_hmac != my_computed_hmac # try to decompress the payload, in case compression is active payload = server.decompress(payload) debug { "received packet nr #{server.sequence_number} type #{payload.getbyte(0)} len #{@packet_length}" } server.increment(@packet_length) @packet = nil return Packet.new(payload) end end end; end; end net-ssh-2.6.8/lib/net/ssh/transport/ctr.rb0000644000004100000410000000354212166626376020465 0ustar www-datawww-datarequire 'openssl' module Net::SSH::Transport # Pure-Ruby implementation of Stateful Decryption Counter(SDCTR) Mode # for Block Ciphers. See RFC4344 for detail. module CTR def self.extended(orig) orig.instance_eval { @remaining = "" @counter = nil @counter_len = orig.block_size orig.encrypt orig.padding = 0 } class <= block_size encrypted += xor!(@remaining.slice!(0, block_size), _update(@counter)) increment_counter! end encrypted end def final unless @remaining.empty? s = xor!(@remaining, _update(@counter)) else s = "" end @remaining = "" s end private def xor!(s1, s2) s = [] s1.unpack('Q*').zip(s2.unpack('Q*')) {|a,b| s.push(a^b) } s.pack('Q*') end def increment_counter! c = @counter_len while ((c -= 1) > 0) if @counter.setbyte(c, (@counter.getbyte(c) + 1) & 0xff) != 0 break end end end end end end end net-ssh-2.6.8/lib/net/ssh/transport/hmac/0000755000004100000410000000000012166626376020254 5ustar www-datawww-datanet-ssh-2.6.8/lib/net/ssh/transport/hmac/md5_96.rb0000644000004100000410000000032112166626376021600 0ustar www-datawww-datarequire 'net/ssh/transport/hmac/md5' module Net::SSH::Transport::HMAC # The MD5-96 HMAC algorithm. This returns only the first 12 bytes of # the digest. class MD5_96 < MD5 mac_length 12 end end net-ssh-2.6.8/lib/net/ssh/transport/hmac/abstract.rb0000644000004100000410000000405412166626376022407 0ustar www-datawww-datarequire 'openssl' require 'openssl/digest' module Net; module SSH; module Transport; module HMAC # The base class of all OpenSSL-based HMAC algorithm wrappers. class Abstract class < %w(ssh-rsa ssh-dss), :kex => %w(diffie-hellman-group-exchange-sha1 diffie-hellman-group1-sha1 diffie-hellman-group14-sha1 diffie-hellman-group-exchange-sha256), :encryption => %w(aes128-cbc 3des-cbc blowfish-cbc cast128-cbc aes192-cbc aes256-cbc rijndael-cbc@lysator.liu.se idea-cbc none arcfour128 arcfour256 arcfour aes128-ctr aes192-ctr aes256-ctr camellia128-cbc camellia192-cbc camellia256-cbc camellia128-cbc@openssh.org camellia192-cbc@openssh.org camellia256-cbc@openssh.org camellia128-ctr camellia192-ctr camellia256-ctr camellia128-ctr@openssh.org camellia192-ctr@openssh.org camellia256-ctr@openssh.org cast128-ctr blowfish-ctr 3des-ctr ), :hmac => %w(hmac-sha1 hmac-md5 hmac-sha1-96 hmac-md5-96 hmac-ripemd160 hmac-ripemd160@openssh.com hmac-sha2-256 hmac-sha2-512 hmac-sha2-256-96 hmac-sha2-512-96 none), :compression => %w(none zlib@openssh.com zlib), :language => %w() } if defined?(OpenSSL::PKey::EC) ALGORITHMS[:host_key] += %w(ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521) ALGORITHMS[:kex] += %w(ecdh-sha2-nistp256 ecdh-sha2-nistp384 ecdh-sha2-nistp521) end # The underlying transport layer session that supports this object attr_reader :session # The hash of options used to initialize this object attr_reader :options # The kex algorithm to use settled on between the client and server. attr_reader :kex # The type of host key that will be used for this session. attr_reader :host_key # The type of the cipher to use to encrypt packets sent from the client to # the server. attr_reader :encryption_client # The type of the cipher to use to decrypt packets arriving from the server. attr_reader :encryption_server # The type of HMAC to use to sign packets sent by the client. attr_reader :hmac_client # The type of HMAC to use to validate packets arriving from the server. attr_reader :hmac_server # The type of compression to use to compress packets being sent by the client. attr_reader :compression_client # The type of compression to use to decompress packets arriving from the server. attr_reader :compression_server # The language that will be used in messages sent by the client. attr_reader :language_client # The language that will be used in messages sent from the server. attr_reader :language_server # The hash of algorithms preferred by the client, which will be told to # the server during algorithm negotiation. attr_reader :algorithms # The session-id for this session, as decided during the initial key exchange. attr_reader :session_id # Returns true if the given packet can be processed during a key-exchange. def self.allowed_packet?(packet) ( 1.. 4).include?(packet.type) || ( 6..19).include?(packet.type) || (21..49).include?(packet.type) end # Instantiates a new Algorithms object, and prepares the hash of preferred # algorithms based on the options parameter and the ALGORITHMS constant. def initialize(session, options={}) @session = session @logger = session.logger @options = options @algorithms = {} @pending = @initialized = false @client_packet = @server_packet = nil prepare_preferred_algorithms! end # Request a rekey operation. This will return immediately, and does not # actually perform the rekey operation. It does cause the session to change # state, however--until the key exchange finishes, no new packets will be # processed. def rekey! @client_packet = @server_packet = nil @initialized = false send_kexinit end # Called by the transport layer when a KEXINIT packet is recieved, indicating # that the server wants to exchange keys. This can be spontaneous, or it # can be in response to a client-initiated rekey request (see #rekey!). Either # way, this will block until the key exchange completes. def accept_kexinit(packet) info { "got KEXINIT from server" } @server_data = parse_server_algorithm_packet(packet) @server_packet = @server_data[:raw] if !pending? send_kexinit else proceed! end end # A convenience method for accessing the list of preferred types for a # specific algorithm (see #algorithms). def [](key) algorithms[key] end # Returns +true+ if a key-exchange is pending. This will be true from the # moment either the client or server requests the key exchange, until the # exchange completes. While an exchange is pending, only a limited number # of packets are allowed, so event processing essentially stops during this # period. def pending? @pending end # Returns true if no exchange is pending, and otherwise returns true or # false depending on whether the given packet is of a type that is allowed # during a key exchange. def allow?(packet) !pending? || Algorithms.allowed_packet?(packet) end # Returns true if the algorithms have been negotiated at all. def initialized? @initialized end private # Sends a KEXINIT packet to the server. If a server KEXINIT has already # been received, this will then invoke #proceed! to proceed with the key # exchange, otherwise it returns immediately (but sets the object to the # pending state). def send_kexinit info { "sending KEXINIT" } @pending = true packet = build_client_algorithm_packet @client_packet = packet.to_s session.send_message(packet) proceed! if @server_packet end # After both client and server have sent their KEXINIT packets, this # will do the algorithm negotiation and key exchange. Once both finish, # the object leaves the pending state and the method returns. def proceed! info { "negotiating algorithms" } negotiate_algorithms exchange_keys @pending = false end # Prepares the list of preferred algorithms, based on the options hash # that was given when the object was constructed, and the ALGORITHMS # constant. Also, when determining the host_key type to use, the known # hosts files are examined to see if the host has ever sent a host_key # before, and if so, that key type is used as the preferred type for # communicating with this server. def prepare_preferred_algorithms! options[:compression] = %w(zlib@openssh.com zlib) if options[:compression] == true ALGORITHMS.each do |algorithm, list| algorithms[algorithm] = list.dup # apply the preferred algorithm order, if any if options[algorithm] algorithms[algorithm] = Array(options[algorithm]).compact.uniq invalid = algorithms[algorithm].detect { |name| !ALGORITHMS[algorithm].include?(name) } raise NotImplementedError, "unsupported #{algorithm} algorithm: `#{invalid}'" if invalid # make sure all of our supported algorithms are tacked onto the # end, so that if the user tries to give a list of which none are # supported, we can still proceed. list.each { |name| algorithms[algorithm] << name unless algorithms[algorithm].include?(name) } end end # for convention, make sure our list has the same keys as the server # list algorithms[:encryption_client ] = algorithms[:encryption_server ] = algorithms[:encryption] algorithms[:hmac_client ] = algorithms[:hmac_server ] = algorithms[:hmac] algorithms[:compression_client] = algorithms[:compression_server] = algorithms[:compression] algorithms[:language_client ] = algorithms[:language_server ] = algorithms[:language] if !options.key?(:host_key) # make sure the host keys are specified in preference order, where any # existing known key for the host has preference. existing_keys = KnownHosts.search_for(options[:host_key_alias] || session.host_as_string, options) host_keys = existing_keys.map { |key| key.ssh_type }.uniq algorithms[:host_key].each do |name| host_keys << name unless host_keys.include?(name) end algorithms[:host_key] = host_keys end end # Parses a KEXINIT packet from the server. def parse_server_algorithm_packet(packet) data = { :raw => packet.content } packet.read(16) # skip the cookie value data[:kex] = packet.read_string.split(/,/) data[:host_key] = packet.read_string.split(/,/) data[:encryption_client] = packet.read_string.split(/,/) data[:encryption_server] = packet.read_string.split(/,/) data[:hmac_client] = packet.read_string.split(/,/) data[:hmac_server] = packet.read_string.split(/,/) data[:compression_client] = packet.read_string.split(/,/) data[:compression_server] = packet.read_string.split(/,/) data[:language_client] = packet.read_string.split(/,/) data[:language_server] = packet.read_string.split(/,/) # TODO: if first_kex_packet_follows, we need to try to skip the # actual kexinit stuff and try to guess what the server is doing... # need to read more about this scenario. # first_kex_packet_follows = packet.read_bool return data end # Given the #algorithms map of preferred algorithm types, this constructs # a KEXINIT packet to send to the server. It does not actually send it, # it simply builds the packet and returns it. def build_client_algorithm_packet kex = algorithms[:kex ].join(",") host_key = algorithms[:host_key ].join(",") encryption = algorithms[:encryption ].join(",") hmac = algorithms[:hmac ].join(",") compression = algorithms[:compression].join(",") language = algorithms[:language ].join(",") Net::SSH::Buffer.from(:byte, KEXINIT, :long, [rand(0xFFFFFFFF), rand(0xFFFFFFFF), rand(0xFFFFFFFF), rand(0xFFFFFFFF)], :string, [kex, host_key, encryption, encryption, hmac, hmac], :string, [compression, compression, language, language], :bool, false, :long, 0) end # Given the parsed server KEX packet, and the client's preferred algorithm # lists in #algorithms, determine which preferred algorithms each has # in common and set those as the selected algorithms. If, for any algorithm, # no type can be settled on, an exception is raised. def negotiate_algorithms @kex = negotiate(:kex) @host_key = negotiate(:host_key) @encryption_client = negotiate(:encryption_client) @encryption_server = negotiate(:encryption_server) @hmac_client = negotiate(:hmac_client) @hmac_server = negotiate(:hmac_server) @compression_client = negotiate(:compression_client) @compression_server = negotiate(:compression_server) @language_client = negotiate(:language_client) rescue "" @language_server = negotiate(:language_server) rescue "" debug do "negotiated:\n" + [:kex, :host_key, :encryption_server, :encryption_client, :hmac_client, :hmac_server, :compression_client, :compression_server, :language_client, :language_server].map do |key| "* #{key}: #{instance_variable_get("@#{key}")}" end.join("\n") end end # Negotiates a single algorithm based on the preferences reported by the # server and those set by the client. This is called by # #negotiate_algorithms. def negotiate(algorithm) match = self[algorithm].find { |item| @server_data[algorithm].include?(item) } if match.nil? raise Net::SSH::Exception, "could not settle on #{algorithm} algorithm" end return match end # Considers the sizes of the keys and block-sizes for the selected ciphers, # and the lengths of the hmacs, and returns the largest as the byte requirement # for the key-exchange algorithm. def kex_byte_requirement sizes = [8] # require at least 8 bytes sizes.concat(CipherFactory.get_lengths(encryption_client)) sizes.concat(CipherFactory.get_lengths(encryption_server)) sizes << HMAC.key_length(hmac_client) sizes << HMAC.key_length(hmac_server) sizes.max end # Instantiates one of the Transport::Kex classes (based on the negotiated # kex algorithm), and uses it to exchange keys. Then, the ciphers and # HMACs are initialized and fed to the transport layer, to be used in # further communication with the server. def exchange_keys debug { "exchanging keys" } algorithm = Kex::MAP[kex].new(self, session, :client_version_string => Net::SSH::Transport::ServerVersion::PROTO_VERSION, :server_version_string => session.server_version.version, :server_algorithm_packet => @server_packet, :client_algorithm_packet => @client_packet, :need_bytes => kex_byte_requirement, :logger => logger) result = algorithm.exchange_keys secret = result[:shared_secret].to_ssh hash = result[:session_id] digester = result[:hashing_algorithm] @session_id ||= hash key = Proc.new { |salt| digester.digest(secret + hash + salt + @session_id) } iv_client = key["A"] iv_server = key["B"] key_client = key["C"] key_server = key["D"] mac_key_client = key["E"] mac_key_server = key["F"] parameters = { :shared => secret, :hash => hash, :digester => digester } cipher_client = CipherFactory.get(encryption_client, parameters.merge(:iv => iv_client, :key => key_client, :encrypt => true)) cipher_server = CipherFactory.get(encryption_server, parameters.merge(:iv => iv_server, :key => key_server, :decrypt => true)) mac_client = HMAC.get(hmac_client, mac_key_client, parameters) mac_server = HMAC.get(hmac_server, mac_key_server, parameters) session.configure_client :cipher => cipher_client, :hmac => mac_client, :compression => normalize_compression_name(compression_client), :compression_level => options[:compression_level], :rekey_limit => options[:rekey_limit], :max_packets => options[:rekey_packet_limit], :max_blocks => options[:rekey_blocks_limit] session.configure_server :cipher => cipher_server, :hmac => mac_server, :compression => normalize_compression_name(compression_server), :rekey_limit => options[:rekey_limit], :max_packets => options[:rekey_packet_limit], :max_blocks => options[:rekey_blocks_limit] @initialized = true end # Given the SSH name for some compression algorithm, return a normalized # name as a symbol. def normalize_compression_name(name) case name when "none" then false when "zlib" then :standard when "zlib@openssh.com" then :delayed else raise ArgumentError, "unknown compression type `#{name}'" end end end end; end; end net-ssh-2.6.8/lib/net/ssh/transport/hmac.rb0000644000004100000410000000362712166626376020611 0ustar www-datawww-datarequire 'net/ssh/transport/key_expander' require 'net/ssh/transport/hmac/md5' require 'net/ssh/transport/hmac/md5_96' require 'net/ssh/transport/hmac/sha1' require 'net/ssh/transport/hmac/sha1_96' require 'net/ssh/transport/hmac/sha2_256' require 'net/ssh/transport/hmac/sha2_256_96' require 'net/ssh/transport/hmac/sha2_512' require 'net/ssh/transport/hmac/sha2_512_96' require 'net/ssh/transport/hmac/ripemd160' require 'net/ssh/transport/hmac/none' # Implements a simple factory interface for fetching hmac implementations, or # for finding the key lengths for hmac implementations.s module Net::SSH::Transport::HMAC # The mapping of SSH hmac algorithms to their implementations MAP = { 'hmac-md5' => MD5, 'hmac-md5-96' => MD5_96, 'hmac-sha1' => SHA1, 'hmac-sha1-96' => SHA1_96, 'hmac-ripemd160' => RIPEMD160, 'hmac-ripemd160@openssh.com' => RIPEMD160, 'none' => None } # add mapping to sha2 hmac algorithms if they're available MAP['hmac-sha2-256'] = SHA2_256 if defined?(::Net::SSH::Transport::HMAC::SHA2_256) MAP['hmac-sha2-256-96'] = SHA2_256_96 if defined?(::Net::SSH::Transport::HMAC::SHA2_256_96) MAP['hmac-sha2-512'] = SHA2_512 if defined?(::Net::SSH::Transport::HMAC::SHA2_512) MAP['hmac-sha2-512-96'] = SHA2_512_96 if defined?(::Net::SSH::Transport::HMAC::SHA2_512_96) # Retrieves a new hmac instance of the given SSH type (+name+). If +key+ is # given, the new instance will be initialized with that key. def self.get(name, key="", parameters = {}) impl = MAP[name] or raise ArgumentError, "hmac not found: #{name.inspect}" impl.new(Net::SSH::Transport::KeyExpander.expand_key(impl.key_length, key, parameters)) end # Retrieves the key length for the hmac of the given SSH type (+name+). def self.key_length(name) impl = MAP[name] or raise ArgumentError, "hmac not found: #{name.inspect}" impl.key_length end end net-ssh-2.6.8/lib/net/ssh/transport/kex/0000755000004100000410000000000012166626376020133 5ustar www-datawww-datanet-ssh-2.6.8/lib/net/ssh/transport/kex/ecdh_sha2_nistp521.rb0000644000004100000410000000056412166626376023752 0ustar www-datawww-datamodule Net; module SSH; module Transport; module Kex # A key-exchange service implementing the "ecdh-sha2-nistp521" # key-exchange algorithm. (defined in RFC 5656) class EcdhSHA2NistP521 < EcdhSHA2NistP256 def digester OpenSSL::Digest::SHA512 end def curve_name OpenSSL::PKey::EC::CurveNameAlias['nistp521'] end end end; end; end; end net-ssh-2.6.8/lib/net/ssh/transport/kex/diffie_hellman_group1_sha1.rb0000644000004100000410000001560612166626376025627 0ustar www-datawww-datarequire 'net/ssh/buffer' require 'net/ssh/errors' require 'net/ssh/loggable' require 'net/ssh/transport/openssl' require 'net/ssh/transport/constants' module Net; module SSH; module Transport; module Kex # A key-exchange service implementing the "diffie-hellman-group1-sha1" # key-exchange algorithm. class DiffieHellmanGroup1SHA1 include Constants, Loggable # The value of 'P', as a string, in hexadecimal P_s = "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" + "C4C6628B" "80DC1CD1" "29024E08" "8A67CC74" + "020BBEA6" "3B139B22" "514A0879" "8E3404DD" + "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" + "4FE1356D" "6D51C245" "E485B576" "625E7EC6" + "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" + "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" + "49286651" "ECE65381" "FFFFFFFF" "FFFFFFFF" # The radix in which P_s represents the value of P P_r = 16 # The group constant G = 2 attr_reader :p attr_reader :g attr_reader :digester attr_reader :algorithms attr_reader :connection attr_reader :data attr_reader :dh # Create a new instance of the DiffieHellmanGroup1SHA1 algorithm. # The data is a Hash of symbols representing information # required by this algorithm, which was acquired during earlier # processing. def initialize(algorithms, connection, data) @p = get_p @g = get_g @digester = OpenSSL::Digest::SHA1 @algorithms = algorithms @connection = connection @data = data.dup @dh = generate_key @logger = @data.delete(:logger) end # Perform the key-exchange for the given session, with the given # data. This method will return a hash consisting of the # following keys: # # * :session_id # * :server_key # * :shared_secret # * :hashing_algorithm # # The caller is expected to be able to understand how to use these # deliverables. def exchange_keys result = send_kexinit verify_server_key(result[:server_key]) session_id = verify_signature(result) confirm_newkeys return { :session_id => session_id, :server_key => result[:server_key], :shared_secret => result[:shared_secret], :hashing_algorithm => digester } end private def get_p OpenSSL::BN.new(P_s, P_r) end def get_g G end # Returns the DH key parameters for the current connection. def get_parameters [p, g] end # Returns the INIT/REPLY constants used by this algorithm. def get_message_types [KEXDH_INIT, KEXDH_REPLY] end # Build the signature buffer to use when verifying a signature from # the server. def build_signature_buffer(result) response = Net::SSH::Buffer.new response.write_string data[:client_version_string], data[:server_version_string], data[:client_algorithm_packet], data[:server_algorithm_packet], result[:key_blob] response.write_bignum dh.pub_key, result[:server_dh_pubkey], result[:shared_secret] response end # Generate a DH key with a private key consisting of the given # number of bytes. def generate_key #:nodoc: dh = OpenSSL::PKey::DH.new dh.p, dh.g = get_parameters dh.priv_key = OpenSSL::BN.rand(data[:need_bytes] * 8) dh.generate_key! until dh.valid? dh end # Send the KEXDH_INIT message, and expect the KEXDH_REPLY. Return the # resulting buffer. # # Parse the buffer from a KEXDH_REPLY message, returning a hash of # the extracted values. def send_kexinit #:nodoc: init, reply = get_message_types # send the KEXDH_INIT message buffer = Net::SSH::Buffer.from(:byte, init, :bignum, dh.pub_key) connection.send_message(buffer) # expect the KEXDH_REPLY message buffer = connection.next_message raise Net::SSH::Exception, "expected REPLY" unless buffer.type == reply result = Hash.new result[:key_blob] = buffer.read_string result[:server_key] = Net::SSH::Buffer.new(result[:key_blob]).read_key result[:server_dh_pubkey] = buffer.read_bignum result[:shared_secret] = OpenSSL::BN.new(dh.compute_key(result[:server_dh_pubkey]), 2) sig_buffer = Net::SSH::Buffer.new(buffer.read_string) sig_type = sig_buffer.read_string if sig_type != algorithms.host_key raise Net::SSH::Exception, "host key algorithm mismatch for signature " + "'#{sig_type}' != '#{algorithms.host_key}'" end result[:server_sig] = sig_buffer.read_string return result end # Verify that the given key is of the expected type, and that it # really is the key for the session's host. Raise Net::SSH::Exception # if it is not. def verify_server_key(key) #:nodoc: if key.ssh_type != algorithms.host_key raise Net::SSH::Exception, "host key algorithm mismatch " + "'#{key.ssh_type}' != '#{algorithms.host_key}'" end blob, fingerprint = generate_key_fingerprint(key) unless connection.host_key_verifier.verify(:key => key, :key_blob => blob, :fingerprint => fingerprint, :session => connection) raise Net::SSH::Exception, "host key verification failed" end end def generate_key_fingerprint(key) blob = Net::SSH::Buffer.from(:key, key).to_s fingerprint = OpenSSL::Digest::MD5.hexdigest(blob).scan(/../).join(":") [blob, fingerprint] rescue ::Exception => e [nil, "(could not generate fingerprint: #{e.message})"] end # Verify the signature that was received. Raise Net::SSH::Exception # if the signature could not be verified. Otherwise, return the new # session-id. def verify_signature(result) #:nodoc: response = build_signature_buffer(result) hash = @digester.digest(response.to_s) unless result[:server_key].ssh_do_verify(result[:server_sig], hash) raise Net::SSH::Exception, "could not verify server signature" end return hash end # Send the NEWKEYS message, and expect the NEWKEYS message in # reply. def confirm_newkeys #:nodoc: # send own NEWKEYS message first (the wodSSHServer won't send first) response = Net::SSH::Buffer.new response.write_byte(NEWKEYS) connection.send_message(response) # wait for the server's NEWKEYS message buffer = connection.next_message raise Net::SSH::Exception, "expected NEWKEYS" unless buffer.type == NEWKEYS end end end; end; end; end net-ssh-2.6.8/lib/net/ssh/transport/kex/ecdh_sha2_nistp384.rb0000644000004100000410000000056412166626376023761 0ustar www-datawww-datamodule Net; module SSH; module Transport; module Kex # A key-exchange service implementing the "ecdh-sha2-nistp256" # key-exchange algorithm. (defined in RFC 5656) class EcdhSHA2NistP384 < EcdhSHA2NistP256 def digester OpenSSL::Digest::SHA384 end def curve_name OpenSSL::PKey::EC::CurveNameAlias['nistp384'] end end end; end; end; end net-ssh-2.6.8/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha1.rb0000644000004100000410000000502612166626376027403 0ustar www-datawww-datarequire 'net/ssh/errors' require 'net/ssh/transport/constants' require 'net/ssh/transport/kex/diffie_hellman_group1_sha1' module Net::SSH::Transport::Kex # A key-exchange service implementing the # "diffie-hellman-group-exchange-sha1" key-exchange algorithm. class DiffieHellmanGroupExchangeSHA1 < DiffieHellmanGroup1SHA1 MINIMUM_BITS = 1024 MAXIMUM_BITS = 8192 KEXDH_GEX_GROUP = 31 KEXDH_GEX_INIT = 32 KEXDH_GEX_REPLY = 33 KEXDH_GEX_REQUEST = 34 private # Compute the number of bits needed for the given number of bytes. def compute_need_bits # for Compatibility: OpenSSH requires (need_bits * 2 + 1) length of parameter need_bits = data[:need_bytes] * 8 * 2 + 1 if need_bits < MINIMUM_BITS need_bits = MINIMUM_BITS elsif need_bits > MAXIMUM_BITS need_bits = MAXIMUM_BITS end data[:need_bits ] = need_bits data[:need_bytes] = need_bits / 8 end # Returns the DH key parameters for the given session. def get_parameters compute_need_bits # request the DH key parameters for the given number of bits. buffer = Net::SSH::Buffer.from(:byte, KEXDH_GEX_REQUEST, :long, MINIMUM_BITS, :long, data[:need_bits], :long, MAXIMUM_BITS) connection.send_message(buffer) buffer = connection.next_message unless buffer.type == KEXDH_GEX_GROUP raise Net::SSH::Exception, "expected KEXDH_GEX_GROUP, got #{buffer.type}" end p = buffer.read_bignum g = buffer.read_bignum [p, g] end # Returns the INIT/REPLY constants used by this algorithm. def get_message_types [KEXDH_GEX_INIT, KEXDH_GEX_REPLY] end # Build the signature buffer to use when verifying a signature from # the server. def build_signature_buffer(result) response = Net::SSH::Buffer.new response.write_string data[:client_version_string], data[:server_version_string], data[:client_algorithm_packet], data[:server_algorithm_packet], result[:key_blob] response.write_long MINIMUM_BITS, data[:need_bits], MAXIMUM_BITS response.write_bignum dh.p, dh.g, dh.pub_key, result[:server_dh_pubkey], result[:shared_secret] response end end end net-ssh-2.6.8/lib/net/ssh/transport/kex/diffie_hellman_group_exchange_sha256.rb0000644000004100000410000000070412166626376027555 0ustar www-datawww-datarequire 'net/ssh/transport/kex/diffie_hellman_group_exchange_sha1' module Net::SSH::Transport::Kex if defined?(OpenSSL::Digest::SHA256) # A key-exchange service implementing the # "diffie-hellman-group-exchange-sha256" key-exchange algorithm. class DiffieHellmanGroupExchangeSHA256 < DiffieHellmanGroupExchangeSHA1 def initialize(*args) super(*args) @digester = OpenSSL::Digest::SHA256 end end end end net-ssh-2.6.8/lib/net/ssh/transport/kex/diffie_hellman_group14_sha1.rb0000644000004100000410000000274112166626376025707 0ustar www-datawww-datarequire 'net/ssh/transport/kex/diffie_hellman_group1_sha1' module Net; module SSH; module Transport; module Kex # A key-exchange service implementing the "diffie-hellman-group14-sha1" # key-exchange algorithm. (defined in RFC 4253) class DiffieHellmanGroup14SHA1 < DiffieHellmanGroup1SHA1 include Constants, Loggable # The value of 'P', as a string, in hexadecimal P_s = "FFFFFFFF" "FFFFFFFF" "C90FDAA2" "2168C234" + "C4C6628B" "80DC1CD1" "29024E08" "8A67CC74" + "020BBEA6" "3B139B22" "514A0879" "8E3404DD" + "EF9519B3" "CD3A431B" "302B0A6D" "F25F1437" + "4FE1356D" "6D51C245" "E485B576" "625E7EC6" + "F44C42E9" "A637ED6B" "0BFF5CB6" "F406B7ED" + "EE386BFB" "5A899FA5" "AE9F2411" "7C4B1FE6" + "49286651" "ECE45B3D" "C2007CB8" "A163BF05" + "98DA4836" "1C55D39A" "69163FA8" "FD24CF5F" + "83655D23" "DCA3AD96" "1C62F356" "208552BB" + "9ED52907" "7096966D" "670C354E" "4ABC9804" + "F1746C08" "CA18217C" "32905E46" "2E36CE3B" + "E39E772C" "180E8603" "9B2783A2" "EC07A28F" + "B5C55DF0" "6F4C52C9" "DE2BCBF6" "95581718" + "3995497C" "EA956AE5" "15D22618" "98FA0510" + "15728E5A" "8AACAA68" "FFFFFFFF" "FFFFFFFF" # The radix in which P_s represents the value of P P_r = 16 # The group constant G = 2 private def get_p OpenSSL::BN.new(P_s, P_r) end def get_g G end end end; end; end; end net-ssh-2.6.8/lib/net/ssh/transport/kex/ecdh_sha2_nistp256.rb0000644000004100000410000000605712166626376023762 0ustar www-datawww-datarequire 'net/ssh/transport/constants' require 'net/ssh/transport/kex/diffie_hellman_group1_sha1' module Net; module SSH; module Transport; module Kex # A key-exchange service implementing the "ecdh-sha2-nistp256" # key-exchange algorithm. (defined in RFC 5656) class EcdhSHA2NistP256 < DiffieHellmanGroup1SHA1 include Constants, Loggable attr_reader :ecdh def digester OpenSSL::Digest::SHA256 end def curve_name OpenSSL::PKey::EC::CurveNameAlias['nistp256'] end def initialize(algorithms, connection, data) @algorithms = algorithms @connection = connection @digester = digester @data = data.dup @ecdh = generate_key @logger = @data.delete(:logger) end private def get_message_types [KEXECDH_INIT, KEXECDH_REPLY] end def build_signature_buffer(result) response = Net::SSH::Buffer.new response.write_string data[:client_version_string], data[:server_version_string], data[:client_algorithm_packet], data[:server_algorithm_packet], result[:key_blob], ecdh.public_key.to_bn.to_s(2), result[:server_ecdh_pubkey] response.write_bignum result[:shared_secret] response end def generate_key #:nodoc: OpenSSL::PKey::EC.new(curve_name).generate_key end def send_kexinit #:nodoc: init, reply = get_message_types # send the KEXECDH_INIT message ## byte SSH_MSG_KEX_ECDH_INIT ## string Q_C, client's ephemeral public key octet string buffer = Net::SSH::Buffer.from(:byte, init, :string, ecdh.public_key.to_bn.to_s(2)) connection.send_message(buffer) # expect the following KEXECDH_REPLY message ## byte SSH_MSG_KEX_ECDH_REPLY ## string K_S, server's public host key ## string Q_S, server's ephemeral public key octet string ## string the signature on the exchange hash buffer = connection.next_message raise Net::SSH::Exception, "expected REPLY" unless buffer.type == reply result = Hash.new result[:key_blob] = buffer.read_string result[:server_key] = Net::SSH::Buffer.new(result[:key_blob]).read_key result[:server_ecdh_pubkey] = buffer.read_string # compute shared secret from server's public key and client's private key pk = OpenSSL::PKey::EC::Point.new(OpenSSL::PKey::EC.new(curve_name).group, OpenSSL::BN.new(result[:server_ecdh_pubkey], 2)) result[:shared_secret] = OpenSSL::BN.new(ecdh.dh_compute_key(pk), 2) sig_buffer = Net::SSH::Buffer.new(buffer.read_string) sig_type = sig_buffer.read_string if sig_type != algorithms.host_key raise Net::SSH::Exception, "host key algorithm mismatch for signature " + "'#{sig_type}' != '#{algorithms.host_key}'" end result[:server_sig] = sig_buffer.read_string return result end end end; end; end; end net-ssh-2.6.8/lib/net/ssh/known_hosts.rb0000644000004100000410000001121412166626376020210 0ustar www-datawww-datarequire 'strscan' require 'net/ssh/buffer' module Net; module SSH # Searches an OpenSSH-style known-host file for a given host, and returns all # matching keys. This is used to implement host-key verification, as well as # to determine what key a user prefers to use for a given host. # # This is used internally by Net::SSH, and will never need to be used directly # by consumers of the library. class KnownHosts if defined?(OpenSSL::PKey::EC) SUPPORTED_TYPE = %w(ssh-rsa ssh-dss ecdsa-sha2-nistp256 ecdsa-sha2-nistp384 ecdsa-sha2-nistp521) else SUPPORTED_TYPE = %w(ssh-rsa ssh-dss) end class <(version) to_i <=> version.to_i end # Converts this version object to a string, where each of the three # version components are joined by the '.' character. E.g., 2.0.0. def to_s @to_s ||= [@major, @minor, @tiny].join(".") end # Converts this version to a canonical integer that may be compared # against other version objects. def to_i @to_i ||= @major * 1_000_000 + @minor * 1_000 + @tiny end # The major component of this version of the Net::SSH library MAJOR = 2 # The minor component of this version of the Net::SSH library MINOR = 6 # The tiny component of this version of the Net::SSH library TINY = 8 # The current version of the Net::SSH library as a Version instance CURRENT = new(MAJOR, MINOR, TINY) # The current version of the Net::SSH library as a String STRING = CURRENT.to_s end end; end net-ssh-2.6.8/lib/net/ssh/test/0000755000004100000410000000000012166626376016267 5ustar www-datawww-datanet-ssh-2.6.8/lib/net/ssh/test/script.rb0000644000004100000410000001477512166626376020136 0ustar www-datawww-datarequire 'net/ssh/test/channel' require 'net/ssh/test/local_packet' require 'net/ssh/test/remote_packet' module Net; module SSH; module Test # Represents a sequence of scripted events that identify the behavior that # a test expects. Methods named "sends_*" create events for packets being # sent from the local to the remote host, and methods named "gets_*" create # events for packets being received by the local from the remote host. # # A reference to a script. is generally obtained in a unit test via the # Net::SSH::Test#story helper method: # # story do |script| # channel = script.opens_channel # ... # end class Script # The list of scripted events. These will be Net::SSH::Test::LocalPacket # and Net::SSH::Test::RemotePacket instances. attr_reader :events # Create a new, empty script. def initialize @events = [] end # Scripts the opening of a channel by adding a local packet sending the # channel open request, and if +confirm+ is true (the default), also # adding a remote packet confirming the new channel. # # A new Net::SSH::Test::Channel instance is returned, which can be used # to script additional channel operations. def opens_channel(confirm=true) channel = Channel.new(self) channel.remote_id = 5555 events << LocalPacket.new(:channel_open) { |p| channel.local_id = p[:remote_id] } if confirm events << RemotePacket.new(:channel_open_confirmation, channel.local_id, channel.remote_id, 0x20000, 0x10000) end channel end # A convenience method for adding an arbitrary local packet to the events # list. def sends(type, *args, &block) events << LocalPacket.new(type, *args, &block) end # A convenience method for adding an arbitrary remote packet to the events # list. def gets(type, *args) events << RemotePacket.new(type, *args) end # Scripts the sending of a new channel request packet to the remote host. # +channel+ should be an instance of Net::SSH::Test::Channel. +request+ # is a string naming the request type to send, +reply+ is a boolean # indicating whether a response to this packet is required , and +data+ # is any additional request-specific data that this packet should send. # +success+ indicates whether the response (if one is required) should be # success or failure. # # If a reply is desired, a remote packet will also be queued, :channel_success # if +success+ is true, or :channel_failure if +success+ is false. # # This will typically be called via Net::SSH::Test::Channel#sends_exec or # Net::SSH::Test::Channel#sends_subsystem. def sends_channel_request(channel, request, reply, data, success=true) events << LocalPacket.new(:channel_request, channel.remote_id, request, reply, data) if reply if success events << RemotePacket.new(:channel_success, channel.local_id) else events << RemotePacket.new(:channel_failure, channel.local_id) end end end # Scripts the sending of a channel data packet. +channel+ must be a # Net::SSH::Test::Channel object, and +data+ is the (string) data to # expect will be sent. # # This will typically be called via Net::SSH::Test::Channel#sends_data. def sends_channel_data(channel, data) events << LocalPacket.new(:channel_data, channel.remote_id, data) end # Scripts the sending of a channel EOF packet from the given # Net::SSH::Test::Channel +channel+. This will typically be called via # Net::SSH::Test::Channel#sends_eof. def sends_channel_eof(channel) events << LocalPacket.new(:channel_eof, channel.remote_id) end # Scripts the sending of a channel close packet from the given # Net::SSH::Test::Channel +channel+. This will typically be called via # Net::SSH::Test::Channel#sends_close. def sends_channel_close(channel) events << LocalPacket.new(:channel_close, channel.remote_id) end # Scripts the reception of a channel data packet from the remote host by # the given Net::SSH::Test::Channel +channel+. This will typically be # called via Net::SSH::Test::Channel#gets_data. def gets_channel_data(channel, data) events << RemotePacket.new(:channel_data, channel.local_id, data) end # Scripts the reception of a channel extended data packet from the remote # host by the given Net::SSH::Test::Channel +channel+. This will typically # be called via Net::SSH::Test::Channel#gets_extended_data. # # Currently the only extended data type is stderr == 1. def gets_channel_extended_data(channel, data) events << RemotePacket.new(:channel_extended_data, channel.local_id, 1, data) end # Scripts the reception of a channel request packet from the remote host by # the given Net::SSH::Test::Channel +channel+. This will typically be # called via Net::SSH::Test::Channel#gets_exit_status. def gets_channel_request(channel, request, reply, data) events << RemotePacket.new(:channel_request, channel.local_id, request, reply, data) end # Scripts the reception of a channel EOF packet from the remote host by # the given Net::SSH::Test::Channel +channel+. This will typically be # called via Net::SSH::Test::Channel#gets_eof. def gets_channel_eof(channel) events << RemotePacket.new(:channel_eof, channel.local_id) end # Scripts the reception of a channel close packet from the remote host by # the given Net::SSH::Test::Channel +channel+. This will typically be # called via Net::SSH::Test::Channel#gets_close. def gets_channel_close(channel) events << RemotePacket.new(:channel_close, channel.local_id) end # By default, removes the next event in the list and returns it. However, # this can also be used to non-destructively peek at the next event in the # list, by passing :first as the argument. # # # remove the next event and return it # event = script.next # # # peek at the next event # event = script.next(:first) def next(mode=:shift) events.send(mode) end # Compare the given packet against the next event in the list. If there is # no next event, an exception will be raised. This is called by # Net::SSH::Test::Extensions::PacketStream#test_enqueue_packet. def process(packet) event = events.shift or raise "end of script reached, but got a packet type #{packet.read_byte}" event.process(packet) end end end; end; endnet-ssh-2.6.8/lib/net/ssh/test/channel.rb0000644000004100000410000001114412166626376020225 0ustar www-datawww-datamodule Net; module SSH; module Test # A mock channel, used for scripting actions in tests. It wraps a # Net::SSH::Test::Script instance, and delegates to it for the most part. # This class has little real functionality on its own, but rather acts as # a convenience for scripting channel-related activity for later comparison # in a unit test. # # story do |session| # channel = session.opens_channel # channel.sends_exec "ls" # channel.gets_data "result of ls" # channel.gets_extended_data "some error coming from ls" # channel.gets_close # channel.sends_close # end class Channel # The Net::SSH::Test::Script instance employed by this mock channel. attr_reader :script # Sets the local-id of this channel object (the id assigned by the client). attr_writer :local_id # Sets the remote-id of this channel object (the id assigned by the mock-server). attr_writer :remote_id # Creates a new Test::Channel instance on top of the given +script+ (which # must be a Net::SSH::Test::Script instance). def initialize(script) @script = script @local_id = @remote_id = nil end # Returns the local (client-assigned) id for this channel, or a Proc object # that will return the local-id later if the local id has not yet been set. # (See Net::SSH::Test::Packet#instantiate!.) def local_id @local_id || Proc.new { @local_id or raise "local-id has not been set yet!" } end # Returns the remote (server-assigned) id for this channel, or a Proc object # that will return the remote-id later if the remote id has not yet been set. # (See Net::SSH::Test::Packet#instantiate!.) def remote_id @remote_id || Proc.new { @remote_id or raise "remote-id has not been set yet!" } end # Because adjacent calls to #gets_data will sometimes cause the data packets # to be concatenated (causing expectations in tests to fail), you may # need to separate those calls with calls to #inject_remote_delay! (which # essentially just mimics receiving an empty data packet): # # channel.gets_data "abcdefg" # channel.inject_remote_delay! # channel.gets_data "hijklmn" def inject_remote_delay! gets_data("") end # Scripts the sending of an "exec" channel request packet to the mock # server. If +reply+ is true, then the server is expected to reply to the # request, otherwise no response to this request will be sent. If +success+ # is +true+, then the request will be successful, otherwise a failure will # be scripted. # # channel.sends_exec "ls -l" def sends_exec(command, reply=true, success=true) script.sends_channel_request(self, "exec", reply, command, success) end # Scripts the sending of a "subsystem" channel request packet to the mock # server. See #sends_exec for a discussion of the meaning of the +reply+ # and +success+ arguments. # # channel.sends_subsystem "sftp" def sends_subsystem(subsystem, reply=true, success=true) script.sends_channel_request(self, "subsystem", reply, subsystem, success) end # Scripts the sending of a data packet across the channel. # # channel.sends_data "foo" def sends_data(data) script.sends_channel_data(self, data) end # Scripts the sending of an EOF packet across the channel. # # channel.sends_eof def sends_eof script.sends_channel_eof(self) end # Scripts the sending of a "channel close" packet across the channel. # # channel.sends_close def sends_close script.sends_channel_close(self) end # Scripts the reception of a channel data packet from the remote end. # # channel.gets_data "bar" def gets_data(data) script.gets_channel_data(self, data) end # Scripts the reception of a channel extended data packet from the remote # end. # # channel.gets_extended_data "whoops" def gets_extended_data(data) script.gets_channel_extended_data(self, data) end # Scripts the reception of an "exit-status" channel request packet. # # channel.gets_exit_status(127) def gets_exit_status(status=0) script.gets_channel_request(self, "exit-status", false, status) end # Scripts the reception of an EOF packet from the remote end. # # channel.gets_eof def gets_eof script.gets_channel_eof(self) end # Scripts the reception of a "channel close" packet from the remote end. # # channel.gets_close def gets_close script.gets_channel_close(self) end end end; end; endnet-ssh-2.6.8/lib/net/ssh/test/local_packet.rb0000644000004100000410000000333412166626376021240 0ustar www-datawww-datarequire 'net/ssh/packet' require 'net/ssh/test/packet' module Net; module SSH; module Test # This is a specialization of Net::SSH::Test::Packet for representing mock # packets that are sent from the local (client) host. These are created # automatically by Net::SSH::Test::Script and Net::SSH::Test::Channel by any # of the sends_* methods. class LocalPacket < Packet attr_reader :init # Extend the default Net::SSH::Test::Packet constructor to also accept an # optional block, which is used to finalize the initialization of the # packet when #process is first called. def initialize(type, *args, &block) super(type, *args) @init = block end # Returns +true+; this is a local packet. def local? true end # Called by Net::SSH::Test::Extensions::PacketStream#test_enqueue_packet # to mimic remote processing of a locally-sent packet. It compares the # packet it was given with the contents of this LocalPacket's data, to see # if what was sent matches what was scripted. If it differs in any way, # an exception is raised. def process(packet) @init.call(Net::SSH::Packet.new(packet.to_s)) if @init type = packet.read_byte raise "expected #{@type}, but got #{type}" if @type != type @data.zip(types).each do |expected, _type| _type ||= case expected when nil then break when Numeric then :long when String then :string when TrueClass, FalseClass then :bool end actual = packet.send("read_#{_type}") next if expected.nil? raise "expected #{_type} #{expected.inspect} but got #{actual.inspect}" unless expected == actual end end end end; end; endnet-ssh-2.6.8/lib/net/ssh/test/kex.rb0000644000004100000410000000270012166626376017402 0ustar www-datawww-datarequire 'openssl' require 'net/ssh/errors' require 'net/ssh/transport/algorithms' require 'net/ssh/transport/constants' require 'net/ssh/transport/kex' module Net; module SSH; module Test # An implementation of a key-exchange strategy specifically for unit tests. # (This strategy would never really work against a real SSH server--it makes # too many assumptions about the server's response.) # # This registers itself with the transport key-exchange system as the # "test" algorithm. class Kex include Net::SSH::Transport::Constants # Creates a new instance of the testing key-exchange algorithm with the # given arguments. def initialize(algorithms, connection, data) @connection = connection end # Exchange keys with the server. This returns a hash of constant values, # and does not actually exchange keys. def exchange_keys result = Net::SSH::Buffer.from(:byte, NEWKEYS) @connection.send_message(result) buffer = @connection.next_message raise Net::SSH::Exception, "expected NEWKEYS" unless buffer.type == NEWKEYS { :session_id => "abc-xyz", :server_key => OpenSSL::PKey::RSA.new(512), :shared_secret => OpenSSL::BN.new("1234567890", 10), :hashing_algorithm => OpenSSL::Digest::SHA1 } end end end; end; end Net::SSH::Transport::Algorithms::ALGORITHMS[:kex] << "test" Net::SSH::Transport::Kex::MAP["test"] = Net::SSH::Test::Kex net-ssh-2.6.8/lib/net/ssh/test/extensions.rb0000644000004100000410000001315512166626376021020 0ustar www-datawww-datarequire 'net/ssh/buffer' require 'net/ssh/packet' require 'net/ssh/buffered_io' require 'net/ssh/connection/channel' require 'net/ssh/connection/constants' require 'net/ssh/transport/constants' require 'net/ssh/transport/packet_stream' module Net; module SSH; module Test # A collection of modules used to extend/override the default behavior of # Net::SSH internals for ease of testing. As a consumer of Net::SSH, you'll # never need to use this directly--they're all used under the covers by # the Net::SSH::Test system. module Extensions # An extension to Net::SSH::BufferedIo (assumes that the underlying IO # is actually a StringIO). Facilitates unit testing. module BufferedIo # Returns +true+ if the position in the stream is less than the total # length of the stream. def select_for_read? pos < size end # Set this to +true+ if you want the IO to pretend to be available for writing attr_accessor :select_for_write # Set this to +true+ if you want the IO to pretend to be in an error state attr_accessor :select_for_error alias select_for_write? select_for_write alias select_for_error? select_for_error end # An extension to Net::SSH::Transport::PacketStream (assumes that the # underlying IO is actually a StringIO). Facilitates unit testing. module PacketStream include BufferedIo # make sure we get the extensions here, too def self.included(base) #:nodoc: base.send :alias_method, :real_available_for_read?, :available_for_read? base.send :alias_method, :available_for_read?, :test_available_for_read? base.send :alias_method, :real_enqueue_packet, :enqueue_packet base.send :alias_method, :enqueue_packet, :test_enqueue_packet base.send :alias_method, :real_poll_next_packet, :poll_next_packet base.send :alias_method, :poll_next_packet, :test_poll_next_packet end # Called when another packet should be inspected from the current # script. If the next packet is a remote packet, it pops it off the # script and shoves it onto this IO object, making it available to # be read. def idle! return false unless script.next(:first) if script.next(:first).remote? self.string << script.next.to_s self.pos = pos end return true end # The testing version of Net::SSH::Transport::PacketStream#available_for_read?. # Returns true if there is data pending to be read. Otherwise calls #idle!. def test_available_for_read? return true if select_for_read? idle! false end # The testing version of Net::SSH::Transport::PacketStream#enqueued_packet. # Simply calls Net::SSH::Test::Script#process on the packet. def test_enqueue_packet(payload) packet = Net::SSH::Buffer.new(payload.to_s) script.process(packet) end # The testing version of Net::SSH::Transport::PacketStream#poll_next_packet. # Reads the next available packet from the IO object and returns it. def test_poll_next_packet return nil if available <= 0 packet = Net::SSH::Buffer.new(read_available(4)) length = packet.read_long Net::SSH::Packet.new(read_available(length)) end end # An extension to Net::SSH::Connection::Channel. Facilitates unit testing. module Channel def self.included(base) #:nodoc: base.send :alias_method, :send_data_for_real, :send_data base.send :alias_method, :send_data, :send_data_for_test end # The testing version of Net::SSH::Connection::Channel#send_data. Calls # the original implementation, and then immediately enqueues the data for # output so that scripted sends are properly interpreted as discrete # (rather than concatenated) data packets. def send_data_for_test(data) send_data_for_real(data) enqueue_pending_output end end # An extension to the built-in ::IO class. Simply redefines IO.select # so that it can be scripted in Net::SSH unit tests. module IO def self.included(base) #:nodoc: base.extend(ClassMethods) end module ClassMethods def self.extended(obj) #:nodoc: class < 4 raise ArgumentError, "expected 3 or 4 parameters, got #{args.length}" end local_port_type = :long socket = begin if defined?(UNIXServer) and args.first.class == UNIXServer local_port_type = :string args.shift else bind_address = "127.0.0.1" bind_address = args.shift if args.first.is_a?(String) && args.first =~ /\D/ local_port = args.shift.to_i local_port_type = :long TCPServer.new(bind_address, local_port) end end remote_host = args.shift remote_port = args.shift.to_i @local_forwarded_ports[[local_port, bind_address]] = socket session.listen_to(socket) do |server| client = server.accept debug { "received connection on #{socket}" } channel = session.open_channel("direct-tcpip", :string, remote_host, :long, remote_port, :string, bind_address, local_port_type, local_port) do |achannel| achannel.info { "direct channel established" } end prepare_client(client, channel, :local) channel.on_open_failed do |ch, code, description| channel.error { "could not establish direct channel: #{description} (#{code})" } channel[:socket].close end end end # Terminates an active local forwarded port. If no such forwarded port # exists, this will raise an exception. Otherwise, the forwarded connection # is terminated. # # ssh.forward.cancel_local(1234) # ssh.forward.cancel_local(1234, "0.0.0.0") def cancel_local(port, bind_address="127.0.0.1") socket = @local_forwarded_ports.delete([port, bind_address]) socket.shutdown rescue nil socket.close rescue nil session.stop_listening_to(socket) end # Returns a list of all active locally forwarded ports. The returned value # is an array of arrays, where each element is a two-element tuple # consisting of the local port and bind address corresponding to the # forwarding port. def active_locals @local_forwarded_ports.keys end # Requests that all connections on the given remote-port be forwarded via # the local host to the given port/host. The last argument describes the # bind address on the remote host, and defaults to 127.0.0.1. # # This method will return immediately, but the port will not actually be # forwarded immediately. If the remote server is not able to begin the # listener for this request, an exception will be raised asynchronously. # # If you want to know when the connection is active, it will show up in the # #active_remotes list. If you want to block until the port is active, you # could do something like this: # # ssh.forward.remote(80, "www.google.com", 1234, "0.0.0.0") # ssh.loop { !ssh.forward.active_remotes.include?([1234, "0.0.0.0"]) } def remote(port, host, remote_port, remote_host="127.0.0.1") session.send_global_request("tcpip-forward", :string, remote_host, :long, remote_port) do |success, response| if success debug { "remote forward from remote #{remote_host}:#{remote_port} to #{host}:#{port} established" } @remote_forwarded_ports[[remote_port, remote_host]] = Remote.new(host, port) else error { "remote forwarding request failed" } raise Net::SSH::Exception, "remote forwarding request failed" end end end # an alias, for token backwards compatibility with the 1.x API alias :remote_to :remote # Requests that a remote forwarded port be cancelled. The remote forwarded # port on the remote host, bound to the given address on the remote host, # will be terminated, but not immediately. This method returns immediately # after queueing the request to be sent to the server. If for some reason # the port cannot be cancelled, an exception will be raised (asynchronously). # # If you want to know when the connection has been cancelled, it will no # longer be present in the #active_remotes list. If you want to block until # the port is no longer active, you could do something like this: # # ssh.forward.cancel_remote(1234, "0.0.0.0") # ssh.loop { ssh.forward.active_remotes.include?([1234, "0.0.0.0"]) } def cancel_remote(port, host="127.0.0.1") session.send_global_request("cancel-tcpip-forward", :string, host, :long, port) do |success, response| if success @remote_forwarded_ports.delete([port, host]) else raise Net::SSH::Exception, "could not cancel remote forward request on #{host}:#{port}" end end end # Returns all active forwarded remote ports. The returned value is an # array of two-element tuples, where the first element is the port on the # remote host and the second is the bind address. def active_remotes @remote_forwarded_ports.keys end # Enables SSH agent forwarding on the given channel. The forwarded agent # will remain active even after the channel closes--the channel is only # used as the transport for enabling the forwarded connection. You should # never need to call this directly--it is called automatically the first # time a session channel is opened, when the connection was created with # :forward_agent set to true: # # Net::SSH.start("remote.host", "me", :forward_agent => true) do |ssh| # ssh.open_channel do |ch| # # agent will be automatically forwarded by this point # end # ssh.loop # end def agent(channel) return if @agent_forwarded @agent_forwarded = true channel.send_channel_request("auth-agent-req@openssh.com") do |achannel, success| if success debug { "authentication agent forwarding is active" } else achannel.send_channel_request("auth-agent-req") do |a2channel, success2| if success2 debug { "authentication agent forwarding is active" } else error { "could not establish forwarding of authentication agent" } end end end end end private # Perform setup operations that are common to all forwarded channels. # +client+ is a socket, +channel+ is the channel that was just created, # and +type+ is an arbitrary string describing the type of the channel. def prepare_client(client, channel, type) client.extend(Net::SSH::BufferedIo) client.extend(Net::SSH::ForwardedBufferedIo) client.logger = logger session.listen_to(client) channel[:socket] = client channel.on_data do |ch, data| debug { "data:#{data.length} on #{type} forwarded channel" } ch[:socket].enqueue(data) end # Handles server close on the sending side by Miklós Fazekas channel.on_eof do |ch| debug { "eof #{type} on #{type} forwarded channel" } begin ch[:socket].send_pending ch[:socket].shutdown Socket::SHUT_WR rescue IOError => e if e.message =~ /closed/ then debug { "epipe in on_eof => shallowing exception:#{e}" } else raise end rescue Errno::EPIPE => e debug { "epipe in on_eof => shallowing exception:#{e}" } rescue Errno::ENOTCONN => e debug { "enotconn in on_eof => shallowing exception:#{e}" } end end channel.on_close do |ch| debug { "closing #{type} forwarded channel" } ch[:socket].close if !client.closed? session.stop_listening_to(ch[:socket]) end channel.on_process do |ch| if ch[:socket].closed? ch.info { "#{type} forwarded connection closed" } ch.close elsif ch[:socket].available > 0 data = ch[:socket].read_available(8192) ch.debug { "read #{data.length} bytes from client, sending over #{type} forwarded connection" } ch.send_data(data) end end end # The callback used when a new "forwarded-tcpip" channel is requested # by the server. This will open a new socket to the host/port specified # when the forwarded connection was first requested. def forwarded_tcpip(session, channel, packet) connected_address = packet.read_string connected_port = packet.read_long originator_address = packet.read_string originator_port = packet.read_long remote = @remote_forwarded_ports[[connected_port, connected_address]] if remote.nil? raise Net::SSH::ChannelOpenFailed.new(1, "unknown request from remote forwarded connection on #{connected_address}:#{connected_port}") end client = TCPSocket.new(remote.host, remote.port) info { "connected #{connected_address}:#{connected_port} originator #{originator_address}:#{originator_port}" } prepare_client(client, channel, :remote) rescue SocketError => err raise Net::SSH::ChannelOpenFailed.new(2, "could not connect to remote host (#{remote.host}:#{remote.port}): #{err.message}") end # The callback used when an auth-agent channel is requested by the server. def auth_agent_channel(session, channel, packet) info { "opening auth-agent channel" } channel[:invisible] = true begin agent = Authentication::Agent.connect(logger) prepare_client(agent.socket, channel, :agent) rescue Exception => e error { "attempted to connect to agent but failed: #{e.class.name} (#{e.message})" } raise Net::SSH::ChannelOpenFailed.new(2, "could not connect to authentication agent") end end end end; end; end net-ssh-2.6.8/lib/net/ssh/errors.rb0000644000004100000410000000733612166626376017162 0ustar www-datawww-datamodule Net; module SSH # A general exception class, to act as the ancestor of all other Net::SSH # exception classes. class Exception < ::RuntimeError; end # This exception is raised when authentication fails (whether it be # public key authentication, password authentication, or whatever). class AuthenticationFailed < Exception; end # This exception is raised when a connection attempt times out. class ConnectionTimeout < Exception; end # This exception is raised when the remote host has disconnected # unexpectedly. class Disconnect < Exception; end # This exception is primarily used internally, but if you have a channel # request handler (see Net::SSH::Connection::Channel#on_request) that you # want to fail in such a way that the server knows it failed, you can # raise this exception in the handler and Net::SSH will translate that into # a "channel failure" message. class ChannelRequestFailed < Exception; end # This is exception is primarily used internally, but if you have a channel # open handler (see Net::SSH::Connection::Session#on_open_channel) and you # want to fail in such a way that the server knows it failed, you can # raise this exception in the handler and Net::SSH will translate that into # a "channel open failed" message. class ChannelOpenFailed < Exception attr_reader :code, :reason def initialize(code, reason) @code, @reason = code, reason super "#{reason} (#{code})" end end # Base class for host key exceptions. When rescuing this exception, you can # inspect the key fingerprint and, if you want to proceed anyway, simply call # the remember_host! method on the exception, and then retry. class HostKeyError < Exception # the callback to use when #remember_host! is called attr_writer :callback #:nodoc: # situation-specific data describing the host (see #host, #port, etc.) attr_writer :data #:nodoc: # An accessor for getting at the data that was used to look up the host # (see also #fingerprint, #host, #port, #ip, and #key). def [](key) @data && @data[key] end # Returns the fingerprint of the key for the host, which either was not # found or did not match. def fingerprint @data && @data[:fingerprint] end # Returns the host name for the remote host, as reported by the socket. def host @data && @data[:peer] && @data[:peer][:host] end # Returns the port number for the remote host, as reported by the socket. def port @data && @data[:peer] && @data[:peer][:port] end # Returns the IP address of the remote host, as reported by the socket. def ip @data && @data[:peer] && @data[:peer][:ip] end # Returns the key itself, as reported by the remote host. def key @data && @data[:key] end # Tell Net::SSH to record this host and key in the known hosts file, so # that subsequent connections will remember them. def remember_host! @callback.call end end # Raised when the cached key for a particular host does not match the # key given by the host, which can be indicative of a man-in-the-middle # attack. When rescuing this exception, you can inspect the key fingerprint # and, if you want to proceed anyway, simply call the remember_host! # method on the exception, and then retry. class HostKeyMismatch < HostKeyError; end # Raised when there is no cached key for a particular host, which probably # means that the host has simply not been seen before. # When rescuing this exception, you can inspect the key fingerprint and, if # you want to proceed anyway, simply call the remember_host! method on the # exception, and then retry. class HostKeyUnknown < HostKeyError; end end; end net-ssh-2.6.8/lib/net/ssh/test.rb0000644000004100000410000000634112166626376016620 0ustar www-datawww-datarequire 'net/ssh/transport/session' require 'net/ssh/connection/session' require 'net/ssh/test/kex' require 'net/ssh/test/socket' module Net; module SSH # This module may be used in unit tests, for when you want to test that your # SSH state machines are really doing what you expect they are doing. You will # typically include this module in your unit test class, and then build a # "story" of expected sends and receives: # # require 'test/unit' # require 'net/ssh/test' # # class MyTest < Test::Unit::TestCase # include Net::SSH::Test # # def test_exec_via_channel_works # story do |session| # channel = session.opens_channel # channel.sends_exec "ls" # channel.gets_data "result of ls" # channel.gets_close # channel.sends_close # end # # assert_scripted do # result = nil # # connection.open_channel do |ch| # ch.exec("ls") do |success| # ch.on_data { |c, data| result = data } # ch.on_close { |c| c.close } # end # end # # connection.loop # assert_equal "result of ls", result # end # end # end # # See Net::SSH::Test::Channel and Net::SSH::Test::Script for more options. # # Note that the Net::SSH::Test system is rather finicky yet, and can be kind # of frustrating to get working. Any suggestions for improvement will be # welcome! module Test # If a block is given, yields the script for the test socket (#socket). # Otherwise, simply returns the socket's script. See Net::SSH::Test::Script. def story yield socket.script if block_given? return socket.script end # Returns the test socket instance to use for these tests (see # Net::SSH::Test::Socket). def socket(options={}) @socket ||= Net::SSH::Test::Socket.new end # Returns the connection session (Net::SSH::Connection::Session) for use # in these tests. It is a fully functional SSH session, operating over # a mock socket (#socket). def connection(options={}) @connection ||= Net::SSH::Connection::Session.new(transport(options), options) end # Returns the transport session (Net::SSH::Transport::Session) for use # in these tests. It is a fully functional SSH transport session, operating # over a mock socket (#socket). def transport(options={}) @transport ||= Net::SSH::Transport::Session.new(options[:host] || "localhost", options.merge(:kex => "test", :host_key => "ssh-rsa", :paranoid => false, :proxy => socket(options))) end # First asserts that a story has been described (see #story). Then yields, # and then asserts that all items described in the script have been # processed. Typically, this is called immediately after a story has # been built, and the SSH commands being tested are then executed within # the block passed to this assertion. def assert_scripted raise "there is no script to be processed" if socket.script.events.empty? yield assert socket.script.events.empty?, "there should not be any remaining scripted events, but there are still #{socket.script.events.length} pending" end end end; endnet-ssh-2.6.8/lib/net/ssh/buffered_io.rb0000644000004100000410000001401512166626376020107 0ustar www-datawww-datarequire 'net/ssh/buffer' require 'net/ssh/loggable' require 'net/ssh/ruby_compat' module Net; module SSH # This module is used to extend sockets and other IO objects, to allow # them to be buffered for both read and write. This abstraction makes it # quite easy to write a select-based event loop # (see Net::SSH::Connection::Session#listen_to). # # The general idea is that instead of calling #read directly on an IO that # has been extended with this module, you call #fill (to add pending input # to the internal read buffer), and then #read_available (to read from that # buffer). Likewise, you don't call #write directly, you call #enqueue to # add data to the write buffer, and then #send_pending or #wait_for_pending_sends # to actually send the data across the wire. # # In this way you can easily use the object as an argument to IO.select, # calling #fill when it is available for read, or #send_pending when it is # available for write, and then call #enqueue and #read_available during # the idle times. # # socket = TCPSocket.new(address, port) # socket.extend(Net::SSH::BufferedIo) # # ssh.listen_to(socket) # # ssh.loop do # if socket.available > 0 # puts socket.read_available # socket.enqueue("response\n") # end # end # # Note that this module must be used to extend an instance, and should not # be included in a class. If you do want to use it via an include, then you # must make sure to invoke the private #initialize_buffered_io method in # your class' #initialize method: # # class Foo < IO # include Net::SSH::BufferedIo # # def initialize # initialize_buffered_io # # ... # end # end module BufferedIo include Loggable # Called when the #extend is called on an object, with this module as the # argument. It ensures that the modules instance variables are all properly # initialized. def self.extended(object) #:nodoc: # need to use __send__ because #send is overridden in Socket object.__send__(:initialize_buffered_io) end # Tries to read up to +n+ bytes of data from the remote end, and appends # the data to the input buffer. It returns the number of bytes read, or 0 # if no data was available to be read. def fill(n=8192) input.consume! data = recv(n) debug { "read #{data.length} bytes" } input.append(data) return data.length end # Read up to +length+ bytes from the input buffer. If +length+ is nil, # all available data is read from the buffer. (See #available.) def read_available(length=nil) input.read(length || available) end # Returns the number of bytes available to be read from the input buffer. # (See #read_available.) def available input.available end # Enqueues data in the output buffer, to be written when #send_pending # is called. Note that the data is _not_ sent immediately by this method! def enqueue(data) output.append(data) end # Returns +true+ if there is data waiting in the output buffer, and # +false+ otherwise. def pending_write? output.length > 0 end # Sends as much of the pending output as possible. Returns +true+ if any # data was sent, and +false+ otherwise. def send_pending if output.length > 0 sent = send(output.to_s, 0) debug { "sent #{sent} bytes" } output.consume!(sent) return sent > 0 else return false end end # Calls #send_pending repeatedly, if necessary, blocking until the output # buffer is empty. def wait_for_pending_sends send_pending while output.length > 0 result = Net::SSH::Compat.io_select(nil, [self]) or next next unless result[1].any? send_pending end end public # these methods are primarily for use in tests def write_buffer #:nodoc: output.to_s end def read_buffer #:nodoc: input.to_s end private #-- # Can't use attr_reader here (after +private+) without incurring the # wrath of "ruby -w". We hates it. #++ def input; @input; end def output; @output; end # Initializes the intput and output buffers for this object. This method # is called automatically when the module is mixed into an object via # Object#extend (see Net::SSH::BufferedIo.extended), but must be called # explicitly in the +initialize+ method of any class that uses # Module#include to add this module. def initialize_buffered_io @input = Net::SSH::Buffer.new @output = Net::SSH::Buffer.new end end # Fixes for two issues by Miklós Fazekas: # # * if client closes a forwarded connection, but the server is # reading, net-ssh terminates with IOError socket closed. # * if client force closes (RST) a forwarded connection, but # server is reading, net-ssh terminates with [an exception] # # See: # # http://net-ssh.lighthouseapp.com/projects/36253/tickets/7 # http://github.com/net-ssh/net-ssh/tree/portfwfix # module ForwardedBufferedIo def fill(n=8192) begin super(n) rescue Errno::ECONNRESET => e debug { "connection was reset => shallowing exception:#{e}" } return 0 rescue IOError => e if e.message =~ /closed/ then debug { "connection was reset => shallowing exception:#{e}" } return 0 else raise end end end def send_pending begin super rescue Errno::ECONNRESET => e debug { "connection was reset => shallowing exception:#{e}" } return 0 rescue IOError => e if e.message =~ /closed/ then debug { "connection was reset => shallowing exception:#{e}" } return 0 else raise end end end end end; end net-ssh-2.6.8/lib/net/ssh/loggable.rb0000644000004100000410000000374412166626376017421 0ustar www-datawww-datamodule Net; module SSH # A simple module to make logging easier to deal with. It assumes that the # logger instance (if not nil) quacks like a Logger object (in Ruby's # standard library). Although used primarily internally by Net::SSH, it # can easily be used to add Net::SSH-like logging to your own programs. # # class MyClass # include Net::SSH::Loggable # end # # Net::SSH.start(...) do |ssh| # obj = MyClass.new # obj.logger = ssh.logger # ... # end module Loggable # The logger instance that will be used to log messages. If nil, nothing # will be logged. attr_accessor :logger # Displays the result of yielding if the log level is Logger::DEBUG or # greater. def debug logger.add(Logger::DEBUG, nil, facility) { yield } if logger && logger.debug? end # Displays the result of yielding if the log level is Logger::INFO or # greater. def info logger.add(Logger::INFO, nil, facility) { yield } if logger && logger.info? end # Displays the result of yielding if the log level is Logger::WARN or # greater. (Called lwarn to avoid shadowing with Kernel#warn.) def lwarn logger.add(Logger::WARN, nil, facility) { yield } if logger && logger.warn? end # Displays the result of yielding if the log level is Logger:ERROR or # greater. def error logger.add(Logger::ERROR, nil, facility) { yield } if logger && logger.error? end # Displays the result of yielding if the log level is Logger::FATAL or # greater. def fatal logger.add(Logger::FATAL, nil, facility) { yield } if logger && logger.fatal? end private # Sets the "facility" value, used for reporting where a log message # originates. It defaults to the name of class with the object_id # appended. def facility @facility ||= self.class.name.gsub(/::/, ".").gsub(/([a-z])([A-Z])/, "\\1_\\2").downcase + "[%x]" % object_id end end end; endnet-ssh-2.6.8/lib/net/ssh/authentication/0000755000004100000410000000000012166626376020327 5ustar www-datawww-datanet-ssh-2.6.8/lib/net/ssh/authentication/session.rb0000644000004100000410000001217512166626376022345 0ustar www-datawww-datarequire 'net/ssh/loggable' require 'net/ssh/transport/constants' require 'net/ssh/authentication/constants' require 'net/ssh/authentication/key_manager' require 'net/ssh/authentication/methods/publickey' require 'net/ssh/authentication/methods/hostbased' require 'net/ssh/authentication/methods/password' require 'net/ssh/authentication/methods/keyboard_interactive' module Net; module SSH; module Authentication # Raised if the current authentication method is not allowed class DisallowedMethod < Net::SSH::Exception end # Represents an authentication session. It manages the authentication of # a user over an established connection (the "transport" object, see # Net::SSH::Transport::Session). # # The use of an authentication session to manage user authentication is # internal to Net::SSH (specifically Net::SSH.start). Consumers of the # Net::SSH library will never need to access this class directly. class Session include Transport::Constants, Constants, Loggable # transport layer abstraction attr_reader :transport # the list of authentication methods to try attr_reader :auth_methods # the list of authentication methods that are allowed attr_reader :allowed_auth_methods # a hash of options, given at construction time attr_reader :options # Instantiates a new Authentication::Session object over the given # transport layer abstraction. def initialize(transport, options={}) self.logger = transport.logger @transport = transport @auth_methods = options[:auth_methods] || %w(none publickey hostbased password keyboard-interactive) @options = options @allowed_auth_methods = @auth_methods end # Attempts to authenticate the given user, in preparation for the next # service request. Returns true if an authentication method succeeds in # authenticating the user, and false otherwise. def authenticate(next_service, username, password=nil) debug { "beginning authentication of `#{username}'" } transport.send_message(transport.service_request("ssh-userauth")) expect_message(SERVICE_ACCEPT) key_manager = KeyManager.new(logger, options) keys.each { |key| key_manager.add(key) } unless keys.empty? key_data.each { |key2| key_manager.add_key_data(key2) } unless key_data.empty? attempted = [] @auth_methods.each do |name| begin next unless @allowed_auth_methods.include?(name) attempted << name debug { "trying #{name}" } begin method = Methods.const_get(name.split(/\W+/).map { |p| p.capitalize }.join).new(self, :key_manager => key_manager) rescue NameError debug{"Mechanism #{name} was requested, but isn't a known type. Ignoring it."} next end return true if method.authenticate(next_service, username, password) rescue Net::SSH::Authentication::DisallowedMethod end end error { "all authorization methods failed (tried #{attempted.join(', ')})" } return false ensure key_manager.finish if key_manager end # Blocks until a packet is received. It silently handles USERAUTH_BANNER # packets, and will raise an error if any packet is received that is not # valid during user authentication. def next_message loop do packet = transport.next_message case packet.type when USERAUTH_BANNER info { packet[:message] } # TODO add a hook for people to retrieve the banner when it is sent when USERAUTH_FAILURE @allowed_auth_methods = packet[:authentications].split(/,/) debug { "allowed methods: #{packet[:authentications]}" } return packet when USERAUTH_METHOD_RANGE, SERVICE_ACCEPT return packet when USERAUTH_SUCCESS transport.hint :authenticated return packet else raise Net::SSH::Exception, "unexpected message #{packet.type} (#{packet})" end end end # Blocks until a packet is received, and returns it if it is of the given # type. If it is not, an exception is raised. def expect_message(type) message = next_message unless message.type == type raise Net::SSH::Exception, "expected #{type}, got #{message.type} (#{message})" end message end private # Returns an array of paths to the key files usually defined # by system default. def default_keys if defined?(OpenSSL::PKey::EC) %w(~/.ssh/id_dsa ~/.ssh/id_rsa ~/.ssh/id_ecdsa ~/.ssh2/id_dsa ~/.ssh2/id_rsa ~/.ssh2/id_ecdsa) else %w(~/.ssh/id_dsa ~/.ssh/id_rsa ~/.ssh2/id_dsa ~/.ssh2/id_rsa) end end # Returns an array of paths to the key files that should be used when # attempting any key-based authentication mechanism. def keys Array(options[:keys] || default_keys) end # Returns an array of the key data that should be used when # attempting any key-based authentication mechanism. def key_data Array(options[:key_data]) end end end; end; end net-ssh-2.6.8/lib/net/ssh/authentication/key_manager.rb0000644000004100000410000002310112166626376023133 0ustar www-datawww-datarequire 'net/ssh/errors' require 'net/ssh/key_factory' require 'net/ssh/loggable' require 'net/ssh/authentication/agent' module Net module SSH module Authentication # A trivial exception class used to report errors in the key manager. class KeyManagerError < Net::SSH::Exception; end # This class encapsulates all operations done by clients on a user's # private keys. In practice, the client should never need a reference # to a private key; instead, they grab a list of "identities" (public # keys) that are available from the KeyManager, and then use # the KeyManager to do various private key operations using those # identities. # # The KeyManager also uses the Agent class to encapsulate the # ssh-agent. Thus, from a client's perspective it is completely # hidden whether an identity comes from the ssh-agent or from a file # on disk. class KeyManager include Loggable # The list of user key files that will be examined attr_reader :key_files # The list of user key data that will be examined attr_reader :key_data # The map of loaded identities attr_reader :known_identities # The map of options that were passed to the key-manager attr_reader :options # Create a new KeyManager. By default, the manager will # use the ssh-agent (if it is running). def initialize(logger, options={}) self.logger = logger @key_files = [] @key_data = [] @use_agent = true @known_identities = {} @agent = nil @options = options end # Clear all knowledge of any loaded user keys. This also clears the list # of default identity files that are to be loaded, thus making it # appropriate to use if a client wishes to NOT use the default identity # files. def clear! key_files.clear key_data.clear known_identities.clear self end # Add the given key_file to the list of key files that will be used. def add(key_file) key_files.push(File.expand_path(key_file)).uniq! self end # Add the given key_file to the list of keys that will be used. def add_key_data(key_data_) key_data.push(key_data_).uniq! self end # This is used as a hint to the KeyManager indicating that the agent # connection is no longer needed. Any other open resources may be closed # at this time. # # Calling this does NOT indicate that the KeyManager will no longer # be used. Identities may still be requested and operations done on # loaded identities, in which case, the agent will be automatically # reconnected. This method simply allows the client connection to be # closed when it will not be used in the immediate future. def finish @agent.close if @agent @agent = nil end # Iterates over all available identities (public keys) known to this # manager. As it finds one, it will then yield it to the caller. # The origin of the identities may be from files on disk or from an # ssh-agent. Note that identities from an ssh-agent are always listed # first in the array, with other identities coming after. # # If key manager was created with :keys_only option, any identity # from ssh-agent will be ignored unless it present in key_files or # key_data. def each_identity prepared_identities = prepare_identities_from_files + prepare_identities_from_data user_identities = load_identities(prepared_identities, false) if agent agent.identities.each do |key| corresponding_user_identity = user_identities.detect { |identity| identity[:public_key] && identity[:public_key].to_pem == key.to_pem } user_identities.delete(corresponding_user_identity) if corresponding_user_identity if !options[:keys_only] || corresponding_user_identity known_identities[key] = { :from => :agent } yield key end end end user_identities = load_identities(user_identities, true) user_identities.each do |identity| key = identity.delete(:public_key) known_identities[key] = identity yield key end self end # Sign the given data, using the corresponding private key of the given # identity. If the identity was originally obtained from an ssh-agent, # then the ssh-agent will be used to sign the data, otherwise the # private key for the identity will be loaded from disk (if it hasn't # been loaded already) and will then be used to sign the data. # # Regardless of the identity's origin or who does the signing, this # will always return the signature in an SSH2-specified "signature # blob" format. def sign(identity, data) info = known_identities[identity] or raise KeyManagerError, "the given identity is unknown to the key manager" if info[:key].nil? && info[:from] == :file begin info[:key] = KeyFactory.load_private_key(info[:file], options[:passphrase], true) rescue Exception, OpenSSL::OpenSSLError => e raise KeyManagerError, "the given identity is known, but the private key could not be loaded: #{e.class} (#{e.message})" end end if info[:key] return Net::SSH::Buffer.from(:string, identity.ssh_type, :string, info[:key].ssh_do_sign(data.to_s)).to_s end if info[:from] == :agent raise KeyManagerError, "the agent is no longer available" unless agent return agent.sign(identity, data.to_s) end raise KeyManagerError, "[BUG] can't determine identity origin (#{info.inspect})" end # Identifies whether the ssh-agent will be used or not. def use_agent? @use_agent end # Toggles whether the ssh-agent will be used or not. If true, an # attempt will be made to use the ssh-agent. If false, any existing # connection to an agent is closed and the agent will not be used. def use_agent=(use_agent) finish if !use_agent @use_agent = use_agent end # Returns an Agent instance to use for communicating with an SSH # agent process. Returns nil if use of an SSH agent has been disabled, # or if the agent is otherwise not available. def agent return unless use_agent? @agent ||= Agent.connect(logger) rescue AgentNotAvailable @use_agent = false nil end private # Prepares identities from user key_files for loading, preserving their order and sources. def prepare_identities_from_files key_files.map do |file| public_key_file = file + ".pub" if File.readable?(public_key_file) { :load_from => :pubkey_file, :file => file } elsif File.readable?(file) { :load_from => :privkey_file, :file => file } end end.compact end # Prepared identities from user key_data, preserving their order and sources. def prepare_identities_from_data key_data.map do |data| { :load_from => :data, :data => data } end end # Load prepared identities. Private key decryption errors ignored if passphrase was not prompted. def load_identities(identities, ask_passphrase) identities.map do |identity| begin case identity[:load_from] when :pubkey_file key = KeyFactory.load_public_key(identity[:file] + ".pub") { :public_key => key, :from => :file, :file => identity[:file] } when :privkey_file private_key = KeyFactory.load_private_key(identity[:file], options[:passphrase], ask_passphrase) key = private_key.send(:public_key) { :public_key => key, :from => :file, :file => identity[:file], :key => private_key } when :data private_key = KeyFactory.load_data_private_key(identity[:data], options[:passphrase], ask_passphrase) key = private_key.send(:public_key) { :public_key => key, :from => :key_data, :data => identity[:data], :key => private_key } else identity end rescue OpenSSL::PKey::RSAError, OpenSSL::PKey::DSAError, OpenSSL::PKey::ECError => e if ask_passphrase process_identity_loading_error(identity, e) nil else identity end rescue Exception => e process_identity_loading_error(identity, e) nil end end.compact end def process_identity_loading_error(identity, e) case identity[:load_from] when :pubkey_file error { "could not load public key file `#{identity[:file]}': #{e.class} (#{e.message})" } when :privkey_file error { "could not load private key file `#{identity[:file]}': #{e.class} (#{e.message})" } else raise e end end end end end end net-ssh-2.6.8/lib/net/ssh/authentication/pageant.rb0000644000004100000410000002002612166626376022273 0ustar www-datawww-datarequire 'dl/import' if RUBY_VERSION < "1.9" require 'dl/struct' else require 'dl/types' require 'dl' end require 'net/ssh/errors' module Net; module SSH; module Authentication # This module encapsulates the implementation of a socket factory that # uses the PuTTY "pageant" utility to obtain information about SSH # identities. # # This code is a slightly modified version of the original implementation # by Guillaume Marçais (guillaume.marcais@free.fr). It is used and # relicensed by permission. module Pageant # From Putty pageant.c AGENT_MAX_MSGLEN = 8192 AGENT_COPYDATA_ID = 0x804e50ba # The definition of the Windows methods and data structures used in # communicating with the pageant process. module Win if RUBY_VERSION < "1.9" extend DL::Importable dlload 'user32' dlload 'kernel32' else extend DL::Importer dlload 'user32','kernel32' include DL::Win32Types end typealias("LPCTSTR", "char *") # From winnt.h typealias("LPVOID", "void *") # From winnt.h typealias("LPCVOID", "const void *") # From windef.h typealias("LRESULT", "long") # From windef.h typealias("WPARAM", "unsigned int *") # From windef.h typealias("LPARAM", "long *") # From windef.h typealias("PDWORD_PTR", "long *") # From basetsd.h # From winbase.h, winnt.h INVALID_HANDLE_VALUE = -1 NULL = nil PAGE_READWRITE = 0x0004 FILE_MAP_WRITE = 2 WM_COPYDATA = 74 SMTO_NORMAL = 0 # From winuser.h # args: lpClassName, lpWindowName extern 'HWND FindWindow(LPCTSTR, LPCTSTR)' # args: none extern 'DWORD GetCurrentThreadId()' # args: hFile, (ignored), flProtect, dwMaximumSizeHigh, # dwMaximumSizeLow, lpName extern 'HANDLE CreateFileMapping(HANDLE, void *, DWORD, DWORD, ' + 'DWORD, LPCTSTR)' # args: hFileMappingObject, dwDesiredAccess, dwFileOffsetHigh, # dwfileOffsetLow, dwNumberOfBytesToMap extern 'LPVOID MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, DWORD)' # args: lpBaseAddress extern 'BOOL UnmapViewOfFile(LPCVOID)' # args: hObject extern 'BOOL CloseHandle(HANDLE)' # args: hWnd, Msg, wParam, lParam, fuFlags, uTimeout, lpdwResult extern 'LRESULT SendMessageTimeout(HWND, UINT, WPARAM, LPARAM, ' + 'UINT, UINT, PDWORD_PTR)' if RUBY_VERSION < "1.9" alias_method :FindWindow,:findWindow module_function :FindWindow end end # This is the pseudo-socket implementation that mimics the interface of # a socket, translating each request into a Windows messaging call to # the pageant daemon. This allows pageant support to be implemented # simply by replacing the socket factory used by the Agent class. class Socket private_class_method :new # The factory method for creating a new Socket instance. The location # parameter is ignored, and is only needed for compatibility with # the general Socket interface. def self.open(location=nil) new end # Create a new instance that communicates with the running pageant # instance. If no such instance is running, this will cause an error. def initialize @win = Win.FindWindow("Pageant", "Pageant") if @win == 0 raise Net::SSH::Exception, "pageant process not running" end @res = nil @pos = 0 end # Forwards the data to #send_query, ignoring any arguments after # the first. Returns 0. def send(data, *args) @res = send_query(data) @pos = 0 end # Packages the given query string and sends it to the pageant # process via the Windows messaging subsystem. The result is # cached, to be returned piece-wise when #read is called. def send_query(query) res = nil filemap = 0 ptr = nil id = DL::PtrData.malloc(DL.sizeof("L")) mapname = "PageantRequest%08x\000" % Win.getCurrentThreadId() filemap = Win.createFileMapping(Win::INVALID_HANDLE_VALUE, Win::NULL, Win::PAGE_READWRITE, 0, AGENT_MAX_MSGLEN, mapname) if filemap == 0 raise Net::SSH::Exception, "Creation of file mapping failed" end ptr = Win.mapViewOfFile(filemap, Win::FILE_MAP_WRITE, 0, 0, AGENT_MAX_MSGLEN) if ptr.nil? || ptr.null? raise Net::SSH::Exception, "Mapping of file failed" end ptr[0] = query cds = [AGENT_COPYDATA_ID, mapname.size + 1, mapname]. pack("LLp").to_ptr succ = Win.sendMessageTimeout(@win, Win::WM_COPYDATA, Win::NULL, cds, Win::SMTO_NORMAL, 5000, id) if succ > 0 retlen = 4 + ptr.to_s(4).unpack("N")[0] res = ptr.to_s(retlen) end return res ensure Win.unmapViewOfFile(ptr) unless ptr.nil? || ptr.null? Win.closeHandle(filemap) if filemap != 0 end # Conceptually close the socket. This doesn't really do anthing # significant, but merely complies with the Socket interface. def close @res = nil @pos = 0 end # Conceptually asks if the socket is closed. As with #close, # this doesn't really do anything significant, but merely # complies with the Socket interface. def closed? @res.nil? && @pos.zero? end # Reads +n+ bytes from the cached result of the last query. If +n+ # is +nil+, returns all remaining data from the last query. def read(n = nil) return nil unless @res if n.nil? start, @pos = @pos, @res.size return @res[start..-1] else start, @pos = @pos, @pos + n return @res[start, n] end end end # Socket changes for Ruby 1.9 # Functionality is the same as Ruby 1.8 but it includes the new calls to # the DL module as well as other pointer transformations class Socket19 < Socket # Packages the given query string and sends it to the pageant # process via the Windows messaging subsystem. The result is # cached, to be returned piece-wise when #read is called. def send_query(query) res = nil filemap = 0 ptr = nil id = DL.malloc(DL::SIZEOF_LONG) mapname = "PageantRequest%08x\000" % Win.GetCurrentThreadId() filemap = Win.CreateFileMapping(Win::INVALID_HANDLE_VALUE, Win::NULL, Win::PAGE_READWRITE, 0, AGENT_MAX_MSGLEN, mapname) if filemap == 0 || filemap == Win::INVALID_HANDLE_VALUE raise Net::SSH::Exception, "Creation of file mapping failed" end ptr = Win.MapViewOfFile(filemap, Win::FILE_MAP_WRITE, 0, 0, 0) if ptr.nil? || ptr.null? raise Net::SSH::Exception, "Mapping of file failed" end DL::CPtr.new(ptr)[0,query.size]=query cds = DL::CPtr.to_ptr [AGENT_COPYDATA_ID, mapname.size + 1, mapname]. pack("LLp") succ = Win.SendMessageTimeout(@win, Win::WM_COPYDATA, Win::NULL, cds, Win::SMTO_NORMAL, 5000, id) if succ > 0 retlen = 4 + ptr.to_s(4).unpack("N")[0] res = ptr.to_s(retlen) end return res ensure Win.UnmapViewOfFile(ptr) unless ptr.nil? || ptr.null? Win.CloseHandle(filemap) if filemap != 0 end end # Selects which socket to use depending on the ruby version # This is needed due changes in the DL module. def self.socket_factory if RUBY_VERSION < "1.9" Socket else Socket19 end end end end; end; end net-ssh-2.6.8/lib/net/ssh/authentication/agent.rb0000644000004100000410000000132312166626376021751 0ustar www-datawww-datarequire 'net/ssh/buffer' require 'net/ssh/errors' require 'net/ssh/loggable' module Net; module SSH; module Authentication PLATFORM = File::ALT_SEPARATOR \ ? RUBY_PLATFORM =~ /java/ ? :java_win32 : :win32 \ : RUBY_PLATFORM =~ /java/ ? :java : :unix # A trivial exception class for representing agent-specific errors. class AgentError < Net::SSH::Exception; end # An exception for indicating that the SSH agent is not available. class AgentNotAvailable < AgentError; end end; end; end case Net::SSH::Authentication::PLATFORM when :java_win32 # Java pageant requires whole different agent. require 'net/ssh/authentication/agent/java_pageant' else require 'net/ssh/authentication/agent/socket' end net-ssh-2.6.8/lib/net/ssh/authentication/constants.rb0000644000004100000410000000106712166626376022674 0ustar www-datawww-datamodule Net; module SSH; module Authentication # Describes the constants used by the Net::SSH::Authentication components # of the Net::SSH library. Individual authentication method implemenations # may define yet more constants that are specific to their implementation. module Constants USERAUTH_REQUEST = 50 USERAUTH_FAILURE = 51 USERAUTH_SUCCESS = 52 USERAUTH_BANNER = 53 USERAUTH_PASSWD_CHANGEREQ = 60 USERAUTH_PK_OK = 60 USERAUTH_METHOD_RANGE = 60..79 end end; end; endnet-ssh-2.6.8/lib/net/ssh/authentication/agent/0000755000004100000410000000000012166626376021425 5ustar www-datawww-datanet-ssh-2.6.8/lib/net/ssh/authentication/agent/java_pageant.rb0000644000004100000410000000557012166626376024401 0ustar www-datawww-datarequire 'jruby_pageant' module Net; module SSH; module Authentication # This class implements an agent for JRuby + Pageant. # # Written by Artūras Šlajus class Agent include Loggable include JRubyPageant # A simple module for extending keys, to allow blobs and comments to be # specified for them. module Key # :blob is used by OpenSSL::PKey::RSA#to_blob attr_accessor :java_blob attr_accessor :comment end # Instantiates a new agent object, connects to a running SSH agent, # negotiates the agent protocol version, and returns the agent object. def self.connect(logger=nil) agent = new(logger) agent.connect! agent end # Creates a new Agent object, using the optional logger instance to # report status. def initialize(logger=nil) self.logger = logger end # Connect to the agent process using the socket factory and socket name # given by the attribute writers. If the agent on the other end of the # socket reports that it is an SSH2-compatible agent, this will fail # (it only supports the ssh-agent distributed by OpenSSH). def connect! debug { "connecting to Pageant ssh-agent (via java connector)" } @agent_proxy = JRubyPageant.create unless @agent_proxy.is_running raise AgentNotAvailable, "Pageant is not running!" end debug { "connection to Pageant ssh-agent (via java connector) succeeded" } rescue AgentProxyException => e error { "could not connect to Pageant ssh-agent (via java connector)" } raise AgentNotAvailable, e.message, e.backtrace end # Return an array of all identities (public keys) known to the agent. # Each key returned is augmented with a +comment+ property which is set # to the comment returned by the agent for that key. def identities debug { "getting identities from Pageant" } @agent_proxy.get_identities.map do |identity| blob = identity.get_blob key = Buffer.new(String.from_java_bytes(blob)).read_key key.extend(Key) key.java_blob = blob key.comment = String.from_java_bytes(identity.get_comment) key end rescue AgentProxyException => e raise AgentError, "Cannot get identities: #{e.message}", e.backtrace end # Simulate agent close. This agent reference is no longer able to # query the agent. def close @agent_proxy = nil end # Using the agent and the given public key, sign the given data. The # signature is returned in SSH2 format. def sign(key, data) signed = @agent_proxy.sign(key.java_blob, data.to_java_bytes) String.from_java_bytes(signed) rescue AgentProxyException => e raise AgentError, "agent could not sign data with requested identity: #{e.message}", e.backtrace end end end; end; end net-ssh-2.6.8/lib/net/ssh/authentication/agent/socket.rb0000644000004100000410000001324312166626376023245 0ustar www-datawww-datarequire 'net/ssh/transport/server_version' # Only load pageant on Windows if Net::SSH::Authentication::PLATFORM == :win32 require 'net/ssh/authentication/pageant' end module Net; module SSH; module Authentication # This class implements a simple client for the ssh-agent protocol. It # does not implement any specific protocol, but instead copies the # behavior of the ssh-agent functions in the OpenSSH library (3.8). # # This means that although it behaves like a SSH1 client, it also has # some SSH2 functionality (like signing data). class Agent include Loggable # A simple module for extending keys, to allow comments to be specified # for them. module Comment attr_accessor :comment end SSH2_AGENT_REQUEST_VERSION = 1 SSH2_AGENT_REQUEST_IDENTITIES = 11 SSH2_AGENT_IDENTITIES_ANSWER = 12 SSH2_AGENT_SIGN_REQUEST = 13 SSH2_AGENT_SIGN_RESPONSE = 14 SSH2_AGENT_FAILURE = 30 SSH2_AGENT_VERSION_RESPONSE = 103 SSH_COM_AGENT2_FAILURE = 102 SSH_AGENT_REQUEST_RSA_IDENTITIES = 1 SSH_AGENT_RSA_IDENTITIES_ANSWER1 = 2 SSH_AGENT_RSA_IDENTITIES_ANSWER2 = 5 SSH_AGENT_FAILURE = 5 # The underlying socket being used to communicate with the SSH agent. attr_reader :socket # Instantiates a new agent object, connects to a running SSH agent, # negotiates the agent protocol version, and returns the agent object. def self.connect(logger=nil) agent = new(logger) agent.connect! agent.negotiate! agent end # Creates a new Agent object, using the optional logger instance to # report status. def initialize(logger=nil) self.logger = logger end # Connect to the agent process using the socket factory and socket name # given by the attribute writers. If the agent on the other end of the # socket reports that it is an SSH2-compatible agent, this will fail # (it only supports the ssh-agent distributed by OpenSSH). def connect! begin debug { "connecting to ssh-agent" } @socket = agent_socket_factory.open(ENV['SSH_AUTH_SOCK']) rescue error { "could not connect to ssh-agent" } raise AgentNotAvailable, $!.message end end # Attempts to negotiate the SSH agent protocol version. Raises an error # if the version could not be negotiated successfully. def negotiate! # determine what type of agent we're communicating with type, body = send_and_wait(SSH2_AGENT_REQUEST_VERSION, :string, Transport::ServerVersion::PROTO_VERSION) if type == SSH2_AGENT_VERSION_RESPONSE raise NotImplementedError, "SSH2 agents are not yet supported" elsif type != SSH_AGENT_RSA_IDENTITIES_ANSWER1 && type != SSH_AGENT_RSA_IDENTITIES_ANSWER2 raise AgentError, "unknown response from agent: #{type}, #{body.to_s.inspect}" end end # Return an array of all identities (public keys) known to the agent. # Each key returned is augmented with a +comment+ property which is set # to the comment returned by the agent for that key. def identities type, body = send_and_wait(SSH2_AGENT_REQUEST_IDENTITIES) raise AgentError, "could not get identity count" if agent_failed(type) raise AgentError, "bad authentication reply: #{type}" if type != SSH2_AGENT_IDENTITIES_ANSWER identities = [] body.read_long.times do key = Buffer.new(body.read_string).read_key key.extend(Comment) key.comment = body.read_string identities.push key end return identities end # Closes this socket. This agent reference is no longer able to # query the agent. def close @socket.close end # Using the agent and the given public key, sign the given data. The # signature is returned in SSH2 format. def sign(key, data) type, reply = send_and_wait(SSH2_AGENT_SIGN_REQUEST, :string, Buffer.from(:key, key), :string, data, :long, 0) if agent_failed(type) raise AgentError, "agent could not sign data with requested identity" elsif type != SSH2_AGENT_SIGN_RESPONSE raise AgentError, "bad authentication response #{type}" end return reply.read_string end private # Returns the agent socket factory to use. def agent_socket_factory if Net::SSH::Authentication::PLATFORM == :win32 Pageant::socket_factory else UNIXSocket end end # Send a new packet of the given type, with the associated data. def send_packet(type, *args) buffer = Buffer.from(*args) data = [buffer.length + 1, type.to_i, buffer.to_s].pack("NCA*") debug { "sending agent request #{type} len #{buffer.length}" } @socket.send data, 0 end # Read the next packet from the agent. This will return a two-part # tuple consisting of the packet type, and the packet's body (which # is returned as a Net::SSH::Buffer). def read_packet buffer = Net::SSH::Buffer.new(@socket.read(4)) buffer.append(@socket.read(buffer.read_long)) type = buffer.read_byte debug { "received agent packet #{type} len #{buffer.length-4}" } return type, buffer end # Send the given packet and return the subsequent reply from the agent. # (See #send_packet and #read_packet). def send_and_wait(type, *args) send_packet(type, *args) read_packet end # Returns +true+ if the parameter indicates a "failure" response from # the agent, and +false+ otherwise. def agent_failed(type) type == SSH_AGENT_FAILURE || type == SSH2_AGENT_FAILURE || type == SSH_COM_AGENT2_FAILURE end end end; end; end net-ssh-2.6.8/lib/net/ssh/authentication/methods/0000755000004100000410000000000012166626376021772 5ustar www-datawww-datanet-ssh-2.6.8/lib/net/ssh/authentication/methods/abstract.rb0000644000004100000410000000350712166626376024127 0ustar www-datawww-datarequire 'net/ssh/buffer' require 'net/ssh/errors' require 'net/ssh/loggable' require 'net/ssh/authentication/constants' module Net; module SSH; module Authentication; module Methods # The base class of all user authentication methods. It provides a few # bits of common functionality. class Abstract include Constants, Loggable # The authentication session object attr_reader :session # The key manager object. Not all authentication methods will require # this. attr_reader :key_manager # Instantiates a new authentication method. def initialize(session, options={}) @session = session @key_manager = options[:key_manager] @options = options self.logger = session.logger end # Returns the session-id, as generated during the first key exchange of # an SSH connection. def session_id session.transport.algorithms.session_id end # Sends a message via the underlying transport layer abstraction. This # will block until the message is completely sent. def send_message(msg) session.transport.send_message(msg) end # Creates a new USERAUTH_REQUEST packet. The extra arguments on the end # must be either boolean values or strings, and are tacked onto the end # of the packet. The new packet is returned, ready for sending. def userauth_request(username, next_service, auth_method, *others) buffer = Net::SSH::Buffer.from(:byte, USERAUTH_REQUEST, :string, username, :string, next_service, :string, auth_method) others.each do |value| case value when true, false then buffer.write_bool(value) when String then buffer.write_string(value) else raise ArgumentError, "don't know how to write #{value.inspect}" end end buffer end end end; end; end; endnet-ssh-2.6.8/lib/net/ssh/authentication/methods/none.rb0000644000004100000410000000213312166626376023255 0ustar www-datawww-datarequire 'net/ssh/errors' require 'net/ssh/authentication/methods/abstract' module Net module SSH module Authentication module Methods # Implements the "none" SSH authentication method. class None < Abstract # Attempt to authenticate as "none" def authenticate(next_service, user="", password="") send_message(userauth_request(user, next_service, "none")) message = session.next_message case message.type when USERAUTH_SUCCESS debug { "none succeeded" } return true when USERAUTH_FAILURE debug { "none failed" } raise Net::SSH::Authentication::DisallowedMethod unless message[:authentications].split(/,/).include? 'none' return false else raise Net::SSH::Exception, "unexpected reply to USERAUTH_REQUEST: #{message.type} (#{message.inspect})" end end end end end end end net-ssh-2.6.8/lib/net/ssh/authentication/methods/publickey.rb0000644000004100000410000000702612166626376024313 0ustar www-datawww-datarequire 'net/ssh/buffer' require 'net/ssh/errors' require 'net/ssh/authentication/methods/abstract' module Net module SSH module Authentication module Methods # Implements the "publickey" SSH authentication method. class Publickey < Abstract # Attempts to perform public-key authentication for the given # username, trying each identity known to the key manager. If any of # them succeed, returns +true+, otherwise returns +false+. This # requires the presence of a key manager. def authenticate(next_service, username, password=nil) return false unless key_manager key_manager.each_identity do |identity| return true if authenticate_with(identity, next_service, username) end return false end private # Builds a packet that contains the request formatted for sending # a public-key request to the server. def build_request(pub_key, username, next_service, has_sig) blob = Net::SSH::Buffer.new blob.write_key pub_key userauth_request(username, next_service, "publickey", has_sig, pub_key.ssh_type, blob.to_s) end # Builds and sends a request formatted for a public-key # authentication request. def send_request(pub_key, username, next_service, signature=nil) msg = build_request(pub_key, username, next_service, !signature.nil?) msg.write_string(signature) if signature send_message(msg) end # Attempts to perform public-key authentication for the given # username, with the given identity (public key). Returns +true+ if # successful, or +false+ otherwise. def authenticate_with(identity, next_service, username) debug { "trying publickey (#{identity.fingerprint})" } send_request(identity, username, next_service) message = session.next_message case message.type when USERAUTH_PK_OK buffer = build_request(identity, username, next_service, true) sig_data = Net::SSH::Buffer.new sig_data.write_string(session_id) sig_data.append(buffer.to_s) sig_blob = key_manager.sign(identity, sig_data) send_request(identity, username, next_service, sig_blob.to_s) message = session.next_message case message.type when USERAUTH_SUCCESS debug { "publickey succeeded (#{identity.fingerprint})" } return true when USERAUTH_FAILURE debug { "publickey failed (#{identity.fingerprint})" } raise Net::SSH::Authentication::DisallowedMethod unless message[:authentications].split(/,/).include? 'publickey' return false else raise Net::SSH::Exception, "unexpected server response to USERAUTH_REQUEST: #{message.type} (#{message.inspect})" end when USERAUTH_FAILURE return false else raise Net::SSH::Exception, "unexpected reply to USERAUTH_REQUEST: #{message.type} (#{message.inspect})" end end end end end end end net-ssh-2.6.8/lib/net/ssh/authentication/methods/password.rb0000644000004100000410000000262212166626376024163 0ustar www-datawww-datarequire 'net/ssh/errors' require 'net/ssh/authentication/methods/abstract' module Net module SSH module Authentication module Methods # Implements the "password" SSH authentication method. class Password < Abstract # Attempt to authenticate the given user for the given service. If # the password parameter is nil, this will never do anything except # return false. def authenticate(next_service, username, password=nil) return false unless password send_message(userauth_request(username, next_service, "password", false, password)) message = session.next_message case message.type when USERAUTH_SUCCESS debug { "password succeeded" } return true when USERAUTH_FAILURE debug { "password failed" } raise Net::SSH::Authentication::DisallowedMethod unless message[:authentications].split(/,/).include? 'password' return false when USERAUTH_PASSWD_CHANGEREQ debug { "password change request received, failing" } return false else raise Net::SSH::Exception, "unexpected reply to USERAUTH_REQUEST: #{message.type} (#{message.inspect})" end end end end end end end net-ssh-2.6.8/lib/net/ssh/authentication/methods/keyboard_interactive.rb0000644000004100000410000000447012166626376026521 0ustar www-datawww-datarequire 'net/ssh/prompt' require 'net/ssh/authentication/methods/abstract' module Net module SSH module Authentication module Methods # Implements the "keyboard-interactive" SSH authentication method. class KeyboardInteractive < Abstract include Prompt USERAUTH_INFO_REQUEST = 60 USERAUTH_INFO_RESPONSE = 61 # Attempt to authenticate the given user for the given service. def authenticate(next_service, username, password=nil) debug { "trying keyboard-interactive" } send_message(userauth_request(username, next_service, "keyboard-interactive", "", "")) loop do message = session.next_message case message.type when USERAUTH_SUCCESS debug { "keyboard-interactive succeeded" } return true when USERAUTH_FAILURE debug { "keyboard-interactive failed" } raise Net::SSH::Authentication::DisallowedMethod unless message[:authentications].split(/,/).include? 'keyboard-interactive' return false when USERAUTH_INFO_REQUEST name = message.read_string instruction = message.read_string debug { "keyboard-interactive info request" } unless password puts(name) unless name.empty? puts(instruction) unless instruction.empty? end _ = message.read_string # lang_tag responses =[] message.read_long.times do text = message.read_string echo = message.read_bool responses << (password || prompt(text, echo)) end # if the password failed the first time around, don't try # and use it on subsequent requests. password = nil msg = Buffer.from(:byte, USERAUTH_INFO_RESPONSE, :long, responses.length, :string, responses) send_message(msg) else raise Net::SSH::Exception, "unexpected reply in keyboard interactive: #{message.type} (#{message.inspect})" end end end end end end end end net-ssh-2.6.8/lib/net/ssh/authentication/methods/hostbased.rb0000644000004100000410000000506512166626376024301 0ustar www-datawww-datarequire 'net/ssh/authentication/methods/abstract' module Net module SSH module Authentication module Methods # Implements the host-based SSH authentication method. class Hostbased < Abstract include Constants # Attempts to perform host-based authorization of the user by trying # all known keys. def authenticate(next_service, username, password=nil) return false unless key_manager key_manager.each_identity do |identity| return true if authenticate_with(identity, next_service, username, key_manager) end return false end private # Returns the hostname as reported by the underlying socket. def hostname session.transport.socket.client_name end # Attempts to perform host-based authentication of the user, using # the given host identity (key). def authenticate_with(identity, next_service, username, key_manager) debug { "trying hostbased (#{identity.fingerprint})" } client_username = ENV['USER'] || username req = build_request(identity, next_service, username, "#{hostname}.", client_username) sig_data = Buffer.from(:string, session_id, :raw, req) sig = key_manager.sign(identity, sig_data.to_s) message = Buffer.from(:raw, req, :string, sig) send_message(message) message = session.next_message case message.type when USERAUTH_SUCCESS info { "hostbased succeeded (#{identity.fingerprint})" } return true when USERAUTH_FAILURE info { "hostbased failed (#{identity.fingerprint})" } raise Net::SSH::Authentication::DisallowedMethod unless message[:authentications].split(/,/).include? 'hostbased' return false else raise Net::SSH::Exception, "unexpected server response to USERAUTH_REQUEST: #{message.type} (#{message.inspect})" end end # Build the "core" hostbased request string. def build_request(identity, next_service, username, hostname, client_username) userauth_request(username, next_service, "hostbased", identity.ssh_type, Buffer.from(:key, identity).to_s, hostname, client_username).to_s end end end end end end net-ssh-2.6.8/lib/net/ssh/prompt.rb0000644000004100000410000000563212166626376017164 0ustar www-datawww-datamodule Net; module SSH # A basic prompt module that can be mixed into other objects. If HighLine is # installed, it will be used to display prompts and read input from the # user. Otherwise, the termios library will be used. If neither HighLine # nor termios is installed, a simple prompt that echos text in the clear # will be used. module PromptMethods # Defines the prompt method to use if the Highline library is installed. module Highline # Uses Highline#ask to present a prompt and accept input. If +echo+ is # +false+, the characters entered by the user will not be echoed to the # screen. def prompt(prompt, echo=true) @highline ||= ::HighLine.new @highline.ask(prompt + " ") { |q| q.echo = echo } end end # Defines the prompt method to use if the Termios library is installed. module Termios # Displays the prompt to $stdout. If +echo+ is false, the Termios # library will be used to disable keystroke echoing for the duration of # this method. def prompt(prompt, echo=true) $stdout.print(prompt) $stdout.flush set_echo(false) unless echo $stdin.gets.chomp ensure if !echo set_echo(true) $stdout.puts end end private # Enables or disables keystroke echoing using the Termios library. def set_echo(enable) term = ::Termios.getattr($stdin) if enable term.c_lflag |= (::Termios::ECHO | ::Termios::ICANON) else term.c_lflag &= ~::Termios::ECHO end ::Termios.setattr($stdin, ::Termios::TCSANOW, term) end end # Defines the prompt method to use when neither Highline nor Termios are # installed. module Clear # Displays the prompt to $stdout and pulls the response from $stdin. # Text is always echoed in the clear, regardless of the +echo+ setting. # The first time a prompt is given and +echo+ is false, a warning will # be written to $stderr recommending that either Highline or Termios # be installed. def prompt(prompt, echo=true) @seen_warning ||= false if !echo && !@seen_warning $stderr.puts "Text will be echoed in the clear. Please install the HighLine or Termios libraries to suppress echoed text." @seen_warning = true end $stdout.print(prompt) $stdout.flush $stdin.gets.chomp end end end # Try to load Highline and Termios in turn, selecting the corresponding # PromptMethods module to use. If neither are available, choose PromptMethods::Clear. Prompt = begin require 'highline' HighLine.track_eof = false PromptMethods::Highline rescue LoadError begin require 'termios' PromptMethods::Termios rescue LoadError PromptMethods::Clear end end end; endnet-ssh-2.6.8/lib/net/ssh/config.rb0000644000004100000410000001652212166626376017110 0ustar www-datawww-datamodule Net; module SSH # The Net::SSH::Config class is used to parse OpenSSH configuration files, # and translates that syntax into the configuration syntax that Net::SSH # understands. This lets Net::SSH scripts read their configuration (to # some extent) from OpenSSH configuration files (~/.ssh/config, /etc/ssh_config, # and so forth). # # Only a subset of OpenSSH configuration options are understood: # # * Ciphers => maps to the :encryption option # * Compression => :compression # * CompressionLevel => :compression_level # * ConnectTimeout => maps to the :timeout option # * ForwardAgent => :forward_agent # * GlobalKnownHostsFile => :global_known_hosts_file # * HostBasedAuthentication => maps to the :auth_methods option # * HostKeyAlgorithms => maps to :host_key option # * HostKeyAlias => :host_key_alias # * HostName => :host_name # * IdentityFile => maps to the :keys option # * IdentitiesOnly => :keys_only # * Macs => maps to the :hmac option # * PasswordAuthentication => maps to the :auth_methods option # * Port => :port # * PreferredAuthentications => maps to the :auth_methods option # * ProxyCommand => maps to the :proxy option # * RekeyLimit => :rekey_limit # * User => :user # * UserKnownHostsFile => :user_known_hosts_file # # Note that you will never need to use this class directly--you can control # whether the OpenSSH configuration files are read by passing the :config # option to Net::SSH.start. (They are, by default.) class Config class << self @@default_files = %w(~/.ssh/config /etc/ssh_config /etc/ssh/ssh_config) # Returns an array of locations of OpenSSH configuration files # to parse by default. def default_files @@default_files end # Loads the configuration data for the given +host+ from all of the # given +files+ (defaulting to the list of files returned by # #default_files), translates the resulting hash into the options # recognized by Net::SSH, and returns them. def for(host, files=default_files) translate(files.inject({}) { |settings, file| load(file, host, settings) }) end # Load the OpenSSH configuration settings in the given +file+ for the # given +host+. If +settings+ is given, the options are merged into # that hash, with existing values taking precedence over newly parsed # ones. Returns a hash containing the OpenSSH options. (See # #translate for how to convert the OpenSSH options into Net::SSH # options.) def load(path, host, settings={}) file = File.expand_path(path) return settings unless File.readable?(file) globals = {} matched_host = nil multi_host = [] seen_host = false IO.foreach(file) do |line| next if line =~ /^\s*(?:#.*)?$/ if line =~ /^\s*(\S+)\s*=(.*)$/ key, value = $1, $2 else key, value = line.strip.split(/\s+/, 2) end # silently ignore malformed entries next if value.nil? key.downcase! value = $1 if value =~ /^"(.*)"$/ value = case value.strip when /^\d+$/ then value.to_i when /^no$/i then false when /^yes$/i then true else value end if key == 'host' # Support "Host host1 host2 hostN". # See http://github.com/net-ssh/net-ssh/issues#issue/6 multi_host = value.to_s.split(/\s+/) matched_host = multi_host.select { |h| host =~ pattern2regex(h) }.first seen_host = true settings[key] = host elsif !seen_host if key == 'identityfile' (globals[key] ||= []) << value else globals[key] = value unless settings.key?(key) end elsif !matched_host.nil? if key == 'identityfile' (settings[key] ||= []) << value else settings[key] = value unless settings.key?(key) end end end settings = globals.merge(settings) if globals return settings end # Given a hash of OpenSSH configuration options, converts them into # a hash of Net::SSH options. Unrecognized options are ignored. The # +settings+ hash must have Strings for keys, all downcased, and # the returned hash will have Symbols for keys. def translate(settings) settings.inject({}) do |hash, (key, value)| case key when 'bindaddress' then hash[:bind_address] = value when 'ciphers' then hash[:encryption] = value.split(/,/) when 'compression' then hash[:compression] = value when 'compressionlevel' then hash[:compression_level] = value when 'connecttimeout' then hash[:timeout] = value when 'forwardagent' then hash[:forward_agent] = value when 'identitiesonly' then hash[:keys_only] = value when 'globalknownhostsfile' hash[:global_known_hosts_file] = value when 'hostbasedauthentication' then if value hash[:auth_methods] ||= [] hash[:auth_methods] << "hostbased" end when 'hostkeyalgorithms' then hash[:host_key] = value.split(/,/) when 'hostkeyalias' then hash[:host_key_alias] = value when 'hostname' then hash[:host_name] = value.gsub(/%h/, settings['host']) when 'identityfile' then hash[:keys] = value when 'macs' then hash[:hmac] = value.split(/,/) when 'passwordauthentication' if value hash[:auth_methods] ||= [] hash[:auth_methods] << "password" end when 'port' hash[:port] = value when 'preferredauthentications' hash[:auth_methods] = value.split(/,/) when 'proxycommand' if value and !(value =~ /^none$/) require 'net/ssh/proxy/command' hash[:proxy] = Net::SSH::Proxy::Command.new(value) end when 'pubkeyauthentication' if value hash[:auth_methods] ||= [] hash[:auth_methods] << "publickey" end when 'rekeylimit' hash[:rekey_limit] = interpret_size(value) when 'user' hash[:user] = value when 'userknownhostsfile' hash[:user_known_hosts_file] = value end hash end end private # Converts an ssh_config pattern into a regex for matching against # host names. def pattern2regex(pattern) pattern = "^" + pattern.to_s.gsub(/\./, "\\."). gsub(/\?/, '.'). gsub(/([+\/])/, '\\\\\\0'). gsub(/\*/, '.*') + "$" Regexp.new(pattern, true) end # Converts the given size into an integer number of bytes. def interpret_size(size) case size when /k$/i then size.to_i * 1024 when /m$/i then size.to_i * 1024 * 1024 when /g$/i then size.to_i * 1024 * 1024 * 1024 else size.to_i end end end end end; end net-ssh-2.6.8/lib/net/ssh/verifiers/0000755000004100000410000000000012166626376017306 5ustar www-datawww-datanet-ssh-2.6.8/lib/net/ssh/verifiers/strict.rb0000644000004100000410000000135512166626376021147 0ustar www-datawww-datarequire 'net/ssh/errors' require 'net/ssh/known_hosts' require 'net/ssh/verifiers/secure' module Net; module SSH; module Verifiers # Does a strict host verification, looking the server up in the known # host files to see if a key has already been seen for this server. If this # server does not appear in any host file, this will silently add the # server. If the server does appear at least once, but the key given does # not match any known for the server, an exception will be raised (HostKeyMismatch). # Otherwise, this returns true. class Strict < Secure def verify(arguments) begin super rescue HostKeyUnknown => err err.remember_host! return true end end end end; end; end net-ssh-2.6.8/lib/net/ssh/verifiers/null.rb0000644000004100000410000000043512166626376020607 0ustar www-datawww-datamodule Net; module SSH; module Verifiers # The Null host key verifier simply allows every key it sees, without # bothering to verify. This is simple, but is not particularly secure. class Null # Returns true. def verify(arguments) true end end end; end; endnet-ssh-2.6.8/lib/net/ssh/verifiers/lenient.rb0000644000004100000410000000204412166626376021271 0ustar www-datawww-datarequire 'net/ssh/verifiers/strict' module Net; module SSH; module Verifiers # Basically the same as the Strict verifier, but does not try to actually # verify a connection if the server is the localhost and the port is a # nonstandard port number. Those two conditions will typically mean the # connection is being tunnelled through a forwarded port, so the known-hosts # file will not be helpful (in general). class Lenient < Strict # Tries to determine if the connection is being tunnelled, and if so, # returns true. Otherwise, performs the standard strict verification. def verify(arguments) return true if tunnelled?(arguments) super end private # A connection is potentially being tunnelled if the port is not 22, # and the ip refers to the localhost. def tunnelled?(args) return false if args[:session].port == Net::SSH::Transport::Session::DEFAULT_PORT ip = args[:session].peer[:ip] return ip == "127.0.0.1" || ip == "::1" end end end; end; endnet-ssh-2.6.8/lib/net/ssh/verifiers/secure.rb0000644000004100000410000000365412166626376021131 0ustar www-datawww-datarequire 'net/ssh/errors' require 'net/ssh/known_hosts' module Net; module SSH; module Verifiers # Does a strict host verification, looking the server up in the known # host files to see if a key has already been seen for this server. If this # server does not appear in any host file, an exception will be raised # (HostKeyUnknown). This is in contrast to the "Strict" class, which will # silently add the key to your known_hosts file. If the server does appear at # least once, but the key given does not match any known for the server, an # exception will be raised (HostKeyMismatch). # Otherwise, this returns true. class Secure def verify(arguments) options = arguments[:session].options host = options[:host_key_alias] || arguments[:session].host_as_string matches = Net::SSH::KnownHosts.search_for(host, arguments[:session].options) # We've never seen this host before, so raise an exception. if matches.empty? process_cache_miss(host, arguments, HostKeyUnknown, "is unknown") end # If we found any matches, check to see that the key type and # blob also match. found = matches.any? do |key| key.ssh_type == arguments[:key].ssh_type && key.to_blob == arguments[:key].to_blob end # If a match was found, return true. Otherwise, raise an exception # indicating that the key was not recognized. unless found process_cache_miss(host, arguments, HostKeyMismatch, "does not match") end found end private def process_cache_miss(host, args, exc_class, message) exception = exc_class.new("fingerprint #{args[:fingerprint]} " + "#{message} for #{host.inspect}") exception.data = args exception.callback = Proc.new do Net::SSH::KnownHosts.add(host, args[:key], args[:session].options) end raise exception end end end; end; end net-ssh-2.6.8/lib/net/ssh/key_factory.rb0000644000004100000410000001054212166626376020156 0ustar www-datawww-datarequire 'net/ssh/transport/openssl' require 'net/ssh/prompt' module Net; module SSH # A factory class for returning new Key classes. It is used for obtaining # OpenSSL key instances via their SSH names, and for loading both public and # private keys. It used used primarily by Net::SSH itself, internally, and # will rarely (if ever) be directly used by consumers of the library. # # klass = Net::SSH::KeyFactory.get("rsa") # assert klass.is_a?(OpenSSL::PKey::RSA) # # key = Net::SSH::KeyFactory.load_public_key("~/.ssh/id_dsa.pub") class KeyFactory # Specifies the mapping of SSH names to OpenSSL key classes. MAP = { "dh" => OpenSSL::PKey::DH, "rsa" => OpenSSL::PKey::RSA, "dsa" => OpenSSL::PKey::DSA, } if defined?(OpenSSL::PKey::EC) MAP["ecdsa"] = OpenSSL::PKey::EC end class < proxy) do |ssh| # ... # end class Command # The command line template attr_reader :command_line_template # The command line for the session attr_reader :command_line # Create a new socket factory that tunnels via a command executed # with the user's shell, which is composed from the given command # template. In the command template, `%h' will be substituted by # the host name to connect and `%p' by the port. def initialize(command_line_template) @command_line_template = command_line_template @command_line = nil end # Return a new socket connected to the given host and port via the # proxy that was requested when the socket factory was instantiated. def open(host, port) command_line = @command_line_template.gsub(/%(.)/) { case $1 when 'h' host when 'p' port.to_s when '%' '%' else raise ArgumentError, "unknown key: #{$1}" end } begin io = IO.popen(command_line, "r+") if result = Net::SSH::Compat.io_select([io], nil, [io], 60) if result.last.any? raise "command failed" end else raise "command timed out" end rescue => e raise ConnectError, "#{e}: #{command_line}" end @command_line = command_line class << io def send(data, flag) write_nonblock(data) end def recv(size) read_nonblock(size) end end io end end end; end; end net-ssh-2.6.8/lib/net/ssh/proxy/socks5.rb0000644000004100000410000001054612166626376020233 0ustar www-datawww-datarequire 'socket' require 'net/ssh/ruby_compat' require 'net/ssh/proxy/errors' module Net module SSH module Proxy # An implementation of a SOCKS5 proxy. To use it, instantiate it, then # pass the instantiated object via the :proxy key to Net::SSH.start: # # require 'net/ssh/proxy/socks5' # # proxy = Net::SSH::Proxy::SOCKS5.new('proxy.host', proxy_port, # :user => 'user', :password => "password") # Net::SSH.start('host', 'user', :proxy => proxy) do |ssh| # ... # end class SOCKS5 # The SOCKS protocol version used by this class VERSION = 5 # The SOCKS authentication type for requests without authentication METHOD_NO_AUTH = 0 # The SOCKS authentication type for requests via username/password METHOD_PASSWD = 2 # The SOCKS authentication type for when there are no supported # authentication methods. METHOD_NONE = 0xFF # The SOCKS packet type for requesting a proxy connection. CMD_CONNECT = 1 # The SOCKS address type for connections via IP address. ATYP_IPV4 = 1 # The SOCKS address type for connections via domain name. ATYP_DOMAIN = 3 # The SOCKS response code for a successful operation. SUCCESS = 0 # The proxy's host name or IP address attr_reader :proxy_host # The proxy's port number attr_reader :proxy_port # The map of options given at initialization attr_reader :options # Create a new proxy connection to the given proxy host and port. # Optionally, :user and :password options may be given to # identify the username and password with which to authenticate. def initialize(proxy_host, proxy_port=1080, options={}) @proxy_host = proxy_host @proxy_port = proxy_port @options = options end # Return a new socket connected to the given host and port via the # proxy that was requested when the socket factory was instantiated. def open(host, port) socket = TCPSocket.new(proxy_host, proxy_port) methods = [METHOD_NO_AUTH] methods << METHOD_PASSWD if options[:user] packet = [VERSION, methods.size, *methods].pack("C*") socket.send packet, 0 version, method = socket.recv(2).unpack("CC") if version != VERSION socket.close raise Net::SSH::Proxy::Error, "invalid SOCKS version (#{version})" end if method == METHOD_NONE socket.close raise Net::SSH::Proxy::Error, "no supported authorization methods" end negotiate_password(socket) if method == METHOD_PASSWD packet = [VERSION, CMD_CONNECT, 0].pack("C*") if host =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/ packet << [ATYP_IPV4, $1.to_i, $2.to_i, $3.to_i, $4.to_i].pack("C*") else packet << [ATYP_DOMAIN, host.length, host].pack("CCA*") end packet << [port].pack("n") socket.send packet, 0 version, reply, = socket.recv(2).unpack("C*") socket.recv(1) address_type = socket.recv(1).getbyte(0) case address_type when 1 socket.recv(4) # get four bytes for IPv4 address when 3 len = socket.recv(1).getbyte(0) hostname = socket.recv(len) when 4 ipv6addr hostname = socket.recv(16) else socket.close raise ConnectionError, "Illegal response type" end portnum = socket.recv(2) unless reply == SUCCESS socket.close raise ConnectError, "#{reply}" end return socket end private # Simple username/password negotiation with the SOCKS5 server. def negotiate_password(socket) packet = [0x01, options[:user].length, options[:user], options[:password].length, options[:password]].pack("CCA*CA*") socket.send packet, 0 version, status = socket.recv(2).unpack("CC") if status != SUCCESS socket.close raise UnauthorizedError, "could not authorize user" end end end end end end net-ssh-2.6.8/lib/net/ssh/proxy/socks4.rb0000644000004100000410000000410512166626376020224 0ustar www-datawww-datarequire 'socket' require 'resolv' require 'ipaddr' require 'net/ssh/proxy/errors' module Net module SSH module Proxy # An implementation of a SOCKS4 proxy. To use it, instantiate it, then # pass the instantiated object via the :proxy key to Net::SSH.start: # # require 'net/ssh/proxy/socks4' # # proxy = Net::SSH::Proxy::SOCKS4.new('proxy.host', proxy_port, :user => 'user') # Net::SSH.start('host', 'user', :proxy => proxy) do |ssh| # ... # end class SOCKS4 # The SOCKS protocol version used by this class VERSION = 4 # The packet type for connection requests CONNECT = 1 # The status code for a successful connection GRANTED = 90 # The proxy's host name or IP address, as given to the constructor. attr_reader :proxy_host # The proxy's port number. attr_reader :proxy_port # The additional options that were given to the proxy's constructor. attr_reader :options # Create a new proxy connection to the given proxy host and port. # Optionally, a :user key may be given to identify the username # with which to authenticate. def initialize(proxy_host, proxy_port=1080, options={}) @proxy_host = proxy_host @proxy_port = proxy_port @options = options end # Return a new socket connected to the given host and port via the # proxy that was requested when the socket factory was instantiated. def open(host, port) socket = TCPSocket.new(proxy_host, proxy_port) ip_addr = IPAddr.new(Resolv.getaddress(host)) packet = [VERSION, CONNECT, port.to_i, ip_addr.to_i, options[:user]].pack("CCnNZ*") socket.send packet, 0 version, status, port, ip = socket.recv(8).unpack("CCnN") if status != GRANTED socket.close raise ConnectError, "error connecting to proxy (#{status})" end return socket end end end end end net-ssh-2.6.8/lib/net/ssh/proxy/errors.rb0000644000004100000410000000055212166626376020334 0ustar www-datawww-datarequire 'net/ssh/errors' module Net; module SSH; module Proxy # A general exception class for all Proxy errors. class Error < Net::SSH::Exception; end # Used for reporting proxy connection errors. class ConnectError < Error; end # Used when the server doesn't recognize the user's credentials. class UnauthorizedError < Error; end end; end; end net-ssh-2.6.8/lib/net/ssh/proxy/http.rb0000644000004100000410000000541012166626376017775 0ustar www-datawww-datarequire 'socket' require 'net/ssh/proxy/errors' module Net; module SSH; module Proxy # An implementation of an HTTP proxy. To use it, instantiate it, then # pass the instantiated object via the :proxy key to Net::SSH.start: # # require 'net/ssh/proxy/http' # # proxy = Net::SSH::Proxy::HTTP.new('proxy.host', proxy_port) # Net::SSH.start('host', 'user', :proxy => proxy) do |ssh| # ... # end # # If the proxy requires authentication, you can pass :user and :password # to the proxy's constructor: # # proxy = Net::SSH::Proxy::HTTP.new('proxy.host', proxy_port, # :user => "user", :password => "password") # # Note that HTTP digest authentication is not supported; Basic only at # this point. class HTTP # The hostname or IP address of the HTTP proxy. attr_reader :proxy_host # The port number of the proxy. attr_reader :proxy_port # The map of additional options that were given to the object at # initialization. attr_reader :options # Create a new socket factory that tunnels via the given host and # port. The +options+ parameter is a hash of additional settings that # can be used to tweak this proxy connection. Specifically, the following # options are supported: # # * :user => the user name to use when authenticating to the proxy # * :password => the password to use when authenticating def initialize(proxy_host, proxy_port=80, options={}) @proxy_host = proxy_host @proxy_port = proxy_port @options = options end # Return a new socket connected to the given host and port via the # proxy that was requested when the socket factory was instantiated. def open(host, port) socket = TCPSocket.new(proxy_host, proxy_port) socket.write "CONNECT #{host}:#{port} HTTP/1.0\r\n" if options[:user] credentials = ["#{options[:user]}:#{options[:password]}"].pack("m*").gsub(/\s/, "") socket.write "Proxy-Authorization: Basic #{credentials}\r\n" end socket.write "\r\n" resp = parse_response(socket) return socket if resp[:code] == 200 socket.close raise ConnectError, resp.inspect end private def parse_response(socket) version, code, reason = socket.gets.chomp.split(/ /, 3) headers = {} while (line = socket.gets.chomp) != "" name, value = line.split(/:/, 2) headers[name.strip] = value.strip end if headers["Content-Length"] body = socket.read(headers["Content-Length"].to_i) end return { :version => version, :code => code.to_i, :reason => reason, :headers => headers, :body => body } end end end; end; end net-ssh-2.6.8/lib/net/ssh/buffer.rb0000644000004100000410000002632612166626376017117 0ustar www-datawww-datarequire 'net/ssh/ruby_compat' require 'net/ssh/transport/openssl' module Net; module SSH # Net::SSH::Buffer is a flexible class for building and parsing binary # data packets. It provides a stream-like interface for sequentially # reading data items from the buffer, as well as a useful helper method # for building binary packets given a signature. # # Writing to a buffer always appends to the end, regardless of where the # read cursor is. Reading, on the other hand, always begins at the first # byte of the buffer and increments the read cursor, with subsequent reads # taking up where the last left off. # # As a consumer of the Net::SSH library, you will rarely come into contact # with these buffer objects directly, but it could happen. Also, if you # are ever implementing a protocol on top of SSH (e.g. SFTP), this buffer # class can be quite handy. class Buffer # This is a convenience method for creating and populating a new buffer # from a single command. The arguments must be even in length, with the # first of each pair of arguments being a symbol naming the type of the # data that follows. If the type is :raw, the value is written directly # to the hash. # # b = Buffer.from(:byte, 1, :string, "hello", :raw, "\1\2\3\4") # #-> "\1\0\0\0\5hello\1\2\3\4" # # The supported data types are: # # * :raw => write the next value verbatim (#write) # * :int64 => write an 8-byte integer (#write_int64) # * :long => write a 4-byte integer (#write_long) # * :byte => write a single byte (#write_byte) # * :string => write a 4-byte length followed by character data (#write_string) # * :bool => write a single byte, interpreted as a boolean (#write_bool) # * :bignum => write an SSH-encoded bignum (#write_bignum) # * :key => write an SSH-encoded key value (#write_key) # # Any of these, except for :raw, accepts an Array argument, to make it # easier to write multiple values of the same type in a briefer manner. def self.from(*args) raise ArgumentError, "odd number of arguments given" unless args.length % 2 == 0 buffer = new 0.step(args.length-1, 2) do |index| type = args[index] value = args[index+1] if type == :raw buffer.append(value.to_s) elsif Array === value buffer.send("write_#{type}", *value) else buffer.send("write_#{type}", value) end end buffer end # exposes the raw content of the buffer attr_reader :content # the current position of the pointer in the buffer attr_accessor :position # Creates a new buffer, initialized to the given content. The position # is initialized to the beginning of the buffer. def initialize(content="") @content = content.to_s @position = 0 end # Returns the length of the buffer's content. def length @content.length end # Returns the number of bytes available to be read (e.g., how many bytes # remain between the current position and the end of the buffer). def available length - position end # Returns a copy of the buffer's content. def to_s (@content || "").dup end # Compares the contents of the two buffers, returning +true+ only if they # are identical in size and content. def ==(buffer) to_s == buffer.to_s end # Returns +true+ if the buffer contains no data (e.g., it is of zero length). def empty? @content.empty? end # Resets the pointer to the start of the buffer. Subsequent reads will # begin at position 0. def reset! @position = 0 end # Returns true if the pointer is at the end of the buffer. Subsequent # reads will return nil, in this case. def eof? @position >= length end # Resets the buffer, making it empty. Also, resets the read position to # 0. def clear! @content = "" @position = 0 end # Consumes n bytes from the buffer, where n is the current position # unless otherwise specified. This is useful for removing data from the # buffer that has previously been read, when you are expecting more data # to be appended. It helps to keep the size of buffers down when they # would otherwise tend to grow without bound. # # Returns the buffer object itself. def consume!(n=position) if n >= length # optimize for a fairly common case clear! elsif n > 0 @content = @content[n..-1] || "" @position -= n @position = 0 if @position < 0 end self end # Appends the given text to the end of the buffer. Does not alter the # read position. Returns the buffer object itself. def append(text) @content << text self end # Returns all text from the current pointer to the end of the buffer as # a new Net::SSH::Buffer object. def remainder_as_buffer Buffer.new(@content[@position..-1]) end # Reads all data up to and including the given pattern, which may be a # String, Fixnum, or Regexp and is interpreted exactly as String#index # does. Returns nil if nothing matches. Increments the position to point # immediately after the pattern, if it does match. Returns all data up to # and including the text that matched the pattern. def read_to(pattern) index = @content.index(pattern, @position) or return nil length = case pattern when String then pattern.length when Fixnum then 1 when Regexp then $&.length end index && read(index+length) end # Reads and returns the next +count+ bytes from the buffer, starting from # the read position. If +count+ is +nil+, this will return all remaining # text in the buffer. This method will increment the pointer. def read(count=nil) count ||= length count = length - @position if @position + count > length @position += count @content[@position-count, count] end # Reads (as #read) and returns the given number of bytes from the buffer, # and then consumes (as #consume!) all data up to the new read position. def read!(count=nil) data = read(count) consume! data end # Return the next 8 bytes as a 64-bit integer (in network byte order). # Returns nil if there are less than 8 bytes remaining to be read in the # buffer. def read_int64 hi = read_long or return nil lo = read_long or return nil return (hi << 32) + lo end # Return the next four bytes as a long integer (in network byte order). # Returns nil if there are less than 4 bytes remaining to be read in the # buffer. def read_long b = read(4) or return nil b.unpack("N").first end # Read and return the next byte in the buffer. Returns nil if called at # the end of the buffer. def read_byte b = read(1) or return nil b.getbyte(0) end # Read and return an SSH2-encoded string. The string starts with a long # integer that describes the number of bytes remaining in the string. # Returns nil if there are not enough bytes to satisfy the request. def read_string length = read_long or return nil read(length) end # Read a single byte and convert it into a boolean, using 'C' rules # (i.e., zero is false, non-zero is true). def read_bool b = read_byte or return nil b != 0 end # Read a bignum (OpenSSL::BN) from the buffer, in SSH2 format. It is # essentially just a string, which is reinterpreted to be a bignum in # binary format. def read_bignum data = read_string return unless data OpenSSL::BN.new(data, 2) end # Read a key from the buffer. The key will start with a string # describing its type. The remainder of the key is defined by the # type that was read. def read_key type = read_string return (type ? read_keyblob(type) : nil) end # Read a keyblob of the given type from the buffer, and return it as # a key. Only RSA, DSA, and ECDSA keys are supported. def read_keyblob(type) case type when "ssh-dss" key = OpenSSL::PKey::DSA.new key.p = read_bignum key.q = read_bignum key.g = read_bignum key.pub_key = read_bignum when "ssh-rsa" key = OpenSSL::PKey::RSA.new key.e = read_bignum key.n = read_bignum when /^ecdsa\-sha2\-(\w*)$/ unless defined?(OpenSSL::PKey::EC) raise NotImplementedError, "unsupported key type `#{type}'" else begin key = OpenSSL::PKey::EC.read_keyblob($1, self) rescue OpenSSL::PKey::ECError raise NotImplementedError, "unsupported key type `#{type}'" end end else raise NotImplementedError, "unsupported key type `#{type}'" end return key end # Reads the next string from the buffer, and returns a new Buffer # object that wraps it. def read_buffer Buffer.new(read_string) end # Writes the given data literally into the string. Does not alter the # read position. Returns the buffer object. def write(*data) data.each { |datum| @content << datum } self end # Writes each argument to the buffer as a network-byte-order-encoded # 64-bit integer (8 bytes). Does not alter the read position. Returns the # buffer object. def write_int64(*n) n.each do |i| hi = (i >> 32) & 0xFFFFFFFF lo = i & 0xFFFFFFFF @content << [hi, lo].pack("N2") end self end # Writes each argument to the buffer as a network-byte-order-encoded # long (4-byte) integer. Does not alter the read position. Returns the # buffer object. def write_long(*n) @content << n.pack("N*") self end # Writes each argument to the buffer as a byte. Does not alter the read # position. Returns the buffer object. def write_byte(*n) n.each { |b| @content << b.chr } self end # Writes each argument to the buffer as an SSH2-encoded string. Each # string is prefixed by its length, encoded as a 4-byte long integer. # Does not alter the read position. Returns the buffer object. def write_string(*text) text.each do |string| s = string.to_s write_long(s.bytesize) write(s) end self end # Writes each argument to the buffer as a (C-style) boolean, with 1 # meaning true, and 0 meaning false. Does not alter the read position. # Returns the buffer object. def write_bool(*b) b.each { |v| @content << (v ? "\1" : "\0") } self end # Writes each argument to the buffer as a bignum (SSH2-style). No # checking is done to ensure that the arguments are, in fact, bignums. # Does not alter the read position. Returns the buffer object. def write_bignum(*n) @content << n.map { |b| b.to_ssh }.join self end # Writes the given arguments to the buffer as SSH2-encoded keys. Does not # alter the read position. Returns the buffer object. def write_key(*key) key.each { |k| append(k.to_blob) } self end end end; end; net-ssh-2.6.8/lib/net/ssh/packet.rb0000644000004100000410000001065212166626376017110 0ustar www-datawww-datarequire 'net/ssh/buffer' require 'net/ssh/transport/constants' require 'net/ssh/authentication/constants' require 'net/ssh/connection/constants' module Net; module SSH # A specialization of Buffer that knows the format of certain common # packet types. It auto-parses those packet types, and allows them to # be accessed via the #[] accessor. # # data = some_channel_request_packet # packet = Net::SSH::Packet.new(data) # # p packet.type #-> 98 (CHANNEL_REQUEST) # p packet[:request] # p packet[:want_reply] # # This is used exclusively internally by Net::SSH, and unless you're doing # protocol-level manipulation or are extending Net::SSH in some way, you'll # never need to use this class directly. class Packet < Buffer @@types = {} # Register a new packet type that should be recognized and auto-parsed by # Net::SSH::Packet. Note that any packet type that is not preregistered # will not be autoparsed. # # The +pairs+ parameter must be either empty, or an array of two-element # tuples, where the first element of each tuple is the name of the field, # and the second is the type. # # register DISCONNECT, [:reason_code, :long], [:description, :string], [:language, :string] def self.register(type, *pairs) @@types[type] = pairs end include Transport::Constants, Authentication::Constants, Connection::Constants #-- # These are the recognized packet types. All other packet types will be # accepted, but not auto-parsed, requiring the client to parse the # fields using the methods provided by Net::SSH::Buffer. #++ register DISCONNECT, [:reason_code, :long], [:description, :string], [:language, :string] register IGNORE, [:data, :string] register UNIMPLEMENTED, [:number, :long] register DEBUG, [:always_display, :bool], [:message, :string], [:language, :string] register SERVICE_ACCEPT, [:service_name, :string] register USERAUTH_BANNER, [:message, :string], [:language, :string] register USERAUTH_FAILURE, [:authentications, :string], [:partial_success, :bool] register GLOBAL_REQUEST, [:request_type, :string], [:want_reply, :bool], [:request_data, :buffer] register CHANNEL_OPEN, [:channel_type, :string], [:remote_id, :long], [:window_size, :long], [:packet_size, :long] register CHANNEL_OPEN_CONFIRMATION, [:local_id, :long], [:remote_id, :long], [:window_size, :long], [:packet_size, :long] register CHANNEL_OPEN_FAILURE, [:local_id, :long], [:reason_code, :long], [:description, :string], [:language, :string] register CHANNEL_WINDOW_ADJUST, [:local_id, :long], [:extra_bytes, :long] register CHANNEL_DATA, [:local_id, :long], [:data, :string] register CHANNEL_EXTENDED_DATA, [:local_id, :long], [:data_type, :long], [:data, :string] register CHANNEL_EOF, [:local_id, :long] register CHANNEL_CLOSE, [:local_id, :long] register CHANNEL_REQUEST, [:local_id, :long], [:request, :string], [:want_reply, :bool], [:request_data, :buffer] register CHANNEL_SUCCESS, [:local_id, :long] register CHANNEL_FAILURE, [:local_id, :long] # The (integer) type of this packet. attr_reader :type # Create a new packet from the given payload. This will automatically # parse the packet if it is one that has been previously registered with # Packet.register; otherwise, the packet will need to be manually parsed # using the methods provided in the Net::SSH::Buffer superclass. def initialize(payload) @named_elements = {} super @type = read_byte instantiate! end # Access one of the auto-parsed fields by name. Raises an error if no # element by the given name exists. def [](name) name = name.to_sym raise ArgumentError, "no such element #{name}" unless @named_elements.key?(name) @named_elements[name] end private # Parse the packet's contents and assign the named elements, as described # by the registered format for the packet. def instantiate! (@@types[type] || []).each do |name, datatype| @named_elements[name.to_sym] = if datatype == :buffer remainder_as_buffer else send("read_#{datatype}") end end end end end; endnet-ssh-2.6.8/lib/net/ssh/ruby_compat.rb0000644000004100000410000000250412166626376020162 0ustar www-datawww-datarequire 'thread' class String if RUBY_VERSION < "1.9" def getbyte(index) self[index] end def setbyte(index, c) self[index] = c end end if RUBY_VERSION < "1.8.7" def bytesize self.size end end end module Net; module SSH # This class contains miscellaneous patches and workarounds # for different ruby implementations. class Compat # A workaround for an IO#select threading bug in certain versions of MRI 1.8. # See: http://net-ssh.lighthouseapp.com/projects/36253/tickets/1-ioselect-threading-bug-in-ruby-18 # The root issue is documented here: http://redmine.ruby-lang.org/issues/show/1993 if RUBY_VERSION >= '1.9' || RUBY_PLATFORM == 'java' def self.io_select(*params) IO.select(*params) end else SELECT_MUTEX = Mutex.new def self.io_select(*params) # It should be safe to wrap calls in a mutex when the timeout is 0 # (that is, the call is not supposed to block). # We leave blocking calls unprotected to avoid causing deadlocks. # This should still catch the main case for Capistrano users. if params[3] == 0 SELECT_MUTEX.synchronize do IO.select(*params) end else IO.select(*params) end end end end end; end net-ssh-2.6.8/lib/net/ssh.rb0000644000004100000410000002507712166626376015650 0ustar www-datawww-data# Make sure HOME is set, regardless of OS, so that File.expand_path works # as expected with tilde characters. ENV['HOME'] ||= ENV['HOMEPATH'] ? "#{ENV['HOMEDRIVE']}#{ENV['HOMEPATH']}" : Dir.pwd require 'logger' require 'net/ssh/config' require 'net/ssh/errors' require 'net/ssh/loggable' require 'net/ssh/transport/session' require 'net/ssh/authentication/session' require 'net/ssh/connection/session' module Net # Net::SSH is a library for interacting, programmatically, with remote # processes via the SSH2 protocol. Sessions are always initiated via # Net::SSH.start. From there, a program interacts with the new SSH session # via the convenience methods on Net::SSH::Connection::Session, by opening # and interacting with new channels (Net::SSH::Connection:Session#open_channel # and Net::SSH::Connection::Channel), or by forwarding local and/or # remote ports through the connection (Net::SSH::Service::Forward). # # The SSH protocol is very event-oriented. Requests are sent from the client # to the server, and are answered asynchronously. This gives great flexibility # (since clients can have multiple requests pending at a time), but it also # adds complexity. Net::SSH tries to manage this complexity by providing # some simpler methods of synchronous communication (see Net::SSH::Connection::Session#exec!). # # In general, though, and if you want to do anything more complicated than # simply executing commands and capturing their output, you'll need to use # channels (Net::SSH::Connection::Channel) to build state machines that are # executed while the event loop runs (Net::SSH::Connection::Session#loop). # # Net::SSH::Connection::Session and Net::SSH::Connection::Channel have more # information about this technique. # # = "Um, all I want to do is X, just show me how!" # # == X == "execute a command and capture the output" # # Net::SSH.start("host", "user", :password => "password") do |ssh| # result = ssh.exec!("ls -l") # puts result # end # # == X == "forward connections on a local port to a remote host" # # Net::SSH.start("host", "user", :password => "password") do |ssh| # ssh.forward.local(1234, "www.google.com", 80) # ssh.loop { true } # end # # == X == "forward connections on a remote port to the local host" # # Net::SSH.start("host", "user", :password => "password") do |ssh| # ssh.forward.remote(80, "www.google.com", 1234) # ssh.loop { true } # end module SSH # This is the set of options that Net::SSH.start recognizes. See # Net::SSH.start for a description of each option. VALID_OPTIONS = [ :auth_methods, :bind_address, :compression, :compression_level, :config, :encryption, :forward_agent, :hmac, :host_key, :kex, :keys, :key_data, :languages, :logger, :paranoid, :password, :port, :proxy, :rekey_blocks_limit,:rekey_limit, :rekey_packet_limit, :timeout, :verbose, :global_known_hosts_file, :user_known_hosts_file, :host_key_alias, :host_name, :user, :properties, :passphrase, :keys_only, :max_pkt_size, :max_win_size ] # The standard means of starting a new SSH connection. When used with a # block, the connection will be closed when the block terminates, otherwise # the connection will just be returned. The yielded (or returned) value # will be an instance of Net::SSH::Connection::Session (q.v.). (See also # Net::SSH::Connection::Channel and Net::SSH::Service::Forward.) # # Net::SSH.start("host", "user") do |ssh| # ssh.exec! "cp /some/file /another/location" # hostname = ssh.exec!("hostname") # # ssh.open_channel do |ch| # ch.exec "sudo -p 'sudo password: ' ls" do |ch, success| # abort "could not execute sudo ls" unless success # # ch.on_data do |ch, data| # print data # if data =~ /sudo password: / # ch.send_data("password\n") # end # end # end # end # # ssh.loop # end # # This method accepts the following options (all are optional): # # * :auth_methods => an array of authentication methods to try # * :bind_address => the IP address on the connecting machine to use in # establishing connection. (:bind_address is discarded if :proxy # is set.) # * :compression => the compression algorithm to use, or +true+ to use # whatever is supported. # * :compression_level => the compression level to use when sending data # * :config => set to +true+ to load the default OpenSSH config files # (~/.ssh/config, /etc/ssh_config), or to +false+ to not load them, or to # a file-name (or array of file-names) to load those specific configuration # files. Defaults to +true+. # * :encryption => the encryption cipher (or ciphers) to use # * :forward_agent => set to true if you want the SSH agent connection to # be forwarded # * :global_known_hosts_file => the location of the global known hosts # file. Set to an array if you want to specify multiple global known # hosts files. Defaults to %w(/etc/ssh/known_hosts /etc/ssh/known_hosts2). # * :hmac => the hmac algorithm (or algorithms) to use # * :host_key => the host key algorithm (or algorithms) to use # * :host_key_alias => the host name to use when looking up or adding a # host to a known_hosts dictionary file # * :host_name => the real host name or IP to log into. This is used # instead of the +host+ parameter, and is primarily only useful when # specified in an SSH configuration file. It lets you specify an # "alias", similarly to adding an entry in /etc/hosts but without needing # to modify /etc/hosts. # * :kex => the key exchange algorithm (or algorithms) to use # * :keys => an array of file names of private keys to use for publickey # and hostbased authentication # * :key_data => an array of strings, with each element of the array being # a raw private key in PEM format. # * :keys_only => set to +true+ to use only private keys from +keys+ and # +key_data+ parameters, even if ssh-agent offers more identities. This # option is intended for situations where ssh-agent offers many different # identites. # * :logger => the logger instance to use when logging # * :max_pkt_size => maximum size we tell the other side that is supported per # packet. Default is 0x8000 (32768 bytes). Increase to 0x10000 (65536 bytes) # for better performance if your SSH server supports it (most do). # * :max_win_size => maximum size we tell the other side that is supported for # the window. # * :paranoid => either false, true, :very, or :secure specifying how # strict host-key verification should be (in increasing order here) # * :passphrase => the passphrase to use when loading a private key (default # is +nil+, for no passphrase) # * :password => the password to use to login # * :port => the port to use when connecting to the remote host # * :properties => a hash of key/value pairs to add to the new connection's # properties (see Net::SSH::Connection::Session#properties) # * :proxy => a proxy instance (see Proxy) to use when connecting # * :rekey_blocks_limit => the max number of blocks to process before rekeying # * :rekey_limit => the max number of bytes to process before rekeying # * :rekey_packet_limit => the max number of packets to process before rekeying # * :timeout => how long to wait for the initial connection to be made # * :user => the user name to log in as; this overrides the +user+ # parameter, and is primarily only useful when provided via an SSH # configuration file. # * :user_known_hosts_file => the location of the user known hosts file. # Set to an array to specify multiple user known hosts files. # Defaults to %w(~/.ssh/known_hosts ~/.ssh/known_hosts2). # * :verbose => how verbose to be (Logger verbosity constants, Logger::DEBUG # is very verbose, Logger::FATAL is all but silent). Logger::FATAL is the # default. The symbols :debug, :info, :warn, :error, and :fatal are also # supported and are translated to the corresponding Logger constant. def self.start(host, user, options={}, &block) invalid_options = options.keys - VALID_OPTIONS if invalid_options.any? raise ArgumentError, "invalid option(s): #{invalid_options.join(', ')}" end options[:user] = user if user options = configuration_for(host, options.fetch(:config, true)).merge(options) host = options.fetch(:host_name, host) if !options.key?(:logger) options[:logger] = Logger.new(STDERR) options[:logger].level = Logger::FATAL end if options[:verbose] options[:logger].level = case options[:verbose] when Fixnum then options[:verbose] when :debug then Logger::DEBUG when :info then Logger::INFO when :warn then Logger::WARN when :error then Logger::ERROR when :fatal then Logger::FATAL else raise ArgumentError, "can't convert #{options[:verbose].inspect} to any of the Logger level constants" end end transport = Transport::Session.new(host, options) auth = Authentication::Session.new(transport, options) user = options.fetch(:user, user) if auth.authenticate("ssh-connection", user, options[:password]) connection = Connection::Session.new(transport, options) if block_given? retval = yield connection connection.close retval else return connection end else transport.close raise AuthenticationFailed, user end end # Returns a hash of the configuration options for the given host, as read # from the SSH configuration file(s). If +use_ssh_config+ is true (the # default), this will load configuration from both ~/.ssh/config and # /etc/ssh_config. If +use_ssh_config+ is nil or false, nothing will be # loaded (and an empty hash returned). Otherwise, +use_ssh_config+ may # be a file name (or array of file names) of SSH configuration file(s) # to read. # # See Net::SSH::Config for the full description of all supported options. def self.configuration_for(host, use_ssh_config=true) files = case use_ssh_config when true then Net::SSH::Config.default_files when false, nil then return {} else Array(use_ssh_config) end Net::SSH::Config.for(host, files) end end end net-ssh-2.6.8/support/0000755000004100000410000000000012166626376014673 5ustar www-datawww-datanet-ssh-2.6.8/support/ssh_tunnel_bug.rb0000755000004100000410000000465312166626376020252 0ustar www-datawww-data#!/usr/bin/ruby # SSH TUNNEL CONNECTION BUG # from: http://net-ssh.lighthouseapp.com/projects/36253/tickets/7-an-existing-connection-was-forcibly-closed-by-the-remote-host#ticket-7-3 # # Steps to reproduce: # # * Start HTTP Proxy # * If running debian in EC2: # * apt-get install squid # * Add the following to /etc/squid/squid.conf: # acl localnet src 1.2.3.0/255.255.255.0 # http_access allow localnet # icp_access allow localnet # visible_hostname netsshtest # * Start squid squid -N -d 1 -D # * Run this script # * Configure browser proxy to use localhost with LOCAL_PORT. # * Load any page, wait for it to load fully. If the page loads # correctly, move on. If not, something needs to be corrected. # * Refresh the page several times. This should cause this # script to failed with the error: "closed stream". You may # need to try a few times. # require 'highline/import' require 'net/ssh' LOCAL_PORT = 8080 PROXY_PORT = 3128 host, user = *ARGV abort "Usage: #{$0} host user" unless ARGV.size == 2 puts "Connecting to #{user}@#{host}..." pass = ask("Password: ") { |q| q.echo = "*" } puts "Configure your browser proxy to localhost:#{LOCAL_PORT}" begin session = Net::SSH.start(host, user, :password => pass) session.forward.local(LOCAL_PORT, host, PROXY_PORT) session.loop{true} rescue => e puts e.message puts e.backtrace end __END__ $ ruby support/ssh_tunnel.rb host user Connecting to user@host... Password: ****** Configure your browser proxy to localhost:8080 closed stream /usr/local/lib/ruby/gems/1.9.1/gems/net-ssh-2.0.15/lib/net/ssh/buffered_io.rb:99:in `send' /usr/local/lib/ruby/gems/1.9.1/gems/net-ssh-2.0.15/lib/net/ssh/buffered_io.rb:99:in `send_pending' /usr/local/lib/ruby/gems/1.9.1/gems/net-ssh-2.0.15/lib/net/ssh/connection/session.rb:236:in `block in postprocess' /usr/local/lib/ruby/gems/1.9.1/gems/net-ssh-2.0.15/lib/net/ssh/connection/session.rb:235:in `each' /usr/local/lib/ruby/gems/1.9.1/gems/net-ssh-2.0.15/lib/net/ssh/connection/session.rb:235:in `postprocess' /usr/local/lib/ruby/gems/1.9.1/gems/net-ssh-2.0.15/lib/net/ssh/connection/session.rb:203:in `process' /usr/local/lib/ruby/gems/1.9.1/gems/net-ssh-2.0.15/lib/net/ssh/connection/session.rb:161:in `block in loop' /usr/local/lib/ruby/gems/1.9.1/gems/net-ssh-2.0.15/lib/net/ssh/connection/session.rb:161:in `loop' /usr/local/lib/ruby/gems/1.9.1/gems/net-ssh-2.0.15/lib/net/ssh/connection/session.rb:161:in `loop' net-ssh-2.6.8/support/arcfour_check.rb0000644000004100000410000000105312166626376020015 0ustar www-datawww-data require 'net/ssh' # ARCFOUR CHECK # # Usage: # $ ruby support/arcfour_check.rb # # Expected Output: # arcfour128: [16, 8] OpenSSL::Cipher::Cipher # arcfour256: [32, 8] OpenSSL::Cipher::Cipher # arcfour512: [64, 8] OpenSSL::Cipher::Cipher [['arcfour128', 16], ['arcfour256', 32], ['arcfour512', 64]].each do |cipher| print "#{cipher[0]}: " a = Net::SSH::Transport::CipherFactory.get_lengths(cipher[0]) b = Net::SSH::Transport::CipherFactory.get(cipher[0], :key => ([].fill('x', 0, cipher[1]).join)) puts "#{a} #{b.class}" end