Parent

Included Modules

Class/Module Index [+]

Quicksearch

Rex::Proto::Http::Server::UnitTest::SrvKlass

Acts as an HTTP server, processing requests and dispatching them to registered procs. Some of this server was modeled after webrick.

Constants

DefaultServer

The default server name that will be returned in the Server attribute of a response.

ExtensionMimeTypes

A hash that associated a file extension with a mime type for use as the content type of responses.

Attributes

comm[RW]
context[RW]
listen_host[RW]
listen_port[RW]
listener[RW]
resources[RW]
server_name[RW]
ssl[RW]
ssl_cert[RW]

Public Class Methods

hardcore_alias(*args) click to toggle source

Returns the hardcore alias for the HTTP service

# File lib/rex/proto/http/server.rb, line 118
def self.hardcore_alias(*args)
        "#{(args[0] || '')}#{(args[1] || '')}"
end
new(port = 80, listen_host = '0.0.0.0', ssl = false, context = {}, comm = nil, ssl_cert = nil) click to toggle source

Initializes an HTTP server as listening on the provided port and hostname.

# File lib/rex/proto/http/server.rb, line 102
def initialize(port = 80, listen_host = '0.0.0.0', ssl = false, context = {}, comm = nil, ssl_cert = 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.listener    = nil
        self.resources   = {}
        self.server_name = DefaultServer
end

Public Instance Methods

add_resource(name, opts) click to toggle source

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.
# File lib/rex/proto/http/server.rb, line 200
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) click to toggle source

Adds Server headers and stuff.

# File lib/rex/proto/http/server.rb, line 224
def add_response_headers(resp)
        resp['Server'] = self.server_name if not resp['Server']
end
alias() click to toggle source

HTTP server.

# File lib/rex/proto/http/server.rb, line 125
def alias
        super || "HTTP Server"
end
close_client(cli) click to toggle source

Closes the supplied client, if valid.

# File lib/rex/proto/http/server.rb, line 173
def close_client(cli)
        listener.close_client(cli)
end
mime_type(file) click to toggle source

Returns the mime type associated with the supplied file. Right now the set of mime types is fairly limited.

# File lib/rex/proto/http/server.rb, line 232
def mime_type(file)
        type = nil

        if (file =~ /\.(.+?)$/)
                type = ExtensionMimeTypes[$1.downcase]
        end

        type || "text/plain"
end
mount(root, handler, long_call = false, *args) click to toggle source

Mounts a directory or resource as being serviced by the supplied handler.

# File lib/rex/proto/http/server.rb, line 180
def mount(root, handler, long_call = false, *args)
        resources[root] = [ handler, long_call, args ]
end
remove_resource(name) click to toggle source

Removes the supplied resource handler.

# File lib/rex/proto/http/server.rb, line 217
def remove_resource(name)
        self.resources.delete(name)
end
send_e404(cli, request) click to toggle source

Sends a 404 error to the client for a given request.

# File lib/rex/proto/http/server.rb, line 245
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() click to toggle source

Listens on the defined port and host and starts monitoring for clients.

# File lib/rex/proto/http/server.rb, line 132
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,
                '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() click to toggle source

Terminates the monitor thread and turns off the listener.

# File lib/rex/proto/http/server.rb, line 157
def stop
        self.listener.stop
        self.listener.close
end
unmount(root) click to toggle source

Remove the mount point.

# File lib/rex/proto/http/server.rb, line 187
def unmount(root)
        resources.delete(root)
end
wait() click to toggle source

Waits for the HTTP service to terminate

# File lib/rex/proto/http/server.rb, line 166
def wait
        self.listener.wait if self.listener
end

Protected Instance Methods

dispatch_request(cli, request) click to toggle source

Dispatches the supplied request for a given connection.

# File lib/rex/proto/http/server.rb, line 313
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
on_client_connect(cli) click to toggle source

Extends new clients with the ServerClient module and initializes them.

# File lib/rex/proto/http/server.rb, line 270
def on_client_connect(cli)
        cli.extend(ServerClient)

        cli.init_cli(self)
end
on_client_data(cli) click to toggle source

Processes data coming in from a client.

# File lib/rex/proto/http/server.rb, line 279
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

[Validate]

Generated with the Darkfish Rdoc Generator 2.