Class: Arachni::Plugin::Manager

Inherits:
Component::Manager show all
Extended by:
Utilities
Includes:
Utilities
Defined in:
lib/arachni/plugin/manager.rb

Overview

Holds and manages the plugins.

Author:

Direct Known Subclasses

RPC::Server::Plugin::Manager

Constant Summary collapse

NAMESPACE =
Arachni::Plugins
DEFAULT =
%w(defaults/*)

Constants inherited from Component::Manager

Component::Manager::EXCLUDE, Component::Manager::WILDCARD

Instance Attribute Summary

Attributes inherited from Component::Manager

#lib, #namespace

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Utilities

cookie_encode, cookies_from_document, cookies_from_file, cookies_from_response, exception_jail, exclude_path?, extract_domain, form_decode, form_encode, form_parse_request_body, forms_from_document, forms_from_response, get_path, hash_keys_to_str, html_decode, html_encode, include_path?, links_from_document, links_from_response, normalize_url, page_from_response, page_from_url, parse_query, parse_set_cookie, parse_url_vars, path_in_domain?, path_too_deep?, remove_constants, seed, skip_path?, to_absolute, uri_decode, uri_encode, uri_parse, uri_parser, url_sanitize

Methods inherited from Component::Manager

#[], #available, #clear, #delete, #include?, #load, #load_all, #load_by_tags, #loaded, #name_to_path, #parse, #path_to_name, #paths, #prep_opts

Methods included from UI::Output

#debug?, #debug_off, #debug_on, #disable_only_positives, #flush_buffer, #mute, #muted?, old_reset_output_options, #only_positives, #only_positives?, #print_bad, #print_debug, #print_debug_backtrace, #print_debug_pp, #print_error, #print_error_backtrace, #print_info, #print_line, #print_ok, #print_status, #print_verbose, #reroute_to_file, #reroute_to_file?, reset_output_options, #set_buffer_cap, #uncap_buffer, #unmute, #verbose, #verbose?

Constructor Details

#initialize(framework) ⇒ Manager

Returns a new instance of Manager.

Parameters:



42
43
44
45
46
47
# File 'lib/arachni/plugin/manager.rb', line 42

def initialize( framework )
    super( framework.opts.dir['plugins'], NAMESPACE )
    @framework = framework

    @jobs = []
end

Class Method Details

.mutexObject



224
225
226
# File 'lib/arachni/plugin/manager.rb', line 224

def self.mutex
    @mutex ||= Mutex.new
end

.resetObject



245
246
247
248
# File 'lib/arachni/plugin/manager.rb', line 245

def self.reset
    results.clear
    remove_constants( NAMESPACE )
end

.resultsObject



231
232
233
# File 'lib/arachni/plugin/manager.rb', line 231

def self.results
    @@results ||= {}
end

.results=(v) ⇒ Object



238
239
240
# File 'lib/arachni/plugin/manager.rb', line 238

def self.results=( v )
    @@results = v
end

Instance Method Details

#blockObject

Blocks until all plug-ins have finished executing.



141
142
143
144
145
146
147
148
149
150
151
# File 'lib/arachni/plugin/manager.rb', line 141

def block
    while !@jobs.empty?
        print_debug
        print_debug( "Waiting on the following (#{@jobs.size}) plugins to finish:" )
        print_debug( job_names.join( ', ' ) )
        print_debug

        @jobs.delete_if { |j| !j.alive? }
        ::IO::select( nil, nil, nil, 1 )
    end
end

#busy?Bool

Will return false if all plug-ins have finished executing.

Returns:

  • (Bool)


158
159
160
# File 'lib/arachni/plugin/manager.rb', line 158

def busy?
    !@jobs.reject{ |j| j.alive? }.empty?
end

#create(name, opts = {}) ⇒ Object



134
135
136
# File 'lib/arachni/plugin/manager.rb', line 134

def create( name, opts ={} )
    self[name].new( @framework, opts )
end

#defaultObject Also known as: defaults



54
55
56
# File 'lib/arachni/plugin/manager.rb', line 54

def default
    parse DEFAULT
end

#get(name) ⇒ Thread

Gets a running plug-in by name.

Parameters:

Returns:

  • (Thread)


198
199
200
201
# File 'lib/arachni/plugin/manager.rb', line 198

def get( name )
    @jobs.each { |job| return job if job[:name] == name }
    nil
end

#job_namesArray

Returns the names of the running plug-ins.

Returns:



167
168
169
# File 'lib/arachni/plugin/manager.rb', line 167

def job_names
    @jobs.map{ |j| j[:name] }
end

#jobsArray<Thread>

Returns all the running threads.

Returns:



176
177
178
# File 'lib/arachni/plugin/manager.rb', line 176

def jobs
    @jobs
end

#kill(name) ⇒ Object

Kills a plug-in by name.

Parameters:



185
186
187
188
189
# File 'lib/arachni/plugin/manager.rb', line 185

def kill( name )
    job = get( name )
    return true if job && job.kill
    false
end

#load_defaultObject Also known as: load_defaults



49
50
51
# File 'lib/arachni/plugin/manager.rb', line 49

def load_default
    load DEFAULT
end

#mutexObject



227
228
229
# File 'lib/arachni/plugin/manager.rb', line 227

def mutex
    self.class.mutex
end

#register_results(plugin, results) ⇒ Object

Registers plugin results

Parameters:



209
210
211
212
213
214
215
216
217
218
219
220
221
222
# File 'lib/arachni/plugin/manager.rb', line 209

def register_results( plugin, results )
    mutex.synchronize {
        name = nil
        self.each do |k, v|
            if plugin.class.name == v.name
                name = k
                break
            end
        end

        return if !name
        self.class.results[name] = { results: results }.merge( plugin.class.info )
    }
end

#resetObject



249
250
251
# File 'lib/arachni/plugin/manager.rb', line 249

def reset
    self.class.reset
end

#resultsObject



234
235
236
# File 'lib/arachni/plugin/manager.rb', line 234

def results
    self.class.results
end

#results=(v) ⇒ Object



241
242
243
# File 'lib/arachni/plugin/manager.rb', line 241

def results=( v )
    self.class.results = v
end

#runObject

Runs each plug-in in its own thread.



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/arachni/plugin/manager.rb', line 62

def run
    ordered   = []
    unordered = []

    loaded.each do |name|
        ph = { name => self[name] }
        if order = self[name].info[:priority]
            ordered[order] ||= []
            ordered[order] << ph
        else
            unordered << ph
        end
    end
    ordered << unordered
    ordered.flatten!

    ordered.each do |ph|
        name   = ph.keys.first
        plugin = ph.values.first

        if( ret = sane_env?( plugin ) ) != true
            deps = ''
            if !ret[:gem_errors].empty?
                print_bad( "[#{name}] The following plug-in dependencies aren't satisfied:" )
                ret[:gem_errors].each { |gem| print_bad( "\t* #{gem}" ) }

                deps = ret[:gem_errors].join( ' ' )
                print_bad( "Try installing them by running:" )
                print_bad( "\tgem install #{deps}" )
            end

            fail "Plug-in dependencies not met: #{name} -- #{deps}"
        end

        opts = @framework.opts.plugins[name]
        opts = prep_opts( name, self[name], opts )

        @jobs << Thread.new {

            exception_jail( false ) {
                Thread.current[:name]     = name
                Thread.current[:instance] = plugin_new = create( name, opts )

                plugin_new.prepare
                plugin_new.run
                plugin_new.clean_up
            }

        }
    end

    if @jobs.size > 0
        print_status( 'Waiting for plugins to settle...' )
        ::IO::select( nil, nil, nil, 1 )
    end
end

#sane_env?(plugin) ⇒ Boolean

Returns:

  • (Boolean)


119
120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/arachni/plugin/manager.rb', line 119

def sane_env?( plugin )
    gem_errors = []

    plugin.gems.each do |gem|
        begin
            require gem
        rescue LoadError
            gem_errors << gem
        end
    end

    return { gem_errors: gem_errors } if !gem_errors.empty?
    true
end