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,90 @@
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 Connection
20
+
21
+ # Terminal opcodes, for use when opening pty's.
22
+ module Term
23
+
24
+ TTY_OP_END = 0
25
+ VINTR = 1
26
+ VQUIT = 2
27
+ VERASE = 3
28
+ VKILL = 4
29
+ VEOF = 5
30
+ VEOL = 6
31
+ VEOL2 = 7
32
+ VSTART = 8
33
+ VSTOP = 9
34
+ VSUSP = 10
35
+ VDSUSP = 11
36
+ VREPRINT = 12
37
+ VWERASE = 13
38
+ VLNEXT = 14
39
+ VFLUSH = 15
40
+ VSWITCH = 16
41
+ VSTATUS = 17
42
+ VDISCARD = 18
43
+
44
+ IGNPAR = 30
45
+ PARMRK = 31
46
+ INPCK = 32
47
+ ISTRIP = 33
48
+ INCLR = 34
49
+ IGNCR = 35
50
+ ICRNL = 36
51
+ IUCLC = 37
52
+ IXON = 38
53
+ IXANY = 39
54
+ IXOFF = 40
55
+ IMAXBEL = 41
56
+
57
+ ISIG = 50
58
+ ICANON = 51
59
+ XCASE = 52
60
+ ECHO = 53
61
+ ECHOE = 54
62
+ ECHOK = 55
63
+ ECHONL = 56
64
+ NOFLSH = 57
65
+ TOSTOP= 58
66
+ IEXTEN = 59
67
+ ECHOCTL = 60
68
+ ECHOKE = 61
69
+ PENDIN = 62
70
+
71
+ OPOST = 70
72
+ OLCUC = 71
73
+ ONLCR = 72
74
+ OCRNL = 73
75
+ ONOCR = 74
76
+ ONLRET = 75
77
+
78
+ CS7 = 90
79
+ CS8 = 91
80
+ PARENB = 92
81
+ PARODD = 93
82
+
83
+ TTY_OP_ISPEED = 128
84
+ TTY_OP_OSPEED = 129
85
+
86
+ end
87
+
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,27 @@
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
+
20
+ # The ancestor class of all exceptions raised in the Net::SSH module.
21
+ class Exception < StandardError; end
22
+
23
+ # Raised when user authentication failed.
24
+ class AuthenticationFailed < Exception; end
25
+
26
+ end
27
+ end
@@ -0,0 +1,34 @@
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
+
19
+ module Net
20
+ module SSH
21
+ module Proxy
22
+
23
+ # A general exception class for all Proxy errors.
24
+ class Error < Net::SSH::Exception; end
25
+
26
+ # Used for reporting proxy connection errors.
27
+ class ConnectError < Error; end
28
+
29
+ # Used when the server doesn't recognize the users credentials
30
+ class UnauthorizedError < Error; end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,126 @@
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 'socket'
18
+ require 'base64'
19
+ require 'net/ssh/proxy/errors'
20
+
21
+ module Net
22
+ module SSH
23
+ module Proxy
24
+
25
+ # An implementation of a socket factory that returns a socket which
26
+ # will tunnel the connection through an HTTP proxy. It allows explicit
27
+ # specification of the user and password, but if none are given it
28
+ # will look in the HTTP_PROXY_USER/HTTP_PROXY_PASSWORD and
29
+ # CONNECT_USER/CONNECT_PASSWORD environment variables as well.
30
+ class HTTP
31
+
32
+ # Create a new socket factory that tunnels via the given host and
33
+ # port.
34
+ def initialize( proxy_host, proxy_port=80, options={} )
35
+ @proxy_host = proxy_host
36
+ @proxy_port = proxy_port
37
+ @options = options
38
+ end
39
+
40
+ # Return a new socket connected to the given host and port via the
41
+ # proxy that was requested when the socket factory was instantiated.
42
+ def open( host, port )
43
+ connect_string = "CONNECT #{host}:#{port} HTTP/1.0"
44
+
45
+ socket = TCPSocket.new( @proxy_host, @proxy_port )
46
+ socket.puts connect_string
47
+ socket.puts
48
+
49
+ resp = parse_response( socket )
50
+
51
+ return socket if resp[:code] == 200
52
+
53
+ socket.shutdown
54
+ raise ConnectError, resp.inspect unless resp[:code] == 407
55
+
56
+ user = proxy_user
57
+ passwd = proxy_password
58
+
59
+ raise UnauthorizedError, "no proxy user given" unless user
60
+
61
+ auth = resp[:headers]["Proxy-Authenticate"]
62
+ scheme, parms = auth.split( / /, 2 )
63
+
64
+ case scheme
65
+ when "Basic"
66
+ credentials =
67
+ Base64.encode64( "#{user}:#{passwd}" ).gsub( /\n/, "" )
68
+ else
69
+ raise NotImplementedError,
70
+ "authorization scheme #{scheme.inspect} is not supported"
71
+ end
72
+
73
+ socket = TCPSocket.new( @proxy_host, @proxy_port )
74
+ socket.puts connect_string
75
+ socket.puts "Proxy-Authorization: #{scheme} #{credentials}"
76
+ socket.puts
77
+
78
+ resp = parse_response( socket )
79
+
80
+ raise ConnectError, resp.inspect if resp[:code] != 200
81
+
82
+ return socket
83
+ end
84
+
85
+ def parse_response( socket )
86
+ version, code, reason = socket.gets.chomp.split( / /, 3 )
87
+ headers = {}
88
+
89
+ while ( line = socket.gets.chomp ) != ""
90
+ name, value = line.split( /:/, 2 ).map { |v| v.strip }
91
+ headers[ name ] = value
92
+ end
93
+
94
+ if headers[ "Content-Length" ]
95
+ body = socket.read( headers[ "Content-Length" ].to_i )
96
+ end
97
+
98
+ return { :version => version,
99
+ :code => code.to_i,
100
+ :reason => reason,
101
+ :headers => headers,
102
+ :body => body }
103
+ end
104
+ private :parse_response
105
+
106
+ def proxy_user
107
+ return @options[ :user ] if @options[ :user ]
108
+ return ENV['HTTP_PROXY_USER'] if ENV['HTTP_PROXY_USER']
109
+ return ENV['CONNECT_USER'] if ENV['CONNECT_USER']
110
+ return nil
111
+ end
112
+ private :proxy_user
113
+
114
+ def proxy_password
115
+ return @options[ :password ] if @options[ :password ]
116
+ return ENV['HTTP_PROXY_PASSWORD'] if ENV['HTTP_PROXY_PASSWORD']
117
+ return ENV['CONNECT_PASSWORD'] if ENV['CONNECT_PASSWORD']
118
+ return ""
119
+ end
120
+ private :proxy_password
121
+
122
+ end
123
+
124
+ end
125
+ end
126
+ end
@@ -0,0 +1,83 @@
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 'socket'
18
+ require 'resolv'
19
+ require 'ipaddr'
20
+ require 'net/ssh/proxy/errors'
21
+
22
+ module Net
23
+ module SSH
24
+ module Proxy
25
+
26
+ # An implementation of a socket factory that returns a socket which
27
+ # will tunnel the connection through a SOCKS4 proxy. It allows explicit
28
+ # specification of the user, but if it is not given it will look in the
29
+ # SOCKS_USER and CONNECT_USER environment variables as well.
30
+ class SOCKS4
31
+
32
+ SOCKS_VERSION = 4
33
+
34
+ SOCKS_CMD_CONNECT = 1
35
+
36
+ SOCKS_GRANTED = 90
37
+ SOCKS_REJECTED = 91
38
+ SOCKS_IDENTD_REJECT = 92
39
+ SOCKS_IDENTD_BAD = 93
40
+
41
+ # Create a new proxy connection to the given proxy host and port.
42
+ # Optionally, a @:user@ option may be given to identify the username
43
+ # with which to authenticate.
44
+ def initialize( proxy_host, proxy_port=1080, options={} )
45
+ @proxy_host = proxy_host
46
+ @proxy_port = proxy_port
47
+ @options = options
48
+ end
49
+
50
+ # Return a new socket connected to the given host and port via the
51
+ # proxy that was requested when the socket factory was instantiated.
52
+ def open( host, port )
53
+ sock = TCPSocket.new( @proxy_host, @proxy_port )
54
+
55
+ ip_addr = IPAddr.new( Resolv.getaddress( host ) )
56
+
57
+ packet = [ SOCKS_VERSION, SOCKS_CMD_CONNECT,
58
+ port.to_i, ip_addr.to_i,
59
+ proxy_user, 0 ].pack( "CCnNA*C" )
60
+ sock.send packet, 0
61
+
62
+ version, status, port, ip = sock.recv( 8 ).unpack( "CCnN" )
63
+ if status != SOCKS_GRANTED
64
+ sock.close
65
+ raise ConnectError, "error connecting to proxy (#{status})"
66
+ end
67
+
68
+ return sock
69
+ end
70
+
71
+ def proxy_user
72
+ return @options[ :user ] if @options[ :user ]
73
+ return ENV['SOCKS_USER'] if ENV['SOCKS_USER']
74
+ return ENV['CONNECT_USER'] if ENV['CONNECT_USER']
75
+ return nil
76
+ end
77
+ private :proxy_user
78
+
79
+ end
80
+
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,160 @@
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 'socket'
18
+ require 'net/ssh/proxy/errors'
19
+
20
+ module Net
21
+ module SSH
22
+ module Proxy
23
+
24
+ # An implementation of a socket factory that returns a socket which
25
+ # will tunnel the connection through a SOCKS5 proxy. It allows explicit
26
+ # specification of the user and password, but if none are given it
27
+ # will look in the SOCKS_USER/SOCKS_PASSWORD and
28
+ # CONNECT_USER/CONNECT_PASSWORD environment variables as well.
29
+ class SOCKS5
30
+
31
+ SOCKS_VERSION = 5
32
+
33
+ SOCKS_METHOD_NO_AUTH = 0
34
+ SOCKS_METHOD_GSSAPI = 1
35
+ SOCKS_METHOD_PASSWD = 2
36
+
37
+ SOCKS_METHOD_NONE = 0xFF
38
+
39
+ SOCKS_CMD_CONNECT = 1
40
+
41
+ SOCKS_ATYP_IPV4 = 1
42
+ SOCKS_ATYP_DOMAIN = 3
43
+ SOCKS_ATYP_IPV6 = 4
44
+
45
+ SOCKS_SUCCESS = 0
46
+ SOCKS_FAILURE = 1
47
+ SOCKS_NOT_ALLOWED = 2
48
+ SOCKS_NETWORK_UNREACHABLE = 3
49
+ SOCKS_HOST_UNREACHABLE = 4
50
+ SOCKS_REFUSED = 5
51
+ SOCKS_TTL_EXPIRED = 6
52
+ SOCKS_CMD_NOT_SUPPORTED = 7
53
+ SOCKS_ADDR_NOT_SUPPORTED = 8
54
+
55
+ # Create a new proxy connection to the given proxy host and port.
56
+ # Optionally, @:user@ and @:password@ options may be given to
57
+ # identify the username and password with which to authenticate.
58
+ def initialize( proxy_host, proxy_port=1080, options={} )
59
+ @proxy_host = proxy_host
60
+ @proxy_port = proxy_port
61
+ @options = options
62
+ end
63
+
64
+ # Return a new socket connected to the given host and port via the
65
+ # proxy that was requested when the socket factory was instantiated.
66
+ def open( host, port )
67
+ sock = TCPSocket.new( @proxy_host, @proxy_port )
68
+
69
+ methods = [ SOCKS_METHOD_NO_AUTH ]
70
+ methods << SOCKS_METHOD_PASSWD if proxy_user
71
+
72
+ packet = [ SOCKS_VERSION, methods.size, *methods ].pack( "C*" )
73
+ sock.send packet, 0
74
+
75
+ version, method = sock.recv( 2 ).unpack( "CC" )
76
+ if version != 5
77
+ sock.close
78
+ raise Net::SSH::Proxy::Error,
79
+ "invalid SOCKS version (#{version})"
80
+ end
81
+
82
+ if method == SOCKS_METHOD_NONE
83
+ sock.close
84
+ raise Net::SSH::Proxy::Error,
85
+ "no supported authorization methods"
86
+ end
87
+
88
+ case method
89
+ when SOCKS_METHOD_NO_AUTH
90
+ # no method-dependent subnegotiation required
91
+
92
+ when SOCKS_METHOD_PASSWD
93
+ negotiate_password( sock )
94
+ end
95
+
96
+ packet = [ SOCKS_VERSION, SOCKS_CMD_CONNECT, 0 ].pack( "C*" )
97
+
98
+ if host =~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/
99
+ packet << [ SOCKS_ATYP_IPV4, $1.to_i, $2.to_i,
100
+ $3.to_i, $4.to_i ].pack( "C*" )
101
+ else
102
+ packet << [ SOCKS_ATYP_DOMAIN, host.length, host ].pack( "CCA*" )
103
+ end
104
+
105
+ packet << [ port ].pack( "n" )
106
+ sock.send packet, 0
107
+
108
+ version, reply, = sock.recv( 4 ).unpack( "C*" )
109
+ len = sock.recv( 1 )[0]
110
+ sock.recv( len + 2 )
111
+
112
+ unless reply == SOCKS_SUCCESS
113
+ sock.close
114
+ raise ConnectError, "#{reply}"
115
+ end
116
+
117
+ return sock
118
+ end
119
+
120
+ # Simple username/password negotiation with the SOCKS5 server.
121
+ def negotiate_password( socket )
122
+ user = proxy_user
123
+ passwd = proxy_password
124
+
125
+ packet = [ SOCKS_VERSION,
126
+ user.length, user,
127
+ passwd.length, passwd ].pack( "CCA*CA*" )
128
+
129
+ socket.send packet, 0
130
+
131
+ version, status = socket.recv( 2 ).unpack( "CC" )
132
+
133
+ if status != SOCKS_SUCCESS
134
+ socket.close
135
+ raise UnauthorizedError, "could not authorize user"
136
+ end
137
+ end
138
+ private :negotiate_password
139
+
140
+ def proxy_user
141
+ return @options[ :user ] if @options[ :user ]
142
+ return ENV['SOCKS_USER'] if ENV['SOCKS_USER']
143
+ return ENV['CONNECT_USER'] if ENV['CONNECT_USER']
144
+ return nil
145
+ end
146
+ private :proxy_user
147
+
148
+ def proxy_password
149
+ return @options[ :password ] if @options[ :password ]
150
+ return ENV['SOCKS_PASSWORD'] if ENV['SOCKS_PASSWORD']
151
+ return ENV['CONNECT_PASSWORD'] if ENV['CONNECT_PASSWORD']
152
+ return ""
153
+ end
154
+ private :proxy_password
155
+
156
+ end
157
+
158
+ end
159
+ end
160
+ end