PageRenderTime 51ms CodeModel.GetById 27ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/rex/socket/comm/local.rb

https://bitbucket.org/technopunk2099/metasploit-framework
Ruby | 459 lines | 321 code | 80 blank | 58 comment | 74 complexity | a5cb59de8dfc825f43af22e04c892c39 MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0, LGPL-2.1, GPL-2.0, MIT
  1. # -*- coding: binary -*-
  2. require 'singleton'
  3. require 'rex/socket'
  4. require 'rex/socket/tcp'
  5. require 'rex/socket/ssl_tcp'
  6. require 'rex/socket/ssl_tcp_server'
  7. require 'rex/socket/udp'
  8. require 'rex/socket/ip'
  9. require 'timeout'
  10. ###
  11. #
  12. # Local communication class factory.
  13. #
  14. ###
  15. class Rex::Socket::Comm::Local
  16. include Singleton
  17. include Rex::Socket::Comm
  18. #
  19. # Creates an instance of a socket using the supplied parameters.
  20. #
  21. def self.create(param)
  22. # Work around jRuby socket implementation issues
  23. if(RUBY_PLATFORM == 'java')
  24. return self.create_jruby(param)
  25. end
  26. case param.proto
  27. when 'tcp'
  28. return create_by_type(param, ::Socket::SOCK_STREAM, ::Socket::IPPROTO_TCP)
  29. when 'udp'
  30. return create_by_type(param, ::Socket::SOCK_DGRAM, ::Socket::IPPROTO_UDP)
  31. when 'ip'
  32. return create_ip(param)
  33. else
  34. raise Rex::UnsupportedProtocol.new(param.proto), caller
  35. end
  36. end
  37. #
  38. # Creates an instance of a socket using the supplied parameters.
  39. # Use various hacks to make this work with jRuby
  40. #
  41. def self.create_jruby(param)
  42. sock = nil
  43. # Notify handlers of the before socket create event.
  44. self.instance.notify_before_socket_create(self, param)
  45. case param.proto
  46. when 'tcp'
  47. if (param.server?)
  48. sock = TCPServer.new(param.localport, param.localhost)
  49. klass = Rex::Socket::TcpServer
  50. if (param.ssl)
  51. klass = Rex::Socket::SslTcpServer
  52. end
  53. sock.extend(klass)
  54. else
  55. sock = TCPSocket.new(param.peerhost, param.peerport)
  56. klass = Rex::Socket::Tcp
  57. if (param.ssl)
  58. klass = Rex::Socket::SslTcp
  59. end
  60. sock.extend(klass)
  61. end
  62. when 'udp'
  63. if (param.server?)
  64. sock = UDPServer.new(param.localport, param.localhost)
  65. klass = Rex::Socket::UdpServer
  66. sock.extend(klass)
  67. else
  68. sock = UDPSocket.new(param.peerhost, param.peerport)
  69. klass = Rex::Socket::Udp
  70. sock.extend(klass)
  71. end
  72. else
  73. raise Rex::UnsupportedProtocol.new(param.proto), caller
  74. end
  75. sock.initsock(param)
  76. self.instance.notify_socket_created(self, sock, param)
  77. return sock
  78. end
  79. #
  80. # Creates a raw IP socket using the supplied Parameter instance.
  81. # Special-cased because of how different it is from UDP/TCP
  82. #
  83. def self.create_ip(param)
  84. self.instance.notify_before_socket_create(self, param)
  85. sock = ::Socket.open(::Socket::PF_INET, ::Socket::SOCK_RAW, ::Socket::IPPROTO_RAW)
  86. sock.setsockopt(::Socket::IPPROTO_IP, ::Socket::IP_HDRINCL, 1)
  87. # Configure broadcast support
  88. sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_BROADCAST, true)
  89. if (param.bare? == false)
  90. sock.extend(::Rex::Socket::Ip)
  91. sock.initsock(param)
  92. end
  93. self.instance.notify_socket_created(self, sock, param)
  94. sock
  95. end
  96. #
  97. # Creates a socket using the supplied Parameter instance.
  98. #
  99. def self.create_by_type(param, type, proto = 0)
  100. # Whether to use IPv6 addressing
  101. usev6 = false
  102. # Detect IPv6 addresses and enable IPv6 accordingly
  103. if ( Rex::Socket.support_ipv6?())
  104. # Allow the caller to force IPv6
  105. if (param.v6)
  106. usev6 = true
  107. end
  108. # Force IPv6 mode for non-connected UDP sockets
  109. if (type == ::Socket::SOCK_DGRAM and not param.peerhost)
  110. # FreeBSD allows IPv6 socket creation, but throws an error on sendto()
  111. if (not Rex::Compat.is_freebsd())
  112. usev6 = true
  113. end
  114. end
  115. local = Rex::Socket.resolv_nbo(param.localhost) if param.localhost
  116. peer = Rex::Socket.resolv_nbo(param.peerhost) if param.peerhost
  117. if (local and local.length == 16)
  118. usev6 = true
  119. end
  120. if (peer and peer.length == 16)
  121. usev6 = true
  122. end
  123. if (usev6)
  124. if (local and local.length == 4)
  125. if (local == "\x00\x00\x00\x00")
  126. param.localhost = '::'
  127. elsif (local == "\x7f\x00\x00\x01")
  128. param.localhost = '::1'
  129. else
  130. param.localhost = '::ffff:' + Rex::Socket.getaddress(param.localhost, true)
  131. end
  132. end
  133. if (peer and peer.length == 4)
  134. if (peer == "\x00\x00\x00\x00")
  135. param.peerhost = '::'
  136. elsif (peer == "\x7f\x00\x00\x01")
  137. param.peerhost = '::1'
  138. else
  139. param.peerhost = '::ffff:' + Rex::Socket.getaddress(param.peerhost, true)
  140. end
  141. end
  142. param.v6 = true
  143. end
  144. else
  145. # No IPv6 support
  146. param.v6 = false
  147. end
  148. # Notify handlers of the before socket create event.
  149. self.instance.notify_before_socket_create(self, param)
  150. # Create the socket
  151. sock = nil
  152. if (param.v6)
  153. sock = ::Socket.new(::Socket::AF_INET6, type, proto)
  154. else
  155. sock = ::Socket.new(::Socket::AF_INET, type, proto)
  156. end
  157. # Bind to a given local address and/or port if they are supplied
  158. if param.localport or param.localhost
  159. begin
  160. sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_REUSEADDR, true)
  161. sock.bind(Rex::Socket.to_sockaddr(param.localhost, param.localport))
  162. rescue ::Errno::EADDRNOTAVAIL,::Errno::EADDRINUSE
  163. sock.close
  164. raise Rex::AddressInUse.new(param.localhost, param.localport), caller
  165. end
  166. end
  167. # Configure broadcast support for all datagram sockets
  168. if (type == ::Socket::SOCK_DGRAM)
  169. sock.setsockopt(::Socket::SOL_SOCKET, ::Socket::SO_BROADCAST, true)
  170. end
  171. # If a server TCP instance is being created...
  172. if (param.server?)
  173. sock.listen(256)
  174. if (param.bare? == false)
  175. klass = Rex::Socket::TcpServer
  176. if (param.ssl)
  177. klass = Rex::Socket::SslTcpServer
  178. end
  179. sock.extend(klass)
  180. sock.initsock(param)
  181. end
  182. # Otherwise, if we're creating a client...
  183. else
  184. chain = []
  185. # If we were supplied with host information
  186. if (param.peerhost)
  187. # A flag that indicates whether we need to try multiple scopes
  188. retry_scopes = false
  189. # Always retry with link-local IPv6 addresses
  190. if Rex::Socket.is_ipv6?( param.peerhost ) and param.peerhost =~ /^fe80::/
  191. retry_scopes = true
  192. end
  193. # Prepare a list of scope IDs to try when connecting to
  194. # link-level addresses. Read from /proc if it is available,
  195. # otherwise increment through the first 255 IDs.
  196. @@ip6_lla_scopes ||= []
  197. if @@ip6_lla_scopes.length == 0 and retry_scopes
  198. # Linux specific interface lookup code
  199. if ::File.exists?( "/proc/self/net/igmp6" )
  200. ::File.open("/proc/self/net/igmp6") do |fd|
  201. fd.each_line do |line|
  202. line = line.strip
  203. tscope, tint, junk = line.split(/\s+/, 3)
  204. next if not tint
  205. # Specifying lo in any connect call results in the socket
  206. # being unusable, even if the correct interface is set.
  207. next if tint == "lo"
  208. @@ip6_lla_scopes << tscope
  209. end
  210. end
  211. else
  212. # Other Unix-like platforms should support a raw scope ID
  213. [*(1 .. 255)].map{ |x| @@ip6_lla_scopes << x.to_s }
  214. end
  215. end
  216. ip6_scope_idx = 0
  217. ip = param.peerhost
  218. port = param.peerport
  219. if param.proxies
  220. chain = param.proxies.dup
  221. chain.push(['host',param.peerhost,param.peerport])
  222. ip = chain[0][1]
  223. port = chain[0][2].to_i
  224. end
  225. begin
  226. begin
  227. Timeout.timeout(param.timeout) do
  228. sock.connect(Rex::Socket.to_sockaddr(ip, port))
  229. end
  230. rescue ::Timeout::Error
  231. raise ::Errno::ETIMEDOUT
  232. end
  233. rescue ::Errno::EHOSTUNREACH,::Errno::ENETDOWN,::Errno::ENETUNREACH,::Errno::ENETRESET,::Errno::EHOSTDOWN,::Errno::EACCES,::Errno::EINVAL
  234. # Rescue errors caused by a bad Scope ID for a link-local address
  235. if retry_scopes and @@ip6_lla_scopes[ ip6_scope_idx ]
  236. ip = param.peerhost + "%" + @@ip6_lla_scopes[ ip6_scope_idx ]
  237. ip6_scope_idx += 1
  238. retry
  239. end
  240. sock.close
  241. raise Rex::HostUnreachable.new(param.peerhost, param.peerport), caller
  242. rescue ::Errno::EADDRNOTAVAIL,::Errno::EADDRINUSE
  243. sock.close
  244. raise Rex::AddressInUse.new(param.peerhost, param.peerport), caller
  245. rescue Errno::ETIMEDOUT
  246. sock.close
  247. raise Rex::ConnectionTimeout.new(param.peerhost, param.peerport), caller
  248. rescue ::Errno::ECONNRESET,::Errno::ECONNREFUSED,::Errno::ENOTCONN,::Errno::ECONNABORTED
  249. sock.close
  250. raise Rex::ConnectionRefused.new(param.peerhost, param.peerport), caller
  251. end
  252. end
  253. if (param.bare? == false)
  254. case param.proto
  255. when 'tcp'
  256. klass = Rex::Socket::Tcp
  257. sock.extend(klass)
  258. sock.initsock(param)
  259. when 'udp'
  260. sock.extend(Rex::Socket::Udp)
  261. sock.initsock(param)
  262. end
  263. end
  264. if chain.size > 1
  265. chain.each_with_index {
  266. |proxy, i|
  267. next_hop = chain[i + 1]
  268. if next_hop
  269. proxy(sock, proxy[0], next_hop[1], next_hop[2])
  270. end
  271. }
  272. end
  273. # Now extend the socket with SSL and perform the handshake
  274. if(param.bare? == false and param.ssl)
  275. klass = Rex::Socket::SslTcp
  276. sock.extend(klass)
  277. sock.initsock(param)
  278. end
  279. end
  280. # Notify handlers that a socket has been created.
  281. self.instance.notify_socket_created(self, sock, param)
  282. sock
  283. end
  284. def self.proxy(sock, type, host, port)
  285. #$stdout.print("PROXY\n")
  286. case type.downcase
  287. when 'http'
  288. setup = "CONNECT #{host}:#{port} HTTP/1.0\r\n\r\n"
  289. size = sock.put(setup)
  290. if (size != setup.length)
  291. raise Rex::ConnectionProxyError.new(host, port, type, "Failed to send the entire request to the proxy"), caller
  292. end
  293. begin
  294. ret = sock.get_once(39,30)
  295. rescue IOError
  296. raise Rex::ConnectionProxyError.new(host, port, type, "Failed to receive a response from the proxy"), caller
  297. end
  298. if ret.nil?
  299. raise Rex::ConnectionProxyError.new(host, port, type, "Failed to receive a response from the proxy"), caller
  300. end
  301. resp = Rex::Proto::Http::Response.new
  302. resp.update_cmd_parts(ret.split(/\r?\n/)[0])
  303. if resp.code != 200
  304. raise Rex::ConnectionProxyError.new(host, port, type, "The proxy returned a non-OK response"), caller
  305. end
  306. when 'socks4'
  307. setup = [4,1,port.to_i].pack('CCn') + Socket.gethostbyname(host)[3] + Rex::Text.rand_text_alpha(rand(8)+1) + "\x00"
  308. size = sock.put(setup)
  309. if (size != setup.length)
  310. raise Rex::ConnectionProxyError.new(host, port, type, "Failed to send the entire request to the proxy"), caller
  311. end
  312. begin
  313. ret = sock.get_once(8, 30)
  314. rescue IOError
  315. raise Rex::ConnectionProxyError.new(host, port, type, "Failed to receive a response from the proxy"), caller
  316. end
  317. if (ret.nil? or ret.length < 8)
  318. raise Rex::ConnectionProxyError.new(host, port, type, "Failed to receive a complete response from the proxy"), caller
  319. end
  320. if ret[1,1] != "\x5a"
  321. raise Rex::ConnectionProxyError.new(host, port, type, "Proxy responded with error code #{ret[0,1].unpack("C")[0]}"), caller
  322. end
  323. when 'socks5'
  324. auth_methods = [5,1,0].pack('CCC')
  325. size = sock.put(auth_methods)
  326. if (size != auth_methods.length)
  327. raise Rex::ConnectionProxyError.new(host, port, type, "Failed to send the entire request to the proxy"), caller
  328. end
  329. ret = sock.get_once(2,30)
  330. if (ret[1,1] == "\xff")
  331. raise Rex::ConnectionProxyError.new(host, port, type, "The proxy requires authentication"), caller
  332. end
  333. if (Rex::Socket.is_ipv4?(host))
  334. addr = Rex::Socket.gethostbyname(host)[3]
  335. setup = [5,1,0,1].pack('C4') + addr + [port.to_i].pack('n')
  336. elsif (Rex::Socket.support_ipv6? and Rex::Socket.is_ipv6?(host))
  337. # IPv6 stuff all untested
  338. addr = Rex::Socket.gethostbyname(host)[3]
  339. setup = [5,1,0,4].pack('C4') + addr + [port.to_i].pack('n')
  340. else
  341. # Then it must be a domain name.
  342. # Unfortunately, it looks like the host has always been
  343. # resolved by the time it gets here, so this code never runs.
  344. setup = [5,1,0,3].pack('C4') + [host.length].pack('C') + host + [port.to_i].pack('n')
  345. end
  346. size = sock.put(setup)
  347. if (size != setup.length)
  348. raise Rex::ConnectionProxyError.new(host, port, type, "Failed to send the entire request to the proxy"), caller
  349. end
  350. begin
  351. response = sock.get_once(10, 30)
  352. rescue IOError
  353. raise Rex::ConnectionProxyError.new(host, port, type, "Failed to receive a response from the proxy"), caller
  354. end
  355. if (response.nil? or response.length < 10)
  356. raise Rex::ConnectionProxyError.new(host, port, type, "Failed to receive a complete response from the proxy"), caller
  357. end
  358. if response[1,1] != "\x00"
  359. raise Rex::ConnectionProxyError.new(host, port, type, "Proxy responded with error code #{response[1,1].unpack("C")[0]}"), caller
  360. end
  361. else
  362. raise RuntimeError, "The proxy type specified is not valid", caller
  363. end
  364. end
  365. ##
  366. #
  367. # Registration
  368. #
  369. ##
  370. def self.register_event_handler(handler) # :nodoc:
  371. self.instance.register_event_handler(handler)
  372. end
  373. def self.deregister_event_handler(handler) # :nodoc:
  374. self.instance.deregister_event_handler(handler)
  375. end
  376. def self.each_event_handler(handler) # :nodoc:
  377. self.instance.each_event_handler(handler)
  378. end
  379. end