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.
- data/doc/LICENSE-BSD +27 -0
- data/doc/LICENSE-GPL +280 -0
- data/doc/LICENSE-RUBY +56 -0
- data/doc/README +13 -0
- data/doc/manual-html/chapter-1.html +333 -0
- data/doc/manual-html/chapter-2.html +455 -0
- data/doc/manual-html/chapter-3.html +413 -0
- data/doc/manual-html/chapter-4.html +353 -0
- data/doc/manual-html/chapter-5.html +393 -0
- data/doc/manual-html/chapter-6.html +296 -0
- data/doc/manual-html/index.html +217 -0
- data/doc/manual-html/manual.css +192 -0
- data/doc/manual/chapter.erb +18 -0
- data/doc/manual/example.erb +18 -0
- data/doc/manual/index.erb +29 -0
- data/doc/manual/manual.css +192 -0
- data/doc/manual/manual.rb +240 -0
- data/doc/manual/manual.yml +67 -0
- data/doc/manual/page.erb +87 -0
- data/doc/manual/parts/channels_callbacks.txt +32 -0
- data/doc/manual/parts/channels_loop.txt +14 -0
- data/doc/manual/parts/channels_open.txt +20 -0
- data/doc/manual/parts/channels_operations.txt +15 -0
- data/doc/manual/parts/channels_types.txt +3 -0
- data/doc/manual/parts/channels_what_are.txt +7 -0
- data/doc/manual/parts/exec_channels.txt +28 -0
- data/doc/manual/parts/exec_open.txt +51 -0
- data/doc/manual/parts/exec_popen3.txt +35 -0
- data/doc/manual/parts/forward_direct.txt +37 -0
- data/doc/manual/parts/forward_handlers.txt +16 -0
- data/doc/manual/parts/forward_intro.txt +18 -0
- data/doc/manual/parts/forward_local.txt +18 -0
- data/doc/manual/parts/forward_remote.txt +14 -0
- data/doc/manual/parts/intro_author.txt +1 -0
- data/doc/manual/parts/intro_getting.txt +39 -0
- data/doc/manual/parts/intro_license.txt +6 -0
- data/doc/manual/parts/intro_support.txt +7 -0
- data/doc/manual/parts/intro_what_is.txt +7 -0
- data/doc/manual/parts/intro_what_is_not.txt +3 -0
- data/doc/manual/parts/proxy_http.txt +52 -0
- data/doc/manual/parts/proxy_intro.txt +1 -0
- data/doc/manual/parts/proxy_socks.txt +23 -0
- data/doc/manual/parts/session_key.txt +66 -0
- data/doc/manual/parts/session_options.txt +42 -0
- data/doc/manual/parts/session_session.txt +14 -0
- data/doc/manual/parts/session_start.txt +49 -0
- data/doc/manual/tutorial.erb +30 -0
- data/examples/channel-demo.rb +81 -0
- data/examples/port-forward.rb +51 -0
- data/examples/process-demo.rb +91 -0
- data/examples/remote-net-port-forward.rb +45 -0
- data/examples/remote-port-forward.rb +80 -0
- data/examples/tail-demo.rb +49 -0
- data/lib/net/ssh.rb +52 -0
- data/lib/net/ssh/connection/channel.rb +411 -0
- data/lib/net/ssh/connection/constants.rb +47 -0
- data/lib/net/ssh/connection/driver.rb +343 -0
- data/lib/net/ssh/connection/services.rb +72 -0
- data/lib/net/ssh/connection/term.rb +90 -0
- data/lib/net/ssh/errors.rb +27 -0
- data/lib/net/ssh/proxy/errors.rb +34 -0
- data/lib/net/ssh/proxy/http.rb +126 -0
- data/lib/net/ssh/proxy/socks4.rb +83 -0
- data/lib/net/ssh/proxy/socks5.rb +160 -0
- data/lib/net/ssh/service/forward/driver.rb +319 -0
- data/lib/net/ssh/service/forward/local-network-handler.rb +74 -0
- data/lib/net/ssh/service/forward/remote-network-handler.rb +81 -0
- data/lib/net/ssh/service/forward/services.rb +76 -0
- data/lib/net/ssh/service/process/driver.rb +153 -0
- data/lib/net/ssh/service/process/open.rb +193 -0
- data/lib/net/ssh/service/process/popen3.rb +160 -0
- data/lib/net/ssh/service/process/services.rb +66 -0
- data/lib/net/ssh/service/services.rb +44 -0
- data/lib/net/ssh/session.rb +242 -0
- data/lib/net/ssh/transport/algorithm-negotiator.rb +267 -0
- data/lib/net/ssh/transport/compress/compressor.rb +53 -0
- data/lib/net/ssh/transport/compress/decompressor.rb +53 -0
- data/lib/net/ssh/transport/compress/none-compressor.rb +39 -0
- data/lib/net/ssh/transport/compress/none-decompressor.rb +39 -0
- data/lib/net/ssh/transport/compress/services.rb +68 -0
- data/lib/net/ssh/transport/compress/zlib-compressor.rb +60 -0
- data/lib/net/ssh/transport/compress/zlib-decompressor.rb +52 -0
- data/lib/net/ssh/transport/constants.rb +66 -0
- data/lib/net/ssh/transport/errors.rb +47 -0
- data/lib/net/ssh/transport/identity-cipher.rb +61 -0
- data/lib/net/ssh/transport/kex/dh-gex.rb +106 -0
- data/lib/net/ssh/transport/kex/dh.rb +231 -0
- data/lib/net/ssh/transport/kex/services.rb +60 -0
- data/lib/net/ssh/transport/ossl/buffer-factory.rb +52 -0
- data/lib/net/ssh/transport/ossl/buffer.rb +87 -0
- data/lib/net/ssh/transport/ossl/cipher-factory.rb +98 -0
- data/lib/net/ssh/transport/ossl/digest-factory.rb +51 -0
- data/lib/net/ssh/transport/ossl/hmac-factory.rb +71 -0
- data/lib/net/ssh/transport/ossl/hmac/hmac.rb +62 -0
- data/lib/net/ssh/transport/ossl/hmac/md5-96.rb +44 -0
- data/lib/net/ssh/transport/ossl/hmac/md5.rb +46 -0
- data/lib/net/ssh/transport/ossl/hmac/none.rb +46 -0
- data/lib/net/ssh/transport/ossl/hmac/services.rb +68 -0
- data/lib/net/ssh/transport/ossl/hmac/sha1-96.rb +44 -0
- data/lib/net/ssh/transport/ossl/hmac/sha1.rb +45 -0
- data/lib/net/ssh/transport/ossl/key-factory.rb +113 -0
- data/lib/net/ssh/transport/ossl/services.rb +149 -0
- data/lib/net/ssh/transport/packet-stream.rb +210 -0
- data/lib/net/ssh/transport/services.rb +146 -0
- data/lib/net/ssh/transport/session.rb +296 -0
- data/lib/net/ssh/transport/version-negotiator.rb +73 -0
- data/lib/net/ssh/userauth/agent.rb +218 -0
- data/lib/net/ssh/userauth/constants.rb +35 -0
- data/lib/net/ssh/userauth/driver.rb +176 -0
- data/lib/net/ssh/userauth/methods/hostbased.rb +119 -0
- data/lib/net/ssh/userauth/methods/password.rb +70 -0
- data/lib/net/ssh/userauth/methods/publickey.rb +137 -0
- data/lib/net/ssh/userauth/methods/services.rb +63 -0
- data/lib/net/ssh/userauth/services.rb +126 -0
- data/lib/net/ssh/userauth/userkeys.rb +258 -0
- data/lib/net/ssh/util/buffer.rb +274 -0
- data/lib/net/ssh/util/openssl.rb +146 -0
- data/lib/net/ssh/util/prompter.rb +73 -0
- data/lib/net/ssh/version.rb +29 -0
- data/test/ALL-TESTS.rb +21 -0
- data/test/connection/tc_channel.rb +136 -0
- data/test/connection/tc_driver.rb +287 -0
- data/test/connection/tc_integration.rb +85 -0
- data/test/proxy/tc_http.rb +209 -0
- data/test/proxy/tc_socks4.rb +148 -0
- data/test/proxy/tc_socks5.rb +214 -0
- data/test/service/forward/tc_driver.rb +289 -0
- data/test/service/forward/tc_local_network_handler.rb +123 -0
- data/test/service/forward/tc_remote_network_handler.rb +108 -0
- data/test/service/process/tc_driver.rb +79 -0
- data/test/service/process/tc_integration.rb +117 -0
- data/test/service/process/tc_open.rb +179 -0
- data/test/service/process/tc_popen3.rb +164 -0
- data/test/tc_integration.rb +79 -0
- data/test/transport/compress/tc_none_compress.rb +41 -0
- data/test/transport/compress/tc_none_decompress.rb +45 -0
- data/test/transport/compress/tc_zlib_compress.rb +61 -0
- data/test/transport/compress/tc_zlib_decompress.rb +48 -0
- data/test/transport/kex/tc_dh.rb +304 -0
- data/test/transport/kex/tc_dh_gex.rb +70 -0
- data/test/transport/ossl/fixtures/dsa-encrypted +15 -0
- data/test/transport/ossl/fixtures/dsa-encrypted-bad +15 -0
- data/test/transport/ossl/fixtures/dsa-unencrypted +12 -0
- data/test/transport/ossl/fixtures/dsa-unencrypted-bad +12 -0
- data/test/transport/ossl/fixtures/dsa-unencrypted.pub +1 -0
- data/test/transport/ossl/fixtures/not-a-private-key +4 -0
- data/test/transport/ossl/fixtures/not-supported +2 -0
- data/test/transport/ossl/fixtures/rsa-encrypted +18 -0
- data/test/transport/ossl/fixtures/rsa-encrypted-bad +18 -0
- data/test/transport/ossl/fixtures/rsa-unencrypted +15 -0
- data/test/transport/ossl/fixtures/rsa-unencrypted-bad +15 -0
- data/test/transport/ossl/fixtures/rsa-unencrypted.pub +1 -0
- data/test/transport/ossl/hmac/tc_hmac.rb +58 -0
- data/test/transport/ossl/hmac/tc_md5.rb +50 -0
- data/test/transport/ossl/hmac/tc_md5_96.rb +50 -0
- data/test/transport/ossl/hmac/tc_none.rb +50 -0
- data/test/transport/ossl/hmac/tc_sha1.rb +50 -0
- data/test/transport/ossl/hmac/tc_sha1_96.rb +50 -0
- data/test/transport/ossl/tc_buffer.rb +97 -0
- data/test/transport/ossl/tc_buffer_factory.rb +67 -0
- data/test/transport/ossl/tc_cipher_factory.rb +84 -0
- data/test/transport/ossl/tc_digest_factory.rb +39 -0
- data/test/transport/ossl/tc_hmac_factory.rb +72 -0
- data/test/transport/ossl/tc_key_factory.rb +199 -0
- data/test/transport/tc_algorithm_negotiator.rb +169 -0
- data/test/transport/tc_identity_cipher.rb +52 -0
- data/test/transport/tc_integration.rb +110 -0
- data/test/transport/tc_packet_stream.rb +183 -0
- data/test/transport/tc_session.rb +283 -0
- data/test/transport/tc_version_negotiator.rb +86 -0
- data/test/userauth/methods/tc_hostbased.rb +136 -0
- data/test/userauth/methods/tc_password.rb +89 -0
- data/test/userauth/methods/tc_publickey.rb +167 -0
- data/test/userauth/tc_agent.rb +223 -0
- data/test/userauth/tc_driver.rb +190 -0
- data/test/userauth/tc_integration.rb +81 -0
- data/test/userauth/tc_userkeys.rb +265 -0
- data/test/util/tc_buffer.rb +217 -0
- 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
|