Class: Rex::Proto::Http::Server
- Inherits:
-
Object
- Object
- Rex::Proto::Http::Server
- Includes:
- Rex::Proto
- Defined in:
- lib/rex/proto/http/server.rb
Overview
Acts as an HTTP server, processing requests and dispatching them to registered procs. Some of this server was modeled after webrick.
Constant Summary collapse
- ExtensionMimeTypes =
A hash that associated a file extension with a mime type for use as the content type of responses.
{ "rhtml" => "text/html", "html" => "text/html", "htm" => "text/htm", "jpg" => "image/jpeg", "jpeg" => "image/jpeg", "gif" => "image/gif", "png" => "image/png", "bmp" => "image/bmp", "txt" => "text/plain", "css" => "text/css", "ico" => "image/x-icon", }
- DefaultServer =
The default server name that will be returned in the Server attribute of a response.
"Rex"
Instance Attribute Summary collapse
-
#comm ⇒ Object
Returns the value of attribute comm.
-
#context ⇒ Object
Returns the value of attribute context.
-
#listen_host ⇒ Object
Returns the value of attribute listen_host.
-
#listen_port ⇒ Object
Returns the value of attribute listen_port.
-
#listener ⇒ Object
Returns the value of attribute listener.
-
#resources ⇒ Object
Returns the value of attribute resources.
-
#server_name ⇒ Object
Returns the value of attribute server_name.
-
#ssl ⇒ Object
Returns the value of attribute ssl.
-
#ssl_cert ⇒ Object
Returns the value of attribute ssl_cert.
-
#ssl_cipher ⇒ Object
Returns the value of attribute ssl_cipher.
-
#ssl_compression ⇒ Object
Returns the value of attribute ssl_compression.
-
#ssl_version ⇒ Object
Returns the value of attribute ssl_version.
Class Method Summary collapse
-
.hardcore_alias(*args) ⇒ Object
Returns the hardcore alias for the HTTP service.
Instance Method Summary collapse
-
#add_resource(name, opts) ⇒ Object
Adds a resource handler, such as one for /, which will be called whenever the resource is requested.
-
#add_response_headers(resp) ⇒ Object
Adds Server headers and stuff.
-
#alias ⇒ Object
HTTP server.
-
#close_client(cli) ⇒ Object
Closes the supplied client, if valid.
-
#dispatch_request(cli, request) ⇒ Object
protected
Dispatches the supplied request for a given connection.
-
#initialize(port = 80, listen_host = '0.0.0.0', ssl = false, context = {}, comm = nil, ssl_cert = nil, ssl_compression = false, ssl_cipher = nil, ssl_version = nil) ⇒ Server
constructor
Initializes an HTTP server as listening on the provided port and hostname.
-
#inspect ⇒ String
More readable inspect that only shows the url and resources.
-
#mime_type(file) ⇒ Object
Returns the mime type associated with the supplied file.
-
#mount(root, handler, long_call = false, *args) ⇒ Object
Mounts a directory or resource as being serviced by the supplied handler.
-
#on_client_connect(cli) ⇒ Object
protected
Extends new clients with the ServerClient module and initializes them.
-
#on_client_data(cli) ⇒ Object
protected
Processes data coming in from a client.
-
#remove_resource(name) ⇒ Object
Removes the supplied resource handler.
-
#send_e404(cli, request) ⇒ Object
Sends a 404 error to the client for a given request.
-
#start ⇒ Object
Listens on the defined port and host and starts monitoring for clients.
-
#stop ⇒ Object
Terminates the monitor thread and turns off the listener.
-
#unmount(root) ⇒ Object
Remove the mount point.
-
#wait ⇒ Object
Waits for the HTTP service to terminate.
Constructor Details
#initialize(port = 80, listen_host = '0.0.0.0', ssl = false, context = {}, comm = nil, ssl_cert = nil, ssl_compression = false, ssl_cipher = nil, ssl_version = nil) ⇒ Server
Initializes an HTTP server as listening on the provided port and hostname.
101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
# File 'lib/rex/proto/http/server.rb', line 101 def initialize(port = 80, listen_host = '0.0.0.0', ssl = false, context = {}, comm = nil, ssl_cert = nil, ssl_compression = false, ssl_cipher = nil, ssl_version = nil) self.listen_host = listen_host self.listen_port = port self.ssl = ssl self.context = context self.comm = comm self.ssl_cert = ssl_cert self.ssl_compression = ssl_compression self.ssl_cipher = ssl_cipher self.ssl_version = ssl_version self.listener = nil self.resources = {} self.server_name = DefaultServer end |
Instance Attribute Details
#comm ⇒ Object
Returns the value of attribute comm.
276 277 278 |
# File 'lib/rex/proto/http/server.rb', line 276 def comm @comm end |
#context ⇒ Object
Returns the value of attribute context.
276 277 278 |
# File 'lib/rex/proto/http/server.rb', line 276 def context @context end |
#listen_host ⇒ Object
Returns the value of attribute listen_host.
276 277 278 |
# File 'lib/rex/proto/http/server.rb', line 276 def listen_host @listen_host end |
#listen_port ⇒ Object
Returns the value of attribute listen_port.
276 277 278 |
# File 'lib/rex/proto/http/server.rb', line 276 def listen_port @listen_port end |
#listener ⇒ Object
Returns the value of attribute listener.
278 279 280 |
# File 'lib/rex/proto/http/server.rb', line 278 def listener @listener end |
#resources ⇒ Object
Returns the value of attribute resources.
278 279 280 |
# File 'lib/rex/proto/http/server.rb', line 278 def resources @resources end |
#server_name ⇒ Object
Returns the value of attribute server_name.
276 277 278 |
# File 'lib/rex/proto/http/server.rb', line 276 def server_name @server_name end |
#ssl ⇒ Object
Returns the value of attribute ssl.
277 278 279 |
# File 'lib/rex/proto/http/server.rb', line 277 def ssl @ssl end |
#ssl_cert ⇒ Object
Returns the value of attribute ssl_cert.
277 278 279 |
# File 'lib/rex/proto/http/server.rb', line 277 def ssl_cert @ssl_cert end |
#ssl_cipher ⇒ Object
Returns the value of attribute ssl_cipher.
277 278 279 |
# File 'lib/rex/proto/http/server.rb', line 277 def ssl_cipher @ssl_cipher end |
#ssl_compression ⇒ Object
Returns the value of attribute ssl_compression.
277 278 279 |
# File 'lib/rex/proto/http/server.rb', line 277 def ssl_compression @ssl_compression end |
#ssl_version ⇒ Object
Returns the value of attribute ssl_version.
277 278 279 |
# File 'lib/rex/proto/http/server.rb', line 277 def ssl_version @ssl_version end |
Class Method Details
.hardcore_alias(*args) ⇒ Object
Returns the hardcore alias for the HTTP service
129 130 131 |
# File 'lib/rex/proto/http/server.rb', line 129 def self.hardcore_alias(*args) "#{(args[0] || '')}-#{(args[1] || '')}-#{args[4] || ''}" end |
Instance Method Details
#add_resource(name, opts) ⇒ Object
Adds a resource handler, such as one for /, which will be called whenever the resource is requested. The “opts” parameter can have any of the following:
Proc (proc) - The procedure to call when a request comes in for this resource. LongCall (bool) - Hints to the server that this resource may have long
request processing times.
214 215 216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/rex/proto/http/server.rb', line 214 def add_resource(name, opts) if (resources[name]) raise RuntimeError, "The supplied resource '#{name}' is already added.", caller end # If a procedure was passed, mount the resource with it. if (opts['Proc']) mount(name, Handler::Proc, false, opts['Proc'], opts['VirtualDirectory']) else raise ArgumentError, "You must specify a procedure." end end |
#add_response_headers(resp) ⇒ Object
Adds Server headers and stuff.
238 239 240 |
# File 'lib/rex/proto/http/server.rb', line 238 def add_response_headers(resp) resp['Server'] = self.server_name if not resp['Server'] end |
#alias ⇒ Object
HTTP server.
136 137 138 |
# File 'lib/rex/proto/http/server.rb', line 136 def alias super || "HTTP Server" end |
#close_client(cli) ⇒ Object
Closes the supplied client, if valid.
187 188 189 |
# File 'lib/rex/proto/http/server.rb', line 187 def close_client(cli) listener.close_client(cli) end |
#dispatch_request(cli, request) ⇒ Object (protected)
Dispatches the supplied request for a given connection.
328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 |
# File 'lib/rex/proto/http/server.rb', line 328 def dispatch_request(cli, request) # Is the client requesting keep-alive? if ((request['Connection']) and (request['Connection'].downcase == 'Keep-Alive'.downcase)) cli.keepalive = true end # Search for the resource handler for the requested URL. This is pretty # inefficient right now, but we can spruce it up later. p = nil len = 0 root = nil resources.each_pair { |k, val| if (request.resource =~ /^#{k}/ and k.length > len) p = val len = k.length root = k end } if (p) # Create an instance of the handler for this resource handler = p[0].new(self, *p[2]) # If the handler class requires a relative resource... if (handler.relative_resource_required?) # Substituted the mount point root in the request to make things # relative to the mount point. request.relative_resource = request.resource.gsub(/^#{root}/, '') request.relative_resource = '/' + request.relative_resource if (request.relative_resource !~ /^\//) end # If we found the resource handler for this resource, call its # procedure. if (p[1] == true) Rex::ThreadFactory.spawn("HTTPServerRequestHandler", false) { handler.on_request(cli, request) } else handler.on_request(cli, request) end else elog("Failed to find handler for resource: #{request.resource}", LogSource) send_e404(cli, request) end # If keep-alive isn't enabled for this client, close the connection if (cli.keepalive == false) close_client(cli) end end |
#inspect ⇒ String
More readable inspect that only shows the url and resources
120 121 122 123 124 |
# File 'lib/rex/proto/http/server.rb', line 120 def inspect resources_str = resources.keys.map{|r| r.inspect }.join ", " "#<#{self.class} http#{ssl ? "s" : ""}://#{listen_host}:#{listen_port} [ #{resources_str} ]>" end |
#mime_type(file) ⇒ Object
Returns the mime type associated with the supplied file. Right now the set of mime types is fairly limited.
246 247 248 249 250 251 252 253 254 |
# File 'lib/rex/proto/http/server.rb', line 246 def mime_type(file) type = nil if (file =~ /\.(.+?)$/) type = ExtensionMimeTypes[$1.downcase] end type || "text/plain" end |
#mount(root, handler, long_call = false, *args) ⇒ Object
Mounts a directory or resource as being serviced by the supplied handler.
194 195 196 |
# File 'lib/rex/proto/http/server.rb', line 194 def mount(root, handler, long_call = false, *args) resources[root] = [ handler, long_call, args ] end |
#on_client_connect(cli) ⇒ Object (protected)
Extends new clients with the ServerClient module and initializes them.
285 286 287 288 289 |
# File 'lib/rex/proto/http/server.rb', line 285 def on_client_connect(cli) cli.extend(ServerClient) cli.init_cli(self) end |
#on_client_data(cli) ⇒ Object (protected)
Processes data coming in from a client.
294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 |
# File 'lib/rex/proto/http/server.rb', line 294 def on_client_data(cli) begin data = cli.read(65535) raise ::EOFError if not data raise ::EOFError if data.empty? case cli.request.parse(data) when Packet::ParseCode::Completed dispatch_request(cli, cli.request) cli.reset_cli when Packet::ParseCode::Partial # Return and wait for the on_client_data handler to be called again # The Request object tracks the state of the request for us return when Packet::ParseCode::Error close_client(cli) end rescue EOFError if (cli.request.completed?) dispatch_request(cli, cli.request) cli.reset_cli end close_client(cli) end end |
#remove_resource(name) ⇒ Object
Removes the supplied resource handler.
231 232 233 |
# File 'lib/rex/proto/http/server.rb', line 231 def remove_resource(name) self.resources.delete(name) end |
#send_e404(cli, request) ⇒ Object
Sends a 404 error to the client for a given request.
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 |
# File 'lib/rex/proto/http/server.rb', line 259 def send_e404(cli, request) resp = Response::E404.new resp['Content-Type'] = 'text/html' resp.body = "<html><head>" + "<title>404 Not Found</title>" + "</head><body>" + "<h1>Not found</h1>" + "The requested URL #{html_escape(request.resource)} was not found on this server.<p><hr>" + "</body></html>" # Send the response to the client like what cli.send_response(resp) end |
#start ⇒ Object
Listens on the defined port and host and starts monitoring for clients.
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/rex/proto/http/server.rb', line 143 def start self.listener = Rex::Socket::TcpServer.create( 'LocalHost' => self.listen_host, 'LocalPort' => self.listen_port, 'Context' => self.context, 'SSL' => self.ssl, 'SSLCert' => self.ssl_cert, 'SSLCompression' => self.ssl_compression, 'SSLCipher' => self.ssl_cipher, 'SSLVersion' => self.ssl_version, 'Comm' => self.comm ) # Register callbacks self.listener.on_client_connect_proc = Proc.new { |cli| on_client_connect(cli) } self.listener.on_client_data_proc = Proc.new { |cli| on_client_data(cli) } self.listener.start end |
#stop ⇒ Object
Terminates the monitor thread and turns off the listener.
171 172 173 174 |
# File 'lib/rex/proto/http/server.rb', line 171 def stop self.listener.stop self.listener.close end |
#unmount(root) ⇒ Object
Remove the mount point.
201 202 203 |
# File 'lib/rex/proto/http/server.rb', line 201 def unmount(root) resources.delete(root) end |
#wait ⇒ Object
Waits for the HTTP service to terminate
180 181 182 |
# File 'lib/rex/proto/http/server.rb', line 180 def wait self.listener.wait if self.listener end |