net-ssh 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. data/doc/LICENSE-BSD +27 -0
  2. data/doc/LICENSE-GPL +280 -0
  3. data/doc/LICENSE-RUBY +56 -0
  4. data/doc/README +13 -0
  5. data/doc/manual-html/chapter-1.html +333 -0
  6. data/doc/manual-html/chapter-2.html +455 -0
  7. data/doc/manual-html/chapter-3.html +413 -0
  8. data/doc/manual-html/chapter-4.html +353 -0
  9. data/doc/manual-html/chapter-5.html +393 -0
  10. data/doc/manual-html/chapter-6.html +296 -0
  11. data/doc/manual-html/index.html +217 -0
  12. data/doc/manual-html/manual.css +192 -0
  13. data/doc/manual/chapter.erb +18 -0
  14. data/doc/manual/example.erb +18 -0
  15. data/doc/manual/index.erb +29 -0
  16. data/doc/manual/manual.css +192 -0
  17. data/doc/manual/manual.rb +240 -0
  18. data/doc/manual/manual.yml +67 -0
  19. data/doc/manual/page.erb +87 -0
  20. data/doc/manual/parts/channels_callbacks.txt +32 -0
  21. data/doc/manual/parts/channels_loop.txt +14 -0
  22. data/doc/manual/parts/channels_open.txt +20 -0
  23. data/doc/manual/parts/channels_operations.txt +15 -0
  24. data/doc/manual/parts/channels_types.txt +3 -0
  25. data/doc/manual/parts/channels_what_are.txt +7 -0
  26. data/doc/manual/parts/exec_channels.txt +28 -0
  27. data/doc/manual/parts/exec_open.txt +51 -0
  28. data/doc/manual/parts/exec_popen3.txt +35 -0
  29. data/doc/manual/parts/forward_direct.txt +37 -0
  30. data/doc/manual/parts/forward_handlers.txt +16 -0
  31. data/doc/manual/parts/forward_intro.txt +18 -0
  32. data/doc/manual/parts/forward_local.txt +18 -0
  33. data/doc/manual/parts/forward_remote.txt +14 -0
  34. data/doc/manual/parts/intro_author.txt +1 -0
  35. data/doc/manual/parts/intro_getting.txt +39 -0
  36. data/doc/manual/parts/intro_license.txt +6 -0
  37. data/doc/manual/parts/intro_support.txt +7 -0
  38. data/doc/manual/parts/intro_what_is.txt +7 -0
  39. data/doc/manual/parts/intro_what_is_not.txt +3 -0
  40. data/doc/manual/parts/proxy_http.txt +52 -0
  41. data/doc/manual/parts/proxy_intro.txt +1 -0
  42. data/doc/manual/parts/proxy_socks.txt +23 -0
  43. data/doc/manual/parts/session_key.txt +66 -0
  44. data/doc/manual/parts/session_options.txt +42 -0
  45. data/doc/manual/parts/session_session.txt +14 -0
  46. data/doc/manual/parts/session_start.txt +49 -0
  47. data/doc/manual/tutorial.erb +30 -0
  48. data/examples/channel-demo.rb +81 -0
  49. data/examples/port-forward.rb +51 -0
  50. data/examples/process-demo.rb +91 -0
  51. data/examples/remote-net-port-forward.rb +45 -0
  52. data/examples/remote-port-forward.rb +80 -0
  53. data/examples/tail-demo.rb +49 -0
  54. data/lib/net/ssh.rb +52 -0
  55. data/lib/net/ssh/connection/channel.rb +411 -0
  56. data/lib/net/ssh/connection/constants.rb +47 -0
  57. data/lib/net/ssh/connection/driver.rb +343 -0
  58. data/lib/net/ssh/connection/services.rb +72 -0
  59. data/lib/net/ssh/connection/term.rb +90 -0
  60. data/lib/net/ssh/errors.rb +27 -0
  61. data/lib/net/ssh/proxy/errors.rb +34 -0
  62. data/lib/net/ssh/proxy/http.rb +126 -0
  63. data/lib/net/ssh/proxy/socks4.rb +83 -0
  64. data/lib/net/ssh/proxy/socks5.rb +160 -0
  65. data/lib/net/ssh/service/forward/driver.rb +319 -0
  66. data/lib/net/ssh/service/forward/local-network-handler.rb +74 -0
  67. data/lib/net/ssh/service/forward/remote-network-handler.rb +81 -0
  68. data/lib/net/ssh/service/forward/services.rb +76 -0
  69. data/lib/net/ssh/service/process/driver.rb +153 -0
  70. data/lib/net/ssh/service/process/open.rb +193 -0
  71. data/lib/net/ssh/service/process/popen3.rb +160 -0
  72. data/lib/net/ssh/service/process/services.rb +66 -0
  73. data/lib/net/ssh/service/services.rb +44 -0
  74. data/lib/net/ssh/session.rb +242 -0
  75. data/lib/net/ssh/transport/algorithm-negotiator.rb +267 -0
  76. data/lib/net/ssh/transport/compress/compressor.rb +53 -0
  77. data/lib/net/ssh/transport/compress/decompressor.rb +53 -0
  78. data/lib/net/ssh/transport/compress/none-compressor.rb +39 -0
  79. data/lib/net/ssh/transport/compress/none-decompressor.rb +39 -0
  80. data/lib/net/ssh/transport/compress/services.rb +68 -0
  81. data/lib/net/ssh/transport/compress/zlib-compressor.rb +60 -0
  82. data/lib/net/ssh/transport/compress/zlib-decompressor.rb +52 -0
  83. data/lib/net/ssh/transport/constants.rb +66 -0
  84. data/lib/net/ssh/transport/errors.rb +47 -0
  85. data/lib/net/ssh/transport/identity-cipher.rb +61 -0
  86. data/lib/net/ssh/transport/kex/dh-gex.rb +106 -0
  87. data/lib/net/ssh/transport/kex/dh.rb +231 -0
  88. data/lib/net/ssh/transport/kex/services.rb +60 -0
  89. data/lib/net/ssh/transport/ossl/buffer-factory.rb +52 -0
  90. data/lib/net/ssh/transport/ossl/buffer.rb +87 -0
  91. data/lib/net/ssh/transport/ossl/cipher-factory.rb +98 -0
  92. data/lib/net/ssh/transport/ossl/digest-factory.rb +51 -0
  93. data/lib/net/ssh/transport/ossl/hmac-factory.rb +71 -0
  94. data/lib/net/ssh/transport/ossl/hmac/hmac.rb +62 -0
  95. data/lib/net/ssh/transport/ossl/hmac/md5-96.rb +44 -0
  96. data/lib/net/ssh/transport/ossl/hmac/md5.rb +46 -0
  97. data/lib/net/ssh/transport/ossl/hmac/none.rb +46 -0
  98. data/lib/net/ssh/transport/ossl/hmac/services.rb +68 -0
  99. data/lib/net/ssh/transport/ossl/hmac/sha1-96.rb +44 -0
  100. data/lib/net/ssh/transport/ossl/hmac/sha1.rb +45 -0
  101. data/lib/net/ssh/transport/ossl/key-factory.rb +113 -0
  102. data/lib/net/ssh/transport/ossl/services.rb +149 -0
  103. data/lib/net/ssh/transport/packet-stream.rb +210 -0
  104. data/lib/net/ssh/transport/services.rb +146 -0
  105. data/lib/net/ssh/transport/session.rb +296 -0
  106. data/lib/net/ssh/transport/version-negotiator.rb +73 -0
  107. data/lib/net/ssh/userauth/agent.rb +218 -0
  108. data/lib/net/ssh/userauth/constants.rb +35 -0
  109. data/lib/net/ssh/userauth/driver.rb +176 -0
  110. data/lib/net/ssh/userauth/methods/hostbased.rb +119 -0
  111. data/lib/net/ssh/userauth/methods/password.rb +70 -0
  112. data/lib/net/ssh/userauth/methods/publickey.rb +137 -0
  113. data/lib/net/ssh/userauth/methods/services.rb +63 -0
  114. data/lib/net/ssh/userauth/services.rb +126 -0
  115. data/lib/net/ssh/userauth/userkeys.rb +258 -0
  116. data/lib/net/ssh/util/buffer.rb +274 -0
  117. data/lib/net/ssh/util/openssl.rb +146 -0
  118. data/lib/net/ssh/util/prompter.rb +73 -0
  119. data/lib/net/ssh/version.rb +29 -0
  120. data/test/ALL-TESTS.rb +21 -0
  121. data/test/connection/tc_channel.rb +136 -0
  122. data/test/connection/tc_driver.rb +287 -0
  123. data/test/connection/tc_integration.rb +85 -0
  124. data/test/proxy/tc_http.rb +209 -0
  125. data/test/proxy/tc_socks4.rb +148 -0
  126. data/test/proxy/tc_socks5.rb +214 -0
  127. data/test/service/forward/tc_driver.rb +289 -0
  128. data/test/service/forward/tc_local_network_handler.rb +123 -0
  129. data/test/service/forward/tc_remote_network_handler.rb +108 -0
  130. data/test/service/process/tc_driver.rb +79 -0
  131. data/test/service/process/tc_integration.rb +117 -0
  132. data/test/service/process/tc_open.rb +179 -0
  133. data/test/service/process/tc_popen3.rb +164 -0
  134. data/test/tc_integration.rb +79 -0
  135. data/test/transport/compress/tc_none_compress.rb +41 -0
  136. data/test/transport/compress/tc_none_decompress.rb +45 -0
  137. data/test/transport/compress/tc_zlib_compress.rb +61 -0
  138. data/test/transport/compress/tc_zlib_decompress.rb +48 -0
  139. data/test/transport/kex/tc_dh.rb +304 -0
  140. data/test/transport/kex/tc_dh_gex.rb +70 -0
  141. data/test/transport/ossl/fixtures/dsa-encrypted +15 -0
  142. data/test/transport/ossl/fixtures/dsa-encrypted-bad +15 -0
  143. data/test/transport/ossl/fixtures/dsa-unencrypted +12 -0
  144. data/test/transport/ossl/fixtures/dsa-unencrypted-bad +12 -0
  145. data/test/transport/ossl/fixtures/dsa-unencrypted.pub +1 -0
  146. data/test/transport/ossl/fixtures/not-a-private-key +4 -0
  147. data/test/transport/ossl/fixtures/not-supported +2 -0
  148. data/test/transport/ossl/fixtures/rsa-encrypted +18 -0
  149. data/test/transport/ossl/fixtures/rsa-encrypted-bad +18 -0
  150. data/test/transport/ossl/fixtures/rsa-unencrypted +15 -0
  151. data/test/transport/ossl/fixtures/rsa-unencrypted-bad +15 -0
  152. data/test/transport/ossl/fixtures/rsa-unencrypted.pub +1 -0
  153. data/test/transport/ossl/hmac/tc_hmac.rb +58 -0
  154. data/test/transport/ossl/hmac/tc_md5.rb +50 -0
  155. data/test/transport/ossl/hmac/tc_md5_96.rb +50 -0
  156. data/test/transport/ossl/hmac/tc_none.rb +50 -0
  157. data/test/transport/ossl/hmac/tc_sha1.rb +50 -0
  158. data/test/transport/ossl/hmac/tc_sha1_96.rb +50 -0
  159. data/test/transport/ossl/tc_buffer.rb +97 -0
  160. data/test/transport/ossl/tc_buffer_factory.rb +67 -0
  161. data/test/transport/ossl/tc_cipher_factory.rb +84 -0
  162. data/test/transport/ossl/tc_digest_factory.rb +39 -0
  163. data/test/transport/ossl/tc_hmac_factory.rb +72 -0
  164. data/test/transport/ossl/tc_key_factory.rb +199 -0
  165. data/test/transport/tc_algorithm_negotiator.rb +169 -0
  166. data/test/transport/tc_identity_cipher.rb +52 -0
  167. data/test/transport/tc_integration.rb +110 -0
  168. data/test/transport/tc_packet_stream.rb +183 -0
  169. data/test/transport/tc_session.rb +283 -0
  170. data/test/transport/tc_version_negotiator.rb +86 -0
  171. data/test/userauth/methods/tc_hostbased.rb +136 -0
  172. data/test/userauth/methods/tc_password.rb +89 -0
  173. data/test/userauth/methods/tc_publickey.rb +167 -0
  174. data/test/userauth/tc_agent.rb +223 -0
  175. data/test/userauth/tc_driver.rb +190 -0
  176. data/test/userauth/tc_integration.rb +81 -0
  177. data/test/userauth/tc_userkeys.rb +265 -0
  178. data/test/util/tc_buffer.rb +217 -0
  179. metadata +256 -0
