CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/msf/core/event_dispatcher.rb
Views: 1904
1
# -*- coding: binary -*-
2
3
module Msf
4
5
6
7
###
8
#
9
# This class manages subscriber registration and is the entry point
10
# for dispatching various events that occur for modules, such as
11
# exploit results and auxiliary module data. The framework
12
# and external modules can register themselves as subscribers to
13
# various events such that they can perform custom actions when
14
# a specific event or events occur.
15
#
16
###
17
class EventDispatcher
18
19
include Framework::Offspring
20
21
def initialize(framework)
22
self.framework = framework
23
self.general_event_subscribers = []
24
self.custom_event_subscribers = []
25
self.exploit_event_subscribers = []
26
self.session_event_subscribers = []
27
self.db_event_subscribers = []
28
self.ui_event_subscribers = []
29
end
30
31
##
32
#
33
# Subscriber registration
34
#
35
##
36
37
#
38
# This method adds a general subscriber. General subscribers receive
39
# notifications when all events occur.
40
#
41
def add_general_subscriber(subscriber)
42
add_event_subscriber(general_event_subscribers, subscriber)
43
end
44
45
#
46
# Removes a general subscriber.
47
#
48
def remove_general_subscriber(subscriber)
49
remove_event_subscriber(general_event_subscribers, subscriber)
50
end
51
52
#
53
# This method adds a db event subscriber. db event subscribers
54
# receive notifications when events occur that pertain to db changes.
55
# The subscriber provided must implement the DatabaseEvent module methods
56
# in some form.
57
#
58
def add_db_subscriber(subscriber)
59
add_event_subscriber(db_event_subscribers, subscriber)
60
end
61
62
#
63
# Removes a db event subscriber.
64
#
65
def remove_db_subscriber(subscriber)
66
remove_event_subscriber(db_event_subscribers, subscriber)
67
end
68
69
70
#
71
# This method adds an exploit event subscriber. Exploit event subscribers
72
# receive notifications when events occur that pertain to exploits, such as
73
# the success or failure of an exploitation attempt. The subscriber
74
# provided must implement the ExploitEvent module methods in some form.
75
#
76
def add_exploit_subscriber(subscriber)
77
add_event_subscriber(exploit_event_subscribers, subscriber)
78
end
79
80
#
81
# Removes an exploit event subscriber.
82
#
83
def remove_exploit_subscriber(subscriber)
84
remove_event_subscriber(exploit_event_subscribers, subscriber)
85
end
86
87
#
88
# This method adds a session event subscriber. Session event subscribers
89
# receive notifications when sessions are opened and closed. The
90
# subscriber provided must implement the SessionEvent module methods in
91
# some form.
92
#
93
def add_session_subscriber(subscriber)
94
add_event_subscriber(session_event_subscribers, subscriber)
95
end
96
97
#
98
# Removes a session event subscriber.
99
#
100
def remove_session_subscriber(subscriber)
101
remove_event_subscriber(session_event_subscribers, subscriber)
102
end
103
104
##
105
#
106
# General events
107
#
108
##
109
110
#
111
# Called when a module is loaded into the framework. This, in turn,
112
# notifies all registered general event subscribers.
113
#
114
# This is covered by the method_missing logic, but defining it manually
115
# reduces startup time by about 10%.
116
#
117
def on_module_load(name, mod)
118
general_event_subscribers.each { |subscriber|
119
subscriber.on_module_load(name, mod)
120
}
121
end
122
123
#
124
# Capture incoming events and pass them off to the subscribers
125
#
126
# When receiving an on_* event, look for a subscriber type matching the
127
# type of the event. If one exists, send the event on to each subscriber
128
# of that type. Otherwise, try to send the event each of the general
129
# subscribers.
130
#
131
# Event method names should be like "on_<type>_<event>", e.g.:
132
# on_exploit_success.
133
#
134
def method_missing(name, *args)
135
136
event,type,rest = name.to_s.split("_", 3)
137
subscribers = "#{type}_event_subscribers"
138
found = false
139
case event
140
when "on"
141
if respond_to?(subscribers, true)
142
found = true
143
self.send(subscribers).each do |sub|
144
next if not sub.respond_to?(name, true)
145
sub.send(name, *args)
146
end
147
else
148
(general_event_subscribers + custom_event_subscribers).each do |sub|
149
next if not sub.respond_to?(name, true)
150
sub.send(name, *args)
151
found = true
152
end
153
end
154
when "add"
155
if respond_to?(subscribers, true)
156
found = true
157
add_event_subscriber(self.send(subscribers), *args)
158
end
159
when "remove"
160
if respond_to?(subscribers, true)
161
found = true
162
remove_event_subscriber(self.send(subscribers), *args)
163
end
164
end
165
166
return found
167
end
168
169
170
protected
171
172
#
173
# Adds an event subscriber to the supplied subscriber array.
174
#
175
def add_event_subscriber(array, subscriber) # :nodoc:
176
array << subscriber
177
end
178
179
#
180
# Removes an event subscriber from the supplied subscriber array.
181
#
182
def remove_event_subscriber(array, subscriber) # :nodoc:
183
array.delete(subscriber)
184
end
185
186
attr_accessor :custom_event_subscribers # :nodoc:
187
attr_accessor :db_event_subscribers # :nodoc:
188
attr_accessor :exploit_event_subscribers # :nodoc:
189
attr_accessor :general_event_subscribers # :nodoc:
190
attr_accessor :session_event_subscribers # :nodoc:
191
attr_accessor :ui_event_subscribers # :nodoc:
192
193
end
194
195
end
196
197