metasploit-framework/lib/msf/ui/web/comm.rb

156 lines
3.0 KiB
Ruby
Raw Normal View History

# -*- coding: binary -*-
module Msf
module Ui
module Web
module Comm
2013-08-30 21:28:33 +00:00
class Channel
def initialize
@id = Comm.next_channel_id
end
2013-08-30 21:28:33 +00:00
def read
nil
end
2013-08-30 21:28:33 +00:00
attr_accessor :id
end
2013-08-30 21:28:33 +00:00
class SessionChannel < Channel
def initialize(session_id, pipe)
super()
2013-08-30 21:28:33 +00:00
@sid = session_id
@pipe = pipe
2013-08-30 21:28:33 +00:00
@pipe.create_subscriber(channel.id)
end
2013-08-30 21:28:33 +00:00
def close
@pipe.remove_subscriber(channel.id)
end
2013-08-30 21:28:33 +00:00
def write_input(msg)
@pipe.write_input(msg)
end
2013-08-30 21:28:33 +00:00
def read
@pipe.read_subscriber(channel.id)
end
end
2013-08-30 21:28:33 +00:00
class SessionEventSubscriber
include Msf::SessionEvent
2013-08-30 21:28:33 +00:00
def on_session_open(session)
pipe = Comm.create_session_pipe(session)
2013-08-30 21:28:33 +00:00
session.init_ui(pipe, pipe)
end
end
2013-08-30 21:28:33 +00:00
@@framework = nil
@@channels = {}
@@channel_id = 0
@@read_event = Rex::Sync::Event.new(false, false)
@@session_pipes = {}
2013-08-30 21:28:33 +00:00
def self.setup(framework)
@framework = framework
2013-08-30 21:28:33 +00:00
framework.events.add_session_subscriber(SessionEventSubscriber.new)
end
2013-08-30 21:28:33 +00:00
def self.wakeup
@read_event.set
end
2013-08-30 21:28:33 +00:00
def self.next_channel_id
@channel_id += 1
end
2013-08-30 21:28:33 +00:00
def self.create_channel(client, request)
create_session_channel(client.qstring['sid'].to_i)
end
2013-08-30 21:28:33 +00:00
def self.create_session_channel(session_id)
channel = SessionChannel.new(session_id, @session_pipes[session_id])
2013-08-30 21:28:33 +00:00
@channels[channel.id] = channel
2013-08-30 21:28:33 +00:00
channel
end
2013-08-30 21:28:33 +00:00
def self.create_session_pipe(session)
pipe = Rex::IO::BidirectionalPipe.new
2013-08-30 21:28:33 +00:00
@session_pipes[session.id] = pipe
2013-08-30 21:28:33 +00:00
pipe
end
2013-08-30 21:28:33 +00:00
def self.write_channel(client, request)
channel_id = request.qstring['channel_id']
data = request.qstring['data']
channel = @channels[channel_id]
2013-08-30 21:28:33 +00:00
if channel.nil? == false
channel.write_input(data)
end
end
2013-08-30 21:28:33 +00:00
def self.read_channels(client, request)
dlog("read_channels: waiting for event")
2013-08-30 21:28:33 +00: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
2013-08-30 21:28:33 +00:00
@@read_event.reset
2013-08-30 21:28:33 +00:00
channels = request.qstring['channels']
2013-08-30 21:28:33 +00:00
if channels.kind_of?(Array) == false
channels = [channels]
end
2013-08-30 21:28:33 +00: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>'
2013-08-30 21:28:33 +00:00
channels.each { |cid|
channel = @channels[cid]
2013-08-30 21:28:33 +00:00
next if channel.nil?
2013-08-30 21:28:33 +00:00
buf = channel.read
2013-08-30 21:28:33 +00:00
next if buf.nil?
2013-08-30 21:28:33 +00:00
body += "<channeldata id=\"#{channel.id}\">#{Base64.encode64(buf)}</channeldata>"
}
2013-08-30 21:28:33 +00:00
body = '</channeldatum>'
2013-08-30 21:28:33 +00:00
# Create and send the response
response = Rex::Proto::Http::Response::OK.new
response.body = body
2013-08-30 21:28:33 +00:00
client.send_response(response)
end
end
end
end
end