@@ -0,0 +1,66 @@
1
+ #--
2
+ # =============================================================================
3
+ # Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
4
+ # All rights reserved.
5
+ #
6
+ # This source file is distributed as part of the Net::SSH Secure Shell Client
7
+ # library for Ruby. This file (and the library as a whole) may be used only as
8
+ # allowed by either the BSD license, or the Ruby license (or, by association
9
+ # with the Ruby license, the GPL). See the "doc" subdirectory of the Net::SSH
10
+ # distribution for the texts of these licenses.
11
+ # -----------------------------------------------------------------------------
12
+ # net-ssh website : http://net-ssh.rubyforge.org
13
+ # project website: http://rubyforge.org/projects/net-ssh
14
+ # =============================================================================
15
+ #++
16
+
17
+ module Net
18
+ module SSH
19
+ module Service
20
+ module Process
21
+
22
+ # Register all services pertaining to the management of remote
23
+ # processes.
24
+ def register_services( container )
25
+
26
+ # All process management services are registered in their own
27
+ # namespace.
28
+ container.namespace_define :process do |ns|
29
+
30
+ # The :open_manager service returns a proc object that can be used
31
+ # to create new OpenManager instances for a given command.
32
+ ns.open_manager do |c,p|
33
+ require 'net/ssh/service/process/open'
34
+ connection = c[:connection][:driver]
35
+ log = c[:log_for, p]
36
+ lambda { |cmd| OpenManager.new( connection, log, cmd ) }
37
+ end
38
+
39
+ # The :popen3_manager service returns a new POpen3Manager instance
40
+ # for managing the execution of commands with a popen3-type
41
+ # interface.
42
+ ns.popen3_manager do |c,p|
43
+ require 'net/ssh/service/process/popen3'
44
+ connection = c[:connection][:driver]
45
+ log = c[:log_for, p]
46
+ POpen3Manager.new( connection, log )
47
+ end
48
+
49
+ # The :driver controls access to all remote process management
50
+ # services.
51
+ ns.driver do |c,p|
52
+ require 'net/ssh/service/process/driver'
53
+ Driver.new( c[:connection][:driver],
54
+ c[:log_for, p],
55
+ :open => c[:open_manager],
56
+ :popen3 => c[:popen3_manager] )
57
+ end
58
+
59
+ end
60
+ end
61
+ module_function :register_services
62
+
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,44 @@
1
+ #--
2
+ # =============================================================================
3
+ # Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
4
+ # All rights reserved.
5
+ #
6
+ # This source file is distributed as part of the Net::SSH Secure Shell Client
7
+ # library for Ruby. This file (and the library as a whole) may be used only as
8
+ # allowed by either the BSD license, or the Ruby license (or, by association
9
+ # with the Ruby license, the GPL). See the "doc" subdirectory of the Net::SSH
10
+ # distribution for the texts of these licenses.
11
+ # -----------------------------------------------------------------------------
12
+ # net-ssh website : http://net-ssh.rubyforge.org
13
+ # project website: http://rubyforge.org/projects/net-ssh
14
+ # =============================================================================
15
+ #++
16
+
17
+ module Net
18
+ module SSH
19
+ module Service
20
+
21
+ # Register all standard SSH services.
22
+ def register_services( container )
23
+
24
+ # Define the hash that will be used to record the registered services.
25
+ # If the hash already exists, don't redefine it.
26
+ unless container.knows_key?( :services )
27
+ container.define.services { Hash.new }
28
+ end
29
+
30
+ # Register the services in their own namespace.
31
+ container.namespace_define :service do |ns|
32
+ ns.require "net/ssh/service/forward/services", "#{self}::Forward"
33
+ ns.require "net/ssh/service/process/services", "#{self}::Process"
34
+ end
35
+
36
+ # Add the services to the services hash.
37
+ container.services[ :forward ] = container.service.forward.driver
38
+ container.services[ :process ] = container.service.process.driver
39
+ end
40
+ module_function :register_services
41
+
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,242 @@
1
+ #--
2
+ # =============================================================================
3
+ # Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
4
+ # All rights reserved.
5
+ #
6
+ # This source file is distributed as part of the Net::SSH Secure Shell Client
7
+ # library for Ruby. This file (and the library as a whole) may be used only as
8
+ # allowed by either the BSD license, or the Ruby license (or, by association
9
+ # with the Ruby license, the GPL). See the "doc" subdirectory of the Net::SSH
10
+ # distribution for the texts of these licenses.
11
+ # -----------------------------------------------------------------------------
12
+ # net-ssh website : http://net-ssh.rubyforge.org
13
+ # project website: http://rubyforge.org/projects/net-ssh
14
+ # =============================================================================
15
+ #++
16
+
17
+ require 'needle'
18
+ require 'net/ssh/errors'
19
+
20
+ module Net
21
+ module SSH
22
+
23
+ # Encapsulates a single session (connection) to a server via SSH.
24
+ class Session
25
+
26
+ # The dependency-injection registry used by this session.
27
+ attr_reader :registry
28
+
29
+ # Create a new SSH session. This method polymorphically accepts a
30
+ # variable number of parameters, as follows:
31
+ #
32
+ # * 1 parameter: must be the hostname to connect to.
33
+ # * 2 parameters: must be the hostname, and either the port (as an
34
+ # integer) or the username to connect as.
35
+ # * 3 parameters: must be the hostname, and either the port (as an
36
+ # integer) and username, or the username and the password.
37
+ # * 4 parameters: must be the hostname, port, username, and password.
38
+ #
39
+ # Any scenario above that omits the username assumes that the USER
40
+ # environment variable is set to the user's name. Any scenario above that
41
+ # omits the password assumes that the user will log in without a password
42
+ # (ie, using a public key). Any scenario above that omits the port number
43
+ # assumes a port number of 22 (the default for SSH).
44
+ #
45
+ # Any of the above scenarios may also accept a Hash as the last
46
+ # parameter, specifying a list of additional options to be used to
47
+ # initialize the session. (See Net::SSH::Session.add_options).
48
+ #
49
+ # Alternatively, named parameters may be used, in which case the first
50
+ # parameter is positional and is always the host to connect to, following
51
+ # which you may specify any of the following named parameters (as
52
+ # symbols):
53
+ #
54
+ # * :port
55
+ # * :username
56
+ # * :password
57
+ #
58
+ # Any additional parameters are treated as options that configure how the
59
+ # connection behaves.
60
+ #
61
+ # Allowed options are:
62
+ #
63
+ # * :keys (the list of filenames identifying the user's keys)
64
+ # * :host_keys (the list of filenames identifying the host's keys)
65
+ # * :auth_methods (a list of authentication methods to use)
66
+ # * :crypto_backend (defaults to :ossl, and specifies the cryptography
67
+ # backend to use)
68
+ # * :registry_options (a hash of options to use when creating the
69
+ # registry)
70
+ # * :container (the registry to use. If not specified, a new registry
71
+ # will be created)
72
+ # * :verbose (how verbose the logging output should be. Defaults to
73
+ # :warn).
74
+ # * :log (the name of the file, or the IO object, to which messages will
75
+ # be logged. Defaults to STDERR.)
76
+ #
77
+ # Also, any options recognized by Net::SSH::Transport::Session may be
78
+ # given, and will be passed through to initialize the transport session.
79
+ #
80
+ # If a block is given to this method, then it is called with the new
81
+ # session object. The session object is then closed when the block
82
+ # terminates. If a block is not given, then the session object is
83
+ # returned (and must be closed explicitly).
84
+ def initialize( *args )
85
+ @open = false
86
+ process_arguments( *args )
87
+
88
+ @registry.define do |b|
89
+ b.crypto_backend { @crypto_backend }
90
+ b.transport_host { @host }
91
+ b.transport_options { @options }
92
+
93
+ b.userauth_keys { @keys }
94
+ b.userauth_host_keys { @host_keys }
95
+ b.userauth_method_order { @auth_methods }
96
+
97
+ b.prompter do
98
+ require 'net/ssh/util/prompter'
99
+ Net::SSH::Util::Prompter.new
100
+ end
101
+
102
+ b.require 'net/ssh/transport/services', "Net::SSH::Transport"
103
+ b.require 'net/ssh/connection/services', "Net::SSH::Connection"
104
+ b.require 'net/ssh/userauth/services', "Net::SSH::UserAuth"
105
+
106
+ b.require 'net/ssh/service/services', "Net::SSH::Service"
107
+ end
108
+
109
+ userauth = @registry[:userauth][:driver]
110
+ if userauth.authenticate( "ssh-connection", @username, @password )
111
+ @open = true
112
+ @connection = @registry[:connection][:driver]
113
+ if block_given?
114
+ yield self
115
+ close
116
+ end
117
+ else
118
+ @registry[:transport][:session].close
119
+ raise AuthenticationFailed, @username
120
+ end
121
+ end
122
+
123
+ # Closes the session, if it is open. If it is not open, this does
124
+ # nothing.
125
+ def close
126
+ @registry[:transport][:session].close if @open
127
+ @open = false
128
+ end
129
+
130
+ # Returns +true+ if the session is currently open.
131
+ def open?
132
+ @open
133
+ end
134
+
135
+ # Opens a new communication channel over the current connection. This
136
+ # returns immediately. The block will be invoked when then the channel
137
+ # has been opened. (See Net::SSH::Connection::Driver#open_channel).
138
+ def open_channel( type="session", data=nil, &block )
139
+ sanity_check
140
+ channel = @connection.open_channel( type, data )
141
+ channel.on_confirm_open &block
142
+ channel
143
+ end
144
+
145
+ # Enters the main communication loop. This processes events occuring over
146
+ # the channel. If a block is given, the loop will continue for as long
147
+ # as the block returns +true+. Otherwise, the loop continues until there
148
+ # are no more open channels. (See Net::SSH::Connection::Driver#loop).
149
+ def loop( &block )
150
+ sanity_check
151
+ @connection.loop &block
152
+ end
153
+
154
+ # Provides convenient access to services that have been registered with
155
+ # the session, such as "process" and "forward".
156
+ #
157
+ # Usage:
158
+ #
159
+ # session.forward.local(...)
160
+ def method_missing( sym, *args, &block )
161
+ if args.empty? && block.nil? && @registry[:services].has_key?( sym )
162
+ return @registry[:services][ sym ]
163
+ else
164
+ super
165
+ end
166
+ end
167
+
168
+ # Processes the argument list, determining the meaning of each argument
169
+ # and allowing polymorphic argument lists. (See #initialize).
170
+ def process_arguments( *args )
171
+ @options = {}
172
+ @username = ENV['USER']
173
+
174
+ raise ArgumentError,
175
+ "you must specify the host to connect to" if args.length < 1
176
+
177
+ @host = args.shift
178
+
179
+ # support for both named arguments, and positional arguments...
180
+ if args.length == 1 && args[0].is_a?( Hash ) &&
181
+ ( args[0][:username] || args[0][:password] ||
182
+ args[0][:port] || args[0][:options] )
183
+ # then
184
+ @username = args[0][:username] || username
185
+ @password = args[0][:password]
186
+
187
+ @options.update args.shift
188
+ else
189
+ @options[ :port ] = args.shift if args.first.is_a? Numeric
190
+ if args.first.nil? || args.first.is_a?( String )
191
+ @username = args.shift || @username
192
+ end
193
+ if args.first.nil? || args.first.is_a?( String )
194
+ @password = args.shift
195
+ end
196
+ @options.update args.shift if args.first.is_a?( Hash )
197
+ end
198
+
199
+ unless args.empty?
200
+ raise ArgumentError, "extra parameters detected: #{args.inspect}"
201
+ end
202
+
203
+ @keys = @options[ :keys ]
204
+ @host_keys = @options[ :host_keys ]
205
+ @auth_methods = @options[ :auth_methods ]
206
+ @crypto_backend = @options.fetch( :crypto_backend, :ossl )
207
+
208
+ verbose = @options.fetch( :verbose, :warn )
209
+ log = @options.fetch( :log, STDERR )
210
+
211
+ @registry_options = @options.fetch( :registry_options, {} )
212
+
213
+ @registry_options[ :logs ] ||= {}
214
+ @registry_options[ :logs ][ :default_level ] = verbose
215
+
216
+ if log.is_a? IO
217
+ @registry_options[ :logs ][ :device ] ||= log
218
+ else
219
+ @registry_options[ :logs ][ :filename ] ||= log
220
+ end
221
+
222
+ @registry = @options[ :container ] ||
223
+ Needle::Registry.new( @registry_options )
224
+
225
+ [ :keys, :host_keys, :auth_methods, :username, :password,
226
+ :crypto_backend, :registry_options, :container, :log, :verbose
227
+ ].each do |i|
228
+ @options.delete i
229
+ end
230
+ end
231
+ private :process_arguments
232
+
233
+ # Make sure we're in an acceptible state.
234
+ def sanity_check
235
+ raise Net::SSH::Exception, "session not open" unless @open
236
+ end
237
+ private :sanity_check
238
+
239
+ end
240
+
241
+ end
242
+ end
@@ -0,0 +1,267 @@
1
+ #--
2
+ # =============================================================================
3
+ # Copyright (c) 2004, Jamis Buck (jgb3@email.byu.edu)
4
+ # All rights reserved.
5
+ #
6
+ # This source file is distributed as part of the Net::SSH Secure Shell Client
7
+ # library for Ruby. This file (and the library as a whole) may be used only as
8
+ # allowed by either the BSD license, or the Ruby license (or, by association
9
+ # with the Ruby license, the GPL). See the "doc" subdirectory of the Net::SSH
10
+ # distribution for the texts of these licenses.
11
+ # -----------------------------------------------------------------------------
12
+ # net-ssh website : http://net-ssh.rubyforge.org
13
+ # project website: http://rubyforge.org/projects/net-ssh
14
+ # =============================================================================
15
+ #++
16
+
17
+ require 'net/ssh/errors'
18
+ require 'net/ssh/transport/constants'
19
+
20
+ module Net
21
+ module SSH
22
+ module Transport
23
+
24
+ # The AlgorithmNegotiator is used for negotiating the algorithms to be
25
+ # employed for a specific SSH session.
26
+ class AlgorithmNegotiator
27
+ include Constants
28
+
29
+ Algorithms = Struct.new( :server_packet,
30
+ :client_packet,
31
+ :kex,
32
+ :host_key,
33
+ :encryption_c2s,
34
+ :encryption_s2c,
35
+ :mac_c2s,
36
+ :mac_s2c,
37
+ :compression_c2s,
38
+ :compression_s2c,
39
+ :language_c2s,
40
+ :language_s2c,
41
+ :compression_level )
42
+
43
+ # Create a new AlgorithmNegotiator instance, using the given logger,
44
+ # set of default algorithms, and buffer factory.
45
+ def initialize( logger, algorithms, buffers )
46
+ @default_algorithms = algorithms
47
+ @buffers = buffers
48
+ @logger = logger
49
+ end
50
+
51
+ # Adds the algorithms of the specified type from +options+ to the
52
+ # @algorithms hash. Also verifies that the specified algorithms are
53
+ # supported.
54
+ def prepare_preferred_algorithm( options, algorithm )
55
+ @algorithms[ algorithm ] = @default_algorithms[ algorithm ].dup
56
+ if options[algorithm]
57
+ algos = [ *options[algorithm] ]
58
+ algos.each do |algo|
59
+ unless @algorithms[algorithm].include?(algo)
60
+ raise NotImplementedError,
61
+ "unsupported algorithm for #{algorithm.inspect}: #{algo}"
62
+ end
63
+ end
64
+ @algorithms[ algorithm ].unshift( *algos ).uniq!
65
+ end
66
+ end
67
+ private :prepare_preferred_algorithm
68
+
69
+ # Builds the @algorithms hash from the values specified in the
70
+ # +options+ hash.
71
+ def prepare_preferred_algorithms( options )
72
+ @algorithms = Hash.new
73
+
74
+ prepare_preferred_algorithm options, :host_key
75
+ prepare_preferred_algorithm options, :kex
76
+ prepare_preferred_algorithm options, :encryption
77
+ prepare_preferred_algorithm options, :hmac
78
+ prepare_preferred_algorithm options, :compression
79
+ prepare_preferred_algorithm options, :languages
80
+
81
+ @compression_level = options[ :compression_level ]
82
+ end
83
+ private :prepare_preferred_algorithms
84
+
85
+ # looks for the first element in list1 that is also in list2
86
+ def first_matching_element( list1, list2 )
87
+ list1 = list1.split( /,/ ) if list1.respond_to? :split
88
+ list2 = list2.split( /,/ ) if list2.respond_to? :split
89
+
90
+ list1.each do |item|
91
+ return item if list2.include? item
92
+ end
93
+
94
+ return nil
95
+ end
96
+ private :first_matching_element
97
+
98
+ # Negotiate the supported algorithms with the server. If a compromise
99
+ # cannot be reached between what the client wants and what the server
100
+ # can provide, this will fail.
101
+ def negotiate( session, options )
102
+ prepare_preferred_algorithms options
103
+
104
+ # first, discover what the server can do
105
+ type, buffer = session.wait_for_message
106
+ raise Net::SSH::Exception, "expected KEXINIT" unless type == KEXINIT
107
+
108
+ server_algorithm_packet = buffer.content
109
+
110
+ cookie = buffer.read( 16 )
111
+ kex_algorithms = buffer.read_string
112
+ server_host_key_algorithms = buffer.read_string
113
+ encryption_algorithms_client_to_server = buffer.read_string
114
+ encryption_algorithms_server_to_client = buffer.read_string
115
+ mac_algorithms_client_to_server = buffer.read_string
116
+ mac_algorithms_server_to_client = buffer.read_string
117
+ compression_algorithms_client_to_server = buffer.read_string
118
+ compression_algorithms_server_to_client = buffer.read_string
119
+ languages_client_to_server = buffer.read_string
120
+ languages_server_to_client = buffer.read_string
121
+ first_kex_packet_follows = buffer.read_bool
122
+ zero = buffer.read_long
123
+
124
+ # TODO: if first_kex_packet_follows, we need to try to skip the
125
+ # actual kexinit stuff and try to guess what the server is doing...
126
+ # need to read more about this scenario.
127
+
128
+ # next, tell the server what we can do
129
+
130
+ my_kex = @algorithms[ :kex ].join( "," )
131
+ my_server_host_key_algorithms = @algorithms[ :host_key ].join( "," )
132
+ my_encryption_algorithms = @algorithms[ :encryption ].join( "," )
133
+ my_mac_algorithms = @algorithms[ :hmac ].join( "," )
134
+ my_compression_algorithms = @algorithms[ :compression ].join( "," )
135
+ my_languages = @algorithms[ :languages ].join( "," )
136
+
137
+ msg = @buffers.writer
138
+ msg.write_byte KEXINIT
139
+ msg.write_long rand(0xFFFFFFFF), rand(0xFFFFFFFF), rand(0xFFFFFFFF),
140
+ rand(0xFFFFFFFF)
141
+ msg.write_string my_kex, my_server_host_key_algorithms
142
+ msg.write_string my_encryption_algorithms, my_encryption_algorithms
143
+ msg.write_string my_mac_algorithms, my_mac_algorithms
144
+ msg.write_string my_compression_algorithms, my_compression_algorithms
145
+ msg.write_string my_languages, my_languages
146
+ msg.write_bool false
147
+ msg.write_long 0
148
+
149
+ client_algorithm_packet = msg.to_s
150
+ session.send_message msg
151
+
152
+ # negotiate algorithms
153
+
154
+ kex_algorithm = first_matching_element( @algorithms[ :kex ],
155
+ kex_algorithms )
156
+ raise Net::SSH::Exception,
157
+ "could not settle on kex algorithm" unless kex_algorithm
158
+ @logger.debug "kex algorithm: #{kex_algorithm}" if @logger.debug?
159
+
160
+ host_key_algorithm = first_matching_element(
161
+ @algorithms[ :host_key ], server_host_key_algorithms )
162
+ raise Net::SSH::Exception,
163
+ "could not settle on host key algorithm" unless host_key_algorithm
164
+ if @logger.debug?
165
+ @logger.debug "host key algorithm: #{host_key_algorithm}"
166
+ end
167
+
168
+ encryption_algorithm_c2s = first_matching_element(
169
+ @algorithms[ :encryption ], encryption_algorithms_client_to_server )
170
+ unless encryption_algorithm_c2s
171
+ raise Net::SSH::Exception,
172
+ "could not settle on client-to-server encryption algorithm"
173
+ end
174
+ if @logger.debug?
175
+ @logger.debug "encryption algorithm (client-to-server): " +
176
+ encryption_algorithm_c2s
177
+ end
178
+
179
+ encryption_algorithm_s2c = first_matching_element(
180
+ @algorithms[ :encryption ], encryption_algorithms_server_to_client )
181
+ unless encryption_algorithm_s2c
182
+ raise Net::SSH::Exception,
183
+ "could not settle on server-to-client encryption algorithm"
184
+ end
185
+ if @logger.debug?
186
+ @logger.debug "encryption algorithm (server-to-client): " +
187
+ encryption_algorithm_s2c
188
+ end
189
+
190
+ mac_algorithm_c2s = first_matching_element(
191
+ @algorithms[ :hmac ], mac_algorithms_client_to_server )
192
+ unless mac_algorithm_c2s
193
+ raise Net::SSH::Exception,
194
+ "could not settle on client-to-server HMAC algorithm"
195
+ end
196
+ if @logger.debug?
197
+ @logger.debug "hmac algorithm (client-to-server): " +
198
+ mac_algorithm_c2s
199
+ end
200
+
201
+ mac_algorithm_s2c = first_matching_element( @algorithms[ :hmac ],
202
+ mac_algorithms_server_to_client )
203
+ unless mac_algorithm_s2c
204
+ raise Net::SSH::Exception,
205
+ "could not settle on server-to-client HMAC algorithm"
206
+ end
207
+ if @logger.debug?
208
+ @logger.debug "hmac algorithm (server-to-client): " +
209
+ mac_algorithm_s2c
210
+ end
211
+
212
+ compression_algorithm_c2s = first_matching_element(
213
+ @algorithms[ :compression ],
214
+ compression_algorithms_client_to_server )
215
+ unless compression_algorithm_c2s
216
+ raise Net::SSH::Exception,
217
+ "could not settle on client-to-server compression algorithm"
218
+ end
219
+ if @logger.debug?
220
+ @logger.debug "compression algorithm (client-to-server): " +
221
+ compression_algorithm_c2s
222
+ end
223
+
224
+ compression_algorithm_s2c = first_matching_element(
225
+ @algorithms[ :compression ],
226
+ compression_algorithms_server_to_client )
227
+ unless compression_algorithm_s2c
228
+ raise Net::SSH::Exception,
229
+ "could not settle on server-to-client compression algorithm"
230
+ end
231
+ if @logger.debug?
232
+ @logger.debug "compression algorithm (server-to-client): " +
233
+ compression_algorithm_s2c
234
+ end
235
+
236
+ language_c2s = first_matching_element( @algorithms[ :languages ],
237
+ languages_client_to_server ) || ""
238
+ if @logger.debug?
239
+ @logger.debug "language (client-to-server): #{language_c2s}"
240
+ end
241
+
242
+ language_s2c = first_matching_element( @algorithms[ :languages ],
243
+ languages_server_to_client ) || ""
244
+ if @logger.debug?
245
+ @logger.debug "language (server-to-client): #{language_s2c}"
246
+ end
247
+
248
+ return Algorithms.new( server_algorithm_packet,
249
+ client_algorithm_packet,
250
+ kex_algorithm,
251
+ host_key_algorithm,
252
+ encryption_algorithm_c2s,
253
+ encryption_algorithm_s2c,
254
+ mac_algorithm_c2s,
255
+ mac_algorithm_s2c,
256
+ compression_algorithm_c2s,
257
+ compression_algorithm_s2c,
258
+ language_c2s,
259
+ language_s2c,
260
+ @compression_level )
261
+ end
262
+
263
+ end
264
+
265
+ end
266
+ end
267
+ end