Files
metasploit-gs/lib/msf/ui/web/comm.rb
T

157 lines
3.0 KiB
Ruby
Raw Normal View History

# -*- coding: binary -*-
2016-08-26 13:51:26 -05:00
require 'rex/ui/text/bidirectional_pipe'
2006-09-10 01:29:05 +00:00
module Msf
module Ui
module Web
module Comm
2013-08-30 16:28:33 -05:00
class Channel
def initialize
@id = Comm.next_channel_id
end
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
def read
nil
end
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
attr_accessor :id
end
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
class SessionChannel < Channel
def initialize(session_id, pipe)
super()
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
@sid = session_id
@pipe = pipe
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
@pipe.create_subscriber(channel.id)
end
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
def close
@pipe.remove_subscriber(channel.id)
end
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
def write_input(msg)
@pipe.write_input(msg)
end
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
def read
@pipe.read_subscriber(channel.id)
end
end
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
class SessionEventSubscriber
include Msf::SessionEvent
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
def on_session_open(session)
pipe = Comm.create_session_pipe(session)
2013-08-30 16:28:33 -05:00
session.init_ui(pipe, pipe)
end
end
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
@@framework = nil
@@channels = {}
@@channel_id = 0
@@read_event = Rex::Sync::Event.new(false, false)
@@session_pipes = {}
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
def self.setup(framework)
@framework = framework
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
framework.events.add_session_subscriber(SessionEventSubscriber.new)
end
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
def self.wakeup
@read_event.set
end
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
def self.next_channel_id
@channel_id += 1
end
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
def self.create_channel(client, request)
create_session_channel(client.qstring['sid'].to_i)
end
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
def self.create_session_channel(session_id)
channel = SessionChannel.new(session_id, @session_pipes[session_id])
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
@channels[channel.id] = channel
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
channel
end
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
def self.create_session_pipe(session)
2016-08-26 13:51:26 -05:00
pipe = Rex::Ui::BidirectionalPipe.new
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
@session_pipes[session.id] = pipe
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
pipe
end
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
def self.write_channel(client, request)
channel_id = request.qstring['channel_id']
data = request.qstring['data']
channel = @channels[channel_id]
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
if channel.nil? == false
channel.write_input(data)
end
end
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
def self.read_channels(client, request)
dlog("read_channels: waiting for event")
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
# Wait to see if there's any data available on channels. If there
# isn't, then we send a response immediately. Otherwise, we check
# to see if any of the requested channels were ones that we're
# interested in.
begin
@@read_event.wait(15)
rescue Timeout::Error
client.send_response(Rex::Proto::Http::Response::OK.new)
return
end
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
@@read_event.reset
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
channels = request.qstring['channels']
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
if channels.kind_of?(Array) == false
channels = [channels]
end
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
# Walk each channel, checking to see if there is any read data. If
# there is, then we'll include it in the response body.
body = '<channeldatum>'
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
channels.each { |cid|
channel = @channels[cid]
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
next if channel.nil?
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
buf = channel.read
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
next if buf.nil?
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
body += "<channeldata id=\"#{channel.id}\">#{Base64.encode64(buf)}</channeldata>"
}
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
body = '</channeldatum>'
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
# Create and send the response
response = Rex::Proto::Http::Response::OK.new
response.body = body
2006-09-10 01:29:05 +00:00
2013-08-30 16:28:33 -05:00
client.send_response(response)
end
2006-09-10 01:29:05 +00:00
end
end
end
end