Module: Rex::Ui::Interactive
- Includes:
- Subscriber
- Included in:
- Msf::Session::Interactive, Post::HWBridge::Ui::Console::InteractiveChannel, Post::Meterpreter::Ui::Console::InteractiveChannel, Post::Sql::Ui::Console::InteractiveSqlClient
- Defined in:
- lib/rex/ui/interactive.rb
Overview
This class implements the stubs that are needed to provide an interactive user interface that is backed against something arbitrary.
Instance Attribute Summary collapse
-
#completed ⇒ Object
Whether or not the session has completed interaction.
-
#interacting ⇒ Object
Whether or not the session is currently being interacted with.
-
#next_session ⇒ Object
If another session needs interaction, this is where it goes.
-
#on_command_proc ⇒ Object
Returns the value of attribute on_command_proc.
-
#on_print_proc ⇒ Object
Returns the value of attribute on_print_proc.
-
#on_run_command_error_proc ⇒ Proc?
A function to be run when running a session command hits an error.
-
#orig_suspend ⇒ Object
protected
The original suspend proc.
-
#orig_usr1 ⇒ Object
protected
Returns the value of attribute orig_usr1.
-
#orig_winch ⇒ Object
protected
Returns the value of attribute orig_winch.
Attributes included from Subscriber::Input
Attributes included from Subscriber::Output
Instance Method Summary collapse
-
#_interact ⇒ Object
protected
Stub method that is meant to handler interaction.
-
#_interact_complete ⇒ Object
protected
Called when interaction has completed and one of the sides has closed.
-
#_interrupt ⇒ Object
protected
Called when an interrupt is sent.
-
#_local_fd ⇒ Object
protected
The local file descriptor handle.
-
#_remote_fd(stream) ⇒ Object
protected
The remote file descriptor handle.
-
#_stream_read_local_write_remote(stream) ⇒ Object
protected
Read from local and write to remote.
-
#_stream_read_remote_write_local(stream) ⇒ Object
protected
Read from remote and write to local.
-
#_suspend ⇒ Object
protected
Called when a suspend is sent.
- #_winch ⇒ Object protected
-
#detach ⇒ Object
Stops the current interaction.
-
#handle_suspend ⇒ Object
protected
Installs a signal handler to monitor suspend signal notifications.
- #handle_usr1 ⇒ Object protected
- #handle_winch ⇒ Object protected
-
#interact(user_input, user_output) ⇒ Object
Starts interacting with the session at the most raw level, simply forwarding input from user_input to rstream and forwarding input from rstream to user_output.
-
#interact_stream(stream) ⇒ Object
protected
Interacts with two streaming connections, reading data from one and writing it to the other.
-
#prompt(query) ⇒ Object
protected
Prompt the user for input if possible.
-
#prompt_yesno(query) ⇒ Object
protected
Check the return value of a yes/no prompt.
-
#restore_suspend ⇒ Object
protected
Restores the previously installed signal handler for suspend notifications.
- #restore_usr1 ⇒ Object protected
- #restore_winch ⇒ Object protected
Methods included from Subscriber
Methods included from Subscriber::Input
Methods included from Subscriber::Output
#flush, #print, #print_blank_line, #print_error, #print_good, #print_line, #print_status, #print_warning
Instance Attribute Details
#completed ⇒ Object
Whether or not the session has completed interaction
126 127 128 |
# File 'lib/rex/ui/interactive.rb', line 126 def completed @completed end |
#interacting ⇒ Object
Whether or not the session is currently being interacted with
116 117 118 |
# File 'lib/rex/ui/interactive.rb', line 116 def interacting @interacting end |
#next_session ⇒ Object
If another session needs interaction, this is where it goes
121 122 123 |
# File 'lib/rex/ui/interactive.rb', line 121 def next_session @next_session end |
#on_command_proc ⇒ Object
Returns the value of attribute on_command_proc.
129 130 131 |
# File 'lib/rex/ui/interactive.rb', line 129 def on_command_proc @on_command_proc end |
#on_print_proc ⇒ Object
Returns the value of attribute on_print_proc.
128 129 130 |
# File 'lib/rex/ui/interactive.rb', line 128 def on_print_proc @on_print_proc end |
#on_run_command_error_proc ⇒ Proc?
A function to be run when running a session command hits an error
135 136 137 |
# File 'lib/rex/ui/interactive.rb', line 135 def on_run_command_error_proc @on_run_command_error_proc end |
#orig_suspend ⇒ Object (protected)
The original suspend proc.
142 143 144 |
# File 'lib/rex/ui/interactive.rb', line 142 def orig_suspend @orig_suspend end |
#orig_usr1 ⇒ Object (protected)
Returns the value of attribute orig_usr1.
143 144 145 |
# File 'lib/rex/ui/interactive.rb', line 143 def orig_usr1 @orig_usr1 end |
#orig_winch ⇒ Object (protected)
Returns the value of attribute orig_winch.
144 145 146 |
# File 'lib/rex/ui/interactive.rb', line 144 def orig_winch @orig_winch end |
Instance Method Details
#_interact ⇒ Object (protected)
Stub method that is meant to handler interaction
149 150 |
# File 'lib/rex/ui/interactive.rb', line 149 def _interact end |
#_interact_complete ⇒ Object (protected)
Called when interaction has completed and one of the sides has closed.
169 170 171 |
# File 'lib/rex/ui/interactive.rb', line 169 def _interact_complete true end |
#_interrupt ⇒ Object (protected)
Called when an interrupt is sent.
155 156 157 |
# File 'lib/rex/ui/interactive.rb', line 155 def _interrupt true end |
#_local_fd ⇒ Object (protected)
The local file descriptor handle.
196 197 198 |
# File 'lib/rex/ui/interactive.rb', line 196 def _local_fd user_input.fd end |
#_remote_fd(stream) ⇒ Object (protected)
The remote file descriptor handle.
203 204 205 |
# File 'lib/rex/ui/interactive.rb', line 203 def _remote_fd(stream) stream.fd end |
#_stream_read_local_write_remote(stream) ⇒ Object (protected)
Read from local and write to remote.
186 187 188 189 190 191 |
# File 'lib/rex/ui/interactive.rb', line 186 def _stream_read_local_write_remote(stream) data = user_input.gets self.on_command_proc.call(data) if self.on_command_proc stream.put(data) end |
#_stream_read_remote_write_local(stream) ⇒ Object (protected)
Read from remote and write to local.
176 177 178 179 180 181 |
# File 'lib/rex/ui/interactive.rb', line 176 def _stream_read_remote_write_local(stream) data = stream.get self.on_print_proc.call(data) if self.on_print_proc user_output.print(data) end |
#_suspend ⇒ Object (protected)
Called when a suspend is sent.
162 163 164 |
# File 'lib/rex/ui/interactive.rb', line 162 def _suspend false end |
#_winch ⇒ Object (protected)
298 299 |
# File 'lib/rex/ui/interactive.rb', line 298 def _winch end |
#detach ⇒ Object
Stops the current interaction
104 105 106 107 108 109 110 111 |
# File 'lib/rex/ui/interactive.rb', line 104 def detach if (self.interacting) self.interacting = false while(not self.completed) ::IO.select(nil, nil, nil, 0.25) end end end |
#handle_suspend ⇒ Object (protected)
Installs a signal handler to monitor suspend signal notifications.
236 237 238 239 240 241 242 243 244 245 |
# File 'lib/rex/ui/interactive.rb', line 236 def handle_suspend if orig_suspend.nil? begin self.orig_suspend = Signal.trap("TSTP") do Thread.new { _suspend }.join end rescue end end end |
#handle_usr1 ⇒ Object (protected)
264 265 266 267 268 269 270 271 272 273 |
# File 'lib/rex/ui/interactive.rb', line 264 def handle_usr1 if orig_usr1.nil? begin self.orig_usr1 = Signal.trap("USR1") do Thread.new { _usr1 }.join end rescue end end end |
#handle_winch ⇒ Object (protected)
275 276 277 278 279 280 281 282 283 284 |
# File 'lib/rex/ui/interactive.rb', line 275 def handle_winch if orig_winch.nil? begin self.orig_winch = Signal.trap("WINCH") do Thread.new { _winch }.join end rescue end end end |
#interact(user_input, user_output) ⇒ Object
Starts interacting with the session at the most raw level, simply forwarding input from user_input to rstream and forwarding input from rstream to user_output.
24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 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 |
# File 'lib/rex/ui/interactive.rb', line 24 def interact(user_input, user_output) # Detach from any existing console if self.interacting detach() end init_ui(user_input, user_output) self.interacting = true self.completed = false eof = false # Start the readline stdin monitor # XXX disabled # user_input.readline_start() if user_input.supports_readline # Handle suspend notifications handle_suspend handle_usr1 handle_winch # As long as we're interacting... while (self.interacting == true) begin _interact rescue Interrupt # If we get an interrupt exception, ask the user if they want to # abort the interaction. If they do, then we return out of # the interact function and call it a day. eof = true if (_interrupt) rescue EOFError, Errno::ECONNRESET, IOError # If we reach EOF or the connection is reset... eof = true end break if eof end begin # Restore the suspend handler restore_suspend restore_winch # If we've hit eof, call the interact complete handler _interact_complete if (eof == true) # Shutdown the readline thread # XXX disabled # user_input.readline_stop() if user_input.supports_readline # Detach from the input/output handles reset_ui() ensure # Mark this as completed self.completed = true end # if another session was requested, store it next_session = self.next_session # clear the value from the object self.next_session = nil # return this session id return next_session end |
#interact_stream(stream) ⇒ Object (protected)
Interacts with two streaming connections, reading data from one and writing it to the other. Both are expected to implement Rex::IO::Stream.
211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 |
# File 'lib/rex/ui/interactive.rb', line 211 def interact_stream(stream) while self.interacting && _remote_fd(stream) # Select input and rstream sd = Rex::ThreadSafe.select([ _local_fd, _remote_fd(stream) ], nil, nil, 0.25) # Cycle through the items that have data # From the stream? Write to user_output. sd[0].each { |s| if (s == _remote_fd(stream)) _stream_read_remote_write_local(stream) # From user_input? Write to stream. elsif (s == _local_fd) _stream_read_local_write_remote(stream) end } if (sd) Thread.pass end end |
#prompt(query) ⇒ Object (protected)
Prompt the user for input if possible. XXX: This is not thread-safe on Windows
317 318 319 320 321 322 |
# File 'lib/rex/ui/interactive.rb', line 317 def prompt(query) if (user_output and user_input) user_output.print("\n" + query) user_input.sysread(2) end end |
#prompt_yesno(query) ⇒ Object (protected)
Check the return value of a yes/no prompt
327 328 329 |
# File 'lib/rex/ui/interactive.rb', line 327 def prompt_yesno(query) (prompt(query + " [y/N] ") =~ /^y/i) ? true : false end |
#restore_suspend ⇒ Object (protected)
Restores the previously installed signal handler for suspend notifications.
252 253 254 255 256 257 258 259 260 261 262 |
# File 'lib/rex/ui/interactive.rb', line 252 def restore_suspend begin if orig_suspend Signal.trap("TSTP", orig_suspend) else Signal.trap("TSTP", "DEFAULT") end self.orig_suspend = nil rescue end end |
#restore_usr1 ⇒ Object (protected)
301 302 303 304 305 306 307 308 309 310 311 |
# File 'lib/rex/ui/interactive.rb', line 301 def restore_usr1 begin if orig_usr1 Signal.trap("USR1", orig_usr1) else Signal.trap("USR1", "DEFAULT") end self.orig_usr1 = nil rescue end end |
#restore_winch ⇒ Object (protected)
286 287 288 289 290 291 292 293 294 295 296 |
# File 'lib/rex/ui/interactive.rb', line 286 def restore_winch begin if orig_winch Signal.trap("WINCH", orig_winch) else Signal.trap("WINCH", "DEFAULT") end self.orig_winch = nil rescue end end |