=begin Arachni Copyright (c) 2010-2012 Tasos "Zapotek" Laskos <tasos.laskos@gmail.com> This is free software; you can copy and distribute and modify this program under the term of the GPL v2.0 License (See LICENSE file for details) =end module Arachni require Options.instance.dir['lib'] + 'rpc/client/instance' require Options.instance.dir['lib'] + 'rpc/client/dispatcher' require Options.instance.dir['lib'] + 'rpc/server/base' require Options.instance.dir['lib'] + 'rpc/server/output' require Options.instance.dir['lib'] + 'rpc/server/options' require Options.instance.dir['lib'] + 'rpc/server/framework' module RPC class Server # # RPC Server class # # Provides an RPC server to assist with general integration and UI development. # # Only instantiated by the Dispatcher to provide support for multiple # and concurent RPC clients/scans. # # @author: Tasos "Zapotek" Laskos # <tasos.laskos@gmail.com> # <zapotek@segfault.gr> # @version: 0.1.5 # class Instance # the output interface for RPC include Arachni::UI::Output include Arachni::Module::Utilities # # Initializes the RPC interface, the HTTP(S) server and the framework. # # @param [Options] opts # def initialize( opts, token ) prep_framework banner @opts = opts @token = token @server = Base.new( @opts, token ) @opts.datastore[:token] = token debug! if @opts.debug if logfile = @opts.reroute_to_logfile reroute_to_file( @opts.dir['logs'] + "Instance - #{Process.pid}-#{@opts.rpc_port}.log" ) else reroute_to_file( false ) end set_handlers # trap interrupts and exit cleanly when required [ 'QUIT', 'INT' ].each { |signal| trap( signal ){ shutdown } if Signal.list.has_key?( signal ) } run end # # Flushes the output buffer and returns all pending system messages. # # All messages are classified based on their type. # # @return [Array<Hash>] # def output( &block ) @framework.output( &block ) end # # Makes the server go bye-bye...Lights out! # def shutdown print_status( 'Shutting down...' ) t = [] @framework.instances.each { |instance| # Don't know why but this works better than EM's stuff t << Thread.new { @framework.instance_eval{ connect_to_instance( instance ).service.shutdown! } } } t.join @server.shutdown return true end alias :shutdown! :shutdown def alive? @server.alive? end private # # Starts the HTTPS server and the RPC service. # def run print_status( 'Starting the server...' ) # start the show! @server.run end def dispatcher @dispatcher ||= Arachni::RPC::Client::Dispatcher.new( @opts, @opts.datastore[:dispatcher_url] ) end # # Initialises the RPC framework. # def prep_framework @framework = Arachni::RPC::Server::Framework.new( Options.instance ) end # # Outputs the Arachni banner.<br/> # Displays version number, revision number, author details etc. # def banner puts 'Arachni - Web Application Security Scanner Framework v' + @framework.version + ' [' + @framework.revision + '] Author: Tasos "Zapotek" Laskos <tasos.laskos@gmail.com> <zapotek@segfault.gr> (With the support of the community and the Arachni Team.) Website: http://github.com/Zapotek/arachni Documentation: http://github.com/Zapotek/arachni/wiki' puts puts end # # Starts the RPC service and attaches it to the HTTP(S) server.<br/> # It also prepares all the RPC handlers. # def set_handlers @server.add_async_check { |method| # methods that expect a block are async method.parameters.flatten.include?( :block ) } @server.add_handler( "service", self ) @server.add_handler( "framework", @framework ) @server.add_handler( "opts", @framework.opts ) @server.add_handler( "modules", @framework.modules ) @server.add_handler( "plugins", @framework.plugins ) end end end end end